Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | merge 9.0b3 |
|---|---|
| Timelines: | family | ancestors | descendants | both | dgp-refactor |
| Files: | files | file ages | folders |
| SHA3-256: |
5c61a0b81a6d366e97bf4f7b39d3a7eb |
| User & Date: | dgp 2025-02-25 18:36:04.329 |
Context
|
2025-02-25
| ||
| 18:50 | conflict free check-in: d487966f45 user: dgp tags: dgp-refactor | |
| 18:36 | merge 9.0b3 check-in: 5c61a0b81a user: dgp tags: dgp-refactor | |
| 18:16 | merge & resolve check-in: 11f14ba10a user: dgp tags: dgp-refactor | |
|
2024-07-31
| ||
| 18:41 | merge release check-in: 71923cd053 user: dgp tags: trunk, main | |
Changes
Changes to .github/workflows/mac-build.yml.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
name: macOS
on:
push:
branches:
- "main"
- "core-8-branch"
- "core-8-6-branch"
tags:
- "core-**"
permissions:
contents: read
jobs:
xcode:
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
name: macOS
on:
push:
branches:
- "main"
- "core-8-branch"
- "core-8-6-branch"
tags:
- "core-**"
permissions:
contents: read
jobs:
xcode:
runs-on: macos-14
defaults:
run:
shell: bash
working-directory: macosx
steps:
- name: Checkout
uses: actions/checkout@v4
|
| ︙ | ︙ | |||
32 33 34 35 36 37 38 |
- name: Run Tests
run: make test styles=develop
env:
ERROR_ON_FAILURES: 1
MAC_CI: 1
timeout-minutes: 15
clang:
| | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
- name: Run Tests
run: make test styles=develop
env:
ERROR_ON_FAILURES: 1
MAC_CI: 1
timeout-minutes: 15
clang:
runs-on: macos-14
strategy:
matrix:
config:
- ""
- "--disable-shared"
- "--disable-zipfs"
- "--enable-symbols"
|
| ︙ | ︙ |
Changes to .github/workflows/onefiledist.yml.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
- name: Upload
uses: actions/upload-artifact@v4
with:
name: Tclsh ${{ env.TCL_PATCHLEVEL }} Linux single-file build (snapshot)
path: 1dist/*.tar
macos:
name: macOS
| | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
- name: Upload
uses: actions/upload-artifact@v4
with:
name: Tclsh ${{ env.TCL_PATCHLEVEL }} Linux single-file build (snapshot)
path: 1dist/*.tar
macos:
name: macOS
runs-on: macos-12
defaults:
run:
shell: bash
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
|
| ︙ | ︙ |
Changes to changes.md.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 | ## Notable incompatibilities - Unqualified varnames resolved in current namespace, not global. - No --disable-threads build option. Always thread-enabled. - I/O malencoding default response: raise error (-profile strict) - Windows platform needs Windows 7 or Windows Server 2008 R2 or later - Ended interpretation of ~ as home directory in pathnames | | > > > | > | 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 | ## Notable incompatibilities - Unqualified varnames resolved in current namespace, not global. - No --disable-threads build option. Always thread-enabled. - I/O malencoding default response: raise error (-profile strict) - Windows platform needs Windows 7 or Windows Server 2008 R2 or later - Ended interpretation of ~ as home directory in pathnames - Removed the "identity" encoding. - Removed the encoding alias "binary" to "iso8859-1". - $::tcl_precision no longer controls string generation of doubles - Removed Tcl 7 legacies: [case], [puts] [read] variant syntaxes - Removed subcommands [trace variable|vdelete|vinfo] - No -eofchar option for channels anymore for writing. - On Windows 10+ (Version 1903 or higher), system encoding is always utf-8. - Removed command ::tcl::unsupported::inject. ## Incompatibilities in C public interface - Many arguments expanded type from int to Tcl_Size - Ended support for Tcl_ChannelTypeVersion less than 5 - Introduced versioning of the Tcl_ObjType struct - Removed macros CONST*: Tcl 9 support means dropping Tcl 8.3 support - Removed routines: > Tcl_Backslash(), Tcl_*VA(), Tcl_*MathFunc*(), Tcl_MakeSafe(), > Tcl_(Save|Restore|Discard|Free)Result(), Tcl_EvalTokens(), > Tcl_(Get|Set)DefaultEncodingDir(), > Tcl_UniCharN(case)cmp(), Tcl_UniCharCaseMatch() ## New commands - `array default`, `array for` - `chan isbinary` - `coroinject`, `coroprobe` - `clock add weekdays` - `const`, `info const*` - `dict getwithdefault` - `file tempdir`, `file home`, `file tildeexpand` - `info commandtype` - `ledit` - `lpop` - `lremove` - `lseq` - `package files` - `string insert`, `string is dict` - `tcl::process` - `*::build-info` - `readFile`, `writeFile`, `foreachLine` ## New command options - `regsub ... -command ...` - `lsearch ... -stride ...` - `clock scan ... -validate ...` - `socket ... -nodelay ... -keepalive ...` - `vwait` controlled by several new options |
| ︙ | ︙ |
Changes to doc/CrtCommand.3.
| ︙ | ︙ | |||
98 99 100 101 102 103 104 | point to constant strings or may be shared with other parts of the interpreter. Note also that the argument strings are encoded in normalized UTF-8 since version 8.1 of Tcl. .PP \fIProc\fR must return an integer code that is expected to be one of \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or | | > | > > | | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | point to constant strings or may be shared with other parts of the interpreter. Note also that the argument strings are encoded in normalized UTF-8 since version 8.1 of Tcl. .PP \fIProc\fR must return an integer code that is expected to be one of \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. See the \fBreturn\fR man page for details on what these codes mean and the use of extended values for an extension's private use. Most normal commands will only return \fBTCL_OK\fR or \fBTCL_ERROR\fR. .PP In addition, \fIproc\fR must set the interpreter result; in the case of a \fBTCL_OK\fR return code this gives the result of the command, and in the case of \fBTCL_ERROR\fR it gives an error message. The \fBTcl_SetResult\fR procedure provides an easy interface for setting the return value; for complete details on how the interpreter result field is managed, see the \fBTcl_Interp\fR man page. Before invoking a command procedure, |
| ︙ | ︙ |
Changes to doc/CrtObjCmd.3.
| ︙ | ︙ | |||
128 129 130 131 132 133 134 | \fBTcl_GetIntFromObj\fR on \fIobjv\fR[\fB2\fR] to obtain the integer representation of that value; that call may change the type of the value that \fIobjv\fR[\fB2\fR] points at, but will not change where \fIobjv\fR[\fB2\fR] points. .PP \fIproc\fR must return an integer code that is either \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. | < | > | > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | \fBTcl_GetIntFromObj\fR on \fIobjv\fR[\fB2\fR] to obtain the integer representation of that value; that call may change the type of the value that \fIobjv\fR[\fB2\fR] points at, but will not change where \fIobjv\fR[\fB2\fR] points. .PP \fIproc\fR must return an integer code that is either \fBTCL_OK\fR, \fBTCL_ERROR\fR, \fBTCL_RETURN\fR, \fBTCL_BREAK\fR, or \fBTCL_CONTINUE\fR. See the \fBreturn\fR man page for details on what these codes mean and the use of extended values for an extension's private use. Most normal commands will only return \fBTCL_OK\fR or \fBTCL_ERROR\fR. .PP In addition, if \fIproc\fR needs to return a non-empty result, it can call \fBTcl_SetObjResult\fR to set the interpreter's result. In the case of a \fBTCL_OK\fR return code this gives the result of the command, and in the case of \fBTCL_ERROR\fR this gives an error message. Before invoking a command procedure, \fBTcl_EvalObjEx\fR sets interpreter's result to |
| ︙ | ︙ |
Changes to doc/TclZlib.3.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 | .nf #include <tcl.h> .sp int \fBTcl_ZlibDeflate\fR(\fIinterp, format, dataObj, level, dictObj\fR) .sp int | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | .nf #include <tcl.h> .sp int \fBTcl_ZlibDeflate\fR(\fIinterp, format, dataObj, level, dictObj\fR) .sp int \fBTcl_ZlibInflate\fR(\fIinterp, format, dataObj, bufferSize, dictObj\fR) .sp unsigned int \fBTcl_ZlibCRC32\fR(\fIinitValue, bytes, length\fR) .sp unsigned int \fBTcl_ZlibAdler32\fR(\fIinitValue, bytes, length\fR) .sp |
| ︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 | \fIformat\fR is \fBTCL_ZLIB_FORMAT_GZIP\fR or \fBTCL_ZLIB_FORMAT_AUTO\fR. If a NULL is passed, a default header will be used on compression and the header will be ignored (apart from integrity checks) on decompression. See the section \fBGZIP OPTIONS DICTIONARY\fR for details about the contents of this dictionary. .AP "unsigned int" initValue in The initial value for the checksum algorithm. .AP "unsigned char" *bytes in An array of bytes to run the checksum algorithm over, or NULL to get the recommended initial value for the checksum algorithm. .AP Tcl_Size length in The number of bytes in the array. .AP int mode in What mode to operate the stream in. Should be either | > > > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | \fIformat\fR is \fBTCL_ZLIB_FORMAT_GZIP\fR or \fBTCL_ZLIB_FORMAT_AUTO\fR. If a NULL is passed, a default header will be used on compression and the header will be ignored (apart from integrity checks) on decompression. See the section \fBGZIP OPTIONS DICTIONARY\fR for details about the contents of this dictionary. .AP "unsigned int" initValue in The initial value for the checksum algorithm. .AP "Tcl_Size" bufferSize in A hint as to what size of buffer is to be used to receive the data. Use 0 to use a geric guess based on the input data. .AP "unsigned char" *bytes in An array of bytes to run the checksum algorithm over, or NULL to get the recommended initial value for the checksum algorithm. .AP Tcl_Size length in The number of bytes in the array. .AP int mode in What mode to operate the stream in. Should be either |
| ︙ | ︙ |
Changes to doc/catch.n.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 | value corresponding to the exceptional return code returned by evaluation of \fIscript\fR. Tcl defines the normal return code from script evaluation to be zero (0), or \fBTCL_OK\fR. Tcl also defines four exceptional return codes: 1 (\fBTCL_ERROR\fR), 2 (\fBTCL_RETURN\fR), 3 (\fBTCL_BREAK\fR), and 4 (\fBTCL_CONTINUE\fR). Errors during evaluation of a script are indicated by a return code of \fBTCL_ERROR\fR. The other exceptional return codes are returned by the \fBreturn\fR, \fBbreak\fR, and \fBcontinue\fR commands | | | | > > | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | value corresponding to the exceptional return code returned by evaluation of \fIscript\fR. Tcl defines the normal return code from script evaluation to be zero (0), or \fBTCL_OK\fR. Tcl also defines four exceptional return codes: 1 (\fBTCL_ERROR\fR), 2 (\fBTCL_RETURN\fR), 3 (\fBTCL_BREAK\fR), and 4 (\fBTCL_CONTINUE\fR). Errors during evaluation of a script are indicated by a return code of \fBTCL_ERROR\fR. The other exceptional return codes are returned by the \fBreturn\fR, \fBbreak\fR, and \fBcontinue\fR commands and in other special situations as documented. New commands defined by Tcl packages as well as scripts that make use of the \fBreturn \-code\fR command can return other integer values as the return code. These must however lie outside the range reserved for Tcl as documented for the \fBreturn\fR command. .PP If the \fIresultVarName\fR argument is given, then the variable it names is set to the result of the script evaluation. When the return code from the script is 1 (\fBTCL_ERROR\fR), the value stored in \fIresultVarName\fR is an error message. When the return code from the script is 0 (\fBTCL_OK\fR), the value stored in \fIresultVarName\fR is the value returned from \fIscript\fR. .PP |
| ︙ | ︙ |
Changes to doc/chan.n.
| ︙ | ︙ | |||
19 20 21 22 23 24 25 | with the \fBopen\fR and \fBsocket\fR commands, or the default named channels \fBstdin\fR, \fBstdout\fR or \fBstderr\fR which correspond to the process's standard input, output and error streams respectively). \fIOption\fR indicates what to do with the channel; any unique abbreviation for \fIoption\fR is acceptable. Valid options are: .\" METHOD: blocked .TP | | | | | | | | | 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 | with the \fBopen\fR and \fBsocket\fR commands, or the default named channels \fBstdin\fR, \fBstdout\fR or \fBstderr\fR which correspond to the process's standard input, output and error streams respectively). \fIOption\fR indicates what to do with the channel; any unique abbreviation for \fIoption\fR is acceptable. Valid options are: .\" METHOD: blocked .TP \fBchan blocked \fIchannel\fR . This tests whether the last input operation on the channel called \fIchannel\fR failed because it would have otherwise caused the process to block, and returns 1 if that was the case. It returns 0 otherwise. Note that this only ever returns 1 when the channel has been configured to be non-blocking; all Tcl channels have blocking turned on by default. .\" METHOD: close .TP \fBchan close \fIchannel\fR ?\fIdirection\fR? . Close and destroy the channel called \fIchannel\fR. Note that this deletes all existing file-events registered on the channel. If the \fIdirection\fR argument (which must be \fBread\fR or \fBwrite\fR or any unique abbreviation of them) is present, the channel will only be half-closed, so that it can go from being read-write to write-only or read-only respectively. If a read-only channel is closed for reading, it is the same as if the channel is fully closed, and respectively similar for write-only channels. Without the \fIdirection\fR argument, the channel is closed for both reading and writing (but only if those directions are currently open). It is an error to close a read-only channel for writing, or a write-only channel for reading. .RS .PP As part of closing the channel, all buffered output is flushed to the channel's output device (only if the channel is ceasing to be writable), any buffered input is discarded (only if the channel is ceasing to be readable), the underlying operating system resource is closed and \fIchannel\fR becomes unavailable for future use (both only if the channel is being completely closed). .PP If the channel is blocking and the channel is ceasing to be writable, the command does not return until all output is flushed. If the channel is non-blocking and there is unflushed output, the channel remains open and the command returns immediately; output will be flushed in the background and the channel will be closed when all the flushing is complete. .PP If \fIchannel\fR is a blocking channel for a command pipeline then \fBchan close\fR waits for the child processes to complete. .PP If the channel is shared between interpreters, then \fBchan close\fR makes \fIchannel\fR unavailable in the invoking interpreter but has no other effect until all of the sharing interpreters have closed the channel. When the last interpreter in which the channel is registered invokes \fBchan close\fR (or \fBclose\fR), the cleanup actions described above occur. With half-closing, the half-close of the channel only applies to the current interpreter's view of the channel until all channels have closed it in that direction (or completely). See the \fBinterp\fR command for a description of channel sharing. |
| ︙ | ︙ | |||
97 98 99 100 101 102 103 | 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 .\" METHOD: configure .TP | | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 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 .\" METHOD: configure .TP \fBchan configure \fIchannel\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?... . Query or set the configuration options of the channel named \fIchannel\fR. .RS .PP If no \fIoptionName\fR or \fIvalue\fR arguments are supplied, the command returns a list containing alternating option names and values for the channel. If \fIoptionName\fR is supplied but no \fIvalue\fR then the command returns the current value of the given option. If one or more pairs of \fIoptionName\fR and \fIvalue\fR are supplied, |
| ︙ | ︙ | |||
161 162 163 164 165 166 167 | input or output. \fInewSize\fR must be a number of no more than one million, allowing buffers of up to one million bytes in size. .\" OPTION: -encoding .TP \fB\-encoding\fR \fIname\fR . This option is used to specify the encoding of the channel as one of | | | | | 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 | input or output. \fInewSize\fR must be a number of no more than one million, allowing buffers of up to one million bytes in size. .\" OPTION: -encoding .TP \fB\-encoding\fR \fIname\fR . This option is used to specify the encoding of the channel as one of the named encodings returned by \fBencoding names\fR, so that the data can be converted to and from Unicode for use in Tcl. For instance, in order for Tcl to read characters from a Japanese file in \fBshiftjis\fR and properly process and display the contents, the encoding would be set to \fBshiftjis\fR. Thereafter, when reading from the channel, the bytes in the Japanese file would be converted to Unicode as they are read. Writing is also supported \- as Tcl strings are written to the channel they will automatically be converted to the specified encoding on output. .RS .PP If a file contains pure binary data (for instance, a JPEG image), the encoding for the channel should be configured to be \fBiso8859-1\fR. Tcl will then assign no interpretation to the data in the file and simply read or write raw bytes. The Tcl \fBbinary\fR command can be used to manipulate this byte-oriented data. It is usually better to set the \fB\-translation\fR option to \fBbinary\fR when you want to transfer binary data, as this turns off the other automatic interpretations of the bytes in the stream as well. .PP |
| ︙ | ︙ | |||
387 388 389 390 391 392 393 | This subcommand is \fBsafe\fR and made accessible to safe interpreters. While it arranges for the execution of arbitrary Tcl code the system also makes sure that the code is always executed within the safe interpreter. .RE .\" METHOD: eof .TP | | | | | | 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 | This subcommand is \fBsafe\fR and made accessible to safe interpreters. While it arranges for the execution of arbitrary Tcl code the system also makes sure that the code is always executed within the safe interpreter. .RE .\" METHOD: eof .TP \fBchan eof \fIchannel\fR . Test whether the last input operation on the channel called \fIchannel\fR failed because the end of the data stream was reached, returning 1 if end-of-file was reached, and 0 otherwise. .\" METHOD: event .TP \fBchan event \fIchannel event\fR ?\fIscript\fR? . Arrange for the Tcl script \fIscript\fR to be installed as a \fIfile event handler\fR to be called whenever the channel called \fIchannel\fR enters the state described by \fIevent\fR (which must be either \fBreadable\fR or \fBwritable\fR); only one such handler may be installed per event per channel at a time. If \fIscript\fR is the empty string, the current handler is deleted (this also happens if the channel is closed or the interpreter deleted). If \fIscript\fR is omitted, the currently installed script is returned (or an empty string if no such handler is installed). The callback is only performed if the event loop is being serviced (e.g. via \fBvwait\fR or |
| ︙ | ︙ | |||
464 465 466 467 468 469 470 | script then the command registered with \fBinterp bgerror\fR is used to report the error. In addition, the file event handler is deleted if it ever returns an error; this is done in order to prevent infinite loops due to buggy handlers. .RE .\" METHOD: flush .TP | | | | | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | script then the command registered with \fBinterp bgerror\fR is used to report the error. In addition, the file event handler is deleted if it ever returns an error; this is done in order to prevent infinite loops due to buggy handlers. .RE .\" METHOD: flush .TP \fBchan flush \fIchannel\fR . Ensures that all pending output for the channel called \fIchannel\fR is written. .RS .PP If the channel is in blocking mode the command does not return until all the buffered output has been flushed to the channel. If the channel is in non-blocking mode, the command may return before all buffered output has been flushed; the remainder will be flushed in the background as fast as the underlying file or device is able to absorb it. .RE .\" METHOD: gets .TP \fBchan gets \fIchannel\fR ?\fIvarName\fR? . Reads a line from the channel consisting of all characters up to the next end-of-line sequence or until end of file is seen. The line feed character corresponding to end-of-line sequence is not included as part of the line. If the \fIvarName\fR argument is specified, the line is stored in the variable of that name and the command returns the length of the line. If \fIvarName\fR is not specified, the command returns the line itself as the result of the command. |
| ︙ | ︙ | |||
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 | .PP If the encoding profile \fBstrict\fR is in effect for the channel, the command will raise an exception with the POSIX error code \fBEILSEQ\fR if any encoding errors are encountered in the channel input data. The file pointer remains unchanged and it is possible to introspect, and in some cases recover, by changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later. .RE .\" METHOD: names .TP \fBchan names\fR ?\fIpattern\fR? . Produces a list of all channel names. If \fIpattern\fR is specified, only those channel names that match it (according to the rules of \fBstring match\fR) will be returned. .\" METHOD: pending .TP | > > > > > > > > | | | 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 549 550 551 552 553 554 555 556 557 558 559 |
.PP
If the encoding profile \fBstrict\fR is in effect for the channel, the command
will raise an exception with the POSIX error code \fBEILSEQ\fR if any encoding
errors are encountered in the channel input data. The file pointer remains
unchanged and it is possible to introspect, and in some cases recover, by
changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later.
.RE
.\" METHOD: isbinary
.TP
\fBchan isbinary \fIchannel\fR
.
Test whether the channel called \fIchannel\fR is a binary channel,
returning 1 if it is and, and 0 otherwise. A binary channel is
a channel with iso8859-1 encoding, -eofchar set to {} and
-translation set to lf.
.\" METHOD: names
.TP
\fBchan names\fR ?\fIpattern\fR?
.
Produces a list of all channel names. If \fIpattern\fR is specified,
only those channel names that match it (according to the rules of
\fBstring match\fR) will be returned.
.\" METHOD: pending
.TP
\fBchan pending \fImode channel\fR
.
Depending on whether \fImode\fR is \fBinput\fR or \fBoutput\fR,
returns the number of
bytes of input or output (respectively) currently buffered
internally for \fIchannel\fR (especially useful in a readable event
callback to impose application-specific limits on input line lengths to avoid
a potential denial-of-service attack where a hostile user crafts
an extremely long line that exceeds the available memory to buffer it).
Returns -1 if the channel was not opened for the mode in question.
.\" METHOD: pipe
.TP
\fBchan pipe\fR
|
| ︙ | ︙ | |||
568 569 570 571 572 573 574 | differences, but the details of what exactly gets written when are not. This is most likely to show up when using pipelines for testing; care should be taken to ensure that deadlocks do not occur and that potential short reads are allowed for. .RE .\" METHOD: pop .TP | | | | | | | 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 | differences, but the details of what exactly gets written when are not. This is most likely to show up when using pipelines for testing; care should be taken to ensure that deadlocks do not occur and that potential short reads are allowed for. .RE .\" METHOD: pop .TP \fBchan pop \fIchannel\fR . Removes the topmost transformation from the channel \fIchannel\fR, if there is any. If there are no transformations added to \fIchannel\fR, this is equivalent to \fBchan close\fR of that channel. The result is normally the empty string, but can be an error in some situations (i.e. where the underlying system stream is closed and that results in an error). .\" METHOD: postevent .TP \fBchan postevent \fIchannel eventSpec\fR . This subcommand is used by command handlers specified with \fBchan create\fR. It notifies the channel represented by the handle \fIchannel\fR that the event(s) listed in the \fIeventSpec\fR have occurred. The argument has to be a list containing any of the strings \fBread\fR and \fBwrite\fR. The list must contain at least one element as it does not make sense to invoke the command if there are no events to post. .RS .PP Note that this subcommand can only be used with channel handles that |
| ︙ | ︙ | |||
614 615 616 617 618 619 620 | current interpreter or in other interpreters or other threads, even where the event is posted from a safe interpreter and listened for by a trusted interpreter. \fBChan event\fR handlers are \fIalways\fR executed in the interpreter that set them up. .RE .\" METHOD: push .TP | | | | | | | | | | | | | | | 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 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 | current interpreter or in other interpreters or other threads, even where the event is posted from a safe interpreter and listened for by a trusted interpreter. \fBChan event\fR handlers are \fIalways\fR executed in the interpreter that set them up. .RE .\" METHOD: push .TP \fBchan push \fIchannel cmdPrefix\fR . Adds a new transformation on top of the channel \fIchannel\fR. The \fIcmdPrefix\fR argument describes a list of one or more words which represent a handler that will be used to implement the transformation. The command prefix must provide the API described in the \fBtranschan\fR manual page. The result of this subcommand is a handle to the transformation. Note that it is important to make sure that the transformation is capable of supporting the channel mode that it is used with or this can make the channel neither readable nor writable. .\" METHOD: puts .TP \fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannel\fR? \fIstring\fR . Writes \fIstring\fR to the channel named \fIchannel\fR followed by a newline character. A trailing newline character is written unless the optional flag \fB\-nonewline\fR is given. If \fIchannel\fR is omitted, the string is written to the standard output channel, \fBstdout\fR. .RS .PP Newline characters in the output are translated by \fBchan puts\fR to platform-specific end-of-line sequences according to the currently configured value of the \fB\-translation\fR option for the channel (for example, on PCs newlines are normally replaced with carriage-return-linefeed sequences; see \fBchan configure\fR above for details). .PP Tcl buffers output internally, so characters written with \fBchan puts\fR may not appear immediately on the output file or device; Tcl will normally delay output until the buffer is full or the channel is closed. You can force output to appear immediately with the \fBchan flush\fR command. .PP When the output buffer fills up, the \fBchan puts\fR command will normally block until all the buffered data has been accepted for output by the operating system. If \fIchannel\fR is in non-blocking mode then the \fBchan puts\fR command will not block even if the operating system cannot accept the data. Instead, Tcl continues to buffer the data and writes it in the background as fast as the underlying file or device can accept it. The application must use the Tcl event loop for non-blocking output to work; otherwise Tcl never finds out that the file or device is ready for more output data. It is possible for an arbitrarily large amount of data to be buffered for a channel in non-blocking mode, which could consume a large amount of memory. To avoid wasting memory, non-blocking I/O should normally be used in an event-driven fashion with the \fBchan event\fR command (do not invoke \fBchan puts\fR unless you have recently been notified via a file event that the channel is ready for more output data). .PP The command will raise an error exception with POSIX error code \fBEILSEQ\fR if the encoding profile \fBstrict\fR is in effect for the channel and the output data cannot be encoded in the encoding configured for the channel. Data may be partially written to the channel in this case. .RE .\" METHOD: read .TP \fBchan read \fIchannel\fR ?\fInumChars\fR? .TP \fBchan read \fR?\fB\-nonewline\fR? \fIchannel\fR . In the first form, the result will be the next \fInumChars\fR characters read from the channel named \fIchannel\fR; if \fInumChars\fR is omitted, all characters up to the point when the channel would signal a failure (whether an end-of-file, blocked or other error condition) are read. In the second form (i.e. when \fInumChars\fR has been omitted) the flag \fB\-nonewline\fR may be given to indicate that any trailing newline in the string that has been read should be trimmed. .RS .PP If \fIchannel\fR is in non-blocking mode, \fBchan read\fR may not read as many characters as requested: once all available input has been read, the command will return the data that is available rather than blocking for more input. If the channel is configured to use a multi-byte encoding, then there may actually be some bytes remaining in the internal buffers that do not form a complete character. These bytes will not be returned until a complete character is available or end-of-file is reached. The \fB\-nonewline\fR switch is ignored if the command returns before reaching the end of the file. .PP \fBChan read\fR translates end-of-line sequences in the input into newline characters according to the \fB\-translation\fR option for the channel (see \fBchan configure\fR above for a discussion on the ways in which \fBchan configure\fR will alter input). .PP When reading from a serial port, most applications should configure the serial port channel to be non-blocking, like this: .PP .CS \fBchan configure \fIchannel \fB\-blocking \fI0\fR. .CE .PP Then \fBchan read\fR behaves much like described above. Note that most serial ports are comparatively slow; it is entirely possible to get a \fBreadable\fR event for each character read from them. Care must be taken when using \fBchan read\fR on blocking serial ports: .TP \fBchan read \fIchannel numChars\fR . In this form \fBchan read\fR blocks until \fInumChars\fR have been received from the serial port. .TP \fBchan read \fIchannel\fR . In this form \fBchan read\fR blocks until the reception of the end-of-file character, see \fBchan configure -eofchar\fR. If there no end-of-file character has been configured for the channel, then \fBchan read\fR will block forever. .PP If the encoding profile \fBstrict\fR is in effect for the channel, the command |
| ︙ | ︙ | |||
741 742 743 744 745 746 747 | blocking channel case, the \fB\-data\fR key is not present in the error option dictionary. In the case of exception thrown due to encoding errors, it is possible to introspect, and in some cases recover, by changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later. .RE .\" METHOD: seek .TP | | | | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 | blocking channel case, the \fB\-data\fR key is not present in the error option dictionary. In the case of exception thrown due to encoding errors, it is possible to introspect, and in some cases recover, by changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later. .RE .\" METHOD: seek .TP \fBchan seek \fIchannel offset\fR ?\fIorigin\fR? . Sets the current access position within the underlying data stream for the channel named \fIchannel\fR to be \fIoffset\fR bytes relative to \fIorigin\fR. \fIOffset\fR must be an integer (which may be negative) and \fIorigin\fR must be one of the following: .RS .IP \fBstart\fR The new access position will be \fIoffset\fR bytes from the start of the underlying file or device. .IP \fBcurrent\fR |
| ︙ | ︙ | |||
775 776 777 778 779 780 781 | .PP Note that \fIoffset\fR values are byte offsets, not character offsets. Both \fBchan seek\fR and \fBchan tell\fR operate in terms of bytes, not characters, unlike \fBchan read\fR. .RE .\" METHOD: tell .TP | | | | | | 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 | .PP Note that \fIoffset\fR values are byte offsets, not character offsets. Both \fBchan seek\fR and \fBchan tell\fR operate in terms of bytes, not characters, unlike \fBchan read\fR. .RE .\" METHOD: tell .TP \fBchan tell \fIchannel\fR . Returns a number giving the current access position within the underlying data stream for the channel named \fIchannel\fR. This value returned is a byte offset that can be passed to \fBchan seek\fR in order to set the channel to a particular position. Note that this value is in terms of bytes, not characters like \fBchan read\fR. The value returned is -1 for channels that do not support seeking. .\" METHOD: truncate .TP \fBchan truncate \fIchannel\fR ?\fIlength\fR? . Sets the byte length of the underlying data stream for the channel named \fIchannel\fR to be \fIlength\fR (or to the current byte offset within the underlying data stream if \fIlength\fR is omitted). The channel is flushed before truncation. . .SH EXAMPLES .SS "SIMPLE CHANNEL OPERATION EXAMPLES" .PP Instruct Tcl to always send output to \fBstdout\fR immediately, |
| ︙ | ︙ | |||
875 876 877 878 879 880 881 |
set data [chan read $chan]
chan puts "[string length $data] $data"
if {[chan eof $chan]} {
chan event $chan readable {}
}
}
| | | 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 |
set data [chan read $chan]
chan puts "[string length $data] $data"
if {[chan eof $chan]} {
chan event $chan readable {}
}
}
chan configure $chan -blocking 0 -translation binary
\fBchan event\fR $chan readable [list GetData $chan]
.CE
.PP
The next example is similar but uses \fBchan gets\fR to read
line-oriented data.
.PP
.CS
|
| ︙ | ︙ | |||
1034 1035 1036 1037 1038 1039 1040 |
% set d
-code 1 -level 0
-errorstack {INNER {invokeStk1 gets file384b6a8}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
% chan tell $f
0
| | | 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 |
% set d
-code 1 -level 0
-errorstack {INNER {invokeStk1 gets file384b6a8}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
% chan tell $f
0
% chan configure $f -translation binary
% chan gets $f
AÃB
.CE
.PP
The following example is similar to the above but demonstrates recovery after a
blocking read. The successfully decoded data "A" is returned in the error options
dictionary key \fB\-data\fR. The file position is advanced on the encoding error
|
| ︙ | ︙ | |||
1058 1059 1060 1061 1062 1063 1064 |
% set d
-data A -code 1 -level 0
-errorstack {INNER {invokeStk1 read file35a65a0}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
% chan tell $f
1
| | | 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 |
% set d
-data A -code 1 -level 0
-errorstack {INNER {invokeStk1 read file35a65a0}}
-errorcode {POSIX EILSEQ {invalid or incomplete multibyte or wide character}}
-errorinfo {...} -errorline 1
% chan tell $f
1
% chan configure $f -translation binary
% chan read $f
ÃB
% chan close $f
.CE
.PP
Finally the same example, but this time with a non-blocking channel.
.PP
|
| ︙ | ︙ |
Changes to doc/clock.n.
| ︙ | ︙ | |||
97 98 99 100 101 102 103 | 1 January 1970, 00:00 UTC. Note that the count of seconds does not include any leap seconds; seconds are counted as if each UTC day has exactly 86400 seconds. Tcl responds to leap seconds by speeding or slowing its clock by a tiny fraction for some minutes until it is back in sync with UTC; its data model does not represent minutes that have 59 or 61 seconds. .TP | | | | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | 1 January 1970, 00:00 UTC. Note that the count of seconds does not include any leap seconds; seconds are counted as if each UTC day has exactly 86400 seconds. Tcl responds to leap seconds by speeding or slowing its clock by a tiny fraction for some minutes until it is back in sync with UTC; its data model does not represent minutes that have 59 or 61 seconds. .TP \fInow\fR Instead of \fItimeVal\fR a non-integer value \fBnow\fR can be used as replacement for today, which is simply interpolated to the runt-time as value of \fBclock seconds\fR. For example: .sp \fBclock format now -f %a; # current day of the week\fR .sp \fBclock add now 1 month; # next month\fR .TP \fIunit\fR . One of the words, \fBseconds\fR, \fBminutes\fR, \fBhours\fR, \fBdays\fR, \fBweekdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR. Used in conjunction with \fIcount\fR to identify an interval of time, for example, \fI3 seconds\fR or \fI1 year\fR. |
| ︙ | ︙ | |||
128 129 130 131 132 133 134 | .TP \fB\-format\fR format . Specifies the desired output format for \fBclock format\fR or the expected input format for \fBclock scan\fR. The \fIformat\fR string consists of any number of characters other than the per-cent sign .PQ \fB%\fR | | | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | .TP \fB\-format\fR format . Specifies the desired output format for \fBclock format\fR or the expected input format for \fBclock scan\fR. The \fIformat\fR string consists of any number of characters other than the per-cent sign .PQ \fB%\fR interspersed with any number of \fIformat groups\fR, which are two- or three-character sequences beginning with the per-cent sign. The permissible format groups, and their interpretation, are described under \fBFORMAT GROUPS\fR. .RS .PP On \fBclock format\fR, the default format is .PP .CS |
| ︙ | ︙ | |||
190 191 192 193 194 195 196 197 198 199 200 201 202 203 | .IP [1] the environment variable \fBTCL_TZ\fR. .IP [2] the environment variable \fBTZ\fR. .IP [3] on Windows systems, the time zone settings from the Control Panel. .RE .PP If none of these is present, the C \fBlocaltime\fR and \fBmktime\fR functions are used to attempt to convert times between local and Greenwich. On 32-bit systems, this approach is likely to have bugs, particularly for times that lie outside the window (approximately the years 1902 to 2037) that can be represented in a 32-bit integer. .SH "CLOCK ARITHMETIC" | > > > > > > > > > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | .IP [1] the environment variable \fBTCL_TZ\fR. .IP [2] the environment variable \fBTZ\fR. .IP [3] on Windows systems, the time zone settings from the Control Panel. .RE .\" OPTION: -validate .TP \fB\-validate\fR boolean . If \fIboolean\fR is true (default), \fBclock scan\fR will raise an error if the input contains invalid values, e.g. day of month greater than number of days in the month. If specified as false, the command makes an adjustment to bring values within acceptable range. See \fBSCANNING TIMES\fR for details. .PP If none of these is present, the C \fBlocaltime\fR and \fBmktime\fR functions are used to attempt to convert times between local and Greenwich. On 32-bit systems, this approach is likely to have bugs, particularly for times that lie outside the window (approximately the years 1902 to 2037) that can be represented in a 32-bit integer. .SH "CLOCK ARITHMETIC" |
| ︙ | ︙ | |||
488 489 490 491 492 493 494 | in the same day, once without and once with Daylight Saving Time. If this situation occurs, the first occurrence of the time is chosen. (For this reason, it is wise to have the input string contain the time zone when converting local times. This caveat does not apply to UTC times.) .PP If the interpretation of the groups yields an impossible time because | > > | | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 | in the same day, once without and once with Daylight Saving Time. If this situation occurs, the first occurrence of the time is chosen. (For this reason, it is wise to have the input string contain the time zone when converting local times. This caveat does not apply to UTC times.) .PP If the interpretation of the groups yields an impossible time because a field is out of range, an exception is raised if the \fB-validate\fR option is not present or passed as true. If passed as false, enough of that field's unit will be added to or subtracted from the time to bring it in range. Thus, if attempting to scan or format day 0 of the month, one day will be subtracted from day 1 of the month, yielding the last day of the previous month. .PP If the interpretation of the groups yields an impossible time because a Daylight Saving Time change skips over that time, or an ambiguous time because a Daylight Saving Time change skips back so that the clock |
| ︙ | ︙ |
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 | .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 \fIchannel\fR ?\fBr\fR(\fBead\fR)|\fBw\fR(\fBrite\fR)? .BE .SH DESCRIPTION .PP The \fBclose\fR command has been superceded by the \fBchan close\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/eof.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH eof n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME eof \- Check for end of file condition on channel .SH SYNOPSIS | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | .TH eof n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME eof \- Check for end of file condition on channel .SH SYNOPSIS \fBeof \fIchannel\fR .BE .SH DESCRIPTION .PP The \fBeof\fR command has been superceded by the \fBchan eof\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/fblocked.n.
1 2 3 4 5 6 7 8 9 10 11 12 | '\" '\" Copyright (c) 1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH fblocked n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fblocked \- Test whether the last input operation exhausted all available input .SH SYNOPSIS | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | '\" '\" Copyright (c) 1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH fblocked n 7.5 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fblocked \- Test whether the last input operation exhausted all available input .SH SYNOPSIS \fBfblocked \fIchannel\fR .BE .SH DESCRIPTION .PP The \fBfblocked\fR command has been superceded by the \fBchan blocked\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/fconfigure.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fconfigure \- Set and get options on a channel .SH SYNOPSIS .nf | | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fconfigure \- Set and get options on a channel .SH SYNOPSIS .nf \fBfconfigure \fIchannel\fR \fBfconfigure \fIchannel name\fR \fBfconfigure \fIchannel name value \fR?\fIname value ...\fR? .fi .BE .SH DESCRIPTION .PP The \fBfconfigure\fR command has been superceded by the \fBchan configure\fR command which supports the same syntax and options. .SH "SEE ALSO" |
| ︙ | ︙ |
Changes to doc/fileevent.n.
| ︙ | ︙ | |||
9 10 11 12 13 14 15 | .TH fileevent n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fileevent \- Execute a script when a channel becomes readable or writable .SH SYNOPSIS | | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | .TH fileevent n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fileevent \- Execute a script when a channel becomes readable or writable .SH SYNOPSIS \fBfileevent \fIchannel \fBreadable \fR?\fIscript\fR? .sp \fBfileevent \fIchannel \fBwritable \fR?\fIscript\fR? .BE .SH DESCRIPTION .PP The \fBfileevent\fR command has been superceded by the \fBchan event\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/flush.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH flush n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME flush \- Flush buffered output for a channel .SH SYNOPSIS | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | .TH flush n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME flush \- Flush buffered output for a channel .SH SYNOPSIS \fBflush \fIchannel\fR .BE .SH DESCRIPTION .PP The \fBflush\fR command has been superceded by the \fBchan flush\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/format.n.
| ︙ | ︙ | |||
137 138 139 140 141 142 143 | function of the \fBexpr\fR command (at least a 64-bit range). If it is \fBz\fR or \fBt\fR it specifies that the integer value is truncated to the range determined by the value of the \fBpointerSize\fR element of the \fBtcl_platform\fR array. If it is \fBL\fR it specifies that an integer or double value is taken without truncation for conversion to a formatted substring. If neither of those are present, the integer value is | | < | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | function of the \fBexpr\fR command (at least a 64-bit range). If it is \fBz\fR or \fBt\fR it specifies that the integer value is truncated to the range determined by the value of the \fBpointerSize\fR element of the \fBtcl_platform\fR array. If it is \fBL\fR it specifies that an integer or double value is taken without truncation for conversion to a formatted substring. If neither of those are present, the integer value is truncated to a 32-bit range. .SS "MANDATORY CONVERSION TYPE" .PP The last thing in a conversion specifier is an alphabetic character that determines what kind of conversion to perform. The following conversion characters are currently supported: .IP \fBd\fR 10 Convert integer to signed decimal string. |
| ︙ | ︙ |
Changes to doc/gets.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH gets n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME gets \- Read a line from a channel .SH SYNOPSIS | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | .TH gets n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME gets \- Read a line from a channel .SH SYNOPSIS \fBgets \fIchannel\fR ?\fIvarName\fR? .BE .SH DESCRIPTION .PP The \fBgets\fR command has been superceded by the \fBchan gets\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/interp.n.
| ︙ | ︙ | |||
388 389 390 391 392 393 394 | application. If your machine has a limit on the size of the C stack, you may get stack overflows before reaching the limit set by the command. If this happens, see if there is a mechanism in your system for increasing the maximum size of the C stack. .RE .\" METHOD: share .TP | | | | | | 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 | application. If your machine has a limit on the size of the C stack, you may get stack overflows before reaching the limit set by the command. If this happens, see if there is a mechanism in your system for increasing the maximum size of the C stack. .RE .\" METHOD: share .TP \fBinterp share\fI srcPath channel destPath\fR . Causes the IO channel identified by \fIchannel\fR to become shared between the interpreter identified by \fIsrcPath\fR and the interpreter identified by \fIdestPath\fR. Both interpreters have the same permissions on the IO channel. Both interpreters must close it to close the underlying IO channel; IO channels accessible in an interpreter are automatically closed when an interpreter is destroyed. .\" METHOD: target .TP \fBinterp target\fI path alias\fR . Returns a Tcl list describing the target interpreter for an alias. The alias is specified with an interpreter path and source command name, just as in \fBinterp alias\fR above. The name of the target interpreter is returned as an interpreter path, relative to the invoking interpreter. If the target interpreter for the alias is the invoking interpreter then an empty list is returned. If the target interpreter for the alias is not the invoking interpreter or one of its descendants then an error is generated. The target command does not have to be defined at the time of this invocation. .\" METHOD: transfer .TP \fBinterp transfer\fI srcPath channel destPath\fR . Causes the IO channel identified by \fIchannel\fR to become available in the interpreter identified by \fIdestPath\fR and unavailable in the interpreter identified by \fIsrcPath\fR. .SH "CHILD COMMAND" .PP For each child interpreter created with the \fBinterp\fR command, a new Tcl command is created in the parent interpreter with the same name as the new interpreter. This command may be used to invoke |
| ︙ | ︙ |
Changes to doc/library.n.
1 2 3 4 5 6 7 8 9 10 11 | '\" '\" Copyright (c) 1991-1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH library n "8.0" Tcl "Tcl Built-In Commands" .so man.macros .BS .SH NAME | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | '\" '\" Copyright (c) 1991-1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH library n "8.0" Tcl "Tcl Built-In Commands" .so man.macros .BS .SH NAME auto_execok, auto_import, auto_load, auto_mkindex, auto_qualify, auto_reset, foreachLine, parray, readFile, tcl_findLibrary, tcl_endOfWord, tcl_startOfNextWord, tcl_startOfPreviousWord, tcl_wordBreakAfter, tcl_wordBreakBefore, writeFile \- standard library of Tcl procedures .SH SYNOPSIS .nf \fBauto_execok \fIcmd\fR \fBauto_import \fIpattern\fR \fBauto_load \fIcmd\fR \fBauto_mkindex \fIdir pattern pattern ...\fR \fBauto_qualify \fIcommand namespace\fR |
| ︙ | ︙ |
Changes to doc/msgcat.n.
| ︙ | ︙ | |||
24 25 26 27 28 29 30 | \fB::msgcat::mcpackagenamespaceget\fR .VE "TIP 490" \fB::msgcat::mclocale \fR?\fInewLocale\fR? .VS "TIP 499" \fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ... .VE "TIP 499" .VS "TIP 412" | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | \fB::msgcat::mcpackagenamespaceget\fR .VE "TIP 490" \fB::msgcat::mclocale \fR?\fInewLocale\fR? .VS "TIP 499" \fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ... .VE "TIP 499" .VS "TIP 412" \fB::msgcat::mcloadedlocales subcommand\fR .VE "TIP 412" \fB::msgcat::mcload \fIdirname\fR \fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR? \fB::msgcat::mcmset \fIlocale src-trans-list\fR \fB::msgcat::mcflset \fIsrc-string \fR?\fItranslate-string\fR? \fB::msgcat::mcflmset \fIsrc-trans-list\fR \fB::msgcat::mcunknown \fIlocale src-string\fR ?\fIarg arg ...\fR? |
| ︙ | ︙ | |||
218 219 220 221 222 223 224 |
.CS
::msgcat::mcpreferences fr en {}
.CE
.RE
.PP
.\" COMMAND: mcloadedlocales
.TP
| | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
.CS
::msgcat::mcpreferences fr en {}
.CE
.RE
.PP
.\" COMMAND: mcloadedlocales
.TP
\fB::msgcat::mcloadedlocales subcommand\fR
.VS "TIP 499"
This group of commands manage the list of loaded locales for packages not
setting a package locale.
.PP
.RS
The subcommand \fBloaded\fR returns the list of currently loaded locales.
.PP
|
| ︙ | ︙ | |||
378 379 380 381 382 383 384 | .PP .CS language[_country][_modifier] .CE .PP On Windows and Cygwin, if none of those environment variables is set, msgcat will attempt to extract locale information from the registry. | | | < | 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | .PP .CS language[_country][_modifier] .CE .PP On Windows and Cygwin, if none of those environment variables is set, msgcat will attempt to extract locale information from the registry. The RFC4747 locale name "lang-script-country-options" is transformed to the locale as "lang_country_script" (Example: sr-Latn-CS -> sr_cs_latin). If all these attempts to discover an initial locale from the user's environment fail, msgcat defaults to an initial locale of .QW C . .PP When a locale is specified by the user, a .QW "best match" search is performed during string translation. For example, if a user |
| ︙ | ︙ | |||
594 595 596 597 598 599 600 | .PP .RS .VS "TIP 499" If a set of locale preferences is given, it is set as package locale preference list. The package locale is set to the first element of the preference list. A package locale is activated, if it was not set so far. .PP | | | 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 | .PP .RS .VS "TIP 499" If a set of locale preferences is given, it is set as package locale preference list. The package locale is set to the first element of the preference list. A package locale is activated, if it was not set so far. .PP Locale preferences are loaded now for the package, if not yet loaded. .VE "TIP 499" .RE .PP .\" METHOD: loaded .TP \fB::msgcat::mcpackagelocale loaded\fR . |
| ︙ | ︙ |
Changes to doc/namespace.n.
| ︙ | ︙ | |||
491 492 493 494 495 496 497 | If you provide a fully-qualified name that starts with a \fB::\fR, there is no question about what command, variable, or namespace you mean. However, if the name does not start with a \fB::\fR (i.e., is \fIrelative\fR), Tcl follows basic rules for looking it up: .IP \(bu | | | > > | < | | < < | | | | | | | | | 491 492 493 494 495 496 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 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 |
If you provide a fully-qualified name that starts with a \fB::\fR,
there is no question about what command, variable, or namespace
you mean.
However, if the name does not start with a \fB::\fR
(i.e., is \fIrelative\fR),
Tcl follows basic rules for looking it up:
.IP \(bu
\fBVariable names\fR are always resolved starting in the current
namespace. In the absence of special resolvers, foo::bar::baz refers to
a variable named "baz" in a namespace named "bar" that is a child of a
namespace named "foo" that is a child of the current namespace of the interpreter.
.IP \(bu
\fBCommand names\fR are always resolved by looking in the current namespace
first. If not found there, they are searched for in every namespace on the
current namespace's command path (which is empty by default). If not found
there, command names are looked up in the global namespace (or, failing that,
are processed by the appropriate \fBnamespace unknown\fR handler.)
.IP \(bu
\fBNamespace names\fR are always resolved by looking in only the current
namespace.
.PP
In the following example,
.PP
.CS
set traceLevel 0
\fBnamespace eval\fR Debug {
printTrace $traceLevel
}
.CE
.PP
Tcl looks for \fBtraceLevel\fR in the namespace \fBDebug\fR.
It looks up the command \fBprintTrace\fR in the same way.
If a variable or command name is not found,
the name is undefined.
To make this point absolutely clear, consider the following example:
.PP
.CS
set traceLevel 0
\fBnamespace eval\fR Foo {
variable traceLevel 3
\fBnamespace eval\fR Debug {
printTrace $traceLevel
}
}
.CE
.PP
Here Tcl looks for \fBtraceLevel\fR in the namespace \fBFoo::Debug\fR.
The variables \fBFoo::traceLevel\fR and \fBFoo::Debug::traceLevel\fR
are completely ignored during the name resolution process.
.PP
You can use the \fBnamespace which\fR command to clear up any question
about name resolution.
For example, the command:
.PP
.CS
\fBnamespace eval\fR Foo::Debug {\fBnamespace which\fR -variable traceLevel}
.CE
.PP
returns the empty string.
The command,
.PP
.CS
\fBnamespace eval\fR Foo {\fBnamespace which\fR -variable traceLevel}
.CE
.PP
returns the empty string as well.
.PP
As mentioned above,
namespace names and variables are looked up differently
than the names of commands.
Namespace names and variables are always resolved in the current namespace.
This means, for example,
that a \fBnamespace eval\fR command that creates a new namespace
always creates a child of the current namespace
unless the new namespace name begins with \fB::\fR.
.PP
Tcl has no access control to limit what variables, commands,
or namespaces you can reference.
|
| ︙ | ︙ |
Changes to doc/object.n.
| ︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 | .\" METHOD: eval .TP \fIobj \fBeval\fR ?\fIarg ...\fR? . This method concatenates the arguments, \fIarg\fR, as if with \fBconcat\fR, and then evaluates the resulting script in the namespace that is uniquely associated with \fIobj\fR, returning the result of the evaluation. .\" METHOD: unknown .TP \fIobj \fBunknown ?\fImethodName\fR? ?\fIarg ...\fR? . This method is called when an attempt to invoke the method \fImethodName\fR on object \fIobj\fR fails. The arguments that the user supplied to the method are given as \fIarg\fR arguments. | > > > > > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | .\" METHOD: eval .TP \fIobj \fBeval\fR ?\fIarg ...\fR? . This method concatenates the arguments, \fIarg\fR, as if with \fBconcat\fR, and then evaluates the resulting script in the namespace that is uniquely associated with \fIobj\fR, returning the result of the evaluation. .RS .PP Note that object-internal commands such as \fBmy\fR and \fBself\fR can be invoked in this context. .RE .\" METHOD: unknown .TP \fIobj \fBunknown ?\fImethodName\fR? ?\fIarg ...\fR? . This method is called when an attempt to invoke the method \fImethodName\fR on object \fIobj\fR fails. The arguments that the user supplied to the method are given as \fIarg\fR arguments. |
| ︙ | ︙ |
Changes to doc/puts.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH puts n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME puts \- Write to a channel .SH SYNOPSIS | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | .TH puts n 7.5 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME puts \- Write to a channel .SH SYNOPSIS \fBputs \fR?\fB\-nonewline\fR? ?\fIchannel\fR? \fIstring\fR .BE .SH DESCRIPTION .PP The \fBputs\fR command has been superceded by the \fBchan puts\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/read.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH read n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME read \- Read from a channel .SH SYNOPSIS | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | .TH read n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME read \- Read from a channel .SH SYNOPSIS \fBread \fR?\fB\-nonewline\fR? \fIchannel\fR .sp \fBread \fIchannel numChars\fR .BE .SH DESCRIPTION .PP The \fBread\fR command has been superceded by the \fBchan read\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/refchan.n.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | .\" Note: do not modify the .SH NAME line immediately below! .SH NAME refchan \- command handler API of reflected channels .SH SYNOPSIS .nf \fBchan create \fImode cmdPrefix\fR | | | | | | | | | | | | | | 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 | .\" Note: do not modify the .SH NAME line immediately below! .SH NAME refchan \- command handler API of reflected channels .SH SYNOPSIS .nf \fBchan create \fImode cmdPrefix\fR \fIcmdPrefix \fBblocking\fI channel mode\fR \fIcmdPrefix \fBcget\fI channel option\fR \fIcmdPrefix \fBcgetall\fI channel\fR \fIcmdPrefix \fBconfigure\fI channel option value\fR \fIcmdPrefix \fBfinalize\fI channel\fR \fIcmdPrefix \fBinitialize\fI channel mode\fR \fIcmdPrefix \fBread\fI channel count\fR \fIcmdPrefix \fBseek\fI channel offset base\fR \fIcmdPrefix \fBwatch\fI channel eventspec\fR \fIcmdPrefix \fBwrite\fI channel data\fR .fi .BE .SH DESCRIPTION .PP The Tcl-level handler for a reflected channel has to be a command with subcommands (termed an \fIensemble\fR, as it is a command such as that created by \fBnamespace ensemble\fR \fBcreate\fR, though the implementation of handlers for reflected channel \fIis not\fR tied to \fBnamespace ensemble\fRs in any way; see \fBEXAMPLE\fR below for how to build an \fBoo::class\fR that supports the API). Note that \fIcmdPrefix\fR is whatever was specified in the call to \fBchan create\fR, and may consist of multiple arguments; this will be expanded to multiple words in place of the prefix. .PP Of all the possible subcommands, the handler \fImust\fR support \fBinitialize\fR, \fBfinalize\fR, and \fBwatch\fR. Support for the other subcommands is optional. .SS "MANDATORY SUBCOMMANDS" .\" METHOD: initialize .TP \fIcmdPrefix \fBinitialize \fIchannel mode\fR . An invocation of this subcommand will be the first call the \fIcmdPrefix\fR will receive for the specified new \fIchannel\fR. It is the responsibility of this subcommand to set up any internal data structures required to keep track of the channel and its state. .RS .PP The return value of the method has to be a list containing the names of all subcommands supported by the \fIcmdPrefix\fR. This also tells the Tcl core which version of the API for reflected channels is used by |
| ︙ | ︙ | |||
71 72 73 74 75 76 77 | will usually contain at least one element. .PP The subcommand must throw an error if the chosen mode is not supported by the \fIcmdPrefix\fR. .RE .\" METHOD: finalize .TP | | | | | | | | | 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 | will usually contain at least one element. .PP The subcommand must throw an error if the chosen mode is not supported by the \fIcmdPrefix\fR. .RE .\" METHOD: finalize .TP \fIcmdPrefix \fBfinalize \fIchannel\fR . An invocation of this subcommand will be the last call the \fIcmdPrefix\fR will receive for the specified \fIchannel\fR. It will be generated just before the destruction of the data structures of the channel held by the Tcl core. The command handler \fImust not\fR access the \fIchannel\fR anymore in no way. Upon this subcommand being called, any internal resources allocated to this channel must be cleaned up. .RS .PP The return value of this subcommand is ignored. .PP If the subcommand throws an error the command which caused its invocation (usually \fBchan close\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as (and converted to) an error. .PP This subcommand is not invoked if the creation of the channel was aborted during \fBinitialize\fR (See above). .RE .\" METHOD: watch .TP \fIcmdPrefix \fBwatch \fIchannel eventspec\fR . This subcommand notifies the \fIcmdPrefix\fR that the specified \fIchannel\fR is interested in the events listed in the \fIeventspec\fR. This argument is a list containing any of \fBread\fR and \fBwrite\fR. The list may be empty, which signals that the channel does not wish to be notified of any events. In that situation, the handler should disable event generation completely. .RS .PP \fBWarning:\fR Any return value of the subcommand is ignored. This includes all errors thrown by the subcommand, \fBbreak\fR, \fBcontinue\fR, and custom return codes. .PP This subcommand interacts with \fBchan postevent\fR. Trying to post an event which was not listed in the last call to \fBwatch\fR will cause \fBchan postevent\fR to throw an error. .RE .SS "OPTIONAL SUBCOMMANDS" .\" METHOD: read .TP \fIcmdPrefix \fBread \fIchannel count\fR . This \fIoptional\fR subcommand is called when the user requests data from the channel \fIchannel\fR. \fIcount\fR specifies how many \fIbytes\fR have been requested. If the subcommand is not supported then it is not possible to read from the channel handled by the command. .RS .PP The return value of this subcommand is taken as the requested data \fIbytes\fR. If the returned data contains more bytes than requested, an error will be signaled and later thrown by the command which |
| ︙ | ︙ | |||
172 173 174 175 176 177 178 | If the subcommand throws any other error, the command which caused its invocation (usually \fBgets\fR, or \fBread\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR, (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .\" METHOD: write .TP | | | | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | If the subcommand throws any other error, the command which caused its invocation (usually \fBgets\fR, or \fBread\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR, (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .\" METHOD: write .TP \fIcmdPrefix \fBwrite \fIchannel data\fR . This \fIoptional\fR subcommand is called when the user writes data to the channel \fIchannel\fR. The \fIdata\fR argument contains \fIbytes\fR, not characters. Any type of transformation (EOL, encoding) configured for the channel has already been applied at this point. If this subcommand is not supported then it is not possible to write to the channel handled by the command. .RS .PP The return value of the subcommand is taken as the number of bytes |
| ︙ | ︙ | |||
230 231 232 233 234 235 236 | If the subcommand throws any other error the command which caused its invocation (usually \fBputs\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .\" METHOD: seek .TP | | | | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | If the subcommand throws any other error the command which caused its invocation (usually \fBputs\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .\" METHOD: seek .TP \fIcmdPrefix \fBseek \fIchannel offset base\fR . This \fIoptional\fR subcommand is responsible for the handling of \fBchan seek\fR and \fBchan tell\fR requests on the channel \fIchannel\fR. If it is not supported then seeking will not be possible for the channel. .RS .PP The \fIbase\fR argument is the same as the equivalent argument of the builtin \fBchan seek\fR, namely: .IP \fBstart\fR 10 Seeking is relative to the beginning of the channel. |
| ︙ | ︙ | |||
267 268 269 270 271 272 273 | .PP The offset/base combination of 0/\fBcurrent\fR signals a \fBchan tell\fR request, i.e.,\ seek nothing relative to the current location, making the new location identical to the current one, which is then returned. .RE .\" METHOD: configure .TP | | | | | | | | | | | | 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 | .PP The offset/base combination of 0/\fBcurrent\fR signals a \fBchan tell\fR request, i.e.,\ seek nothing relative to the current location, making the new location identical to the current one, which is then returned. .RE .\" METHOD: configure .TP \fIcmdPrefix \fBconfigure \fIchannel option value\fR . This \fIoptional\fR subcommand is for setting the type-specific options of channel \fIchannel\fR. The \fIoption\fR argument indicates the option to be written, and the \fIvalue\fR argument indicates the value to set the option to. .RS .PP This subcommand will never try to update more than one option at a time; that is behavior implemented in the Tcl channel core. .PP The return value of the subcommand is ignored. .PP If the subcommand throws an error the command which performed the (re)configuration or query (usually \fBfconfigure\fR or \fBchan configure\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .\" METHOD: cget .TP \fIcmdPrefix \fBcget \fIchannel option\fR . This \fIoptional\fR subcommand is used when reading a single type-specific option of channel \fIchannel\fR. If this subcommand is supported then the subcommand \fBcgetall\fR must be supported as well. .RS .PP The subcommand should return the value of the specified \fIoption\fR. .PP If the subcommand throws an error, the command which performed the (re)configuration or query (usually \fBfconfigure\fR or \fBchan configure\fR) will appear to have thrown this error. Any exception beyond \fIerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .\" METHOD: cgetall .TP \fIcmdPrefix \fBcgetall \fIchannel\fR . This \fIoptional\fR subcommand is used for reading all type-specific options of channel \fIchannel\fR. If this subcommand is supported then the subcommand \fBcget\fR has to be supported as well. .RS .PP The subcommand should return a list of all options and their values. This list must have an even number of elements. .PP If the subcommand throws an error the command which performed the (re)configuration or query (usually \fBfconfigure\fR or \fBchan configure\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .\" METHOD: blocking .TP \fIcmdPrefix \fBblocking \fIchannel mode\fR . This \fIoptional\fR subcommand handles changes to the blocking mode of the channel \fIchannel\fR. The \fImode\fR is a boolean flag. A true value means that the channel has to be set to blocking, and a false value means that the channel should be non-blocking. .RS .PP The return value of the subcommand is ignored. .PP If the subcommand throws an error the command which caused its invocation (usually \fBfconfigure\fR or \fBchan configure\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. .RE .\" METHOD: truncate .TP \fIcmdPrefix \fBtruncate\fI channel length\fR . This \fIoptional\fR subcommand handles changing the length of the underlying data stream for the channel \fIchannel\fR. Its length gets set to \fIlength\fR. .RS .PP If the subcommand throws an error the command which caused its invocation (usually \fBchan truncate\fR) will appear to have thrown this error. Any exception beyond \fBerror\fR (e.g.,\ \fBbreak\fR, etc.) is treated as and converted to an error. |
| ︙ | ︙ |
Changes to doc/return.n.
| ︙ | ︙ | |||
74 75 76 77 78 79 80 | The return code of the procedure is 4 (\fBTCL_CONTINUE\fR). The procedure command behaves in its calling context as if it were the command \fBcontinue\fR. .TP 13 \fIvalue\fR . \fIValue\fR must be an integer; it will be returned as the | | > > > | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | The return code of the procedure is 4 (\fBTCL_CONTINUE\fR). The procedure command behaves in its calling context as if it were the command \fBcontinue\fR. .TP 13 \fIvalue\fR . \fIValue\fR must be an integer; it will be returned as the return code for the current procedure. Applications and packages should use values in the range 5 to 1073741823 (0x3fffffff) for their own purposes. Values outside this range are reserved for use by Tcl. .LP When a procedure wants to signal that it has received invalid arguments from its caller, it may use \fBreturn -code error\fR with \fIresult\fR set to a suitable error message. Otherwise usage of the \fBreturn -code\fR option is mostly limited to procedures that implement a new control structure. .PP |
| ︙ | ︙ |
Changes to doc/scan.n.
| ︙ | ︙ | |||
69 70 71 72 73 74 75 | at most once and the empty positions will be filled in with empty strings. .SS "OPTIONAL SIZE MODIFIER" .PP The size modifier field is used only when scanning a substring into one of Tcl's integer values. The size modifier field dictates the integer range acceptable to be stored in a variable, or, for the inline case, in a position in the result list. | | > | | | < | | > | | | > | 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 | at most once and the empty positions will be filled in with empty strings. .SS "OPTIONAL SIZE MODIFIER" .PP The size modifier field is used only when scanning a substring into one of Tcl's integer values. The size modifier field dictates the integer range acceptable to be stored in a variable, or, for the inline case, in a position in the result list. The syntactically valid values for the size modifier are \fBh\fR, \fBl\fR, \fBz\fR, \fBt\fR, \fBq\fR, \fBj\fR, \fBll\fR, and \fBL\fR. The \fBh\fR size modifier value is equivalent to the absence of a size modifier in the the conversion specifier. Either one indicates the integer range to be stored is limited to the 32-bit range. The \fBL\fR size modifier is equivalent to the \fBll\fR size modifier. Either one indicates the integer range to be stored is unlimited. The \fBl\fR (or \fBq\fR or \fBj\fR) size modifier indicates that the integer range to be stored is limited to the same range produced by the \fBwide()\fR function of the \fBexpr\fR command. The \fBz\fR and \fBt\fR modifiers indicate the integer range to be the same as for either \fBh\fR or \fBl\fR, depending on the value of the \fBpointerSize\fR element of the \fBtcl_platform\fR array. .SS "MANDATORY CONVERSION CHARACTER" .PP The following conversion characters are supported: .IP \fBd\fR The input substring must be a decimal integer. It is read in and the integer value is stored in the variable, truncated as required by the size modifier value. |
| ︙ | ︙ | |||
243 244 245 246 247 248 249 | puts "X=$x, Y=$y" .CE .PP An interactive session demonstrating the truncation of integer values determined by size modifiers: .PP .CS | < < | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | puts "X=$x, Y=$y" .CE .PP An interactive session demonstrating the truncation of integer values determined by size modifiers: .PP .CS \fI%\fR scan 20000000000000000000 %d 2147483647 \fI%\fR scan 20000000000000000000 %ld 9223372036854775807 \fI%\fR scan 20000000000000000000 %lld 20000000000000000000 .CE |
| ︙ | ︙ |
Changes to doc/seek.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH seek n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME seek \- Change the access position for an open channel .SH SYNOPSIS | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | .TH seek n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME seek \- Change the access position for an open channel .SH SYNOPSIS \fBseek \fIchannel offset \fR?\fIorigin\fR? .BE .SH DESCRIPTION .PP The \fBseek\fR command has been superceded by the \fBchan seek\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/string.n.
| ︙ | ︙ | |||
146 147 148 149 150 151 152 | .IP \fBdigit\fR 12 Any Unicode digit character. Note that this includes characters outside of the [0\-9] range. .IP \fBdouble\fR 12 Any of the forms allowed to \fBTcl_GetDoubleFromObj\fR. .IP \fBentier\fR 12 . | | < < | | | | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | .IP \fBdigit\fR 12 Any Unicode digit character. Note that this includes characters outside of the [0\-9] range. .IP \fBdouble\fR 12 Any of the forms allowed to \fBTcl_GetDoubleFromObj\fR. .IP \fBentier\fR 12 . Synonym for \fBinteger\fR. .IP \fBfalse\fR 12 Any of the forms allowed to \fBTcl_GetBoolean\fR where the value is false. .IP \fBgraph\fR 12 Any Unicode printing character, except space. .IP \fBinteger\fR 12 Any of the valid string formats for an integer value of arbitrary size in Tcl, with optional surrounding whitespace. The formats accepted are exactly those accepted by the C routine \fBTcl_GetBignumFromObj\fR. .IP \fBlist\fR 12 Any proper list structure, with optional surrounding whitespace. In case of improper list structure, 0 is returned and the \fIvarname\fR will contain the index of the .QW element where the list parsing fails, or \-1 if this cannot be determined. .IP \fBlower\fR 12 |
| ︙ | ︙ |
Changes to doc/tell.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH tell n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tell \- Return current access position for an open channel .SH SYNOPSIS | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | .TH tell n 8.1 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME tell \- Return current access position for an open channel .SH SYNOPSIS \fBtell \fIchannel\fR .BE .SH DESCRIPTION .PP The \fBtell\fR command has been superceded by the \fBchan tell\fR command which supports the same syntax and options. .SH "SEE ALSO" chan(n) |
| ︙ | ︙ |
Changes to doc/tm.n.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 | .SH NAME tm \- Facilities for locating and loading of Tcl Modules .SH SYNOPSIS .nf \fB::tcl::tm::path add \fR?\fIpath\fR...? \fB::tcl::tm::path remove \fR?\fIpath\fR...? \fB::tcl::tm::path list\fR | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | .SH NAME tm \- Facilities for locating and loading of Tcl Modules .SH SYNOPSIS .nf \fB::tcl::tm::path add \fR?\fIpath\fR...? \fB::tcl::tm::path remove \fR?\fIpath\fR...? \fB::tcl::tm::path list\fR \fB::tcl::tm::roots \fR\fIpaths\fR .fi .BE .SH DESCRIPTION .PP This document describes the facilities for locating and loading Tcl Modules (see \fBMODULE DEFINITION\fR for the definition of a Tcl Module). The following commands are supported: |
| ︙ | ︙ | |||
57 58 59 60 61 62 63 | .TP \fB::tcl::tm::path list\fR . Returns a list containing all registered module paths, in the order that they are searched for modules. .\" COMMAND: roots .TP | | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | .TP \fB::tcl::tm::path list\fR . Returns a list containing all registered module paths, in the order that they are searched for modules. .\" COMMAND: roots .TP \fB::tcl::tm::roots \fR\fIpaths\fR . Similar to \fBpath add\fR, and layered on top of it. This command takes a single argument containing a list of paths, extends each with .QW "\fBtcl\fIX\fB/site-tcl\fR" , and .QW "\fBtcl\fIX\fB/\fIX\fB.\fIy\fR" , for major version \fIX\fR of the Tcl interpreter and minor version \fIy\fR less than or equal to the minor version of the interpreter, and adds the resulting set of paths to the list of paths to search. |
| ︙ | ︙ |
Changes to doc/transchan.n.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 | .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME transchan \- command handler API of channel transforms .SH SYNOPSIS .nf | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME transchan \- command handler API of channel transforms .SH SYNOPSIS .nf \fBchan push \fIchannel cmdPrefix\fR \fIcmdPrefix \fBclear \fIhandle\fR \fIcmdPrefix \fBdrain \fIhandle\fR \fIcmdPrefix \fBfinalize \fIhandle\fR \fIcmdPrefix \fBflush \fIhandle\fR \fIcmdPrefix \fBinitialize \fIhandle mode\fR \fIcmdPrefix \fBlimit? \fIhandle\fR |
| ︙ | ︙ |
Changes to generic/tcl.decls.
| ︙ | ︙ | |||
2228 2229 2230 2231 2232 2233 2234 |
declare 656 {
const char *Tcl_UtfPrev(const char *src, const char *start)
}
# TIP 656
declare 658 {
int Tcl_ExternalToUtfDStringEx(Tcl_Interp *interp, Tcl_Encoding encoding,
| | | | | | 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 |
declare 656 {
const char *Tcl_UtfPrev(const char *src, const char *start)
}
# TIP 656
declare 658 {
int Tcl_ExternalToUtfDStringEx(Tcl_Interp *interp, Tcl_Encoding encoding,
const char *src, Tcl_Size srcLen, int flags, Tcl_DString *dsPtr,
Tcl_Size *errorLocationPtr)
}
declare 659 {
int Tcl_UtfToExternalDStringEx(Tcl_Interp *interp, Tcl_Encoding encoding,
const char *src, Tcl_Size srcLen, int flags, Tcl_DString *dsPtr,
Tcl_Size *errorLocationPtr)
}
# TIP #511
declare 660 {
int Tcl_AsyncMarkFromSignal(Tcl_AsyncHandler async, int sigNumber)
}
|
| ︙ | ︙ |
Changes to generic/tcl.h.
| ︙ | ︙ | |||
450 451 452 453 454 455 456 | #define TCL_REG_CANMATCH 001000 /* Report details on partial/limited * matches. */ /* * Flags values passed to Tcl_RegExpExecObj. */ | | | 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | #define TCL_REG_CANMATCH 001000 /* Report details on partial/limited * matches. */ /* * Flags values passed to Tcl_RegExpExecObj. */ #define TCL_REG_NOTBOL 0001 /* Beginning of string does not match ^. */ #define TCL_REG_NOTEOL 0002 /* End of string does not match $. */ /* * Structures filled in by Tcl_RegExpInfo. Note that all offset values are * relative to the start of the match string, not the beginning of the entire * string. */ |
| ︙ | ︙ | |||
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 | * TCL_RETURN The command requests that the current function return; * the interpreter's result contains the function's * return value. * TCL_BREAK The command requests that the innermost loop be * exited; the interpreter's result is meaningless. * TCL_CONTINUE Go on to the next iteration of the current loop; the * interpreter's result is meaningless. */ #define TCL_OK 0 #define TCL_ERROR 1 #define TCL_RETURN 2 #define TCL_BREAK 3 #define TCL_CONTINUE 4 /* *---------------------------------------------------------------------------- * Flags to control what substitutions are performed by Tcl_SubstObj(): */ #define TCL_SUBST_COMMANDS 001 | > > > > | 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 | * TCL_RETURN The command requests that the current function return; * the interpreter's result contains the function's * return value. * TCL_BREAK The command requests that the innermost loop be * exited; the interpreter's result is meaningless. * TCL_CONTINUE Go on to the next iteration of the current loop; the * interpreter's result is meaningless. * Integer return codes in the range TCL_CODE_USER_MIN to TCL_CODE_USER_MAX are * reserved for the use of packages. */ #define TCL_OK 0 #define TCL_ERROR 1 #define TCL_RETURN 2 #define TCL_BREAK 3 #define TCL_CONTINUE 4 #define TCL_CODE_USER_MIN 5 #define TCL_CODE_USER_MAX 0x3fffffff /* 1073741823 */ /* *---------------------------------------------------------------------------- * Flags to control what substitutions are performed by Tcl_SubstObj(): */ #define TCL_SUBST_COMMANDS 001 |
| ︙ | ︙ | |||
661 662 663 664 665 666 667 |
/* Called to update the string rep from the
* type's internal representation. */
Tcl_SetFromAnyProc *setFromAnyProc;
/* Called to convert the object's internal rep
* to this type. Frees the internal rep of the
* old type. Returns TCL_ERROR on failure. */
#if TCL_MAJOR_VERSION > 8
| | | 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 |
/* Called to update the string rep from the
* type's internal representation. */
Tcl_SetFromAnyProc *setFromAnyProc;
/* Called to convert the object's internal rep
* to this type. Frees the internal rep of the
* old type. Returns TCL_ERROR on failure. */
#if TCL_MAJOR_VERSION > 8
size_t version; /* Version field for future-proofing. */
/* List emulation functions - ObjType Version 1 */
Tcl_ObjTypeLengthProc *lengthProc;
/* Return the [llength] of the AbstractList */
Tcl_ObjTypeIndexProc *indexProc;
/* Return a value (Tcl_Obj) at a given index */
Tcl_ObjTypeSliceProc *sliceProc;
|
| ︙ | ︙ | |||
799 800 801 802 803 804 805 |
* declared as "dummyX".
*
* WARNING!! The structure definition must be kept consistent with the
* CallFrame structure in tclInt.h. If you change one, change the other.
*/
typedef struct Tcl_CallFrame {
| | | 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 |
* declared as "dummyX".
*
* WARNING!! The structure definition must be kept consistent with the
* CallFrame structure in tclInt.h. If you change one, change the other.
*/
typedef struct Tcl_CallFrame {
Tcl_Namespace *nsPtr; /* Current namespace for the call frame. */
int dummy1;
Tcl_Size dummy2;
void *dummy3;
void *dummy4;
void *dummy5;
Tcl_Size dummy6;
void *dummy7;
|
| ︙ | ︙ | |||
1284 1285 1286 1287 1288 1289 1290 |
/*
* Positions to pass to Tcl_QueueEvent/Tcl_ThreadQueueEvent:
*/
typedef enum {
TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK,
| | | 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 |
/*
* Positions to pass to Tcl_QueueEvent/Tcl_ThreadQueueEvent:
*/
typedef enum {
TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK,
TCL_QUEUE_ALERT_IF_EMPTY=4
} Tcl_QueuePosition;
/*
* Values to pass to Tcl_SetServiceMode to specify the behavior of notifier
* event routines.
*/
|
| ︙ | ︙ | |||
1680 1681 1682 1683 1684 1685 1686 |
* arbitrary additional data to files in a
* filesystem. */
Tcl_FSFileAttrsGetProc *fileAttrsGetProc;
/* Called by 'Tcl_FSFileAttrsGet()' and by
* 'file attributes'. */
Tcl_FSFileAttrsSetProc *fileAttrsSetProc;
/* Called by 'Tcl_FSFileAttrsSet()' and by
| | | 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 |
* arbitrary additional data to files in a
* filesystem. */
Tcl_FSFileAttrsGetProc *fileAttrsGetProc;
/* Called by 'Tcl_FSFileAttrsGet()' and by
* 'file attributes'. */
Tcl_FSFileAttrsSetProc *fileAttrsSetProc;
/* Called by 'Tcl_FSFileAttrsSet()' and by
* 'file attributes'. */
Tcl_FSCreateDirectoryProc *createDirectoryProc;
/* Called by 'Tcl_FSCreateDirectory()'. May be
* NULL if the filesystem is read-only. */
Tcl_FSRemoveDirectoryProc *removeDirectoryProc;
/* Called by 'Tcl_FSRemoveDirectory()'. May be
* NULL if the filesystem is read-only. */
Tcl_FSDeleteFileProc *deleteFileProc;
|
| ︙ | ︙ | |||
1961 1962 1963 1964 1965 1966 1967 |
* encoding type. */
Tcl_EncodingConvertProc *toUtfProc;
/* Function to convert from external encoding
* into UTF-8. */
Tcl_EncodingConvertProc *fromUtfProc;
/* Function to convert from UTF-8 into
* external encoding. */
| | < | 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 |
* encoding type. */
Tcl_EncodingConvertProc *toUtfProc;
/* Function to convert from external encoding
* into UTF-8. */
Tcl_EncodingConvertProc *fromUtfProc;
/* Function to convert from UTF-8 into
* external encoding. */
Tcl_FreeProc *freeProc; /* If non-NULL, function to call when this
* encoding is deleted. */
void *clientData; /* Arbitrary value associated with encoding
* type. Passed to conversion functions. */
Tcl_Size nullSize; /* Number of zero bytes that signify
* end-of-string in this encoding. This number
* is used to determine the source string
* length when the srcLen argument is
|
| ︙ | ︙ | |||
2506 2507 2508 2509 2510 2511 2512 |
static inline void
TclBounceRefCount(
Tcl_Obj* objPtr,
const char* fn,
int line)
{
if (objPtr) {
| | | | 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 |
static inline void
TclBounceRefCount(
Tcl_Obj* objPtr,
const char* fn,
int line)
{
if (objPtr) {
if ((objPtr)->refCount == 0) {
Tcl_DbDecrRefCount(objPtr, fn, line);
}
}
}
#else
# undef Tcl_IncrRefCount
# define Tcl_IncrRefCount(objPtr) \
((void)++(objPtr)->refCount)
|
| ︙ | ︙ | |||
2544 2545 2546 2547 2548 2549 2550 |
TclBounceRefCount(objPtr);
static inline void
TclBounceRefCount(
Tcl_Obj* objPtr)
{
if (objPtr) {
| | | | 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 |
TclBounceRefCount(objPtr);
static inline void
TclBounceRefCount(
Tcl_Obj* objPtr)
{
if (objPtr) {
if ((objPtr)->refCount == 0) {
Tcl_DecrRefCount(objPtr);
}
}
}
#endif
/*
|
| ︙ | ︙ |
Changes to generic/tclArithSeries.c.
| ︙ | ︙ | |||
508 509 510 511 512 513 514 |
Tcl_WideInt *intNumberPtr,
double *dblNumberPtr,
Tcl_Obj *numberObj)
{
void *clientData;
int tcl_number_type;
| | | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 |
Tcl_WideInt *intNumberPtr,
double *dblNumberPtr,
Tcl_Obj *numberObj)
{
void *clientData;
int tcl_number_type;
if (Tcl_GetNumberFromObj(interp, numberObj, &clientData,
&tcl_number_type) != TCL_OK) {
return TCL_ERROR;
}
if (tcl_number_type == TCL_NUMBER_BIG) {
/* bignum is not supported yet. */
Tcl_WideInt w;
(void)Tcl_GetWideIntFromObj(interp, numberObj, &w);
|
| ︙ | ︙ |
Changes to generic/tclBasic.c.
| ︙ | ︙ | |||
233 234 235 236 237 238 239 | static Tcl_NRPostProc TEOV_Exception; static Tcl_NRPostProc TEOV_NotFoundCallback; static Tcl_NRPostProc TEOV_RestoreVarFrame; static Tcl_NRPostProc TEOV_RunLeaveTraces; static Tcl_NRPostProc EvalObjvCore; static Tcl_NRPostProc Dispatch; | < | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | static Tcl_NRPostProc TEOV_Exception; static Tcl_NRPostProc TEOV_NotFoundCallback; static Tcl_NRPostProc TEOV_RestoreVarFrame; static Tcl_NRPostProc TEOV_RunLeaveTraces; static Tcl_NRPostProc EvalObjvCore; static Tcl_NRPostProc Dispatch; static Tcl_NRPostProc NRPostInvoke; static Tcl_ObjCmdProc CoroTypeObjCmd; static Tcl_ObjCmdProc TclNRCoroInjectObjCmd; static Tcl_ObjCmdProc TclNRCoroProbeObjCmd; static Tcl_NRPostProc InjectHandler; static Tcl_NRPostProc InjectHandlerPostCall; |
| ︙ | ︙ | |||
1193 1194 1195 1196 1197 1198 1199 |
/* Adding the bytecode assembler command */
cmdPtr = (Command *) Tcl_NRCreateCommand(interp,
"::tcl::unsupported::assemble", Tcl_AssembleObjCmd,
TclNRAssembleObjCmd, NULL, NULL);
cmdPtr->compileProc = &TclCompileAssembleCmd;
/* Coroutine monkeybusiness */
| < < > > > > | 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 |
/* Adding the bytecode assembler command */
cmdPtr = (Command *) Tcl_NRCreateCommand(interp,
"::tcl::unsupported::assemble", Tcl_AssembleObjCmd,
TclNRAssembleObjCmd, NULL, NULL);
cmdPtr->compileProc = &TclCompileAssembleCmd;
/* Coroutine monkeybusiness */
Tcl_CreateObjCommand(interp, "::tcl::unsupported::corotype",
CoroTypeObjCmd, NULL, NULL);
/* Load and intialize ICU */
Tcl_CreateObjCommand(interp, "::tcl::unsupported::loadIcu",
TclLoadIcuObjCmd, NULL, NULL);
/* Export unsupported commands */
nsPtr = Tcl_FindNamespace(interp, "::tcl::unsupported", NULL, 0);
if (nsPtr) {
Tcl_Export(interp, nsPtr, "*", 1);
}
#ifdef USE_DTRACE
|
| ︙ | ︙ | |||
2791 2792 2793 2794 2795 2796 2797 |
* name. */
void *clientData, /* Arbitrary value to pass to object
* function. */
Tcl_CmdDeleteProc *deleteProc)
/* If not NULL, gives a function to call when
* this command is deleted. */
{
| | | | 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 |
* name. */
void *clientData, /* Arbitrary value to pass to object
* function. */
Tcl_CmdDeleteProc *deleteProc)
/* If not NULL, gives a function to call when
* this command is deleted. */
{
Interp *iPtr = (Interp *)interp;
Namespace *nsPtr;
const char *tail;
if (iPtr->flags & DELETED) {
/*
* The interpreter is being deleted. Don't create any new commands;
* it's not safe to muck with the interpreter anymore.
*/
return NULL;
}
/*
* Determine where the command should reside. If its name contains
* namespace qualifiers, we put it in the specified namespace;
* otherwise, we always put it in the global namespace.
*/
|
| ︙ | ︙ | |||
9273 9274 9275 9276 9277 9278 9279 |
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 |
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* CoroTypeObjCmd --
*
* Implementation of [::tcl::unsupported::corotype] command.
*
*----------------------------------------------------------------------
*/
|
| ︙ | ︙ | |||
9624 9625 9626 9627 9628 9629 9630 |
Tcl_Size numLevels = iPtr->numLevels;
iPtr->numLevels = corPtr->auxNumLevels;
corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels;
iPtr->execEnvPtr = corPtr->callerEEPtr;
}
return result;
}
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 |
Tcl_Size numLevels = iPtr->numLevels;
iPtr->numLevels = corPtr->auxNumLevels;
corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels;
iPtr->execEnvPtr = corPtr->callerEEPtr;
}
return result;
}
int
TclNRInterpCoroutine(
void *clientData,
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
|
| ︙ | ︙ |
Changes to generic/tclBinary.c.
| ︙ | ︙ | |||
181 182 183 184 185 186 187 |
unsigned char bytes[TCLFLEXARRAY]; /* The array of bytes. The actual size of this
* field depends on the 'allocated' field
* above. */
} ByteArray;
#define BYTEARRAY_MAX_LEN (TCL_SIZE_MAX - (Tcl_Size)offsetof(ByteArray, bytes))
#define BYTEARRAY_SIZE(len) \
| | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
unsigned char bytes[TCLFLEXARRAY]; /* The array of bytes. The actual size of this
* field depends on the 'allocated' field
* above. */
} ByteArray;
#define BYTEARRAY_MAX_LEN (TCL_SIZE_MAX - (Tcl_Size)offsetof(ByteArray, bytes))
#define BYTEARRAY_SIZE(len) \
( (len < 0 || BYTEARRAY_MAX_LEN < (len)) \
? (Tcl_Panic("negative length specified or max size of a Tcl value exceeded"), 0) \
: (offsetof(ByteArray, bytes) + (len)) )
#define GET_BYTEARRAY(irPtr) ((ByteArray *) (irPtr)->twoPtrValue.ptr1)
#define SET_BYTEARRAY(irPtr, baPtr) \
(irPtr)->twoPtrValue.ptr1 = (baPtr)
int
|
| ︙ | ︙ | |||
436 437 438 439 440 441 442 |
*----------------------------------------------------------------------
*/
unsigned char *
Tcl_SetByteArrayLength(
Tcl_Obj *objPtr, /* The ByteArray object. */
Tcl_Size numBytes) /* Number of bytes in resized array
| | | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
*----------------------------------------------------------------------
*/
unsigned char *
Tcl_SetByteArrayLength(
Tcl_Obj *objPtr, /* The ByteArray object. */
Tcl_Size numBytes) /* Number of bytes in resized array
* Must be >= 0 */
{
ByteArray *byteArrayPtr;
Tcl_ObjInternalRep *irPtr;
assert(numBytes >= 0);
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength");
|
| ︙ | ︙ |
Changes to generic/tclCkalloc.c.
| ︙ | ︙ | |||
167 168 169 170 171 172 173 |
TclDumpMemoryInfo(
void *clientData,
int flags)
{
char buf[1024];
if (clientData == NULL) {
| | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
TclDumpMemoryInfo(
void *clientData,
int flags)
{
char buf[1024];
if (clientData == NULL) {
return 0;
}
snprintf(buf, sizeof(buf),
"total mallocs %10" TCL_Z_MODIFIER "u\n"
"total frees %10" TCL_Z_MODIFIER "u\n"
"current packets allocated %10" TCL_Z_MODIFIER "u\n"
"current bytes allocated %10" TCL_Z_MODIFIER "u\n"
"maximum packets allocated %10" TCL_Z_MODIFIER "u\n"
|
| ︙ | ︙ | |||
822 823 824 825 826 827 828 |
if (fileName == NULL) {
return TCL_ERROR;
}
result = Tcl_DumpActiveMemory(fileName);
Tcl_DStringFree(&buffer);
if (result != TCL_OK) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf("error accessing %s: %s",
| | | 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 |
if (fileName == NULL) {
return TCL_ERROR;
}
result = Tcl_DumpActiveMemory(fileName);
Tcl_DStringFree(&buffer);
if (result != TCL_OK) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf("error accessing %s: %s",
TclGetString(objv[2]), Tcl_PosixError(interp)));
return TCL_ERROR;
}
return TCL_OK;
}
if (strcmp(TclGetString(objv[1]),"break_on_malloc") == 0) {
Tcl_WideInt value;
if (objc != 3) {
|
| ︙ | ︙ | |||
867 868 869 870 871 872 873 |
fileName = Tcl_TranslateFileName(interp, TclGetString(objv[2]), &buffer);
if (fileName == NULL) {
return TCL_ERROR;
}
fileP = fopen(fileName, "w");
if (fileP == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
| | | | 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 |
fileName = Tcl_TranslateFileName(interp, TclGetString(objv[2]), &buffer);
if (fileName == NULL) {
return TCL_ERROR;
}
fileP = fopen(fileName, "w");
if (fileP == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"cannot open output file: %s",
Tcl_PosixError(interp)));
return TCL_ERROR;
}
TclDbDumpActiveObjects(fileP);
fclose(fileP);
Tcl_DStringFree(&buffer);
return TCL_OK;
}
|
| ︙ | ︙ | |||
932 933 934 935 936 937 938 |
goto bad_suboption;
}
validate_memory = (strcmp(TclGetString(objv[2]),"on") == 0);
return TCL_OK;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
| | | | | 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 |
goto bad_suboption;
}
validate_memory = (strcmp(TclGetString(objv[2]),"on") == 0);
return TCL_OK;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad option \"%s\": should be active, break_on_malloc, info, "
"init, objs, onexit, tag, trace, trace_on_at_malloc, or validate",
TclGetString(objv[1])));
return TCL_ERROR;
argError:
Tcl_WrongNumArgs(interp, 2, objv, "count");
return TCL_ERROR;
bad_suboption:
|
| ︙ | ︙ |
Changes to generic/tclClock.c.
| ︙ | ︙ | |||
3413 3414 3415 3416 3417 3418 3419 |
}
/* Base (by scan or add) or clock value (by format) */
if (opts->baseObj != NULL) {
Tcl_Obj *baseObj = opts->baseObj;
| | > > | | | | | > > | 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 |
}
/* Base (by scan or add) or clock value (by format) */
if (opts->baseObj != NULL) {
Tcl_Obj *baseObj = opts->baseObj;
/* bypass integer recognition if looks like "now" or "-now" */
if ((baseObj->bytes &&
((baseObj->length == 3 && baseObj->bytes[0] == 'n') ||
(baseObj->length == 4 && baseObj->bytes[1] == 'n')))
|| TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK) {
/* we accept "now" and "-now" as current date-time */
static const char *const nowOpts[] = {
"now", "-now", NULL
};
int idx;
if (Tcl_GetIndexFromObj(NULL, baseObj, nowOpts, "seconds",
TCL_EXACT, &idx) == TCL_OK) {
goto baseNow;
}
if (TclHasInternalRep(baseObj, &tclBignumType)) {
goto baseOverflow;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad seconds \"%s\": must be now or integer",
TclGetString(baseObj)));
i = baseIdx;
goto badOption;
}
/*
* Seconds could be an unsigned number that overflowed. Make sure
* that it isn't. Additionally it may be too complex to calculate
* julianday etc (forwards/backwards) by too large/small values, thus
|
| ︙ | ︙ | |||
3523 3524 3525 3526 3527 3528 3529 |
ClockFormatObjCmd(
void *clientData, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
int objc, /* Parameter count */
Tcl_Obj *const objv[]) /* Parameter values */
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
| | | 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 |
ClockFormatObjCmd(
void *clientData, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
int objc, /* Parameter count */
Tcl_Obj *const objv[]) /* Parameter values */
{
ClockClientData *dataPtr = (ClockClientData *)clientData;
static const char *syntax = "clock format clockval|now "
"?-format string? "
"?-gmt boolean? "
"?-locale LOCALE? ?-timezone ZONE?";
int ret;
ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */
DateFormat dateFmt; /* Common structure used for formatting */
|
| ︙ | ︙ | |||
3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 |
if (curJDN > opts->dataPtr->maxJDN) {
Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
"requested date too large to represent", TCL_AUTO_LENGTH));
Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL);
return TCL_ERROR;
}
}
/* Local seconds to UTC (stored in yydate.seconds) */
if (info->flags & CLF_ASSEMBLE_SECONDS) {
yydate.localSeconds =
-210866803200LL
+ (SECONDS_PER_DAY * yydate.julianDay)
| > > > > > > | | 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 |
if (curJDN > opts->dataPtr->maxJDN) {
Tcl_SetObjResult(opts->interp, Tcl_NewStringObj(
"requested date too large to represent", TCL_AUTO_LENGTH));
Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL);
return TCL_ERROR;
}
}
/* If seconds overflows the day (no validate case), increase days */
if (yySecondOfDay >= SECONDS_PER_DAY) {
yydate.julianDay += (yySecondOfDay / SECONDS_PER_DAY);
yySecondOfDay %= SECONDS_PER_DAY;
}
/* Local seconds to UTC (stored in yydate.seconds) */
if (info->flags & CLF_ASSEMBLE_SECONDS) {
yydate.localSeconds =
-210866803200LL
+ (SECONDS_PER_DAY * yydate.julianDay)
+ yySecondOfDay;
}
if (info->flags & (CLF_ASSEMBLE_SECONDS | CLF_LOCALSEC)) {
if (ConvertLocalToUTC(opts->dataPtr, opts->interp, &yydate,
opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) {
return TCL_ERROR;
}
|
| ︙ | ︙ | |||
4348 4349 4350 4351 4352 4353 4354 |
int
ClockAddObjCmd(
void *clientData, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
int objc, /* Parameter count */
Tcl_Obj *const objv[]) /* Parameter values */
{
| | | 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 |
int
ClockAddObjCmd(
void *clientData, /* Client data containing literal pool */
Tcl_Interp *interp, /* Tcl interpreter */
int objc, /* Parameter count */
Tcl_Obj *const objv[]) /* Parameter values */
{
static const char *syntax = "clock add clockval|now ?number units?..."
"?-gmt boolean? "
"?-locale LOCALE? ?-timezone ZONE?";
ClockClientData *dataPtr = (ClockClientData *)clientData;
int ret;
ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */
DateInfo yy; /* Common structure used for parsing */
DateInfo *info = &yy;
|
| ︙ | ︙ |
Changes to generic/tclClockFmt.c.
| ︙ | ︙ | |||
1789 1790 1791 1792 1793 1794 1795 |
/*
* Build a date from julian day (integer and fraction).
* Note, astronomical JDN starts at noon in opposite to calendar julianday.
*/
fractJD = (int)tok->map->offs /* 0 for calendar or 43200 for astro JD */
+ (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv);
| | | 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 |
/*
* Build a date from julian day (integer and fraction).
* Note, astronomical JDN starts at noon in opposite to calendar julianday.
*/
fractJD = (int)tok->map->offs /* 0 for calendar or 43200 for astro JD */
+ (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv);
if (fractJD >= SECONDS_PER_DAY) {
fractJD %= SECONDS_PER_DAY;
intJD += 1;
}
yydate.secondOfDay = fractJD;
yydate.julianDay = intJD;
yydate.seconds =
|
| ︙ | ︙ |
Changes to generic/tclCmdAH.c.
| ︙ | ︙ | |||
2343 2344 2345 2346 2347 2348 2349 |
Tcl_Obj *field, *value, *result;
unsigned short mode;
if (varName == NULL) {
TclNewObj(result);
Tcl_IncrRefCount(result);
#define DOBJPUT(key, objValue) \
| | | | | 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 |
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));
DOBJPUT("nlink", Tcl_NewWideIntObj((long)statPtr->st_nlink));
DOBJPUT("uid", Tcl_NewWideIntObj((long)statPtr->st_uid));
DOBJPUT("gid", Tcl_NewWideIntObj((long)statPtr->st_gid));
DOBJPUT("size", Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
|
| ︙ | ︙ |
Changes to generic/tclCmdIL.c.
| ︙ | ︙ | |||
1146 1147 1148 1149 1150 1151 1152 |
cmdFramePtrPtr = &((*cmdFramePtrPtr)->nextPtr);
}
if (corPtr->caller.cmdFramePtr) {
*cmdFramePtrPtr = corPtr->caller.cmdFramePtr;
}
corPtr = corPtr->callerEEPtr->corPtr;
}
| | | | 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 |
cmdFramePtrPtr = &((*cmdFramePtrPtr)->nextPtr);
}
if (corPtr->caller.cmdFramePtr) {
*cmdFramePtrPtr = corPtr->caller.cmdFramePtr;
}
corPtr = corPtr->callerEEPtr->corPtr;
}
topLevel += *cmdFramePtrPtr ? (*cmdFramePtrPtr)->level : 1;
if (iPtr->cmdFramePtr && topLevel != iPtr->cmdFramePtr->level) {
framePtr = iPtr->cmdFramePtr;
while (framePtr) {
framePtr->level = topLevel--;
framePtr = framePtr->nextPtr;
}
if (topLevel) {
Tcl_Panic("Broken frame level calculation");
|
| ︙ | ︙ | |||
1265 1266 1267 1268 1269 1270 1271 |
/*
* This array is indexed by the TCL_LOCATION_... values, except
* for _LAST.
*/
static const char *const typeString[TCL_LOCATION_LAST] = {
"eval", "eval", "eval", "precompiled", "source", "proc"
};
| | > > > > > | 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 |
/*
* This array is indexed by the TCL_LOCATION_... values, except
* for _LAST.
*/
static const char *const typeString[TCL_LOCATION_LAST] = {
"eval", "eval", "eval", "precompiled", "source", "proc"
};
Proc *procPtr = NULL;
int needsFree = -1;
if (!framePtr) {
goto precompiled;
}
procPtr = framePtr->framePtr ? framePtr->framePtr->procPtr : NULL;
/*
* Pull the information and construct the dictionary to return, as list.
* Regarding use of the CmdFrame fields see tclInt.h, and its definition.
*/
#define ADD_PAIR(name, value) \
TclNewLiteralStringObj(tmpObj, name); \
|
| ︙ | ︙ | |||
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 |
} else {
ADD_PAIR("line", Tcl_NewWideIntObj(1));
}
ADD_PAIR("cmd", TclGetSourceFromFrame(framePtr, 0, NULL));
break;
case TCL_LOCATION_PREBC:
/*
* Precompiled. Result contains the type as signal, nothing else.
*/
| > < | | 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 |
} else {
ADD_PAIR("line", Tcl_NewWideIntObj(1));
}
ADD_PAIR("cmd", TclGetSourceFromFrame(framePtr, 0, NULL));
break;
case TCL_LOCATION_PREBC:
precompiled:
/*
* Precompiled. Result contains the type as signal, nothing else.
*/
ADD_PAIR("type", Tcl_NewStringObj(typeString[TCL_LOCATION_PREBC], -1));
break;
case TCL_LOCATION_BC: {
/*
* Execution of bytecode. Talk to the BC engine to fill out the frame.
*/
|
| ︙ | ︙ | |||
1414 1415 1416 1417 1418 1419 1420 |
}
/*
* 'level'. Common to all frame types. Conditional on having an associated
* _visible_ CallFrame.
*/
| | | 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 |
}
/*
* 'level'. Common to all frame types. Conditional on having an associated
* _visible_ CallFrame.
*/
if (framePtr && (framePtr->framePtr != NULL) && (iPtr->varFramePtr != NULL)) {
CallFrame *current = framePtr->framePtr;
CallFrame *top = iPtr->varFramePtr;
CallFrame *idx;
for (idx=top ; idx!=NULL ; idx=idx->callerVarPtr) {
if (idx == current) {
int c = framePtr->framePtr->level;
|
| ︙ | ︙ |
Changes to generic/tclCompCmds.c.
| ︙ | ︙ | |||
963 964 965 966 967 968 969 |
&localIndex, &isScalar, 1);
/*
* If the user specified an array element, we don't bother handling
* that.
*/
if (!isScalar) {
| | | 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 |
&localIndex, &isScalar, 1);
/*
* If the user specified an array element, we don't bother handling
* that.
*/
if (!isScalar) {
return TCL_ERROR;
}
/*
* We are doing an assignment to set the value of the constant. This will
* need to be extended to push a value for each argument.
*/
|
| ︙ | ︙ | |||
3444 3445 3446 3447 3448 3449 3450 |
TclLocalScalar(
const char *bytes,
size_t numBytes,
CompileEnv *envPtr)
{
Tcl_Token token[2] = {
{TCL_TOKEN_SIMPLE_WORD, NULL, 0, 1},
| | | 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 |
TclLocalScalar(
const char *bytes,
size_t numBytes,
CompileEnv *envPtr)
{
Tcl_Token token[2] = {
{TCL_TOKEN_SIMPLE_WORD, NULL, 0, 1},
{TCL_TOKEN_TEXT, NULL, 0, 0}
};
token[1].start = bytes;
token[1].size = numBytes;
return TclLocalScalarFromToken(token, envPtr);
}
|
| ︙ | ︙ |
Changes to generic/tclDate.c.
| ︙ | ︙ | |||
65 66 67 68 69 70 71 72 73 74 75 76 77 78 | /* Substitute the variable and function names. */ #define yyparse TclDateparse #define yylex TclDatelex #define yyerror TclDateerror #define yydebug TclDatedebug /* First part of user prologue. */ /* * tclDate.c -- * * This file is generated from a yacc grammar defined in the file | > | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | /* Substitute the variable and function names. */ #define yyparse TclDateparse #define yylex TclDatelex #define yyerror TclDateerror #define yydebug TclDatedebug #define yynerrs TclDatenerrs /* First part of user prologue. */ /* * tclDate.c -- * * This file is generated from a yacc grammar defined in the file |
| ︙ | ︙ | |||
1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 |
/* Location data for the lookahead symbol. */
static YYLTYPE yyloc_default
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
= { 1, 1, 1, 1 }
# endif
;
YYLTYPE yylloc = yyloc_default;
yy_state_fast_t yystate = 0;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus = 0;
/* Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
| > > > | 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 |
/* Location data for the lookahead symbol. */
static YYLTYPE yyloc_default
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
= { 1, 1, 1, 1 }
# endif
;
YYLTYPE yylloc = yyloc_default;
/* Number of syntax errors so far. */
int yynerrs = 0;
yy_state_fast_t yystate = 0;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus = 0;
/* Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
|
| ︙ | ︙ | |||
1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 |
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
yyerror (&yylloc, info, YY_("syntax error"));
}
yyerror_range[1] = yylloc;
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
| > | 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 |
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
yyerror (&yylloc, info, YY_("syntax error"));
}
yyerror_range[1] = yylloc;
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
|
| ︙ | ︙ | |||
1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 |
| yyerrorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
yyerrorlab:
/* Pacify compilers when the user code never invokes YYERROR and the
label yyerrorlab therefore never appears in user code. */
if (0)
YYERROR;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
YYPOPSTACK (yylen);
yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
yystate = *yyssp;
| > | 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 |
| yyerrorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
yyerrorlab:
/* Pacify compilers when the user code never invokes YYERROR and the
label yyerrorlab therefore never appears in user code. */
if (0)
YYERROR;
++yynerrs;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
YYPOPSTACK (yylen);
yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
yystate = *yyssp;
|
| ︙ | ︙ | |||
2116 2117 2118 2119 2120 2121 2122 |
{ "july", tMONTH, 7 },
{ "august", tMONTH, 8 },
{ "september", tMONTH, 9 },
{ "sept", tMONTH, 9 },
{ "october", tMONTH, 10 },
{ "november", tMONTH, 11 },
{ "december", tMONTH, 12 },
| | | 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 |
{ "july", tMONTH, 7 },
{ "august", tMONTH, 8 },
{ "september", tMONTH, 9 },
{ "sept", tMONTH, 9 },
{ "october", tMONTH, 10 },
{ "november", tMONTH, 11 },
{ "december", tMONTH, 12 },
{ "sunday", tDAY, 7 },
{ "monday", tDAY, 1 },
{ "tuesday", tDAY, 2 },
{ "tues", tDAY, 2 },
{ "wednesday", tDAY, 3 },
{ "wednes", tDAY, 3 },
{ "thursday", tDAY, 4 },
{ "thur", tDAY, 4 },
|
| ︙ | ︙ | |||
2334 2335 2336 2337 2338 2339 2340 |
int
ToSeconds(
int Hours,
int Minutes,
int Seconds,
MERIDIAN Meridian)
{
| < < < < < < < < < < < < | 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 |
int
ToSeconds(
int Hours,
int Minutes,
int Seconds,
MERIDIAN Meridian)
{
switch (Meridian) {
case MER24:
return (Hours * 60 + Minutes) * 60 + Seconds;
case MERam:
return ((Hours % 12) * 60 + Minutes) * 60 + Seconds;
case MERpm:
return (((Hours % 12) + 12) * 60 + Minutes) * 60 + Seconds;
}
return -1; /* Should never be reached */
}
static int
LookupWord(
|
| ︙ | ︙ |
Changes to generic/tclDictObj.c.
| ︙ | ︙ | |||
148 149 150 151 152 153 154 |
UpdateStringOfDict, /* updateStringProc */
SetDictFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0
};
#define DictSetInternalRep(objPtr, dictRepPtr) \
do { \
| | | | | | | | | 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 |
UpdateStringOfDict, /* updateStringProc */
SetDictFromAny, /* setFromAnyProc */
TCL_OBJTYPE_V0
};
#define DictSetInternalRep(objPtr, dictRepPtr) \
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)
/*
* The type of the specially adapted version of the Tcl_Obj*-containing hash
* table defined in the tclObj.c code. This version differs in that it
* allocates a bit more space in each hash entry in order to hold the pointers
* used to keep the hash entries in a linked list.
|
| ︙ | ︙ |
Changes to generic/tclEnsemble.c.
| ︙ | ︙ | |||
273 274 275 276 277 278 279 | * * Side effects: * Creates the ensemble for the namespace if one did not previously * exist. * * Note: * Can't use SetEnsembleConfigOptions() here. Different (but overlapping) | | | 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
*
* Side effects:
* Creates the ensemble for the namespace if one did not previously
* exist.
*
* Note:
* Can't use SetEnsembleConfigOptions() here. Different (but overlapping)
* options are supported.
*
*----------------------------------------------------------------------
*/
static Tcl_Command
InitEnsembleFromOptions(
Tcl_Interp *interp,
int objc,
|
| ︙ | ︙ | |||
882 883 884 885 886 887 888 | * Reports an error in the interpreter (if non-NULL) if the command is * not an ensemble. * *---------------------------------------------------------------------- */ static inline EnsembleConfig * GetEnsembleFromCommand( | | | 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 |
* Reports an error in the interpreter (if non-NULL) if the command is
* not an ensemble.
*
*----------------------------------------------------------------------
*/
static inline EnsembleConfig *
GetEnsembleFromCommand(
Tcl_Interp *interp, /* Where to report an error. May be NULL. */
Tcl_Command token) /* What to check for ensemble-ness. */
{
Command *cmdPtr = (Command *) token;
if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
| ︙ | ︙ | |||
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 |
map[i].nreProc, map[i].clientData, NULL);
Tcl_DStringSetLength(&hiddenBuf, hiddenLen);
if (Tcl_HideCommand(interp, "___tmp",
Tcl_DStringAppend(&hiddenBuf, map[i].name,
TCL_AUTO_LENGTH))) {
Tcl_Panic("%s", Tcl_GetStringResult(interp));
}
} else {
/*
* Not hidden, so just create it. Yay!
*/
cmdPtr = (Command *)
Tcl_NRCreateCommand(interp, TclGetString(toObj),
map[i].proc, map[i].nreProc, map[i].clientData,
NULL);
| > > < | > | 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 |
map[i].nreProc, map[i].clientData, NULL);
Tcl_DStringSetLength(&hiddenBuf, hiddenLen);
if (Tcl_HideCommand(interp, "___tmp",
Tcl_DStringAppend(&hiddenBuf, map[i].name,
TCL_AUTO_LENGTH))) {
Tcl_Panic("%s", Tcl_GetStringResult(interp));
}
/* don't compile unsafe subcommands in safe interp */
cmdPtr->compileProc = NULL;
} else {
/*
* Not hidden, so just create it. Yay!
*/
cmdPtr = (Command *)
Tcl_NRCreateCommand(interp, TclGetString(toObj),
map[i].proc, map[i].nreProc, map[i].clientData,
NULL);
cmdPtr->compileProc = map[i].compileProc;
}
}
}
Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict);
}
Tcl_DStringFree(&buf);
Tcl_DStringFree(&hiddenBuf);
|
| ︙ | ︙ | |||
3175 3176 3177 3178 3179 3180 3181 |
}
targetCmdObj = elems[0];
oldCmdPtr = cmdPtr;
Tcl_IncrRefCount(targetCmdObj);
newCmdPtr = (Command *) Tcl_GetCommandFromObj(interp, targetCmdObj);
TclDecrRefCount(targetCmdObj);
| | < | 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 |
}
targetCmdObj = elems[0];
oldCmdPtr = cmdPtr;
Tcl_IncrRefCount(targetCmdObj);
newCmdPtr = (Command *) Tcl_GetCommandFromObj(interp, targetCmdObj);
TclDecrRefCount(targetCmdObj);
if (newCmdPtr == NULL || (Tcl_IsSafe(interp) && !cmdPtr->compileProc)
|| newCmdPtr->nsPtr->flags & NS_SUPPRESS_COMPILATION
|| newCmdPtr->flags & CMD_HAS_EXEC_TRACES
|| ((Interp *) interp)->flags & DONT_COMPILE_CMDS_INLINE) {
/*
* Maps to an undefined command or a command without a compiler.
* Cannot compile.
*/
goto cleanup;
}
cmdPtr = newCmdPtr;
depth++;
/*
* See whether we have a nested ensemble. If we do, we can go round the
|
| ︙ | ︙ |
Changes to generic/tclExecute.c.
| ︙ | ︙ | |||
636 637 638 639 640 641 642 | 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, Tcl_Size *cmdIdxPtr); static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, size_t growth, int move); | | | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | 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, Tcl_Size *cmdIdxPtr); static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, size_t growth, int move); static void IllegalExprOperandType(Tcl_Interp *interp, const char *ord, 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, size_t numWords); static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, size_t numWords); |
| ︙ | ︙ | |||
5870 5871 5872 5873 5874 5875 5876 |
if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
|| (type1==TCL_NUMBER_DOUBLE) || (type1==TCL_NUMBER_NAN)) {
TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(valuePtr),
O2S(value2Ptr), (valuePtr->typePtr?
valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
| | | | 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 |
if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
|| (type1==TCL_NUMBER_DOUBLE) || (type1==TCL_NUMBER_NAN)) {
TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(valuePtr),
O2S(value2Ptr), (valuePtr->typePtr?
valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "left ", pc, valuePtr);
CACHE_STACK_INFO();
goto gotError;
}
if ((GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK)
|| (type2==TCL_NUMBER_DOUBLE) || (type2==TCL_NUMBER_NAN)) {
TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", O2S(valuePtr),
O2S(value2Ptr), (value2Ptr->typePtr?
value2Ptr->typePtr->name : "null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "right ", pc, value2Ptr);
CACHE_STACK_INFO();
goto gotError;
}
/*
* Check for common, simple case.
*/
|
| ︙ | ︙ | |||
6091 6092 6093 6094 6095 6096 6097 |
if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
|| IsErroringNaNType(type1)) {
TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
O2S(value2Ptr), O2S(valuePtr),
(valuePtr->typePtr? valuePtr->typePtr->name: "null")));
DECACHE_STACK_INFO();
| | | | 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 |
if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
|| IsErroringNaNType(type1)) {
TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n",
O2S(value2Ptr), O2S(valuePtr),
(valuePtr->typePtr? valuePtr->typePtr->name: "null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "left ", pc, valuePtr);
CACHE_STACK_INFO();
goto gotError;
}
#ifdef ACCEPT_NAN
if (type1 == TCL_NUMBER_NAN) {
/*
* NaN first argument -> result is also NaN.
*/
NEXT_INST_F(1, 1, 0);
}
#endif
if ((GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK)
|| IsErroringNaNType(type2)) {
TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n",
O2S(value2Ptr), O2S(valuePtr),
(value2Ptr->typePtr? value2Ptr->typePtr->name: "null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "right ", pc, value2Ptr);
CACHE_STACK_INFO();
goto gotError;
}
#ifdef ACCEPT_NAN
if (type2 == TCL_NUMBER_NAN) {
/*
|
| ︙ | ︙ | |||
6254 6255 6256 6257 6258 6259 6260 |
/* TODO - check claim that taking address of b harms performance */
/* TODO - consider optimization search for constants */
if (TclGetBooleanFromObj(NULL, valuePtr, &b) != TCL_OK) {
TRACE(("\"%.20s\" => ERROR: illegal type %s\n", O2S(valuePtr),
(valuePtr->typePtr? valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
| | | 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 |
/* TODO - check claim that taking address of b harms performance */
/* TODO - consider optimization search for constants */
if (TclGetBooleanFromObj(NULL, valuePtr, &b) != TCL_OK) {
TRACE(("\"%.20s\" => ERROR: illegal type %s\n", O2S(valuePtr),
(valuePtr->typePtr? valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "", pc, valuePtr);
CACHE_STACK_INFO();
goto gotError;
}
/* TODO: Consider peephole opt. */
objResultPtr = TCONST(!b);
TRACE_WITH_OBJ(("%s => ", O2S(valuePtr)), objResultPtr);
NEXT_INST_F(1, 1, 1);
|
| ︙ | ︙ | |||
6276 6277 6278 6279 6280 6281 6282 |
/*
* ... ~$NonInteger => raise an error.
*/
TRACE_APPEND(("ERROR: illegal type %s\n",
(valuePtr->typePtr? valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
| | | 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 |
/*
* ... ~$NonInteger => raise an error.
*/
TRACE_APPEND(("ERROR: illegal type %s\n",
(valuePtr->typePtr? valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "", pc, valuePtr);
CACHE_STACK_INFO();
goto gotError;
}
if (type1 == TCL_NUMBER_INT) {
w1 = *((const Tcl_WideInt *) ptr1);
if (Tcl_IsShared(valuePtr)) {
TclNewIntObj(objResultPtr, ~w1);
|
| ︙ | ︙ | |||
6308 6309 6310 6311 6312 6313 6314 |
valuePtr = OBJ_AT_TOS;
TRACE(("\"%.20s\" => ", O2S(valuePtr)));
if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
|| IsErroringNaNType(type1)) {
TRACE_APPEND(("ERROR: illegal type %s \n",
(valuePtr->typePtr? valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
| | | 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 |
valuePtr = OBJ_AT_TOS;
TRACE(("\"%.20s\" => ", O2S(valuePtr)));
if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK)
|| IsErroringNaNType(type1)) {
TRACE_APPEND(("ERROR: illegal type %s \n",
(valuePtr->typePtr? valuePtr->typePtr->name : "null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "", pc, valuePtr);
CACHE_STACK_INFO();
goto gotError;
}
switch (type1) {
case TCL_NUMBER_NAN:
/* -NaN => NaN */
TRACE_APPEND(("%s\n", O2S(valuePtr)));
|
| ︙ | ︙ | |||
6361 6362 6363 6364 6365 6366 6367 |
/*
* ... +$NonNumeric => raise an error.
*/
TRACE_APPEND(("ERROR: illegal type %s\n",
(valuePtr->typePtr? valuePtr->typePtr->name:"null")));
DECACHE_STACK_INFO();
| | | | 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 |
/*
* ... +$NonNumeric => raise an error.
*/
TRACE_APPEND(("ERROR: illegal type %s\n",
(valuePtr->typePtr? valuePtr->typePtr->name:"null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "", pc, valuePtr);
CACHE_STACK_INFO();
goto gotError;
}
/* ... TryConvertToNumeric($NonNumeric) is acceptable */
TRACE_APPEND(("not numeric\n"));
NEXT_INST_F(1, 0, 0);
}
if (IsErroringNaNType(type1)) {
if (*pc == INST_UPLUS) {
/*
* ... +$NonNumeric => raise an error.
*/
TRACE_APPEND(("ERROR: illegal type %s\n",
(valuePtr->typePtr? valuePtr->typePtr->name:"null")));
DECACHE_STACK_INFO();
IllegalExprOperandType(interp, "", pc, valuePtr);
CACHE_STACK_INFO();
} else {
/*
* Numeric conversion of NaN -> error.
*/
TRACE_APPEND(("ERROR: IEEE floating pt error\n"));
|
| ︙ | ︙ | |||
9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 |
*----------------------------------------------------------------------
*/
static void
IllegalExprOperandType(
Tcl_Interp *interp, /* Interpreter to which error information
* pertains. */
const unsigned char *pc, /* Points to the instruction being executed
* when the illegal type was found. */
Tcl_Obj *opndPtr) /* Points to the operand holding the value
* with the illegal type. */
{
void *ptr;
int type;
const unsigned char opcode = *pc;
const char *description, *op = "unknown";
if (opcode == INST_EXPON) {
op = "**";
} else if (opcode <= INST_LNOT) {
op = operatorStrings[opcode - INST_BITOR];
}
if (GetNumberFromObj(NULL, opndPtr, &ptr, &type) != TCL_OK) {
description = "non-numeric string";
} else if (type == TCL_NUMBER_NAN) {
description = "non-numeric floating-point value";
} else if (type == TCL_NUMBER_DOUBLE) {
description = "floating-point value";
} else {
/* TODO: No caller needs this. Eliminate? */
description = "(big) integer";
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
| > > > > > > > > > > > > > > > > | | | 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 |
*----------------------------------------------------------------------
*/
static void
IllegalExprOperandType(
Tcl_Interp *interp, /* Interpreter to which error information
* pertains. */
const char *ord, /* "first ", "second " or "" */
const unsigned char *pc, /* Points to the instruction being executed
* when the illegal type was found. */
Tcl_Obj *opndPtr) /* Points to the operand holding the value
* with the illegal type. */
{
void *ptr;
int type;
const unsigned char opcode = *pc;
const char *description, *op = "unknown";
if (opcode == INST_EXPON) {
op = "**";
} else if (opcode <= INST_LNOT) {
op = operatorStrings[opcode - INST_BITOR];
}
if (GetNumberFromObj(NULL, opndPtr, &ptr, &type) != TCL_OK) {
Tcl_Size length;
if (TclHasInternalRep(opndPtr, &tclDictType)) {
Tcl_DictObjSize(NULL, opndPtr, &length);
if (length > 1) {
listRep:
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"cannot use a list as %soperand of \"%s\"", ord, op));
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "list", (char *)NULL);
return;
}
}
Tcl_ObjTypeLengthProc *lengthProc = TclObjTypeHasProc(opndPtr, lengthProc);
if (lengthProc && lengthProc(opndPtr) > 1) {
goto listRep;
}
description = "non-numeric string";
} else if (type == TCL_NUMBER_NAN) {
description = "non-numeric floating-point value";
} else if (type == TCL_NUMBER_DOUBLE) {
description = "floating-point value";
} else {
/* TODO: No caller needs this. Eliminate? */
description = "(big) integer";
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"cannot use %s \"%s\" as %soperand of \"%s\"", description,
TclGetString(opndPtr), ord, op));
Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", description, (char *)NULL);
}
/*
*----------------------------------------------------------------------
*
* TclGetSrcInfoForPc, GetSrcInfoForPc, TclGetSourceFromFrame --
|
| ︙ | ︙ |
Changes to generic/tclFCmd.c.
| ︙ | ︙ | |||
914 915 916 917 918 919 920 |
Tcl_Obj *splitPtr;
Tcl_Obj *resultPtr = NULL;
splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
Tcl_IncrRefCount(splitPtr);
if (objc != 0) {
| | | | 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 |
Tcl_Obj *splitPtr;
Tcl_Obj *resultPtr = NULL;
splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
Tcl_IncrRefCount(splitPtr);
if (objc != 0) {
/*
* Return the last component, unless it is the only component, and it
* is the root of an absolute path.
*/
if (objc > 0) {
Tcl_ListObjIndex(NULL, splitPtr, objc-1, &resultPtr);
if ((objc == 1) &&
(Tcl_FSGetPathType(resultPtr) != TCL_PATH_RELATIVE)) {
|
| ︙ | ︙ |
Changes to generic/tclFileName.c.
| ︙ | ︙ | |||
386 387 388 389 390 391 392 |
Tcl_Obj **driveNameRef)
{
Tcl_PathType type = TCL_PATH_ABSOLUTE;
const char *path = TclGetString(pathPtr);
switch (tclPlatform) {
case TCL_PLATFORM_UNIX: {
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 |
Tcl_Obj **driveNameRef)
{
Tcl_PathType type = TCL_PATH_ABSOLUTE;
const char *path = TclGetString(pathPtr);
switch (tclPlatform) {
case TCL_PLATFORM_UNIX: {
const char *origPath = path;
/*
* Paths that begin with / are absolute.
*/
if (path[0] == '/') {
++path;
/*
* Check for "//" network path prefix
*/
if ((*path == '/') && path[1] && (path[1] != '/')) {
path += 2;
while (*path && *path != '/') {
++path;
}
}
if (driveNameLengthPtr != NULL) {
/*
* We need this addition in case the "//" code was used.
*/
*driveNameLengthPtr = (path - origPath);
}
} else {
type = TCL_PATH_RELATIVE;
}
break;
}
case TCL_PLATFORM_WINDOWS: {
Tcl_DString ds;
const char *rootEnd;
Tcl_DStringInit(&ds);
rootEnd = ExtractWinRoot(path, &ds, 0, &type);
if ((rootEnd != path) && (driveNameLengthPtr != NULL)) {
*driveNameLengthPtr = rootEnd - path;
if (driveNameRef != NULL) {
*driveNameRef = Tcl_DStringToObj(&ds);
Tcl_IncrRefCount(*driveNameRef);
}
}
Tcl_DStringFree(&ds);
break;
}
}
return type;
}
/*
*---------------------------------------------------------------------------
|
| ︙ | ︙ | |||
651 652 653 654 655 656 657 |
elementStart = path;
while ((*path != '\0') && (*path != '/')) {
path++;
}
length = path - elementStart;
if (length > 0) {
Tcl_Obj *nextElt;
| | | | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 |
elementStart = path;
while ((*path != '\0') && (*path != '/')) {
path++;
}
length = path - elementStart;
if (length > 0) {
Tcl_Obj *nextElt;
nextElt = Tcl_NewStringObj(elementStart, length);
Tcl_ListObjAppendElement(NULL, result, nextElt);
}
if (*path++ == '\0') {
break;
}
}
return result;
}
|
| ︙ | ︙ |
Changes to generic/tclGetDate.y.
| ︙ | ︙ | |||
492 493 494 495 496 497 498 |
{ "july", tMONTH, 7 },
{ "august", tMONTH, 8 },
{ "september", tMONTH, 9 },
{ "sept", tMONTH, 9 },
{ "october", tMONTH, 10 },
{ "november", tMONTH, 11 },
{ "december", tMONTH, 12 },
| | | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 |
{ "july", tMONTH, 7 },
{ "august", tMONTH, 8 },
{ "september", tMONTH, 9 },
{ "sept", tMONTH, 9 },
{ "october", tMONTH, 10 },
{ "november", tMONTH, 11 },
{ "december", tMONTH, 12 },
{ "sunday", tDAY, 7 },
{ "monday", tDAY, 1 },
{ "tuesday", tDAY, 2 },
{ "tues", tDAY, 2 },
{ "wednesday", tDAY, 3 },
{ "wednes", tDAY, 3 },
{ "thursday", tDAY, 4 },
{ "thur", tDAY, 4 },
|
| ︙ | ︙ | |||
710 711 712 713 714 715 716 |
int
ToSeconds(
int Hours,
int Minutes,
int Seconds,
MERIDIAN Meridian)
{
| < < < < < < < < < < < < | 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 |
int
ToSeconds(
int Hours,
int Minutes,
int Seconds,
MERIDIAN Meridian)
{
switch (Meridian) {
case MER24:
return (Hours * 60 + Minutes) * 60 + Seconds;
case MERam:
return ((Hours % 12) * 60 + Minutes) * 60 + Seconds;
case MERpm:
return (((Hours % 12) + 12) * 60 + Minutes) * 60 + Seconds;
}
return -1; /* Should never be reached */
}
static int
LookupWord(
|
| ︙ | ︙ |
Changes to generic/tclIO.c.
| ︙ | ︙ | |||
339 340 341 342 343 344 345 |
FreeChannelInternalRep, /* freeIntRepProc */
DupChannelInternalRep, /* dupIntRepProc */
NULL, /* updateStringProc */
NULL, /* setFromAnyProc */
TCL_OBJTYPE_V0
};
| < < < | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 |
FreeChannelInternalRep, /* freeIntRepProc */
DupChannelInternalRep, /* dupIntRepProc */
NULL, /* updateStringProc */
NULL, /* setFromAnyProc */
TCL_OBJTYPE_V0
};
#define ChanSetInternalRep(objPtr, resPtr) \
do { \
Tcl_ObjInternalRep ir; \
(resPtr)->refCount++; \
ir.twoPtrValue.ptr1 = (resPtr); \
ir.twoPtrValue.ptr2 = NULL; \
Tcl_StoreInternalRep((objPtr), &chanObjType, &ir); \
|
| ︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 |
}
statePtr->channelName = tmp;
statePtr->flags = mask;
statePtr->maxPerms = mask; /* Save max privileges for close callback */
/*
* Set the channel to system default encoding.
| < < < < < < | 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 |
}
statePtr->channelName = tmp;
statePtr->flags = mask;
statePtr->maxPerms = mask; /* Save max privileges for close callback */
/*
* Set the channel to system default encoding.
*/
name = Tcl_GetEncodingName(NULL);
statePtr->encoding = Tcl_GetEncoding(NULL, name);
statePtr->inputEncodingState = NULL;
statePtr->inputEncodingFlags = TCL_ENCODING_START;
statePtr->outputEncodingState = NULL;
|
| ︙ | ︙ | |||
7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 |
return 0;
}
/*
*----------------------------------------------------------------------
*
* Tcl_Eof --
*
* Returns 1 if the channel is at EOF, 0 otherwise.
*
* Results:
* 1 or 0, always.
*
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 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 7572 7573 7574 |
return 0;
}
/*
*----------------------------------------------------------------------
*
* TclChanIsBinary --
*
* Returns 1 if the channel is a binary channel, 0 otherwise.
*
* Results:
* 1 or 0, always.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
TclChanIsBinary(
Tcl_Channel chan) /* Does this channel have EOF? */
{
ChannelState *statePtr = ((Channel *) chan)->state;
/* State of real channel structure. */
return ((statePtr->encoding == GetBinaryEncoding()) && !statePtr->inEofChar
&& (!GotFlag(statePtr, TCL_READABLE) || (statePtr->inputTranslation == TCL_TRANSLATE_LF))
&& (!GotFlag(statePtr, TCL_WRITABLE) || (statePtr->outputTranslation == TCL_TRANSLATE_LF)));
}
/*
*----------------------------------------------------------------------
*
* Tcl_Eof --
*
* Returns 1 if the channel is at EOF, 0 otherwise.
*
* Results:
* 1 or 0, always.
*
|
| ︙ | ︙ | |||
8230 8231 8232 8233 8234 8235 8236 |
}
Tcl_SetChannelBufferSize(chan, newBufferSize);
return TCL_OK;
} else if (HaveOpt(2, "-encoding")) {
Tcl_Encoding encoding;
int profile;
| | > > > > | > > | 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 |
}
Tcl_SetChannelBufferSize(chan, newBufferSize);
return TCL_OK;
} else if (HaveOpt(2, "-encoding")) {
Tcl_Encoding encoding;
int profile;
if ((newValue[0] == '\0') || !strcmp(newValue, "binary")) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"unknown encoding \"%s\": No longer supported.\n"
"\tplease use either \"-translation binary\" "
"or \"-encoding iso8859-1\"", newValue));
}
return TCL_ERROR;
} else {
encoding = Tcl_GetEncoding(interp, newValue);
if (encoding == NULL) {
return TCL_ERROR;
}
}
|
| ︙ | ︙ | |||
9191 9192 9193 9194 9195 9196 9197 |
const char *chanName;
int modeIndex; /* Index of mode argument. */
int mask;
static const char *const modeOptions[] = {"readable", "writable", NULL};
static const int maskArray[] = {TCL_READABLE, TCL_WRITABLE};
if ((objc != 3) && (objc != 4)) {
| | | 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 |
const char *chanName;
int modeIndex; /* Index of mode argument. */
int mask;
static const char *const modeOptions[] = {"readable", "writable", NULL};
static const int maskArray[] = {TCL_READABLE, TCL_WRITABLE};
if ((objc != 3) && (objc != 4)) {
Tcl_WrongNumArgs(interp, 1, objv, "channel event ?script?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[2], modeOptions, "event name", 0,
&modeIndex) != TCL_OK) {
return TCL_ERROR;
}
mask = maskArray[modeIndex];
|
| ︙ | ︙ |
Changes to generic/tclIOCmd.c.
| ︙ | ︙ | |||
134 135 136 137 138 139 140 |
chanObjPtr = objv[2];
string = objv[3];
break;
}
/* Fall through */
default: /* [puts] or
* [puts some bad number of arguments...] */
| | | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
chanObjPtr = objv[2];
string = objv[3];
break;
}
/* Fall through */
default: /* [puts] or
* [puts some bad number of arguments...] */
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channel? string");
return TCL_ERROR;
}
if (chanObjPtr == NULL) {
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (!tsdPtr->initialized) {
|
| ︙ | ︙ | |||
218 219 220 221 222 223 224 |
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Obj *chanObjPtr;
Tcl_Channel chan; /* The channel to flush on. */
int mode;
if (objc != 2) {
| | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Obj *chanObjPtr;
Tcl_Channel chan; /* The channel to flush on. */
int mode;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channel");
return TCL_ERROR;
}
chanObjPtr = objv[1];
if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
if (!(mode & TCL_WRITABLE)) {
|
| ︙ | ︙ | |||
284 285 286 287 288 289 290 |
Tcl_Channel chan; /* The channel to read from. */
Tcl_Size lineLen; /* Length of line just read. */
int mode; /* Mode in which channel is opened. */
Tcl_Obj *linePtr, *chanObjPtr;
int code = TCL_OK;
if ((objc != 2) && (objc != 3)) {
| | | 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
Tcl_Channel chan; /* The channel to read from. */
Tcl_Size lineLen; /* Length of line just read. */
int mode; /* Mode in which channel is opened. */
Tcl_Obj *linePtr, *chanObjPtr;
int code = TCL_OK;
if ((objc != 2) && (objc != 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "channel ?varName?");
return TCL_ERROR;
}
chanObjPtr = objv[1];
if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
if (!(mode & TCL_READABLE)) {
|
| ︙ | ︙ | |||
375 376 377 378 379 380 381 |
Tcl_Obj *resultPtr, *chanObjPtr;
if ((objc != 2) && (objc != 3)) {
Interp *iPtr;
argerror:
iPtr = (Interp *) interp;
| | | | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
Tcl_Obj *resultPtr, *chanObjPtr;
if ((objc != 2) && (objc != 3)) {
Interp *iPtr;
argerror:
iPtr = (Interp *) interp;
Tcl_WrongNumArgs(interp, 1, objv, "channel ?numChars?");
/*
* Do not append directly; that makes ensembles using this command as
* a subcommand produce the wrong message.
*/
iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? channel");
return TCL_ERROR;
}
i = 1;
newline = 0;
if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) {
newline = 1;
|
| ︙ | ︙ | |||
511 512 513 514 515 516 517 |
int optionIndex;
static const char *const originOptions[] = {
"start", "current", "end", NULL
};
static const int modeArray[] = {SEEK_SET, SEEK_CUR, SEEK_END};
if ((objc != 3) && (objc != 4)) {
| | | 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
int optionIndex;
static const char *const originOptions[] = {
"start", "current", "end", NULL
};
static const int modeArray[] = {SEEK_SET, SEEK_CUR, SEEK_END};
if ((objc != 3) && (objc != 4)) {
Tcl_WrongNumArgs(interp, 1, objv, "channel offset ?origin?");
return TCL_ERROR;
}
if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
if (TclGetWideIntFromObj(interp, objv[2], &offset) != TCL_OK) {
return TCL_ERROR;
|
| ︙ | ︙ | |||
580 581 582 583 584 585 586 |
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan; /* The channel to tell on. */
Tcl_WideInt newLoc;
int code;
if (objc != 2) {
| | | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 |
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan; /* The channel to tell on. */
Tcl_WideInt newLoc;
int code;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channel");
return TCL_ERROR;
}
/*
* Try to find a channel with the right name and permissions in the IO
* channel table of this interpreter.
*/
|
| ︙ | ︙ | |||
643 644 645 646 647 648 649 |
Tcl_Channel chan; /* The channel to close. */
static const char *const dirOptions[] = {
"read", "write", NULL
};
static const int dirArray[] = {TCL_CLOSE_READ, TCL_CLOSE_WRITE};
if ((objc != 2) && (objc != 3)) {
| | | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 |
Tcl_Channel chan; /* The channel to close. */
static const char *const dirOptions[] = {
"read", "write", NULL
};
static const int dirArray[] = {TCL_CLOSE_READ, TCL_CLOSE_WRITE};
if ((objc != 2) && (objc != 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "channel ?direction?");
return TCL_ERROR;
}
if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
|
| ︙ | ︙ | |||
749 750 751 752 753 754 755 |
Tcl_Obj *const objv[]) /* Argument objects. */
{
const char *optionName, *valueName;
Tcl_Channel chan; /* The channel to set a mode on. */
int i; /* Iterate over arg-value pairs. */
if ((objc < 2) || (((objc % 2) == 1) && (objc != 3))) {
| | | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 |
Tcl_Obj *const objv[]) /* Argument objects. */
{
const char *optionName, *valueName;
Tcl_Channel chan; /* The channel to set a mode on. */
int i; /* Iterate over arg-value pairs. */
if ((objc < 2) || (((objc % 2) == 1) && (objc != 3))) {
Tcl_WrongNumArgs(interp, 1, objv, "channel ?-option value ...?");
return TCL_ERROR;
}
if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
|
| ︙ | ︙ | |||
822 823 824 825 826 827 828 |
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
if (objc != 2) {
| | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channel");
return TCL_ERROR;
}
if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Tcl_Eof(chan)));
return TCL_OK;
}
/*
*---------------------------------------------------------------------------
*
* ChanIsBinaryCmd --
*
* This function is invoked to process the Tcl "chan isbinary" command. See the
* user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Sets interp's result to boolean true or false depending on whether the
* specified channel is a binary channel.
*
*---------------------------------------------------------------------------
*/
static int
ChanIsBinaryCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channel");
return TCL_ERROR;
}
if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(TclChanIsBinary(chan)));
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_ExecObjCmd --
*
* This function is invoked to process the "exec" Tcl command. See the
|
| ︙ | ︙ | |||
1034 1035 1036 1037 1038 1039 1040 |
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
int mode;
if (objc != 2) {
| | | 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 |
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
int mode;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channel");
return TCL_ERROR;
}
if (TclGetChannelFromObj(interp, objv[1], &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
if (!(mode & TCL_READABLE)) {
|
| ︙ | ︙ | |||
1804 1805 1806 1807 1808 1809 1810 |
{
Tcl_Channel chan;
static const char *const options[] = {"input", "output", NULL};
enum pendingOptionsEnum {PENDING_INPUT, PENDING_OUTPUT} index;
int mode;
if (objc != 3) {
| | | 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 |
{
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 channel");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], options, "mode", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
|
| ︙ | ︙ | |||
1864 1865 1866 1867 1868 1869 1870 |
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
Tcl_WideInt length;
if ((objc < 2) || (objc > 3)) {
| | | 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 |
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
Tcl_WideInt length;
if ((objc < 2) || (objc > 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "channel ?length?");
return TCL_ERROR;
}
if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
return TCL_ERROR;
}
if (objc == 3) {
|
| ︙ | ︙ | |||
2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 |
{"close", Tcl_CloseObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
{"copy", Tcl_FcopyObjCmd, NULL, NULL, NULL, 0},
{"create", TclChanCreateObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */
{"eof", Tcl_EofObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"event", Tcl_FileEventObjCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0},
{"flush", Tcl_FlushObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"gets", Tcl_GetsObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
{"names", TclChannelNamesCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
{"pending", ChanPendingObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #287 */
{"pipe", ChanPipeObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, /* TIP #304 */
{"pop", TclChanPopObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, /* TIP #230 */
{"postevent", TclChanPostEventObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */
{"push", TclChanPushObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #230 */
{"puts", Tcl_PutsObjCmd, NULL, NULL, NULL, 0},
| > | 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 |
{"close", Tcl_CloseObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
{"copy", Tcl_FcopyObjCmd, NULL, NULL, NULL, 0},
{"create", TclChanCreateObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */
{"eof", Tcl_EofObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"event", Tcl_FileEventObjCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0},
{"flush", Tcl_FlushObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"gets", Tcl_GetsObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
{"isbinary", ChanIsBinaryCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"names", TclChannelNamesCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0},
{"pending", ChanPendingObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #287 */
{"pipe", ChanPipeObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, /* TIP #304 */
{"pop", TclChanPopObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, /* TIP #230 */
{"postevent", TclChanPostEventObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */
{"push", TclChanPushObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #230 */
{"puts", Tcl_PutsObjCmd, NULL, NULL, NULL, 0},
|
| ︙ | ︙ |
Changes to generic/tclIORTrans.c.
| ︙ | ︙ | |||
595 596 597 598 599 600 601 |
/*
* Verify the result.
* - List, of method names. Convert to mask. Check for non-optionals
* through the mask. Compare open mode against optional r/w.
*/
if (TclListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
| | | | | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 |
/*
* Verify the result.
* - List, of method names. Convert to mask. Check for non-optionals
* through the mask. Compare open mode against optional r/w.
*/
if (TclListObjGetElements(NULL, resObj, &listc, &listv) != TCL_OK) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"chan handler \"%s initialize\" returned non-list: %s",
TclGetString(cmdObj), TclGetString(resObj)));
Tcl_DecrRefCount(resObj);
goto error;
}
methods = 0;
while (listc > 0) {
if (Tcl_GetIndexFromObj(interp, listv[listc-1], methodNames,
|
| ︙ | ︙ | |||
620 621 622 623 624 625 626 |
methods |= FLAG(methIndex);
listc--;
}
Tcl_DecrRefCount(resObj);
if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) {
| | | | | | | | | | | | | | 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 |
methods |= FLAG(methIndex);
listc--;
}
Tcl_DecrRefCount(resObj);
if ((REQUIRED_METHODS & methods) != REQUIRED_METHODS) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"chan handler \"%s\" does not support all required methods",
TclGetString(cmdObj)));
goto error;
}
/*
* Mode tell us what the parent channel supports. The methods tell us what
* the handler supports. We remove the non-supported bits from the mode
* and check that the channel is not completely inaccessible. Afterward the
* mode tells us which methods are still required, and these methods will
* also be supported by the handler, by design of the check.
*/
if (!HAS(methods, METH_READ)) {
mode &= ~TCL_READABLE;
}
if (!HAS(methods, METH_WRITE)) {
mode &= ~TCL_WRITABLE;
}
if (!mode) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"chan handler \"%s\" makes the channel inaccessible",
TclGetString(cmdObj)));
goto error;
}
/*
* The mode and support for it is ok, now check the internal constraints.
*/
if (!IMPLIES(HAS(methods, METH_DRAIN), HAS(methods, METH_READ))) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"chan handler \"%s\" supports \"drain\" but not \"read\"",
TclGetString(cmdObj)));
goto error;
}
if (!IMPLIES(HAS(methods, METH_FLUSH), HAS(methods, METH_WRITE))) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"chan handler \"%s\" supports \"flush\" but not \"write\"",
TclGetString(cmdObj)));
goto error;
}
Tcl_ResetResult(interp);
/*
* Everything is fine now.
|
| ︙ | ︙ |
Changes to generic/tclIOSock.c.
| ︙ | ︙ | |||
259 260 261 262 263 264 265 |
if (result != 0) {
*errorMsgPtr =
#ifdef EAI_SYSTEM /* Doesn't exist on Windows */
(result == EAI_SYSTEM) ? Tcl_PosixError(interp) :
#endif /* EAI_SYSTEM */
gai_strerror(result);
| | | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
if (result != 0) {
*errorMsgPtr =
#ifdef EAI_SYSTEM /* Doesn't exist on Windows */
(result == EAI_SYSTEM) ? Tcl_PosixError(interp) :
#endif /* EAI_SYSTEM */
gai_strerror(result);
return 0;
}
/*
* Put IPv4 addresses before IPv6 addresses to maximize backwards
* compatibility of [fconfigure -sockname] output.
*
* There might be more elegant/efficient ways to do this.
|
| ︙ | ︙ |
Added generic/tclIcu.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 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 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 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 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 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 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 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 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 |
/*
* tclIcu.c --
*
* tclIcu.c implements various Tcl commands that make use of
* the ICU library if present on the system.
* (Adapted from tkIcu.c)
*
* Copyright © 2021 Jan Nijtmans
* Copyright © 2024 Ashok P. Nadkarni
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
/*
* Runtime linking of libicu.
*/
typedef enum UBreakIteratorTypex {
UBRK_CHARACTERX = 0,
UBRK_WORDX = 1
} UBreakIteratorTypex;
typedef enum UErrorCodex {
U_AMBIGUOUS_ALIAS_WARNING = -122,
U_ZERO_ERRORZ = 0, /**< No error, no warning. */
} UErrorCodex;
#define U_SUCCESS(x) ((x)<=U_ZERO_ERRORZ)
#define U_FAILURE(x) ((x)>U_ZERO_ERRORZ)
struct UEnumeration;
typedef struct UEnumeration UEnumeration;
struct UCharsetDetector;
typedef struct UCharsetDetector UCharsetDetector;
struct UCharsetMatch;
typedef struct UCharsetMatch UCharsetMatch;
/*
* Prototypes for ICU functions sorted by category.
*/
typedef void (*fn_u_cleanup)(void);
typedef const char *(*fn_u_errorName)(UErrorCodex);
typedef uint16_t (*fn_ucnv_countAliases)(const char *, UErrorCodex *);
typedef int32_t (*fn_ucnv_countAvailable)();
typedef const char *(*fn_ucnv_getAlias)(const char *, uint16_t, UErrorCodex *);
typedef const char *(*fn_ucnv_getAvailableName)(int32_t);
typedef void *(*fn_ubrk_open)(UBreakIteratorTypex, const char *,
const uint16_t *, int32_t, UErrorCodex *);
typedef void (*fn_ubrk_close)(void *);
typedef int32_t (*fn_ubrk_preceding)(void *, int32_t);
typedef int32_t (*fn_ubrk_following)(void *, int32_t);
typedef int32_t (*fn_ubrk_previous)(void *);
typedef int32_t (*fn_ubrk_next)(void *);
typedef void (*fn_ubrk_setText)(void *, const void *, int32_t, UErrorCodex *);
typedef UCharsetDetector * (*fn_ucsdet_open)(UErrorCodex *status);
typedef void (*fn_ucsdet_close)(UCharsetDetector *ucsd);
typedef void (*fn_ucsdet_setText)(UCharsetDetector *ucsd, const char *textIn, int32_t len, UErrorCodex *status);
typedef const char * (*fn_ucsdet_getName)(const UCharsetMatch *ucsm, UErrorCodex *status);
typedef UEnumeration * (*fn_ucsdet_getAllDetectableCharsets)(UCharsetDetector *ucsd, UErrorCodex *status);
typedef const UCharsetMatch * (*fn_ucsdet_detect)(UCharsetDetector *ucsd, UErrorCodex *status);
typedef const UCharsetMatch ** (*fn_ucsdet_detectAll)(UCharsetDetector *ucsd, int32_t *matchesFound, UErrorCodex *status);
typedef void (*fn_uenum_close)(UEnumeration *);
typedef int32_t (*fn_uenum_count)(UEnumeration *, UErrorCodex *);
typedef const char *(*fn_uenum_next)(UEnumeration *, int32_t *, UErrorCodex *);
#define FIELD(name) fn_ ## name _ ## name
static struct {
size_t nopen; /* Total number of references to ALL libraries */
/*
* Depending on platform, ICU symbols may be distributed amongst
* multiple libraries. For current functionality at most 2 needed.
* Order of library loading is not guaranteed.
*/
Tcl_LoadHandle libs[2];
FIELD(u_cleanup);
FIELD(u_errorName);
FIELD(ubrk_open);
FIELD(ubrk_close);
FIELD(ubrk_preceding);
FIELD(ubrk_following);
FIELD(ubrk_previous);
FIELD(ubrk_next);
FIELD(ubrk_setText);
FIELD(ucnv_countAliases);
FIELD(ucnv_countAvailable);
FIELD(ucnv_getAlias);
FIELD(ucnv_getAvailableName);
FIELD(ucsdet_close);
FIELD(ucsdet_detect);
FIELD(ucsdet_detectAll);
FIELD(ucsdet_getAllDetectableCharsets);
FIELD(ucsdet_getName);
FIELD(ucsdet_open);
FIELD(ucsdet_setText);
FIELD(uenum_close);
FIELD(uenum_count);
FIELD(uenum_next);
} icu_fns = {
0, {NULL, NULL}, /* Reference count, library handles */
NULL, NULL, /* u_* */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* ubrk* */
NULL, NULL, NULL, NULL, /* ucnv_* */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* ucsdet* */
NULL, NULL, NULL, /* uenum_* */
};
#define u_cleanup icu_fns._u_cleanup
#define u_errorName icu_fns._u_errorName
#define ubrk_open icu_fns._ubrk_open
#define ubrk_close icu_fns._ubrk_close
#define ubrk_preceding icu_fns._ubrk_preceding
#define ubrk_following icu_fns._ubrk_following
#define ubrk_previous icu_fns._ubrk_previous
#define ubrk_next icu_fns._ubrk_next
#define ubrk_setText icu_fns._ubrk_setText
#define ucnv_countAliases icu_fns._ucnv_countAliases
#define ucnv_countAvailable icu_fns._ucnv_countAvailable
#define ucnv_getAlias icu_fns._ucnv_getAlias
#define ucnv_getAvailableName icu_fns._ucnv_getAvailableName
#define ucsdet_close icu_fns._ucsdet_close
#define ucsdet_detect icu_fns._ucsdet_detect
#define ucsdet_detectAll icu_fns._ucsdet_detectAll
#define ucsdet_getAllDetectableCharsets icu_fns._ucsdet_getAllDetectableCharsets
#define ucsdet_getName icu_fns._ucsdet_getName
#define ucsdet_open icu_fns._ucsdet_open
#define ucsdet_setText icu_fns._ucsdet_setText
#define uenum_next icu_fns._uenum_next
#define uenum_close icu_fns._uenum_close
#define uenum_count icu_fns._uenum_count
TCL_DECLARE_MUTEX(icu_mutex);
static int FunctionNotAvailableError(Tcl_Interp *interp) {
if (interp) {
Tcl_SetObjResult(interp,
Tcl_NewStringObj("ICU function not available", TCL_INDEX_NONE));
}
return TCL_ERROR;
}
static int IcuError(Tcl_Interp *interp, const char *message, UErrorCodex code)
{
if (interp) {
const char *codeMessage = NULL;
if (u_errorName) {
codeMessage = u_errorName(code);
}
Tcl_SetObjResult(interp,
Tcl_ObjPrintf("%s. ICU error (%d): %s",
message,
code,
codeMessage ? codeMessage : ""));
}
return TCL_ERROR;
}
static int DetectEncoding(Tcl_Interp *interp, Tcl_Obj *objPtr, int all)
{
Tcl_Size len;
const char *bytes;
const UCharsetMatch *match;
const UCharsetMatch **matches;
int nmatches;
int ret;
if (ucsdet_open == NULL || ucsdet_setText == NULL ||
ucsdet_detect == NULL || ucsdet_detectAll == NULL ||
ucsdet_getName == NULL || ucsdet_close == NULL) {
return FunctionNotAvailableError(interp);
}
bytes = (char *) Tcl_GetBytesFromObj(interp, objPtr, &len);
if (bytes == NULL) {
return TCL_ERROR;
}
UErrorCodex status = U_ZERO_ERRORZ;
UCharsetDetector* csd = ucsdet_open(&status);
if (U_FAILURE(status)) {
return IcuError(interp, "Could not open charset detector.", status);
}
ucsdet_setText(csd, bytes, len, &status);
if (U_FAILURE(status)) {
IcuError(interp, "Could not set detection text.", status);
ucsdet_close(csd);
return TCL_ERROR;
}
if (all) {
matches = ucsdet_detectAll(csd, &nmatches, &status);
}
else {
match = ucsdet_detect(csd, &status);
matches = &match;
nmatches = match ? 1 : 0;
}
if (U_FAILURE(status) || nmatches == 0) {
ret = IcuError(interp, "Could not detect character set.", status);
}
else {
int i;
Tcl_Obj *resultObj = Tcl_NewListObj(nmatches, NULL);
for (i = 0; i < nmatches; ++i) {
const char *name = ucsdet_getName(matches[i], &status);
if (U_FAILURE(status) || name == NULL) {
name = "unknown";
status = U_ZERO_ERRORZ; /* Reset on failure */
}
Tcl_ListObjAppendElement(
NULL, resultObj, Tcl_NewStringObj(name, -1));
}
Tcl_SetObjResult(interp, resultObj);
ret = TCL_OK;
}
ucsdet_close(csd);
return ret;
}
static int DetectableEncodings(Tcl_Interp *interp)
{
if (ucsdet_open == NULL || ucsdet_getAllDetectableCharsets == NULL ||
ucsdet_close == NULL || uenum_next == NULL || uenum_count == NULL ||
uenum_close == NULL) {
return FunctionNotAvailableError(interp);
}
UErrorCodex status = U_ZERO_ERRORZ;
UCharsetDetector* csd = ucsdet_open(&status);
if (U_FAILURE(status)) {
return IcuError(interp, "Could not open charset detector.", status);
}
int ret;
UEnumeration *enumerator = ucsdet_getAllDetectableCharsets(csd, &status);
if (U_FAILURE(status) || enumerator == NULL) {
IcuError(interp, "Could not get list of detectable encodings.", status);
ret = TCL_ERROR;
} else {
int32_t count;
count = uenum_count(enumerator, &status);
if (U_FAILURE(status)) {
IcuError(interp, "Could not get charset enumerator count.", status);
ret = TCL_ERROR;
} else {
int i;
Tcl_Obj *resultObj = Tcl_NewListObj(0, NULL);
for (i = 0; i < count; ++i) {
const char *name;
int32_t len;
name = uenum_next(enumerator, &len, &status);
if (name == NULL || U_FAILURE(status)) {
name = "unknown";
len = 7;
status = U_ZERO_ERRORZ; /* Reset on error */
}
Tcl_ListObjAppendElement(
interp, resultObj, Tcl_NewStringObj(name, len));
}
Tcl_SetObjResult(interp, resultObj);
ret = TCL_OK;
}
uenum_close(enumerator);
}
ucsdet_close(csd);
return ret;
}
/*
*------------------------------------------------------------------------
*
* EncodingDetectObjCmd --
*
* Implements the Tcl command EncodingDetect.
* encdetect - returns names of all detectable encodings
* encdetect BYTES ?-all? - return detected encoding(s)
*
* Results:
* TCL_OK - Success.
* TCL_ERROR - Error.
*
* Side effects:
* Interpreter result holds result or error message.
*
*------------------------------------------------------------------------
*/
static int
IcuDetectObjCmd(
TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
if (objc > 3) {
Tcl_WrongNumArgs(interp, 1 , objv, "?bytes ?-all??");
return TCL_ERROR;
}
if (objc == 1) {
return DetectableEncodings(interp);
}
int all = 0;
if (objc == 3) {
if (strcmp("-all", Tcl_GetString(objv[2]))) {
Tcl_SetObjResult(
interp,
Tcl_ObjPrintf("Invalid option %s, must be \"-all\"",
Tcl_GetString(objv[2])));
return TCL_ERROR;
}
all = 1;
}
return DetectEncoding(interp, objv[1], all);
}
/*
*------------------------------------------------------------------------
*
* IcuConverterNamesObjCmd --
*
* Sets interp result to list of available ICU converters.
*
* Results:
* TCL_OK - Success.
* TCL_ERROR - Error.
*
* Side effects:
* Interpreter result holds list of converter names.
*
*------------------------------------------------------------------------
*/
static int
IcuConverterNamesObjCmd (
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1 , objv, "");
return TCL_ERROR;
}
if (ucnv_countAvailable == NULL || ucnv_getAvailableName == NULL) {
return FunctionNotAvailableError(interp);
}
int32_t count = ucnv_countAvailable();
if (count <= 0) {
return TCL_OK;
}
Tcl_Obj *resultObj = Tcl_NewListObj(count, NULL);
int32_t i;
for (i = 0; i < count; ++i) {
const char *name = ucnv_getAvailableName(i);
if (name) {
Tcl_ListObjAppendElement(
NULL, resultObj, Tcl_NewStringObj(name, -1));
}
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
/*
*------------------------------------------------------------------------
*
* IcuConverterAliasesObjCmd --
*
* Sets interp result to list of available ICU converters.
*
* Results:
* TCL_OK - Success.
* TCL_ERROR - Error.
*
* Side effects:
* Interpreter result holds list of converter names.
*
*------------------------------------------------------------------------
*/
static int
IcuConverterAliasesObjCmd (
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1 , objv, "convertername");
return TCL_ERROR;
}
if (ucnv_countAliases == NULL || ucnv_getAlias == NULL) {
return FunctionNotAvailableError(interp);
}
const char *name = Tcl_GetString(objv[1]);
UErrorCodex status = U_ZERO_ERRORZ;
uint16_t count = ucnv_countAliases(name, &status);
if (status != U_AMBIGUOUS_ALIAS_WARNING && U_FAILURE(status)) {
return IcuError(interp, "Could not get aliases.", status);
}
if (count <= 0) {
return TCL_OK;
}
Tcl_Obj *resultObj = Tcl_NewListObj(count, NULL);
uint16_t i;
for (i = 0; i < count; ++i) {
status = U_ZERO_ERRORZ; /* Reset in case U_AMBIGUOUS_ALIAS_WARNING */
const char *aliasName = ucnv_getAlias(name, i, &status);
if (status != U_AMBIGUOUS_ALIAS_WARNING && U_FAILURE(status)) {
status = U_ZERO_ERRORZ; /* Reset error for next iteration */
continue;
}
if (aliasName) {
Tcl_ListObjAppendElement(
NULL, resultObj, Tcl_NewStringObj(aliasName, -1));
}
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
static void
TclIcuCleanup(
TCL_UNUSED(void *))
{
Tcl_MutexLock(&icu_mutex);
if (icu_fns.nopen-- <= 1) {
int i;
if (u_cleanup != NULL) {
u_cleanup();
}
for (i = 0; i < (int)(sizeof(icu_fns.libs) / sizeof(icu_fns.libs[0]));
++i) {
if (icu_fns.libs[i] != NULL) {
Tcl_FSUnloadFile(NULL, icu_fns.libs[i]);
}
}
memset(&icu_fns, 0, sizeof(icu_fns));
}
Tcl_MutexUnlock(&icu_mutex);
}
static void
TclIcuInit(
Tcl_Interp *interp)
{
Tcl_MutexLock(&icu_mutex);
char symbol[256];
char icuversion[4] = "_80"; /* Highest ICU version + 1 */
/*
* The initialization below clones the existing one from Tk. May need
* revisiting.
* ICU shared library names as well as function names *may* be versioned.
* See https://unicode-org.github.io/icu/userguide/icu4c/packaging.html
* for the gory details.
*/
if (icu_fns.nopen == 0) {
int i = 0;
Tcl_Obj *nameobj;
static const char *iculibs[] = {
#if defined(_WIN32)
# define DLLNAME "icu%s%s.dll"
"icuuc??.dll", /* Windows, user-provided */
NULL,
"cygicuuc??.dll", /* When running under Cygwin */
#elif defined(__CYGWIN__)
# define DLLNAME "cygicu%s%s.dll"
"cygicuuc??.dll",
#elif defined(MAC_OSX_TCL)
# define DLLNAME "libicu%s.%s.dylib"
"libicuuc.??.dylib",
#else
# define DLLNAME "libicu%s.so.%s"
"libicuuc.so.??",
#endif
NULL
};
/* Going back down to ICU version 60 */
while ((icu_fns.libs[0] == NULL) && (icuversion[1] >= '6')) {
if (--icuversion[2] < '0') {
icuversion[1]--; icuversion[2] = '9';
}
#if defined(__CYGWIN__)
i = 2;
#else
i = 0;
#endif
while (iculibs[i] != NULL) {
Tcl_ResetResult(interp);
nameobj = Tcl_NewStringObj(iculibs[i], TCL_INDEX_NONE);
char *nameStr = Tcl_GetString(nameobj);
char *p = strchr(nameStr, '?');
if (p != NULL) {
memcpy(p, icuversion+1, 2);
}
Tcl_IncrRefCount(nameobj);
if (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[0])
== TCL_OK) {
if (p == NULL) {
icuversion[0] = '\0';
}
Tcl_DecrRefCount(nameobj);
break;
}
Tcl_DecrRefCount(nameobj);
++i;
}
}
if (icu_fns.libs[0] != NULL) {
/* Loaded icuuc, load others with the same version */
nameobj = Tcl_ObjPrintf(DLLNAME, "i18n", icuversion+1);
Tcl_IncrRefCount(nameobj);
/* Ignore errors. Calls to contained functions will fail. */
(void) Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[1]);
Tcl_DecrRefCount(nameobj);
}
#if defined(_WIN32)
/*
* On Windows, if no ICU install found, look for the system's
* (Win10 1703 or later). There are two cases. Newer systems
* have icu.dll containing all functions. Older systems have
* icucc.dll and icuin.dll
*/
if (icu_fns.libs[0] == NULL) {
Tcl_ResetResult(interp);
nameobj = Tcl_NewStringObj("icu.dll", TCL_INDEX_NONE);
Tcl_IncrRefCount(nameobj);
if (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[0])
== TCL_OK) {
/* Reload same for second set of functions. */
(void) Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[1]);
/* Functions do NOT have version suffixes */
icuversion[0] = '\0';
}
Tcl_DecrRefCount(nameobj);
}
if (icu_fns.libs[0] == NULL) {
/* No icu.dll. Try last fallback */
Tcl_ResetResult(interp);
nameobj = Tcl_NewStringObj("icuuc.dll", TCL_INDEX_NONE);
Tcl_IncrRefCount(nameobj);
if (Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[0])
== TCL_OK) {
Tcl_DecrRefCount(nameobj);
nameobj = Tcl_NewStringObj("icuin.dll", TCL_INDEX_NONE);
Tcl_IncrRefCount(nameobj);
(void) Tcl_LoadFile(interp, nameobj, NULL, 0, NULL, &icu_fns.libs[1]);
/* Functions do NOT have version suffixes */
icuversion[0] = '\0';
}
Tcl_DecrRefCount(nameobj);
}
#endif
#define ICUUC_SYM(name) \
strcpy(symbol, #name ); \
strcat(symbol, icuversion); \
icu_fns._##name = (fn_ ## name) \
Tcl_FindSymbol(NULL, icu_fns.libs[0], symbol)
if (icu_fns.libs[0] != NULL) {
ICUUC_SYM(u_cleanup);
ICUUC_SYM(u_errorName);
ICUUC_SYM(ucnv_countAliases);
ICUUC_SYM(ucnv_countAvailable);
ICUUC_SYM(ucnv_getAlias);
ICUUC_SYM(ucnv_getAvailableName);
ICUUC_SYM(ubrk_open);
ICUUC_SYM(ubrk_close);
ICUUC_SYM(ubrk_preceding);
ICUUC_SYM(ubrk_following);
ICUUC_SYM(ubrk_previous);
ICUUC_SYM(ubrk_next);
ICUUC_SYM(ubrk_setText);
ICUUC_SYM(uenum_close);
ICUUC_SYM(uenum_count);
ICUUC_SYM(uenum_next);
#undef ICUUC_SYM
}
#define ICUIN_SYM(name) \
strcpy(symbol, #name ); \
strcat(symbol, icuversion); \
icu_fns._##name = (fn_ ## name) \
Tcl_FindSymbol(NULL, icu_fns.libs[1], symbol)
if (icu_fns.libs[1] != NULL) {
ICUIN_SYM(ucsdet_close);
ICUIN_SYM(ucsdet_detect);
ICUIN_SYM(ucsdet_detectAll);
ICUIN_SYM(ucsdet_getName);
ICUIN_SYM(ucsdet_getAllDetectableCharsets);
ICUIN_SYM(ucsdet_open);
ICUIN_SYM(ucsdet_setText);
#undef ICUIN_SYM
}
}
#undef ICU_SYM
Tcl_MutexUnlock(&icu_mutex);
if (icu_fns.libs[0] != NULL) {
/*
* Note refcounts updated BEFORE command definition to protect
* against self redefinition.
*/
if (icu_fns.libs[1] != NULL) {
/* Commands needing both libraries */
/* Ref count number of commands */
icu_fns.nopen += 1;
Tcl_CreateObjCommand(interp,
"::tcl::unsupported::icu::detect",
IcuDetectObjCmd,
0,
TclIcuCleanup);
}
/* Commands needing only libs[0] (icuuc) */
/* Ref count number of commands */
icu_fns.nopen += 2;
Tcl_CreateObjCommand(interp,
"::tcl::unsupported::icu::converters",
IcuConverterNamesObjCmd,
0,
TclIcuCleanup);
Tcl_CreateObjCommand(interp,
"::tcl::unsupported::icu::aliases",
IcuConverterAliasesObjCmd,
0,
TclIcuCleanup);
}
}
/*
*------------------------------------------------------------------------
*
* TclLoadIcuObjCmd --
*
* Loads and initializes ICU
*
* Results:
* TCL_OK - Success.
* TCL_ERROR - Error.
*
* Side effects:
* Interpreter result holds result or error message.
*
*------------------------------------------------------------------------
*/
int
TclLoadIcuObjCmd (
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1 , objv, "");
return TCL_ERROR;
}
TclIcuInit(interp);
return TCL_OK;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* coding: utf-8
* End:
*/
|
Changes to generic/tclInt.decls.
| ︙ | ︙ | |||
204 205 206 207 208 209 210 |
const char *procName)
}
declare 93 {
void TclProcDeleteProc(void *clientData)
}
declare 96 {
int TclRenameCommand(Tcl_Interp *interp, const char *oldName,
| | | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
const char *procName)
}
declare 93 {
void TclProcDeleteProc(void *clientData)
}
declare 96 {
int TclRenameCommand(Tcl_Interp *interp, const char *oldName,
const char *newName)
}
declare 97 {
void TclResetShadowedCmdRefs(Tcl_Interp *interp, Command *newCmdPtr)
}
declare 98 {
int TclServiceIdle(void)
}
|
| ︙ | ︙ | |||
468 469 470 471 472 473 474 |
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,
| | | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
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)
}
declare 218 {
void TclPopStackFrame(Tcl_Interp *interp)
}
# TIP 431: temporary directory creation function
declare 219 {
Tcl_Obj *TclpCreateTemporaryDirectory(Tcl_Obj *dirObj,
|
| ︙ | ︙ | |||
505 506 507 508 509 510 511 |
Tcl_Size keyc, Tcl_Obj *const keyv[], int flags)
}
declare 226 {
int TclObjBeingDeleted(Tcl_Obj *objPtr)
}
declare 227 {
void TclSetNsPath(Namespace *nsPtr, Tcl_Size pathLength,
| | | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 |
Tcl_Size keyc, Tcl_Obj *const keyv[], int flags)
}
declare 226 {
int TclObjBeingDeleted(Tcl_Obj *objPtr)
}
declare 227 {
void TclSetNsPath(Namespace *nsPtr, Tcl_Size pathLength,
Tcl_Namespace *pathAry[])
}
declare 229 {
int TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr,
const char *myName, int myFlags, int index)
}
declare 230 {
Var *TclObjLookupVar(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
| ︙ | ︙ | |||
533 534 535 536 537 538 539 |
declare 233 {
void TclGetSrcInfoForPc(CmdFrame *contextPtr)
}
# Exports for VarReform compat: Itcl, XOTcl like to peek into our varTables :(
declare 234 {
Var *TclVarHashCreateVar(TclVarHashTable *tablePtr, const char *key,
| | | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 |
declare 233 {
void TclGetSrcInfoForPc(CmdFrame *contextPtr)
}
# Exports for VarReform compat: Itcl, XOTcl like to peek into our varTables :(
declare 234 {
Var *TclVarHashCreateVar(TclVarHashTable *tablePtr, const char *key,
int *newPtr)
}
declare 235 {
void TclInitVarHashTable(TclVarHashTable *tablePtr, Namespace *nsPtr)
}
# TIP #285: Script cancellation support.
declare 237 {
|
| ︙ | ︙ |
Changes to generic/tclInt.h.
| ︙ | ︙ | |||
225 226 227 228 229 230 231 |
* Special hashtable for variables: This is just a Tcl_HashTable with nsPtr
* and arrayPtr fields added at the end so that variables can find their
* namespace and possibly containing array without having to copy a pointer in
* their struct by accessing them via their hPtr->tablePtr.
*/
typedef struct TclVarHashTable {
| | | | > | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
* Special hashtable for variables: This is just a Tcl_HashTable with nsPtr
* and arrayPtr fields added at the end so that variables can find their
* namespace and possibly containing array without having to copy a pointer in
* their struct by accessing them via their hPtr->tablePtr.
*/
typedef struct TclVarHashTable {
Tcl_HashTable table; /* "Inherit" from Tcl_HashTable. */
struct Namespace *nsPtr; /* The namespace containing the variables. */
#if TCL_MAJOR_VERSION > 8
struct Var *arrayPtr; /* The array containing the variables, if they
* are variables in an array at all. */
#endif /* TCL_MAJOR_VERSION > 8 */
} TclVarHashTable;
/*
* This is for itcl - it likes to search our varTables directly :(
*/
|
| ︙ | ︙ | |||
630 631 632 633 634 635 636 |
* to in a procedure, or a variable created by
* "upvar", this field points to the
* referenced variable's Var struct. */
} value;
} Var;
typedef struct VarInHash {
| | | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 |
* to in a procedure, or a variable created by
* "upvar", this field points to the
* referenced variable's Var struct. */
} value;
} Var;
typedef struct VarInHash {
Var var; /* "Inherit" from Var. */
Tcl_Size refCount; /* Counts number of active uses of this
* variable: 1 for the entry in the hash
* table, 1 for each additional variable whose
* linkPtr points here, 1 for each nested
* trace active on variable, and 1 if the
* variable is a namespace variable. This
* record can't be deleted until refCount
|
| ︙ | ︙ | |||
1121 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 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 |
static inline Tcl_Size
TclObjTypeLength(
Tcl_Obj *objPtr)
{
Tcl_ObjTypeLengthProc *proc = TclObjTypeHasProc(objPtr, lengthProc);
return proc(objPtr);
}
static inline int
TclObjTypeIndex(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size index,
Tcl_Obj **elemObjPtr)
{
Tcl_ObjTypeIndexProc *proc = TclObjTypeHasProc(objPtr, indexProc);
return proc(interp, objPtr, index, elemObjPtr);
}
static inline int
TclObjTypeSlice(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size fromIdx,
Tcl_Size toIdx,
Tcl_Obj **newObjPtr)
{
Tcl_ObjTypeSliceProc *proc = TclObjTypeHasProc(objPtr, sliceProc);
return proc(interp, objPtr, fromIdx, toIdx, newObjPtr);
}
static inline int
TclObjTypeReverse(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Obj **newObjPtr)
{
Tcl_ObjTypeReverseProc *proc = TclObjTypeHasProc(objPtr, reverseProc);
return proc(interp, objPtr, newObjPtr);
}
static inline int
TclObjTypeGetElements(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size *objCPtr,
Tcl_Obj ***objVPtr)
{
Tcl_ObjTypeGetElements *proc = TclObjTypeHasProc(objPtr, getElementsProc);
return proc(interp, objPtr, objCPtr, objVPtr);
}
static inline Tcl_Obj*
TclObjTypeSetElement(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size indexCount,
Tcl_Obj *const indexArray[],
Tcl_Obj *valueObj)
{
Tcl_ObjTypeSetElement *proc = TclObjTypeHasProc(objPtr, setElementProc);
return proc(interp, objPtr, indexCount, indexArray, valueObj);
}
static inline int
TclObjTypeReplace(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size first,
Tcl_Size numToDelete,
Tcl_Size numToInsert,
Tcl_Obj *const insertObjs[])
{
Tcl_ObjTypeReplaceProc *proc = TclObjTypeHasProc(objPtr, replaceProc);
return proc(interp, objPtr, first, numToDelete, numToInsert, insertObjs);
}
static inline int
TclObjTypeInOperator(
Tcl_Interp *interp,
Tcl_Obj *valueObj,
Tcl_Obj *listObj,
int *boolResult)
{
| > > > > > > > | 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 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 |
static inline Tcl_Size
TclObjTypeLength(
Tcl_Obj *objPtr)
{
Tcl_ObjTypeLengthProc *proc = TclObjTypeHasProc(objPtr, lengthProc);
return proc(objPtr);
}
static inline int
TclObjTypeIndex(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size index,
Tcl_Obj **elemObjPtr)
{
Tcl_ObjTypeIndexProc *proc = TclObjTypeHasProc(objPtr, indexProc);
return proc(interp, objPtr, index, elemObjPtr);
}
static inline int
TclObjTypeSlice(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size fromIdx,
Tcl_Size toIdx,
Tcl_Obj **newObjPtr)
{
Tcl_ObjTypeSliceProc *proc = TclObjTypeHasProc(objPtr, sliceProc);
return proc(interp, objPtr, fromIdx, toIdx, newObjPtr);
}
static inline int
TclObjTypeReverse(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Obj **newObjPtr)
{
Tcl_ObjTypeReverseProc *proc = TclObjTypeHasProc(objPtr, reverseProc);
return proc(interp, objPtr, newObjPtr);
}
static inline int
TclObjTypeGetElements(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size *objCPtr,
Tcl_Obj ***objVPtr)
{
Tcl_ObjTypeGetElements *proc = TclObjTypeHasProc(objPtr, getElementsProc);
return proc(interp, objPtr, objCPtr, objVPtr);
}
static inline Tcl_Obj*
TclObjTypeSetElement(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size indexCount,
Tcl_Obj *const indexArray[],
Tcl_Obj *valueObj)
{
Tcl_ObjTypeSetElement *proc = TclObjTypeHasProc(objPtr, setElementProc);
return proc(interp, objPtr, indexCount, indexArray, valueObj);
}
static inline int
TclObjTypeReplace(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
Tcl_Size first,
Tcl_Size numToDelete,
Tcl_Size numToInsert,
Tcl_Obj *const insertObjs[])
{
Tcl_ObjTypeReplaceProc *proc = TclObjTypeHasProc(objPtr, replaceProc);
return proc(interp, objPtr, first, numToDelete, numToInsert, insertObjs);
}
static inline int
TclObjTypeInOperator(
Tcl_Interp *interp,
Tcl_Obj *valueObj,
Tcl_Obj *listObj,
int *boolResult)
{
|
| ︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 |
/*
* Will be grown to contain: pointers to the varnames (allocated at the end),
* plus the init values for each variable (suitable to be memcopied on init)
*/
typedef struct LocalCache {
| | | | | 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 |
/*
* Will be grown to contain: pointers to the varnames (allocated at the end),
* plus the init values for each variable (suitable to be memcopied on init)
*/
typedef struct LocalCache {
Tcl_Size refCount; /* Reference count. */
Tcl_Size numVars; /* Number of variables. */
Tcl_Obj *varName0; /* First variable name. */
} LocalCache;
#define localName(framePtr, i) \
((&((framePtr)->localCachePtr->varName0))[(i)])
MODULE_SCOPE void TclFreeLocalCache(Tcl_Interp *interp,
LocalCache *localCachePtr);
|
| ︙ | ︙ | |||
1291 1292 1293 1294 1295 1296 1297 | * of this field is defined by the code that * sets it, and it should only ever be set by * the code that is pushing the frame. In that * case, the code that sets it should also * have some means of discovering what the * meaning of the value is, which we do not * specify. */ | | > > | | | 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 |
* of this field is defined by the code that
* sets it, and it should only ever be set by
* the code that is pushing the frame. In that
* case, the code that sets it should also
* have some means of discovering what the
* meaning of the value is, which we do not
* specify. */
LocalCache *localCachePtr; /* Pointer to the start of the cached variable
* names and initialisation data for local
* variables. */
Tcl_Obj *tailcallPtr; /* NULL if no tailcall is scheduled */
} CallFrame;
#define FRAME_IS_PROC 0x1 /* Frame is a procedure body. */
#define FRAME_IS_LAMBDA 0x2 /* Frame is a lambda term body. */
#define FRAME_IS_METHOD 0x4 /* The frame is a method body, and the frame's
* clientData field contains a CallContext
* reference. Part of TIP#257. */
#define FRAME_IS_OO_DEFINE 0x8 /* The frame is part of the inside workings of
* the [oo::define] command; the clientData
* field contains an Object reference that has
* been confirmed to refer to a class. Part of
|
| ︙ | ︙ | |||
1337 1338 1339 1340 1341 1342 1343 |
* General data. Always available.
*/
int type; /* Values see below. */
int level; /* Number of frames in stack, prevent O(n)
* scan of list. */
Tcl_Size *line; /* Lines the words of the command start on. */
| | | 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 |
* General data. Always available.
*/
int type; /* Values see below. */
int level; /* Number of frames in stack, prevent O(n)
* scan of list. */
Tcl_Size *line; /* Lines the words of the command start on. */
Tcl_Size nline; /* Number of lines in CmdFrame.line. */
CallFrame *framePtr; /* Procedure activation record, may be
* NULL. */
struct CmdFrame *nextPtr; /* Link to calling frame. */
/*
* Data needed for Eval vs TEBC
*
* EXECUTION CONTEXTS and usage of CmdFrame
|
| ︙ | ︙ | |||
1567 1568 1569 1570 1571 1572 1573 | * SetByteCodeFromAny. */ typedef int (CompileHookProc)(Tcl_Interp *interp, struct CompileEnv *compEnvPtr, void *clientData); /* | | > > > | | | | | > > > > > > > > > > > > > < < < < < < < | > | > | > > | 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 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 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 |
* SetByteCodeFromAny.
*/
typedef int (CompileHookProc)(Tcl_Interp *interp,
struct CompileEnv *compEnvPtr, void *clientData);
/*
* The data structure for a (linked list of) execution stacks. Note that the
* first word on a particular execution stack is NULL, which is used as a
* marker to say "go to the previous stack in the list" when unwinding the
* stack.
*/
typedef struct ExecStack {
struct ExecStack *prevPtr; /* Previous stack in list. */
struct ExecStack *nextPtr; /* Next stack in list. */
Tcl_Obj **markerPtr; /* The location of the NULL marker. */
Tcl_Obj **endPtr; /* Where the stack end is. */
Tcl_Obj **tosPtr; /* Where the stack top is. */
Tcl_Obj *stackWords[TCLFLEXARRAY];
/* The actual stack space, following this
* structure in memory. */
} ExecStack;
/*
* Saved copies of the stack frame references from the interpreter. Have to be
* restored into the interpreter to be used.
*/
typedef struct CorContext {
struct CallFrame *framePtr; /* See Interp.framePtr */
struct CallFrame *varFramePtr; /* See Interp.varFramePtr */
struct CmdFrame *cmdFramePtr; /* See Interp.cmdFramePtr */
Tcl_HashTable *lineLABCPtr; /* See Interp.lineLABCPtr */
} CorContext;
/*
* The data structure defining the execution environment for ByteCode's.
* There is one ExecEnv structure per Tcl interpreter. It holds the evaluation
* stack that holds command operands and results. The stack grows towards
* increasing addresses. The member stackPtr points to the stackItems of the
* currently active execution stack.
*/
typedef struct CoroutineData {
struct Command *cmdPtr; /* The command handle for the coroutine. */
struct ExecEnv *eePtr; /* The special execution environment (stacks,
* etc.) for the coroutine. */
struct ExecEnv *callerEEPtr;/* The execution environment for the caller of
* the coroutine, which might be the
* interpreter global environment or another
* coroutine. */
CorContext caller; /* Caller's saved execution context. */
CorContext running; /* This coroutine's saved execution context. */
Tcl_HashTable *lineLABCPtr; /* See Interp.lineLABCPtr */
void *stackLevel; /* C stack frame reference. Used to try to
* ensure we don't overflow that stack. */
Tcl_Size auxNumLevels; /* While the coroutine is running the
* numLevels of the create/resume command is
* stored here; for suspended coroutines it
* holds the nesting numLevels at yield. */
Tcl_Size nargs; /* Number of args required for resuming this
* coroutine; COROUTINE_ARGUMENTS_SINGLE_OPTIONAL
* means "0 or 1" (default),
* COROUTINE_ARGUMENTS_ARBITRARY means "any" */
Tcl_Obj *yieldPtr; /* The command to yield to. Stored here in
* order to reset splice point in
* TclNRCoroutineActivateCallback if the
* coroutine is busy. */
} CoroutineData;
typedef struct ExecEnv {
ExecStack *execStackPtr; /* Points to the first item in the evaluation
* stack on the heap. */
Tcl_Obj *constants[2]; /* Pointers to constant "0" and "1" objs. */
struct Tcl_Interp *interp; /* Owning interpreter. */
struct NRE_callback *callbackPtr;
/* Top callback in NRE's stack. */
struct CoroutineData *corPtr;
/* Current coroutine. */
int rewind; /* Set when exception trapping is disabled
* because a context is being deleted (e.g.,
* the current coroutine has been deleted). */
} ExecEnv;
#define COR_IS_SUSPENDED(corPtr) \
((corPtr)->stackLevel == NULL)
/*
* The definitions for the LiteralTable and LiteralEntry structures. Each
|
| ︙ | ︙ | |||
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 |
* of hidden commands on a per-interp
* basis. */
void *interpInfo; /* Information used by tclInterp.c to keep
* track of parent/child interps on a
* per-interp basis. */
#if TCL_MAJOR_VERSION > 8
void (*optimizer)(void *envPtr);
#else
union {
void (*optimizer)(void *envPtr);
Tcl_HashTable unused2; /* No longer used (was mathFuncTable). The
* unused space in interp was repurposed for
* pluggable bytecode optimizers. The core
* contains one optimizer, which can be
| > > | 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 |
* of hidden commands on a per-interp
* basis. */
void *interpInfo; /* Information used by tclInterp.c to keep
* track of parent/child interps on a
* per-interp basis. */
#if TCL_MAJOR_VERSION > 8
void (*optimizer)(void *envPtr);
/* Reference to the bytecode optimizer, if one
* is set. */
#else
union {
void (*optimizer)(void *envPtr);
Tcl_HashTable unused2; /* No longer used (was mathFuncTable). The
* unused space in interp was repurposed for
* pluggable bytecode optimizers. The core
* contains one optimizer, which can be
|
| ︙ | ︙ | |||
2254 2255 2256 2257 2258 2259 2260 |
* Note that these are the same for all interps in the same thread. They
* just have to be initialised for the thread's parent interp, children
* inherit the value.
*
* They are used by the macros defined below.
*/
| | | 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 |
* Note that these are the same for all interps in the same thread. They
* just have to be initialised for the thread's parent interp, children
* inherit the value.
*
* They are used by the macros defined below.
*/
AllocCache *allocCache; /* Allocator cache for stack frames. */
void *pendingObjDataPtr; /* Pointer to the Cache and PendingObjData
* structs for this interp's thread; see
* tclObj.c and tclThreadAlloc.c */
int *asyncReadyPtr; /* Pointer to the asyncReady indicator for
* this interp's thread; see tclAsync.c */
/*
* The pointer to the object system root ekeko. c.f. TIP #257.
|
| ︙ | ︙ | |||
2289 2290 2291 2292 2293 2294 2295 |
Tcl_Obj *asyncCancelMsg; /* Error message set by async cancel handler
* for the propagation of arbitrary Tcl
* errors. This information, if present
* (asyncCancelMsg not NULL), takes precedence
* over the default error messages returned by
* a script cancellation operation. */
| | | | | 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 |
Tcl_Obj *asyncCancelMsg; /* Error message set by async cancel handler
* for the propagation of arbitrary Tcl
* errors. This information, if present
* (asyncCancelMsg not NULL), takes precedence
* over the default error messages returned by
* a script cancellation operation. */
/*
* TIP #348 IMPLEMENTATION - Substituted error stack
*/
Tcl_Obj *errorStack; /* [info errorstack] value (as a Tcl_Obj). */
Tcl_Obj *upLiteral; /* "UP" literal for [info errorstack] */
Tcl_Obj *callLiteral; /* "CALL" literal for [info errorstack] */
Tcl_Obj *innerLiteral; /* "INNER" literal for [info errorstack] */
Tcl_Obj *innerContext; /* cached list for fast reallocation */
int resetErrorStack; /* controls cleaning up of ::errorStack */
|
| ︙ | ︙ | |||
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 3106 3107 3108 3109 3110 |
* 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)
{
| > > > > > > > > | 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 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 |
* 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)
{
|
| ︙ | ︙ | |||
3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 | MODULE_SCOPE int TclChannelGetBlockingMode(Tcl_Channel chan); MODULE_SCOPE int TclCheckArrayTraces(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *name, int index); MODULE_SCOPE int TclCheckEmptyString(Tcl_Obj *objPtr); MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp, Tcl_Channel chan); MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd; MODULE_SCOPE Tcl_NRPostProc TclClearRootEnsemble; MODULE_SCOPE int TclCompareTwoNumbers(Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, Tcl_Size num, Tcl_Size *loc); MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr, Tcl_Size start, Tcl_Size *clNext); | > | 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 | MODULE_SCOPE int TclChannelGetBlockingMode(Tcl_Channel chan); MODULE_SCOPE int TclCheckArrayTraces(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *name, int index); MODULE_SCOPE int TclCheckEmptyString(Tcl_Obj *objPtr); MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp, Tcl_Channel chan); MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd; MODULE_SCOPE int TclChanIsBinary(Tcl_Channel chan); MODULE_SCOPE Tcl_NRPostProc TclClearRootEnsemble; MODULE_SCOPE int TclCompareTwoNumbers(Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, Tcl_Size num, Tcl_Size *loc); MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr, Tcl_Size start, Tcl_Size *clNext); |
| ︙ | ︙ | |||
3759 3760 3761 3762 3763 3764 3765 | # define TCL_WIDE_CLICKS 1 MODULE_SCOPE long long TclpGetWideClicks(void); MODULE_SCOPE double TclpWideClickInMicrosec(void); # define TclpWideClicksToNanoseconds(clicks) \ ((double)(clicks) * TclpWideClickInMicrosec() * 1000) # endif #endif | | | 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 | # define TCL_WIDE_CLICKS 1 MODULE_SCOPE long long TclpGetWideClicks(void); MODULE_SCOPE double TclpWideClickInMicrosec(void); # define TclpWideClicksToNanoseconds(clicks) \ ((double)(clicks) * TclpWideClickInMicrosec() * 1000) # endif #endif MODULE_SCOPE long long TclpGetMicroseconds(void); MODULE_SCOPE int TclZlibInit(Tcl_Interp *interp); MODULE_SCOPE void * TclpThreadCreateKey(void); MODULE_SCOPE void TclpThreadDeleteKey(void *keyPtr); MODULE_SCOPE void TclpThreadSetGlobalTSD(void *tsdKeyPtr, void *ptr); MODULE_SCOPE void * TclpThreadGetGlobalTSD(void *tsdKeyPtr); MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp, |
| ︙ | ︙ | |||
3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 | MODULE_SCOPE int TclDictWithFinish(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int index, int pathc, Tcl_Obj *const pathv[], Tcl_Obj *keysPtr); MODULE_SCOPE Tcl_Obj * TclDictWithInit(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size pathc, Tcl_Obj *const pathv[]); MODULE_SCOPE Tcl_ObjCmdProc Tcl_DisassembleObjCmd; /* Assemble command function */ MODULE_SCOPE Tcl_ObjCmdProc Tcl_AssembleObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRAssembleObjCmd; MODULE_SCOPE Tcl_Command TclInitEncodingCmd(Tcl_Interp *interp); MODULE_SCOPE Tcl_ObjCmdProc Tcl_EofObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_ErrorObjCmd; | > | 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 | MODULE_SCOPE int TclDictWithFinish(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int index, int pathc, Tcl_Obj *const pathv[], Tcl_Obj *keysPtr); MODULE_SCOPE Tcl_Obj * TclDictWithInit(Tcl_Interp *interp, Tcl_Obj *dictPtr, Tcl_Size pathc, Tcl_Obj *const pathv[]); MODULE_SCOPE Tcl_ObjCmdProc Tcl_DisassembleObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclLoadIcuObjCmd; /* Assemble command function */ MODULE_SCOPE Tcl_ObjCmdProc Tcl_AssembleObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRAssembleObjCmd; MODULE_SCOPE Tcl_Command TclInitEncodingCmd(Tcl_Interp *interp); MODULE_SCOPE Tcl_ObjCmdProc Tcl_EofObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_ErrorObjCmd; |
| ︙ | ︙ |
Changes to generic/tclInterp.c.
| ︙ | ︙ | |||
1060 1061 1062 1063 1064 1065 1066 |
}
case OPT_TRANSFER:
case OPT_SHARE: {
Tcl_Interp *parentInterp; /* The parent of the child. */
Tcl_Channel chan;
if (objc != 5) {
| | | 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 |
}
case OPT_TRANSFER:
case OPT_SHARE: {
Tcl_Interp *parentInterp; /* The parent of the child. */
Tcl_Channel chan;
if (objc != 5) {
Tcl_WrongNumArgs(interp, 2, objv, "srcPath channel destPath");
return TCL_ERROR;
}
parentInterp = GetInterp(interp, objv[2]);
if (parentInterp == NULL) {
return TCL_ERROR;
}
chan = Tcl_GetChannel(parentInterp, TclGetString(objv[3]), NULL);
|
| ︙ | ︙ |
Changes to generic/tclLink.c.
| ︙ | ︙ | |||
111 112 113 114 115 116 117 |
static const Tcl_ObjType invalidRealType = {
"invalidReal", /* name */
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
NULL, /* updateStringProc */
NULL, /* setFromAnyProc */
| | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
static const Tcl_ObjType invalidRealType = {
"invalidReal", /* name */
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
NULL, /* updateStringProc */
NULL, /* setFromAnyProc */
TCL_OBJTYPE_V1(TclLengthOne)
};
/*
* Convenience macro for accessing the value of the C variable pointed to by a
* link. Note that this macro produces something that may be regarded as an
* lvalue or rvalue; it may be assigned to as well as read. Also note that
* this macro assumes the name of the variable being accessed (linkPtr); this
|
| ︙ | ︙ |
Changes to generic/tclListObj.c.
| ︙ | ︙ | |||
2960 2961 2962 2963 2964 2965 2966 | /* ...the index we're trying to use isn't an index at all. */ result = TCL_ERROR; indexArray++; /* Why bother with this increment? TBD */ break; } indexArray++; | | | | | | | 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 |
/* ...the index we're trying to use isn't an index at all. */
result = TCL_ERROR;
indexArray++; /* Why bother with this increment? TBD */
break;
}
indexArray++;
/*
* Special case 0-length lists. The Tcl indexing function treat
* will return any value beyond length as TCL_SIZE_MAX for this
* case.
*/
if ((index == TCL_SIZE_MAX) && (elemCount == 0)) {
index = 0;
}
if (index < 0 || index > elemCount
|| (valueObj == NULL && index >= elemCount)) {
/* ...the index points outside the sublist. */
if (interp != NULL) {
|
| ︙ | ︙ |
Changes to generic/tclLoad.c.
| ︙ | ︙ | |||
856 857 858 859 860 861 862 |
goto done;
}
/*
* Remove this library from the interpreter's library cache.
*/
| > | > | | | | | | | | | | | | | | | > > | 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 |
goto done;
}
/*
* Remove this library from the interpreter's library cache.
*/
if (!interpExiting) {
ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
if (ipFirstPtr) {
ipPtr = ipFirstPtr;
if (ipPtr->libraryPtr == libraryPtr) {
ipFirstPtr = ipFirstPtr->nextPtr;
} else {
InterpLibrary *ipPrevPtr;
for (ipPrevPtr = ipPtr; ipPtr != NULL;
ipPrevPtr = ipPtr, ipPtr = ipPtr->nextPtr) {
if (ipPtr->libraryPtr == libraryPtr) {
ipPrevPtr->nextPtr = ipPtr->nextPtr;
break;
}
}
}
Tcl_Free(ipPtr);
Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr);
}
}
if (IsStatic(libraryPtr)) {
goto done;
}
/*
* The unload function was called succesfully.
|
| ︙ | ︙ | |||
1181 1182 1183 1184 1185 1186 1187 | * Storage for all of the InterpLibrary functions for interp get deleted. * *---------------------------------------------------------------------- */ static void LoadCleanupProc( | | | | < < < < | > > > > > | 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 |
* Storage for all of the InterpLibrary functions for interp get deleted.
*
*----------------------------------------------------------------------
*/
static void
LoadCleanupProc(
void *clientData, /* Pointer to first InterpLibrary structure
* for interp. */
Tcl_Interp *interp)
{
InterpLibrary *ipPtr = (InterpLibrary *)clientData, *nextPtr;
LoadedLibrary *libraryPtr;
while (ipPtr) {
libraryPtr = ipPtr->libraryPtr;
UnloadLibrary(interp, interp, libraryPtr, 0, "", 1);
/* UnloadLibrary doesn't free it by interp delete, so do it here and
* repeat for next. */
nextPtr = ipPtr->nextPtr;
Tcl_Free(ipPtr);
ipPtr = nextPtr;
}
}
/*
*----------------------------------------------------------------------
*
* TclFinalizeLoad --
|
| ︙ | ︙ |
Changes to generic/tclOO.c.
| ︙ | ︙ | |||
747 748 749 750 751 752 753 |
tracePtr->nextPtr = NULL;
tracePtr->refCount = 1;
oPtr->myCommand = TclNRCreateCommandInNs(interp, "my", oPtr->namespacePtr,
TclOOPrivateObjectCmd, PrivateNRObjectCmd, oPtr, MyDeleted);
oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
| | | 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 |
tracePtr->nextPtr = NULL;
tracePtr->refCount = 1;
oPtr->myCommand = TclNRCreateCommandInNs(interp, "my", oPtr->namespacePtr,
TclOOPrivateObjectCmd, PrivateNRObjectCmd, oPtr, MyDeleted);
oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
MyClassDeleted);
return oPtr;
}
/*
* ----------------------------------------------------------------------
*
* SquelchCachedName --
|
| ︙ | ︙ |
Changes to generic/tclOOBasic.c.
| ︙ | ︙ | |||
440 441 442 443 444 445 446 |
/*
* Make the object's namespace the current namespace and evaluate the
* command(s).
*/
(void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
| | > | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 |
/*
* Make the object's namespace the current namespace and evaluate the
* command(s).
*/
(void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
Tcl_GetObjectNamespace(object), FRAME_IS_METHOD);
framePtr->clientData = context;
framePtr->objc = objc;
framePtr->objv = objv; /* Reference counts do not need to be
* incremented here. */
if (!(contextPtr->callPtr->flags & PUBLIC_METHOD)) {
object = NULL; /* Now just for error mesage printing. */
}
|
| ︙ | ︙ | |||
825 826 827 828 829 830 831 832 833 834 835 836 837 838 |
TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to", 1, 1, &aryVar);
Tcl_DecrRefCount(varNamePtr);
if (varPtr == NULL) {
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, (char *)NULL);
return TCL_ERROR;
}
/*
* Now that we've pinned down what variable we're really talking about
* (including traversing variable links), convert back to a name.
*/
TclNewObj(varNamePtr);
if (aryVar != NULL) {
| > > > > > | 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 |
TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to", 1, 1, &aryVar);
Tcl_DecrRefCount(varNamePtr);
if (varPtr == NULL) {
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, (char *)NULL);
return TCL_ERROR;
}
/*
* The variable reference must not disappear too soon. [Bug 74b6110204]
*/
TclSetVarNamespaceVar(varPtr);
/*
* Now that we've pinned down what variable we're really talking about
* (including traversing variable links), convert back to a name.
*/
TclNewObj(varNamePtr);
if (aryVar != NULL) {
|
| ︙ | ︙ |
Changes to generic/tclOOInt.h.
| ︙ | ︙ | |||
525 526 527 528 529 530 531 | MODULE_SCOPE void TclOOAddToInstances(Object *oPtr, Class *clsPtr); MODULE_SCOPE void TclOOAddToMixinSubs(Class *subPtr, Class *mixinPtr); MODULE_SCOPE void TclOOAddToSubclasses(Class *subPtr, Class *superPtr); MODULE_SCOPE Class * TclOOAllocClass(Tcl_Interp *interp, Object *useThisObj); MODULE_SCOPE int TclMethodIsType(Tcl_Method method, | | | | | | | | | | 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | MODULE_SCOPE void TclOOAddToInstances(Object *oPtr, Class *clsPtr); MODULE_SCOPE void TclOOAddToMixinSubs(Class *subPtr, Class *mixinPtr); MODULE_SCOPE void TclOOAddToSubclasses(Class *subPtr, Class *superPtr); MODULE_SCOPE Class * TclOOAllocClass(Tcl_Interp *interp, Object *useThisObj); MODULE_SCOPE int TclMethodIsType(Tcl_Method method, const Tcl_MethodType *typePtr, void **clientDataPtr); MODULE_SCOPE Tcl_Method TclNewInstanceMethod(Tcl_Interp *interp, Tcl_Object object, Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, void *clientData); MODULE_SCOPE Tcl_Method TclNewMethod(Tcl_Interp *interp, Tcl_Class cls, Tcl_Obj *nameObj, int flags, const Tcl_MethodType *typePtr, void *clientData); MODULE_SCOPE int TclNRNewObjectInstance(Tcl_Interp *interp, Tcl_Class cls, const char *nameStr, const char *nsNameStr, Tcl_Size objc, Tcl_Obj *const *objv, Tcl_Size skip, Tcl_Object *objectPtr); MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp, Class *classPtr, |
| ︙ | ︙ |
Changes to generic/tclObj.c.
| ︙ | ︙ | |||
74 75 76 77 78 79 80 |
*
* Notice that different structures with the same name appear in other files.
* The structure defined below is used in this file only.
*/
typedef struct {
Tcl_HashTable *lineCLPtr; /* This table remembers for each Tcl_Obj
| | | | | | | | | | | | | | 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 |
*
* Notice that different structures with the same name appear in other files.
* The structure defined below is used in this file only.
*/
typedef struct {
Tcl_HashTable *lineCLPtr; /* This table remembers for each Tcl_Obj
* generated by a call to the function
* TclSubstTokens() from a literal text
* where bs+nl sequences occurred in it, if
* any. I.e. this table keeps track of
* invisible and stripped continuation lines.
* Its keys are Tcl_Obj pointers, the values
* are ContLineLoc pointers. See the file
* tclCompile.h for the definition of this
* structure, and for references to all
* related places in the core. */
#if TCL_THREADS && defined(TCL_MEM_DEBUG)
Tcl_HashTable *objThreadMap;/* Thread local table that is used to check
* that a Tcl_Obj was not allocated by some
* other thread. */
#endif /* TCL_MEM_DEBUG && TCL_THREADS */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
static void TclThreadFinalizeContLines(void *clientData);
static ThreadSpecificData *TclGetContLineTable(void);
|
| ︙ | ︙ | |||
174 175 176 177 178 179 180 |
/*
* Macros to pack/unpack a bignum's fields in a Tcl_Obj internal rep
*/
#define PACK_BIGNUM(bignum, objPtr) \
if ((bignum).used > 0x7FFF) { \
| | | | | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
/*
* Macros to pack/unpack a bignum's fields in a Tcl_Obj internal rep
*/
#define PACK_BIGNUM(bignum, objPtr) \
if ((bignum).used > 0x7FFF) { \
mp_int *temp = (mp_int *)Tcl_Alloc(sizeof(mp_int)); \
*temp = bignum; \
(objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
} else if (((bignum).alloc <= 0x7FFF) || (mp_shrink(&(bignum))) == MP_OKAY) { \
(objPtr)->internalRep.twoPtrValue.ptr1 = (bignum).dp; \
(objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(((bignum).sign << 30) \
| ((bignum).alloc << 15) | ((bignum).used)); \
}
/*
* Prototypes for functions defined later in this file:
*/
static int ParseBoolean(Tcl_Obj *objPtr);
|
| ︙ | ︙ | |||
372 373 374 375 376 377 378 |
TclInitObjSubsystem(void)
{
Tcl_MutexLock(&tableMutex);
typeTableInitialized = 1;
Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
Tcl_MutexUnlock(&tableMutex);
| | | | | | | | | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 |
TclInitObjSubsystem(void)
{
Tcl_MutexLock(&tableMutex);
typeTableInitialized = 1;
Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
Tcl_MutexUnlock(&tableMutex);
Tcl_RegisterObjType(&tclByteCodeType);
Tcl_RegisterObjType(&tclCmdNameType);
Tcl_RegisterObjType(&tclDictType);
Tcl_RegisterObjType(&tclDoubleType);
Tcl_RegisterObjType(&tclListType);
Tcl_RegisterObjType(&tclProcBodyType);
Tcl_RegisterObjType(&tclRegexpType);
Tcl_RegisterObjType(&tclStringType);
#ifdef TCL_COMPILE_STATS
Tcl_MutexLock(&tclObjMutex);
tclObjsAlloced = 0;
tclObjsFreed = 0;
{
int i;
|
| ︙ | ︙ | |||
699 700 701 702 703 704 705 |
void
TclContinuationsCopy(
Tcl_Obj *objPtr,
Tcl_Obj *originObjPtr)
{
ThreadSpecificData *tsdPtr = TclGetContLineTable();
Tcl_HashEntry *hPtr =
| | | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 |
void
TclContinuationsCopy(
Tcl_Obj *objPtr,
Tcl_Obj *originObjPtr)
{
ThreadSpecificData *tsdPtr = TclGetContLineTable();
Tcl_HashEntry *hPtr =
Tcl_FindHashEntry(tsdPtr->lineCLPtr, originObjPtr);
if (hPtr) {
ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_GetHashValue(hPtr);
TclContinuationsEnter(objPtr, clLocPtr->num, clLocPtr->loc);
}
}
|
| ︙ | ︙ | |||
733 734 735 736 737 738 739 |
ContLineLoc *
TclContinuationsGet(
Tcl_Obj *objPtr)
{
ThreadSpecificData *tsdPtr = TclGetContLineTable();
Tcl_HashEntry *hPtr =
| | | | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 |
ContLineLoc *
TclContinuationsGet(
Tcl_Obj *objPtr)
{
ThreadSpecificData *tsdPtr = TclGetContLineTable();
Tcl_HashEntry *hPtr =
Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
if (!hPtr) {
return NULL;
}
return (ContLineLoc *)Tcl_GetHashValue(hPtr);
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
1375 1376 1377 1378 1379 1380 1381 |
* already killed the thread-global data structures. Performing
* TCL_TSD_INIT will leave us with an uninitialized memory block upon
* which we crash (if we where to access the uninitialized hashtable).
*/
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
| | | | 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 |
* already killed the thread-global data structures. Performing
* TCL_TSD_INIT will leave us with an uninitialized memory block upon
* which we crash (if we where to access the uninitialized hashtable).
*/
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
Tcl_HashEntry *hPtr;
if (tsdPtr->lineCLPtr) {
hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
if (hPtr) {
Tcl_Free(Tcl_GetHashValue(hPtr));
Tcl_DeleteHashEntry(hPtr);
}
}
}
}
|
| ︙ | ︙ | |||
1466 1467 1468 1469 1470 1471 1472 |
* already killed the thread-global data structures. Performing
* TCL_TSD_INIT will leave us with an uninitialized memory block upon
* which we crash (if we where to access the uninitialized hashtable).
*/
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
| | | | 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 |
* already killed the thread-global data structures. Performing
* TCL_TSD_INIT will leave us with an uninitialized memory block upon
* which we crash (if we where to access the uninitialized hashtable).
*/
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
Tcl_HashEntry *hPtr;
if (tsdPtr->lineCLPtr) {
hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
if (hPtr) {
Tcl_Free(Tcl_GetHashValue(hPtr));
Tcl_DeleteHashEntry(hPtr);
}
}
}
}
|
| ︙ | ︙ | |||
2423 2424 2425 2426 2427 2428 2429 |
{
do {
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (isnan(objPtr->internalRep.doubleValue)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"floating point value is Not a Number", -1));
| | | | 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 |
{
do {
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (isnan(objPtr->internalRep.doubleValue)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"floating point value is Not a Number", -1));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DOUBLE", "NAN",
(char *)NULL);
}
return TCL_ERROR;
}
*dblPtr = (double) objPtr->internalRep.doubleValue;
return TCL_OK;
}
if (TclHasInternalRep(objPtr, &tclIntType)) {
|
| ︙ | ︙ | |||
2674 2675 2676 2677 2678 2679 2680 |
return TCL_OK;
}
goto tooLarge;
}
#endif
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (interp != NULL) {
| | | | | 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 |
return TCL_OK;
}
goto tooLarge;
}
#endif
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
TclGetString(objPtr)));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
}
return TCL_ERROR;
}
if (TclHasInternalRep(objPtr, &tclBignumType)) {
/*
* Must check for those bignum values that can fit in a long, even
|
| ︙ | ︙ | |||
2982 2983 2984 2985 2986 2987 2988 |
do {
if (TclHasInternalRep(objPtr, &tclIntType)) {
*wideIntPtr = objPtr->internalRep.wideValue;
return TCL_OK;
}
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (interp != NULL) {
| | | | | 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 |
do {
if (TclHasInternalRep(objPtr, &tclIntType)) {
*wideIntPtr = objPtr->internalRep.wideValue;
return TCL_OK;
}
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
TclGetString(objPtr)));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
}
return TCL_ERROR;
}
if (TclHasInternalRep(objPtr, &tclBignumType)) {
/*
* Must check for those bignum values that can fit in a
|
| ︙ | ︙ | |||
3151 3152 3153 3154 3155 3156 3157 |
do {
if (TclHasInternalRep(objPtr, &tclIntType)) {
*wideIntPtr = objPtr->internalRep.wideValue;
return TCL_OK;
}
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (interp != NULL) {
| | | | | 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 |
do {
if (TclHasInternalRep(objPtr, &tclIntType)) {
*wideIntPtr = objPtr->internalRep.wideValue;
return TCL_OK;
}
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
TclGetString(objPtr)));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
}
return TCL_ERROR;
}
if (TclHasInternalRep(objPtr, &tclBignumType)) {
mp_int big;
mp_err err;
|
| ︙ | ︙ | |||
3475 3476 3477 3478 3479 3480 3481 |
objPtr->internalRep.wideValue) != MP_OKAY) {
return TCL_ERROR;
}
return TCL_OK;
}
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (interp != NULL) {
| | | | | 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 |
objPtr->internalRep.wideValue) != MP_OKAY) {
return TCL_ERROR;
}
return TCL_OK;
}
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected integer but got \"%s\"",
TclGetString(objPtr)));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (char *)NULL);
}
return TCL_ERROR;
}
} while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
TCL_PARSE_INTEGER_ONLY)==TCL_OK);
return TCL_ERROR;
|
| ︙ | ︙ | |||
3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 |
int
Tcl_GetNumberFromObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
void **clientDataPtr,
int *typePtr)
{
do {
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (isnan(objPtr->internalRep.doubleValue)) {
*typePtr = TCL_NUMBER_NAN;
} else {
*typePtr = TCL_NUMBER_DOUBLE;
}
| > | 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 |
int
Tcl_GetNumberFromObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
void **clientDataPtr,
int *typePtr)
{
Tcl_Size length;
do {
if (TclHasInternalRep(objPtr, &tclDoubleType)) {
if (isnan(objPtr->internalRep.doubleValue)) {
*typePtr = TCL_NUMBER_NAN;
} else {
*typePtr = TCL_NUMBER_DOUBLE;
}
|
| ︙ | ︙ | |||
3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 |
mp_int *bigPtr = (mp_int *)Tcl_GetThreadData(&bignumKey,
sizeof(mp_int));
TclUnpackBignum(objPtr, *bigPtr);
*typePtr = TCL_NUMBER_BIG;
*clientDataPtr = bigPtr;
return TCL_OK;
}
} while (TCL_OK ==
TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0));
return TCL_ERROR;
}
int
Tcl_GetNumber(
Tcl_Interp *interp,
const char *bytes,
| > > > > > > > > > > > > > > > > > > > > > | 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 |
mp_int *bigPtr = (mp_int *)Tcl_GetThreadData(&bignumKey,
sizeof(mp_int));
TclUnpackBignum(objPtr, *bigPtr);
*typePtr = TCL_NUMBER_BIG;
*clientDataPtr = bigPtr;
return TCL_OK;
}
/* Handle dict separately, because it doesn't have a lengthProc */
if (TclHasInternalRep(objPtr, &tclDictType)) {
Tcl_DictObjSize(NULL, objPtr, &length);
if (length > 1) {
listRep:
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("expected number but got a list", -1));
}
return TCL_ERROR;
}
}
Tcl_ObjTypeLengthProc *lengthProc = TclObjTypeHasProc(objPtr, lengthProc);
if (lengthProc && lengthProc(objPtr) != 1) {
goto listRep;
}
} while (TCL_OK ==
TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0));
/* Don't try to convert index or boolean's to a list */
if (!TclHasInternalRep(objPtr, &tclIndexType)
&& !TclHasInternalRep(objPtr, &tclBooleanType)
&& (TCL_OK == Tcl_ListObjLength(NULL, objPtr, &length)) && (length > 1)) {
goto listRep;
}
return TCL_ERROR;
}
int
Tcl_GetNumber(
Tcl_Interp *interp,
const char *bytes,
|
| ︙ | ︙ | |||
3883 3884 3885 3886 3887 3888 3889 |
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
if (!hPtr) {
Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
| | | 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 |
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
if (!hPtr) {
Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
"incr ref count");
}
}
# endif /* TCL_THREADS */
++(objPtr)->refCount;
}
#else /* !TCL_MEM_DEBUG */
void
|
| ︙ | ︙ | |||
3956 3957 3958 3959 3960 3961 3962 |
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
if (!hPtr) {
Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
| | | 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 |
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
if (!hPtr) {
Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
"decr ref count");
}
}
# endif /* TCL_THREADS */
if (objPtr->refCount-- <= 1) {
TclFreeObj(objPtr);
}
|
| ︙ | ︙ | |||
4038 4039 4040 4041 4042 4043 4044 |
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
if (!hPtr) {
Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
| | | 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 |
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
if (!hPtr) {
Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
"check shared status");
}
}
# endif /* TCL_THREADS */
#endif /* TCL_MEM_DEBUG */
#ifdef TCL_COMPILE_STATS
Tcl_MutexLock(&tclObjMutex);
|
| ︙ | ︙ | |||
4150 4151 4152 4153 4154 4155 4156 |
size_t l1, l2;
/*
* If the object pointers are the same then they match.
* OPT: this comparison was moved to the caller
if (objPtr1 == objPtr2) {
| | | 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 |
size_t l1, l2;
/*
* If the object pointers are the same then they match.
* OPT: this comparison was moved to the caller
if (objPtr1 == objPtr2) {
return 1;
}
*/
/*
* Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
* in a register.
*/
|
| ︙ | ︙ | |||
4331 4332 4333 4334 4335 4336 4337 |
*
* If any check fails, then force another conversion to the command type,
* to discard the old rep and create a new one.
*/
resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
if (TclHasInternalRep(objPtr, &tclCmdNameType)) {
| | | | | | | | | | | | | | | 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 |
*
* If any check fails, then force another conversion to the command type,
* to discard the old rep and create a new one.
*/
resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
if (TclHasInternalRep(objPtr, &tclCmdNameType)) {
Command *cmdPtr = resPtr->cmdPtr;
if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch)
&& (interp == cmdPtr->nsPtr->interp)
&& !(cmdPtr->nsPtr->flags & NS_DYING)) {
Namespace *refNsPtr = (Namespace *)
TclGetCurrentNamespace(interp);
if ((resPtr->refNsPtr == NULL)
|| ((refNsPtr == resPtr->refNsPtr)
&& (resPtr->refNsId == refNsPtr->nsId)
&& (resPtr->refNsCmdEpoch == refNsPtr->cmdRefEpoch))) {
return (Tcl_Command) cmdPtr;
}
}
}
/*
* OK, must create a new internal representation (or fail) as any cache we
* had is invalid one way or another.
*/
/* See [07d13d99b0a9] why we cannot call SetCmdNameFromAny() directly here. */
if (tclCmdNameType.setFromAnyProc(interp, objPtr) != TCL_OK) {
return NULL;
}
resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
return (Tcl_Command) (resPtr ? resPtr->cmdPtr : NULL);
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
4664 4665 4666 4667 4668 4669 4670 |
Tcl_AppendPrintfToObj(descObj, ", internal representation %p:%p",
(void *) objv[1]->internalRep.twoPtrValue.ptr1,
(void *) objv[1]->internalRep.twoPtrValue.ptr2);
}
}
if (objv[1]->bytes) {
| | | | 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 |
Tcl_AppendPrintfToObj(descObj, ", internal representation %p:%p",
(void *) objv[1]->internalRep.twoPtrValue.ptr1,
(void *) objv[1]->internalRep.twoPtrValue.ptr2);
}
}
if (objv[1]->bytes) {
Tcl_AppendToObj(descObj, ", string representation \"", -1);
Tcl_AppendLimitedToObj(descObj, objv[1]->bytes, objv[1]->length,
16, "...");
Tcl_AppendToObj(descObj, "\"", -1);
} else {
Tcl_AppendToObj(descObj, ", no string representation", -1);
}
Tcl_SetObjResult(interp, descObj);
return TCL_OK;
|
| ︙ | ︙ |
Changes to generic/tclProc.c.
| ︙ | ︙ | |||
91 92 93 94 95 96 97 |
*
* Uses the default behaviour throughout, and never disposes of the string
* rep; it's just a cache type.
*/
static const Tcl_ObjType levelReferenceType = {
"levelReference",
| > > > > | | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
*
* Uses the default behaviour throughout, and never disposes of the string
* rep; it's just a cache type.
*/
static const Tcl_ObjType levelReferenceType = {
"levelReference",
NULL,
NULL,
NULL,
NULL,
TCL_OBJTYPE_V1(TclLengthOne)
};
/*
* The type of lambdas. Note that every lambda will *always* have a string
* representation.
*
* Internally, ptr1 is a pointer to a Proc instance that is not bound to a
|
| ︙ | ︙ |
Changes to generic/tclResult.c.
| ︙ | ︙ | |||
712 713 714 715 716 717 718 |
if (code == TCL_ERROR) {
if (iPtr->errorInfo) {
Tcl_DecrRefCount(iPtr->errorInfo);
iPtr->errorInfo = NULL;
}
Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO],
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 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 |
if (code == TCL_ERROR) {
if (iPtr->errorInfo) {
Tcl_DecrRefCount(iPtr->errorInfo);
iPtr->errorInfo = NULL;
}
Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO],
&valuePtr);
if (valuePtr != NULL) {
Tcl_Size length;
(void)TclGetStringFromObj(valuePtr, &length);
if (length) {
iPtr->errorInfo = valuePtr;
Tcl_IncrRefCount(iPtr->errorInfo);
iPtr->flags |= ERR_ALREADY_LOGGED;
}
}
Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORSTACK],
&valuePtr);
if (valuePtr != NULL) {
Tcl_Size len, valueObjc;
Tcl_Obj **valueObjv;
if (Tcl_IsShared(iPtr->errorStack)) {
Tcl_Obj *newObj;
newObj = Tcl_DuplicateObj(iPtr->errorStack);
Tcl_DecrRefCount(iPtr->errorStack);
Tcl_IncrRefCount(newObj);
iPtr->errorStack = newObj;
}
/*
* List extraction done after duplication to avoid moving the rug
* if someone does [return -errorstack [info errorstack]]
*/
if (TclListObjGetElements(interp, valuePtr, &valueObjc,
&valueObjv) == TCL_ERROR) {
return TCL_ERROR;
}
iPtr->resetErrorStack = 0;
TclListObjLength(interp, iPtr->errorStack, &len);
/*
* Reset while keeping the list internalrep as much as possible.
*/
Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, valueObjc,
valueObjv);
}
Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE],
&valuePtr);
if (valuePtr != NULL) {
Tcl_SetObjErrorCode(interp, valuePtr);
} else {
Tcl_SetErrorCode(interp, "NONE", (void *)NULL);
}
Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE],
&valuePtr);
if (valuePtr != NULL) {
TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine);
}
}
if (level != 0) {
iPtr->returnLevel = level;
iPtr->returnCode = code;
|
| ︙ | ︙ | |||
839 840 841 842 843 844 845 |
if (TCL_ERROR == Tcl_DictObjFirst(NULL, dict, &search,
&keyPtr, &valuePtr, &done)) {
/*
* Value is not a legal dictionary.
*/
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
| | | | 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 |
if (TCL_ERROR == Tcl_DictObjFirst(NULL, dict, &search,
&keyPtr, &valuePtr, &done)) {
/*
* Value is not a legal dictionary.
*/
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad %s value: expected dictionary but got \"%s\"",
compare, TclGetString(objv[1])));
Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS",
(void *)NULL);
goto error;
}
while (!done) {
Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr);
|
| ︙ | ︙ | |||
870 871 872 873 874 875 876 |
/*
* Check for bogus -code value.
*/
Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr);
if (valuePtr != NULL) {
if (TclGetCompletionCodeFromObj(interp, valuePtr,
| | | | | | | | | | | | | | | | | 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 956 957 958 959 960 961 962 963 964 |
/*
* Check for bogus -code value.
*/
Tcl_DictObjGet(NULL, returnOpts, keys[KEY_CODE], &valuePtr);
if (valuePtr != NULL) {
if (TclGetCompletionCodeFromObj(interp, valuePtr,
&code) == TCL_ERROR) {
goto error;
}
Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_CODE]);
}
/*
* Check for bogus -level value.
*/
Tcl_DictObjGet(NULL, returnOpts, keys[KEY_LEVEL], &valuePtr);
if (valuePtr != NULL) {
if ((TCL_ERROR == TclGetIntFromObj(NULL, valuePtr, &level))
|| (level < 0)) {
/*
* Value is not a legal level.
*/
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad -level value: expected non-negative integer but got"
" \"%s\"", TclGetString(valuePtr)));
Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_LEVEL", (void *)NULL);
goto error;
}
Tcl_DictObjRemove(NULL, returnOpts, keys[KEY_LEVEL]);
}
/*
* Check for bogus -errorcode value.
*/
Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORCODE], &valuePtr);
if (valuePtr != NULL) {
Tcl_Size length;
if (TCL_ERROR == TclListObjLength(NULL, valuePtr, &length )) {
/*
* Value is not a list, which is illegal for -errorcode.
*/
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad -errorcode value: expected a list but got \"%s\"",
TclGetString(valuePtr)));
Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_ERRORCODE",
(void *)NULL);
goto error;
}
}
/*
* Check for bogus -errorstack value.
*/
Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORSTACK], &valuePtr);
if (valuePtr != NULL) {
Tcl_Size length;
if (TCL_ERROR == TclListObjLength(NULL, valuePtr, &length)) {
/*
* Value is not a list, which is illegal for -errorstack.
*/
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad -errorstack value: expected a list but got \"%s\"",
TclGetString(valuePtr)));
Tcl_SetErrorCode(interp, "TCL", "RESULT", "NONLIST_ERRORSTACK",
(void *)NULL);
goto error;
}
if (length % 2) {
/*
* Errorstack must always be an even-sized list
*/
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"forbidden odd-sized list for -errorstack: \"%s\"",
TclGetString(valuePtr)));
Tcl_SetErrorCode(interp, "TCL", "RESULT",
"ODDSIZEDLIST_ERRORSTACK", (void *)NULL);
goto error;
}
}
/*
* Convert [return -code return -level X] to [return -code ok -level X+1]
*/
if (code == TCL_RETURN) {
|
| ︙ | ︙ | |||
1030 1031 1032 1033 1034 1035 1036 |
Tcl_NewWideIntObj(result));
Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
Tcl_NewWideIntObj(0));
}
if (result == TCL_ERROR) {
Tcl_AddErrorInfo(interp, "");
| | | 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 |
Tcl_NewWideIntObj(result));
Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL],
Tcl_NewWideIntObj(0));
}
if (result == TCL_ERROR) {
Tcl_AddErrorInfo(interp, "");
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack);
}
if (iPtr->errorCode) {
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode);
}
if (iPtr->errorInfo) {
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo);
Tcl_DictObjPut(NULL, options, keys[KEY_ERRORLINE],
|
| ︙ | ︙ | |||
1101 1102 1103 1104 1105 1106 1107 |
int level, code;
Tcl_Obj **objv, *mergedOpts;
Tcl_IncrRefCount(options);
if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv)
|| (objc % 2)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
| | | 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 |
int level, code;
Tcl_Obj **objv, *mergedOpts;
Tcl_IncrRefCount(options);
if (TCL_ERROR == TclListObjGetElements(interp, options, &objc, &objv)
|| (objc % 2)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected dict but got \"%s\"", TclGetString(options)));
Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS", (void *)NULL);
code = TCL_ERROR;
} else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv,
&mergedOpts, &code, &level)) {
code = TCL_ERROR;
} else {
code = TclProcessReturn(interp, code, level, mergedOpts);
|
| ︙ | ︙ |
Changes to generic/tclScan.c.
| ︙ | ︙ | |||
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
}
/*
* Handle any size specifier.
*/
switch (ch) {
case 'l':
if (*format == 'l') {
flags |= SCAN_BIG;
format += 1;
format += TclUtfToUniChar(format, &ch);
break;
}
/* FALLTHRU */
| > > > > > > > > > > > | > | 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 |
}
/*
* Handle any size specifier.
*/
switch (ch) {
case 'z':
case 't':
if (sizeof(void *) > sizeof(int)) {
flags |= SCAN_LONGER;
}
format += TclUtfToUniChar(format, &ch);
break;
case 'L':
flags |= SCAN_BIG;
format += TclUtfToUniChar(format, &ch);
break;
case 'l':
if (*format == 'l') {
flags |= SCAN_BIG;
format += 1;
format += TclUtfToUniChar(format, &ch);
break;
}
/* FALLTHRU */
case 'j':
case 'q':
flags |= SCAN_LONGER;
/* FALLTHRU */
case 'h':
format += TclUtfToUniChar(format, &ch);
}
if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) {
|
| ︙ | ︙ | |||
588 589 590 591 592 593 594 |
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
const char *format;
int numVars, nconversions, totalVars = -1;
int objIndex, offset, i, result, code;
| | | 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 |
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
const char *format;
int numVars, nconversions, totalVars = -1;
int objIndex, offset, i, result, code;
int value;
const char *string, *end, *baseString;
char op = 0;
int underflow = 0;
Tcl_Size width;
Tcl_WideInt wideValue;
Tcl_UniChar ch = 0, sch = 0;
Tcl_Obj **objs = NULL, *objPtr = NULL;
|
| ︙ | ︙ | |||
981 982 983 984 985 986 987 |
"unsigned bignum scans are invalid", -1));
Tcl_SetErrorCode(interp, "TCL", "FORMAT",
"BADUNSIGNED", (char *)NULL);
return TCL_ERROR;
}
}
} else {
| | | | | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 |
"unsigned bignum scans are invalid", -1));
Tcl_SetErrorCode(interp, "TCL", "FORMAT",
"BADUNSIGNED", (char *)NULL);
return TCL_ERROR;
}
}
} else {
if (TclGetIntFromObj(NULL, objPtr, &value) != TCL_OK) {
if (TclGetString(objPtr)[0] == '-') {
value = INT_MIN;
} else {
value = INT_MAX;
}
}
if ((flags & SCAN_UNSIGNED) && (value < 0)) {
#ifdef TCL_WIDE_INT_IS_LONG
mp_int big;
if (mp_init_u64(&big, (unsigned long)value) != MP_OKAY) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
| ︙ | ︙ | |||
1091 1092 1093 1094 1095 1096 1097 |
}
} 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.
*/
| | < < > > | < | 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 |
}
} 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 = NULL;
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 {
/*
* More %-specifiers than matching chars, so we just spit out
* empty strings for these.
*/
if (!emptyObj) {
TclNewObj(emptyObj);
}
code = Tcl_ListObjAppendElement(interp, objPtr, emptyObj);
}
}
if (code != TCL_OK) {
/* If error'ed out, free up remaining. i contains last index freed */
while (++i < totalVars) {
if (objs[i] != NULL) {
Tcl_DecrRefCount(objs[i]);
}
}
|
| ︙ | ︙ |
Changes to generic/tclStringObj.c.
| ︙ | ︙ | |||
1871 1872 1873 1874 1875 1876 1877 |
*/
while (*format != '\0') {
char *end;
int gotMinus = 0, gotHash = 0, gotZero = 0, gotSpace = 0, gotPlus = 0;
int gotPrecision, sawFlag, useShort = 0, useBig = 0;
Tcl_WideInt width, precision;
| < < | 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 |
*/
while (*format != '\0') {
char *end;
int gotMinus = 0, gotHash = 0, gotZero = 0, gotSpace = 0, gotPlus = 0;
int gotPrecision, sawFlag, useShort = 0, useBig = 0;
Tcl_WideInt width, precision;
int useWide = 0;
int newXpg, allocSegment = 0;
Tcl_Size numChars, segmentLimit, segmentNumBytes;
Tcl_Obj *segment;
int step = TclUtfToUniChar(format, &ch);
format += step;
if (ch != '%') {
|
| ︙ | ︙ | |||
2078 2079 2080 2081 2082 2083 2084 |
} else if (ch == 'l') {
format += step;
step = TclUtfToUniChar(format, &ch);
if (ch == 'l') {
useBig = 1;
format += step;
step = TclUtfToUniChar(format, &ch);
| < < < < < < < < | 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 |
} else if (ch == 'l') {
format += step;
step = TclUtfToUniChar(format, &ch);
if (ch == 'l') {
useBig = 1;
format += step;
step = TclUtfToUniChar(format, &ch);
} else {
useWide = 1;
}
} else if (ch == 'I') {
if ((format[1] == '6') && (format[2] == '4')) {
format += (step + 2);
step = TclUtfToUniChar(format, &ch);
useWide = 1;
} else if ((format[1] == '3') && (format[2] == '2')) {
format += (step + 2);
step = TclUtfToUniChar(format, &ch);
} else {
format += step;
step = TclUtfToUniChar(format, &ch);
}
} else if ((ch == 'q') || (ch == 'j')) {
format += step;
step = TclUtfToUniChar(format, &ch);
useWide = 1;
} else if ((ch == 't') || (ch == 'z')) {
format += step;
step = TclUtfToUniChar(format, &ch);
if (sizeof(void *) > sizeof(int)) {
useWide = 1;
}
} else if (ch == 'L') {
format += step;
step = TclUtfToUniChar(format, &ch);
useBig = 1;
}
format += step;
|
| ︙ | ︙ | |||
2176 2177 2178 2179 2180 2181 2182 |
case 'o':
case 'p':
case 'x':
case 'X':
case 'b': {
short s = 0; /* Silence compiler warning; only defined and
* used when useShort is true. */
| | < < < < | | | | | | | 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 |
case 'o':
case 'p':
case 'x':
case 'X':
case 'b': {
short s = 0; /* Silence compiler warning; only defined and
* used when useShort is true. */
int l;
Tcl_WideInt w;
mp_int big;
int isNegative = 0;
Tcl_Size toAppend;
if ((ch == 'p') && (sizeof(void *) > sizeof(int))) {
useWide = 1;
}
if (useBig) {
int cmpResult;
if (Tcl_GetBignumFromObj(interp, segment, &big) != TCL_OK) {
goto error;
}
cmpResult = mp_cmp_d(&big, 0);
isNegative = (cmpResult == MP_LT);
if (cmpResult == MP_EQ) {
gotHash = 0;
}
if (ch == 'u') {
if (isNegative) {
mp_clear(&big);
msg = "unsigned bignum format is invalid";
errCode = "BADUNSIGNED";
goto errorMsg;
} else {
ch = 'd';
}
}
} else if (useWide) {
if (TclGetWideBitsFromObj(interp, segment, &w) != TCL_OK) {
goto error;
}
isNegative = (w < (Tcl_WideInt) 0);
if (w == (Tcl_WideInt) 0) {
gotHash = 0;
}
} else if (TclGetIntFromObj(NULL, segment, &l) != TCL_OK) {
if (TclGetWideBitsFromObj(interp, segment, &w) != TCL_OK) {
goto error;
} else {
l = (int) w;
}
if (useShort) {
s = (short) l;
isNegative = (s < (short) 0);
if (s == (short) 0) {
gotHash = 0;
}
} else {
isNegative = (l < (int) 0);
if (l == (int) 0) {
gotHash = 0;
}
}
} else if (useShort) {
s = (short) l;
isNegative = (s < (short) 0);
if (s == (short) 0) {
gotHash = 0;
}
} else {
isNegative = (l < (int) 0);
if (l == (int) 0) {
gotHash = 0;
}
}
TclNewObj(segment);
allocSegment = 1;
segmentLimit = TCL_SIZE_MAX;
|
| ︙ | ︙ | |||
2290 2291 2292 2293 2294 2295 2296 |
case 'd': {
Tcl_Size length;
Tcl_Obj *pure;
const char *bytes;
if (useShort) {
TclNewIntObj(pure, s);
| < < | 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 |
case 'd': {
Tcl_Size length;
Tcl_Obj *pure;
const char *bytes;
if (useShort) {
TclNewIntObj(pure, s);
} else if (useWide) {
TclNewIntObj(pure, w);
} else if (useBig) {
pure = Tcl_NewBignumObj(&big);
} else {
TclNewIntObj(pure, l);
}
Tcl_IncrRefCount(pure);
bytes = TclGetStringFromObj(pure, &length);
|
| ︙ | ︙ | |||
2378 2379 2380 2381 2382 2383 2384 |
unsigned short us = (unsigned short) s;
bits = (Tcl_WideUInt) us;
while (us) {
numDigits++;
us /= base;
}
| < < | | 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 |
unsigned short us = (unsigned short) s;
bits = (Tcl_WideUInt) us;
while (us) {
numDigits++;
us /= base;
}
} else if (useWide) {
Tcl_WideUInt uw = (Tcl_WideUInt) w;
bits = uw;
while (uw) {
numDigits++;
uw /= base;
}
} else if (useBig && !mp_iszero(&big)) {
int leftover = (big.used * MP_DIGIT_BIT) % numBits;
mp_digit mask = (~(mp_digit)0) << (MP_DIGIT_BIT-leftover);
numDigits = 1 +
(((Tcl_WideInt) big.used * MP_DIGIT_BIT) / numBits);
while ((mask & big.dp[big.used-1]) == 0) {
numDigits--;
mask >>= numBits;
}
if (numDigits > INT_MAX) {
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
} else if (!useBig) {
unsigned ul = (unsigned) l;
bits = (Tcl_WideUInt) ul;
while (ul) {
numDigits++;
ul /= base;
}
}
|
| ︙ | ︙ | |||
2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 |
*p++ = (char) ch;
*p = '\0';
TclNewObj(segment);
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';
| > > > > > > | 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 |
*p++ = (char) ch;
*p = '\0';
TclNewObj(segment);
allocSegment = 1;
if (!Tcl_AttemptSetObjLength(segment, length)) {
if (allocSegment) {
Tcl_DecrRefCount(segment);
}
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
bytes = TclGetString(segment);
if (!Tcl_AttemptSetObjLength(segment, snprintf(bytes, segment->length, spec, d))) {
if (allocSegment) {
Tcl_DecrRefCount(segment);
}
msg = overflow;
errCode = "OVERFLOW";
goto errorMsg;
}
if (ch == 'A') {
char *q = TclGetString(segment) + 1;
*q = 'x';
|
| ︙ | ︙ |
Changes to generic/tclTest.c.
| ︙ | ︙ | |||
6489 6490 6491 6492 6493 6494 6495 |
if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
/*
* Syntax: transform channel -command command
*/
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
| | | 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 |
if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
/*
* Syntax: transform channel -command command
*/
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" transform channel -command cmd\"", (char *)NULL);
return TCL_ERROR;
}
if (strcmp(argv[3], "-command") != 0) {
Tcl_AppendResult(interp, "bad argument \"", argv[3],
"\": should be \"-command\"", (char *)NULL);
return TCL_ERROR;
}
|
| ︙ | ︙ |
Changes to generic/tclTestABSList.c.
| ︙ | ︙ | |||
71 72 73 74 75 76 77 | my_LStringObjLength, /* Length */ my_LStringObjIndex, /* Index */ my_LStringObjRange, /* Slice */ my_LStringObjReverse, /* Reverse */ my_LStringGetElements, /* GetElements */ my_LStringObjSetElem, /* SetElement */ my_LStringReplace, /* Replace */ | | | | | | | | | | | | | | 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 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 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 |
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*1*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
NULL, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*2*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
NULL, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*3*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
NULL, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*4*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
NULL, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*5*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
NULL, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*6*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
NULL, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*7*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
NULL, /* Replace */
NULL) /* "in" operator */
},
{/*8*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*9*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
},
{/*10*/
"lstring",
freeRep,
DupLStringRep,
UpdateStringOfLString,
NULL,
TCL_OBJTYPE_V2(
my_LStringObjLength, /* Length */
my_LStringObjIndex, /* Index */
my_LStringObjRange, /* Slice */
my_LStringObjReverse, /* Reverse */
my_LStringGetElements, /* GetElements */
my_LStringObjSetElem, /* SetElement */
my_LStringReplace, /* Replace */
NULL) /* "in" operator */
}
};
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
852 853 854 855 856 857 858 |
if (llen <= LOCAL_SIZE) {
flagPtr = localFlags;
} else {
/* We know numElems <= LIST_MAX, so this is safe. */
flagPtr = (int *) Tcl_Alloc(llen*sizeof(int));
}
for (bytesNeeded = 0, i = 0; i < llen; i++) {
| | | | | | | | | | 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 |
if (llen <= LOCAL_SIZE) {
flagPtr = localFlags;
} else {
/* We know numElems <= LIST_MAX, so this is safe. */
flagPtr = (int *) Tcl_Alloc(llen*sizeof(int));
}
for (bytesNeeded = 0, i = 0; i < llen; i++) {
Tcl_Obj *elemObj;
const char *elemStr;
Tcl_Size elemLen;
flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0);
typePtr->indexProc(NULL, objPtr, i, &elemObj);
Tcl_IncrRefCount(elemObj);
elemStr = Tcl_GetStringFromObj(elemObj, &elemLen);
/* Note TclScanElement updates flagPtr[i] */
bytesNeeded += Tcl_ScanCountedElement(elemStr, elemLen, &flagPtr[i]);
if (bytesNeeded < 0) {
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
Tcl_DecrRefCount(elemObj);
}
if (bytesNeeded > INT_MAX - llen + 1) {
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
bytesNeeded += llen; /* Separating spaces and terminating nul */
/*
* Pass 2: generate the string repr.
*/
objPtr->bytes = (char *) Tcl_Alloc(bytesNeeded);
p = objPtr->bytes;
for (i = 0; i < llen; i++) {
Tcl_Obj *elemObj;
const char *elemStr;
Tcl_Size elemLen;
flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0);
typePtr->indexProc(NULL, objPtr, i, &elemObj);
Tcl_IncrRefCount(elemObj);
elemStr = Tcl_GetStringFromObj(elemObj, &elemLen);
p += Tcl_ConvertCountedElement(elemStr, elemLen, p, flagPtr[i]);
*p++ = ' ';
Tcl_DecrRefCount(elemObj);
|
| ︙ | ︙ | |||
980 981 982 983 984 985 986 |
// EVAL DIRECT to avoid interfering with bytecode compile which may be
// active on the stack
int flags = TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT;
int status = Tcl_EvalObjEx(intrp, genCmd, flags);
elemObj = Tcl_GetObjResult(intrp);
if (status != TCL_OK) {
Tcl_SetObjResult(intrp, Tcl_ObjPrintf(
| | | 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 |
// EVAL DIRECT to avoid interfering with bytecode compile which may be
// active on the stack
int flags = TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT;
int status = Tcl_EvalObjEx(intrp, genCmd, flags);
elemObj = Tcl_GetObjResult(intrp);
if (status != TCL_OK) {
Tcl_SetObjResult(intrp, Tcl_ObjPrintf(
"Error: %s\nwhile executing %s\n",
elemObj ? Tcl_GetString(elemObj) : "NULL", Tcl_GetString(genCmd)));
return NULL;
}
}
return elemObj;
}
|
| ︙ | ︙ | |||
1098 1099 1100 1101 1102 1103 1104 |
NULL, /* SetFromAnyProc */
TCL_OBJTYPE_V2(
lgenSeriesObjLength,
lgenSeriesObjIndex,
NULL, /* slice */
NULL, /* reverse */
NULL, /* get elements */
| | | | | 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 |
NULL, /* SetFromAnyProc */
TCL_OBJTYPE_V2(
lgenSeriesObjLength,
lgenSeriesObjIndex,
NULL, /* slice */
NULL, /* reverse */
NULL, /* get elements */
NULL, /* set element */
NULL, /* replace */
NULL) /* "in" operator */
};
/*
* ObjType Duplicate Internal Rep Function
*/
static void
DupLgenSeriesRep(
|
| ︙ | ︙ |
Changes to generic/tclTestObj.c.
| ︙ | ︙ | |||
1181 1182 1183 1184 1185 1186 1187 |
} else {
const char *typeName;
if (objv[2]->typePtr == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
} else {
typeName = objv[2]->typePtr->name;
| < < < < < | 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 |
} else {
const char *typeName;
if (objv[2]->typePtr == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1));
} else {
typeName = objv[2]->typePtr->name;
Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1));
}
}
return TCL_OK;
case TESTOBJ_NEWOBJ:
if (objc != 3) {
goto wrongNumArgs;
|
| ︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 |
break;
case TESTOBJ_TYPE:
if (objc != 3) {
goto wrongNumArgs;
}
if (varPtr[varIndex]->typePtr == NULL) { /* a string! */
Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1);
| < < < < < | 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 |
break;
case TESTOBJ_TYPE:
if (objc != 3) {
goto wrongNumArgs;
}
if (varPtr[varIndex]->typePtr == NULL) { /* a string! */
Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1);
} else {
Tcl_AppendToObj(Tcl_GetObjResult(interp),
varPtr[varIndex]->typePtr->name, -1);
}
break;
default:
break;
|
| ︙ | ︙ |
Changes to generic/tclThreadAlloc.c.
| ︙ | ︙ | |||
210 211 212 213 214 215 216 |
cachePtr = (Cache*)TclpGetAllocCache();
if (cachePtr == NULL) {
cachePtr = (Cache*)TclpSysAlloc(sizeof(Cache));
if (cachePtr == NULL) {
Tcl_Panic("alloc: could not allocate new cache");
}
| | | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
cachePtr = (Cache*)TclpGetAllocCache();
if (cachePtr == NULL) {
cachePtr = (Cache*)TclpSysAlloc(sizeof(Cache));
if (cachePtr == NULL) {
Tcl_Panic("alloc: could not allocate new cache");
}
memset(cachePtr, 0, sizeof(Cache));
Tcl_MutexLock(listLockPtr);
cachePtr->nextPtr = firstCachePtr;
firstCachePtr = cachePtr;
Tcl_MutexUnlock(listLockPtr);
cachePtr->owner = Tcl_GetCurrentThread();
TclpSetAllocCache(cachePtr);
}
|
| ︙ | ︙ |
Changes to generic/tclTimer.c.
| ︙ | ︙ | |||
819 820 821 822 823 824 825 |
if (TclGetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) {
if (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index)
!= TCL_OK) {
const char *arg = TclGetString(objv[1]);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
| | | | | | 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 |
if (TclGetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) {
if (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index)
!= TCL_OK) {
const char *arg = TclGetString(objv[1]);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad argument \"%s\": must be"
" cancel, idle, info, or an integer", arg));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "argument",
arg, (void *)NULL);
return TCL_ERROR;
}
}
/*
* At this point, either index = -1 and ms contains the number of ms
* to wait, or else index is the index of a subcommand.
|
| ︙ | ︙ | |||
948 949 950 951 952 953 954 |
for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
afterPtr = afterPtr->nextPtr) {
if (assocPtr->interp == interp) {
Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf(
"after#%d", afterPtr->id));
}
}
| | | | | | | 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 |
for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;
afterPtr = afterPtr->nextPtr) {
if (assocPtr->interp == interp) {
Tcl_ListObjAppendElement(NULL, resultObj, Tcl_ObjPrintf(
"after#%d", afterPtr->id));
}
}
Tcl_SetObjResult(interp, resultObj);
return TCL_OK;
}
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "?id?");
return TCL_ERROR;
}
afterPtr = GetAfterEvent(assocPtr, objv[2]);
if (afterPtr == NULL) {
const char *eventStr = TclGetString(objv[2]);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"event \"%s\" doesn't exist", eventStr));
Tcl_SetErrorCode(interp, "TCL","LOOKUP","EVENT", eventStr, (void *)NULL);
return TCL_ERROR;
} else {
Tcl_Obj *resultListPtr;
TclNewObj(resultListPtr);
Tcl_ListObjAppendElement(interp, resultListPtr,
afterPtr->commandPtr);
Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
(afterPtr->token == NULL) ? "idle" : "timer", -1));
Tcl_SetObjResult(interp, resultListPtr);
}
break;
default:
Tcl_Panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds");
}
return TCL_OK;
}
|
| ︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 |
}
if (iPtr->limit.timeEvent == NULL
|| TCL_TIME_BEFORE(endTime, iPtr->limit.time)) {
diff = TCL_TIME_DIFF_MS_CEILING(endTime, now);
if (diff > TCL_TIME_MAXIMUM_SLICE) {
diff = TCL_TIME_MAXIMUM_SLICE;
}
| | | | | | | | | | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 |
}
if (iPtr->limit.timeEvent == NULL
|| TCL_TIME_BEFORE(endTime, iPtr->limit.time)) {
diff = TCL_TIME_DIFF_MS_CEILING(endTime, now);
if (diff > TCL_TIME_MAXIMUM_SLICE) {
diff = TCL_TIME_MAXIMUM_SLICE;
}
if (diff == 0 && TCL_TIME_BEFORE(now, endTime)) {
diff = 1;
}
if (diff > 0) {
Tcl_Sleep((int) diff);
if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) {
break;
}
} else {
break;
}
} else {
diff = TCL_TIME_DIFF_MS(iPtr->limit.time, now);
if (diff > TCL_TIME_MAXIMUM_SLICE) {
diff = TCL_TIME_MAXIMUM_SLICE;
}
if (diff > 0) {
Tcl_Sleep((int) diff);
|
| ︙ | ︙ |
Changes to generic/tclTrace.c.
| ︙ | ︙ | |||
1115 1116 1117 1118 1119 1120 1121 | /* * None of the remaining traces on this command are execution traces. * We therefore remove this flag: */ cmdPtr->flags &= ~CMD_HAS_EXEC_TRACES; | | | 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 |
/*
* None of the remaining traces on this command are execution traces.
* We therefore remove this flag:
*/
cmdPtr->flags &= ~CMD_HAS_EXEC_TRACES;
/*
* Bug 3484621: up the interp's epoch if this is a BC'ed command
*/
if (cmdPtr->compileProc != NULL) {
iPtr->compileEpoch++;
}
}
|
| ︙ | ︙ | |||
2543 2544 2545 2546 2547 2548 2549 |
}
}
}
/* Keep the original pointer for possible use in an error message */
element = part2;
if (part2 == NULL) {
| | | | | | | | | | 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 |
}
}
}
/* Keep the original pointer for possible use in an error message */
element = part2;
if (part2 == NULL) {
if (TclIsVarArrayElement(varPtr)) {
Tcl_Obj *keyObj = VarHashGetKey(varPtr);
part2 = Tcl_GetString(keyObj);
}
} else if ((flags & VAR_TRACED_UNSET) && !(flags & VAR_ARRAY_ELEMENT)) {
/* On unset traces, part2 has already been set by the caller, and
* the VAR_ARRAY_ELEMENT flag indicates whether the accessed
* variable actually has a second part, or is a scalar */
element = NULL;
}
/*
* Invoke traces on the array containing the variable, if relevant.
*/
result = NULL;
|
| ︙ | ︙ |
Changes to generic/tclUtil.c.
| ︙ | ︙ | |||
3228 3229 3230 3231 3232 3233 3234 |
* Reconsider this if we ever start treating non-ASCII Unicode
* characters as meaningful list syntax, expanded Unicode spaces as
* element separators, for example.)
*
end = Tcl_UtfPrev(end, start);
while (*end == '{') {
| | | | | | | 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 |
* Reconsider this if we ever start treating non-ASCII Unicode
* characters as meaningful list syntax, expanded Unicode spaces as
* element separators, for example.)
*
end = Tcl_UtfPrev(end, start);
while (*end == '{') {
if (end == start) {
return 0;
}
end = Tcl_UtfPrev(end, start);
}
*
*/
while ((--end >= start) && (*end == '{')) {
}
if (end < start) {
return 0;
}
/*
* (c) the trailing character of the string is already a list-element
* separator, Use the same testing routine as TclFindElement to
* enforce consistency.
*/
|
| ︙ | ︙ | |||
3362 3363 3364 3365 3366 3367 3368 |
GetWideForIndex(
Tcl_Interp *interp, /* Interpreter to use for error reporting. If
* NULL, then no error message is left after
* errors. */
Tcl_Obj *objPtr, /* Points to the value to be parsed */
Tcl_WideInt endValue, /* The value to be stored at *widePtr if
* objPtr holds "end".
| | | | | 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 |
GetWideForIndex(
Tcl_Interp *interp, /* Interpreter to use for error reporting. If
* NULL, then no error message is left after
* errors. */
Tcl_Obj *objPtr, /* Points to the value to be parsed */
Tcl_WideInt endValue, /* The value to be stored at *widePtr if
* objPtr holds "end".
* NOTE: this value may be TCL_INDEX_NONE. */
Tcl_WideInt *widePtr) /* Location filled in with a wide integer
* representing an index. */
{
int numType;
void *cd;
int code = Tcl_GetNumberFromObj(NULL, objPtr, &cd, &numType);
if (code == TCL_OK) {
if (numType == TCL_NUMBER_INT) {
/* objPtr holds an integer in the signed wide range */
*widePtr = *(Tcl_WideInt *)cd;
if ((*widePtr < 0)) {
*widePtr = (endValue == -1) ? WIDE_MIN : -1;
}
return TCL_OK;
}
if (numType == TCL_NUMBER_BIG) {
/* objPtr holds an integer outside the signed wide range */
/* Truncate to the signed wide range. */
|
| ︙ | ︙ | |||
3449 3450 3451 3452 3453 3454 3455 |
if (indexPtr != NULL) {
/* Note: check against TCL_SIZE_MAX needed for 32-bit builds */
if (wide >= 0 && wide <= TCL_SIZE_MAX) {
*indexPtr = (Tcl_Size)wide; /* A valid index */
} else if (wide > TCL_SIZE_MAX) {
*indexPtr = TCL_SIZE_MAX; /* Beyond max possible index */
} else if (wide < -1-TCL_SIZE_MAX) {
| | | | | | 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 |
if (indexPtr != NULL) {
/* Note: check against TCL_SIZE_MAX needed for 32-bit builds */
if (wide >= 0 && wide <= TCL_SIZE_MAX) {
*indexPtr = (Tcl_Size)wide; /* A valid index */
} else if (wide > TCL_SIZE_MAX) {
*indexPtr = TCL_SIZE_MAX; /* Beyond max possible index */
} else if (wide < -1-TCL_SIZE_MAX) {
*indexPtr = -1-TCL_SIZE_MAX; /* Below most negative index */
} else if ((wide < 0) && (endValue >= 0)) {
*indexPtr = TCL_INDEX_NONE; /* No clue why this special case */
} else {
*indexPtr = (Tcl_Size) wide;
}
}
return TCL_OK;
}
/*
|
| ︙ | ︙ | |||
3493 3494 3495 3496 3497 3498 3499 |
*/
static int
GetEndOffsetFromObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr, /* Pointer to the object to parse */
Tcl_WideInt endValue, /* The value to be stored at "widePtr" if
| | | | 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 |
*/
static int
GetEndOffsetFromObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr, /* Pointer to the object to parse */
Tcl_WideInt endValue, /* The value to be stored at "widePtr" if
* "objPtr" holds "end". */
Tcl_WideInt *widePtr) /* Location filled in with an integer
* representing an index. */
{
Tcl_ObjInternalRep *irPtr;
Tcl_WideInt offset = -1; /* Offset in the "end-offset" expression - 1 */
void *cd;
while ((irPtr = TclFetchInternalRep(objPtr, &endOffsetType)) == NULL) {
Tcl_ObjInternalRep ir;
|
| ︙ | ︙ | |||
3528 3529 3530 3531 3532 3533 3534 | /* * Quick scan to see if multi-value list is even possible. * This relies on TclGetString() returning a NUL-terminated string. */ if ((TclMaxListLength(bytes, TCL_INDEX_NONE, NULL) > 1) /* If it's possible, do the full list parse. */ | | | | | | 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 |
/*
* Quick scan to see if multi-value list is even possible.
* This relies on TclGetString() returning a NUL-terminated string.
*/
if ((TclMaxListLength(bytes, TCL_INDEX_NONE, NULL) > 1)
/* If it's possible, do the full list parse. */
&& (TCL_OK == TclListObjLength(NULL, objPtr, &length))
&& (length > 1)) {
goto parseError;
}
/* Passed the list screen, so parse for index arithmetic expression */
if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, NULL, TCL_INDEX_NONE, &opPtr,
TCL_PARSE_INTEGER_ONLY)) {
Tcl_WideInt w1=0, w2=0;
/* value starts with valid integer... */
if ((*opPtr == '-') || (*opPtr == '+')) {
/* ... value continues with [-+] ... */
|
| ︙ | ︙ | |||
3694 3695 3696 3697 3698 3699 3700 |
}
offset = irPtr->wideValue;
if (offset == WIDE_MAX) {
/*
* Encodes end+1. This is distinguished from end+n as noted
| | | | | | | | | | | | 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 |
}
offset = irPtr->wideValue;
if (offset == WIDE_MAX) {
/*
* Encodes end+1. This is distinguished from end+n as noted
* in function header.
* NOTE: this may wrap around if the caller passes (as lset does)
* listLen-1 as endValue and and listLen is 0. The -1 will be
* interpreted as FF...FF and adding 1 will result in 0 which
* is what we want. Callers like lset which pass in listLen-1 == -1
* as endValue will have to adjust accordingly.
*/
*widePtr = (endValue == -1) ? WIDE_MAX : endValue + 1;
} else if (offset == WIDE_MIN) {
*widePtr = (endValue == -1) ? WIDE_MIN : -1;
} else if (offset < 0) {
/* end-(n-1) - Different signs, sum cannot overflow */
*widePtr = endValue + offset + 1;
} else {
/* 0:WIDE_MAX - plain old index. */
*widePtr = offset;
}
return TCL_OK;
/* Report a parse error. */
parseError:
if (interp != NULL) {
char * bytes = TclGetString(objPtr);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"bad index \"%s\": must be integer?[+-]integer? or"
" end?[+-]integer?", bytes));
if (!strncmp(bytes, "end-", 4)) {
bytes += 4;
}
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", (char *)NULL);
}
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to generic/tclVar.c.
| ︙ | ︙ | |||
2501 2502 2503 2504 2505 2506 2507 |
/*
* It's an error to unset an undefined variable.
*/
if (result != TCL_OK) {
if (flags & TCL_LEAVE_ERR_MSG) {
TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "unset",
| | | 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 |
/*
* It's an error to unset an undefined variable.
*/
if (result != TCL_OK) {
if (flags & TCL_LEAVE_ERR_MSG) {
TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "unset",
((initialArrayPtr == NULL) ? NOSUCHVAR : NOSUCHELEMENT), index);
Tcl_SetErrorCode(interp, "TCL", "UNSET", "VARNAME", (char *)NULL);
}
}
/*
* Finally, if the variable is truly not in use then free up its Var
* structure and remove it from its hash table, if any. The ref count of
|
| ︙ | ︙ | |||
2610 2611 2612 2613 2614 2615 2616 |
Tcl_SetHashValue(tPtr, tracePtr);
}
}
if ((dummyVar.flags & VAR_TRACED_UNSET)
|| (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET))) {
| | | | | | | | | | | | | | | 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 2637 2638 2639 |
Tcl_SetHashValue(tPtr, tracePtr);
}
}
if ((dummyVar.flags & VAR_TRACED_UNSET)
|| (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET))) {
/*
* Pass the array element name to TclObjCallVarTraces(), because
* it cannot be determined from dummyVar. Alternatively, indicate
* via flags whether the variable involved in the code that caused
* the trace to be triggered was an array element, for the correct
* formatting of error messages.
*/
if (part2Ptr) {
flags |= VAR_ARRAY_ELEMENT;
} else if (TclIsVarArrayElement(varPtr)) {
part2Ptr = VarHashGetKey(varPtr);
}
dummyVar.flags &= ~VAR_TRACE_ACTIVE;
TclObjCallVarTraces(iPtr, arrayPtr, &dummyVar, part1Ptr, part2Ptr,
(flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|VAR_ARRAY_ELEMENT))
| TCL_TRACE_UNSETS,
/* leaveErrMsg */ 0, index);
/*
* The traces that we just called may have triggered a change in
* the set of traces. If so, reload the traces to manipulate.
*/
|
| ︙ | ︙ | |||
5994 5995 5996 5997 5998 5999 6000 |
Tcl_Obj *const objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
const char *varName, *pattern, *simplePattern;
Tcl_HashSearch search;
Var *varPtr;
Namespace *nsPtr;
| < | 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 |
Tcl_Obj *const objv[]) /* Argument objects. */
{
Interp *iPtr = (Interp *) interp;
const char *varName, *pattern, *simplePattern;
Tcl_HashSearch search;
Var *varPtr;
Namespace *nsPtr;
Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
Tcl_Obj *listPtr, *elemObjPtr, *varNamePtr;
int specificNsInPattern = 0;/* Init. to avoid compiler warning. */
Tcl_Obj *simplePatternPtr = NULL;
/*
* Get the pattern and find the "effective namespace" in which to list
|
| ︙ | ︙ | |||
6075 6076 6077 6078 6079 6080 6081 |
Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
elemObjPtr);
} else {
elemObjPtr = VarHashGetKey(varPtr);
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
}
| < < < < < < < < < < | 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 |
Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr,
elemObjPtr);
} else {
elemObjPtr = VarHashGetKey(varPtr);
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
}
}
} else {
/*
* Have to scan the tables of variables.
*/
varPtr = VarHashFirstVar(&nsPtr->varTable, &search);
|
| ︙ | ︙ | |||
6110 6111 6112 6113 6114 6115 6116 |
} else {
elemObjPtr = varNamePtr;
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
}
}
varPtr = VarHashNextVar(&search);
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 |
} else {
elemObjPtr = varNamePtr;
}
Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
}
}
varPtr = VarHashNextVar(&search);
}
}
} else if (iPtr->varFramePtr->procPtr != NULL) {
AppendLocals(interp, listPtr, simplePatternPtr, 1, 0);
}
if (simplePatternPtr) {
|
| ︙ | ︙ | |||
7082 7083 7084 7085 7086 7087 7088 |
*
* array default set v 1
* lappend v(a) 2; # returns a new object {1 2}
* set v(b); # returns the original default object "1"
*/
if (tablePtr->defaultObj) {
| | | | | | 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 |
*
* array default set v 1
* lappend v(a) 2; # returns a new object {1 2}
* set v(b); # returns the original default object "1"
*/
if (tablePtr->defaultObj) {
Tcl_DecrRefCount(tablePtr->defaultObj);
Tcl_DecrRefCount(tablePtr->defaultObj);
}
tablePtr->defaultObj = defaultObj;
if (tablePtr->defaultObj) {
Tcl_IncrRefCount(tablePtr->defaultObj);
Tcl_IncrRefCount(tablePtr->defaultObj);
}
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Changes to generic/tclZipfs.c.
| ︙ | ︙ | |||
1655 1656 1657 1658 1659 1660 1661 |
*/
zf->length = Tcl_Seek(zf->chan, 0, SEEK_END);
if (zf->length == (size_t) TCL_INDEX_NONE) {
ZIPFS_POSIX_ERROR(interp, "seek error");
goto error;
}
| | | 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 |
*/
zf->length = Tcl_Seek(zf->chan, 0, SEEK_END);
if (zf->length == (size_t) TCL_INDEX_NONE) {
ZIPFS_POSIX_ERROR(interp, "seek error");
goto error;
}
/* What's the magic about 64 * 1024 * 1024 ? */
if ((zf->length <= ZIP_CENTRAL_END_LEN) ||
(zf->length - ZIP_CENTRAL_END_LEN) >
(64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) {
ZIPFS_ERROR(interp, "illegal file size");
ZIPFS_ERROR_CODE(interp, "FILE_SIZE");
goto error;
}
|
| ︙ | ︙ | |||
6214 6215 6216 6217 6218 6219 6220 |
{"root", ZipFSRootObjCmd, NULL, NULL, NULL, 0},
{NULL, NULL, NULL, NULL, NULL, 0}
};
static const char findproc[] =
"namespace eval ::tcl::zipfs {}\n"
"proc ::tcl::zipfs::Find dir {\n"
" set result {}\n"
| | > > | 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 |
{"root", ZipFSRootObjCmd, NULL, NULL, NULL, 0},
{NULL, NULL, NULL, NULL, NULL, 0}
};
static const char findproc[] =
"namespace eval ::tcl::zipfs {}\n"
"proc ::tcl::zipfs::Find dir {\n"
" set result {}\n"
" if {[catch {\n"
" concat [glob -directory $dir -nocomplain *] [glob -directory $dir -types hidden -nocomplain *]\n"
" } list]} {\n"
" return $result\n"
" }\n"
" foreach file $list {\n"
" if {[file tail $file] in {. ..}} {\n"
" continue\n"
" }\n"
" lappend result $file {*}[Find $file]\n"
|
| ︙ | ︙ |
Changes to generic/tclZlib.c.
| ︙ | ︙ | |||
2697 2698 2699 2700 2701 2702 2703 |
return TCL_OK;
case zs_checksum: /* $strm checksum */
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
| | | 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 |
return TCL_OK;
case zs_checksum: /* $strm checksum */
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
(uint32_t) Tcl_ZlibStreamChecksum(zstream)));
return TCL_OK;
case zs_reset: /* $strm reset */
if (objc != 2) {
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
}
return Tcl_ZlibStreamReset(zstream);
|
| ︙ | ︙ |
Added library/icu.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 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 |
#----------------------------------------------------------------------
#
# icu.tcl --
#
# This file implements the portions of the [tcl::unsupported::icu]
# ensemble that are coded in Tcl.
#
#----------------------------------------------------------------------
#
# Copyright © 2024 Ashok P. Nadkarni
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#----------------------------------------------------------------------
::tcl::unsupported::loadIcu
namespace eval ::tcl::unsupported::icu {
# Map Tcl encoding names to ICU and back. Note ICU has multiple aliases
# for the same encoding.
variable tclToIcu
variable icuToTcl
proc LogError {message} {
puts stderr $message
}
proc Init {} {
variable tclToIcu
variable icuToTcl
# There are some special cases where names do not line up
# at all. Map Tcl -> ICU
array set specialCases {
ebcdic ebcdic-cp-us
macCentEuro maccentraleurope
utf16 UTF16_PlatformEndian
utf-16be UnicodeBig
utf-16le UnicodeLittle
utf32 UTF32_PlatformEndian
}
# Ignore all errors. Do not want to hold up Tcl
# if ICU not available
if {[catch {
foreach tclName [encoding names] {
if {[catch {
set icuNames [aliases $tclName]
} erMsg]} {
LogError "Could not get aliases for $tclName: $erMsg"
continue
}
if {[llength $icuNames] == 0} {
# E.g. macGreek -> x-MacGreek
set icuNames [aliases x-$tclName]
if {[llength $icuNames] == 0} {
# Still no joy, check for special cases
if {[info exists specialCases($tclName)]} {
set icuNames [aliases $specialCases($tclName)]
}
}
}
# If the Tcl name is also an ICU name use it else use
# the first name which is the canonical ICU name
set pos [lsearch -exact -nocase $icuNames $tclName]
if {$pos >= 0} {
lappend tclToIcu($tclName) [lindex $icuNames $pos] {*}[lreplace $icuNames $pos $pos]
} else {
set tclToIcu($tclName) $icuNames
}
foreach icuName $icuNames {
lappend icuToTcl($icuName) $tclName
}
}
} errMsg]} {
LogError $errMsg
}
array default set tclToIcu ""
array default set icuToTcl ""
# Redefine ourselves to no-op.
proc Init {} {}
}
# Primarily used during development
proc MappedIcuNames {{pat *}} {
Init
variable icuToTcl
return [array names icuToTcl $pat]
}
# Primarily used during development
proc UnmappedIcuNames {{pat *}} {
Init
variable icuToTcl
set unmappedNames {}
foreach icuName [converters] {
if {[llength [icuToTcl $icuName]] == 0} {
lappend unmappedNames $icuName
}
foreach alias [aliases $icuName] {
if {[llength [icuToTcl $alias]] == 0} {
lappend unmappedNames $alias
}
}
}
# Aliases can be duplicates. Remove
return [lsort -unique [lsearch -inline -all $unmappedNames $pat]]
}
# Primarily used during development
proc UnmappedTclNames {{pat *}} {
Init
variable tclToIcu
set unmappedNames {}
foreach tclName [encoding names] {
# Note entry will always exist. Check if empty
if {[llength [tclToIcu $tclName]] == 0} {
lappend unmappedNames $tclName
}
}
return [lsearch -inline -all $unmappedNames $pat]
}
# Returns the Tcl equivalent of an ICU encoding name or
# the empty string in case not found.
proc icuToTcl {icuName} {
Init
proc icuToTcl {icuName} {
variable icuToTcl
return [lindex $icuToTcl($icuName) 0]
}
icuToTcl $icuName
}
# Returns the ICU equivalent of an Tcl encoding name or
# the empty string in case not found.
proc tclToIcu {tclName} {
Init
proc tclToIcu {tclName} {
variable tclToIcu
return [lindex $tclToIcu($tclName) 0]
}
tclToIcu $tclName
}
namespace export {[a-z]*}
namespace ensemble create
}
|
Changes to library/init.tcl.
| ︙ | ︙ | |||
39 40 41 42 43 44 45 |
#
# (Ticket 41c9857bdd) In a safe interpreter, this file does not set
# ::auto_path (other than to {} if it is undefined). The caller, typically
# a Safe Base command, is responsible for setting ::auto_path.
if {![info exists auto_path]} {
if {[info exists env(TCLLIBPATH)] && (![interp issafe])} {
| | | | | | | | | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#
# (Ticket 41c9857bdd) In a safe interpreter, this file does not set
# ::auto_path (other than to {} if it is undefined). The caller, typically
# a Safe Base command, is responsible for setting ::auto_path.
if {![info exists auto_path]} {
if {[info exists env(TCLLIBPATH)] && (![interp issafe])} {
set auto_path [apply {{} {
lmap path $::env(TCLLIBPATH) {
# Paths relative to unresolvable home dirs are ignored
if {[catch {file tildeexpand $path} expanded_path]} {
continue
}
set expanded_path
}
}}]
} else {
set auto_path ""
}
}
namespace eval tcl {
if {![interp issafe]} {
|
| ︙ | ︙ |
Changes to library/msgcat/msgcat.tcl.
| ︙ | ︙ | |||
1222 1223 1224 1225 1226 1227 1228 |
proc ::msgcat::PackageNamespaceGet {} {
set ns [uplevel 2 { namespace current }]
if {![string match {::oo::*} $ns]} {
# Not in object environment
return $ns
}
| | > > | | | | | | | | | | | | | | | | < < < > > | 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 1256 1257 1258 |
proc ::msgcat::PackageNamespaceGet {} {
set ns [uplevel 2 { namespace current }]
if {![string match {::oo::*} $ns]} {
# Not in object environment
return $ns
}
# Ticket 91b3a5bb14: call to self may fail if namespace is stored
# so catch all this
try {
# Check self namespace to determine environment
switch -exact -- [uplevel 2 { namespace which -command self }] {
{::oo::define::self} {
# We are within a class definition
return [namespace qualifiers [uplevel 2 { self }]]
}
{::oo::Helpers::self} {
# We are within an object
set Class [info object class [uplevel 2 { self }]]
# Check for classless defined object
if {$Class eq {::oo::object}} {
return [namespace qualifiers [uplevel 2 { self }]]
}
# Class defined object
return [namespace qualifiers $Class]
}
}
} on error {} {
}
return $ns
}
# Initialize the default locale
proc msgcat::mcutil::getsystemlocale {} {
global env
#
|
| ︙ | ︙ |
Changes to library/tclIndex.
| ︙ | ︙ | |||
105 106 107 108 109 110 111 | set auto_index(::tcl::UpdateWordBreakREs) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_wordBreakAfter) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_wordBreakBefore) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_endOfWord) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_startOfNextWord) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_startOfPreviousWord) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(writeFile) [list ::tcl::Pkg::source [file join $dir writefile.tcl]] | > | 105 106 107 108 109 110 111 112 | set auto_index(::tcl::UpdateWordBreakREs) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_wordBreakAfter) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_wordBreakBefore) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_endOfWord) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_startOfNextWord) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(tcl_startOfPreviousWord) [list ::tcl::Pkg::source [file join $dir word.tcl]] set auto_index(writeFile) [list ::tcl::Pkg::source [file join $dir writefile.tcl]] set auto_index(::tcl::unsupported::icu) [list ::tcl::Pkg::source [file join $dir icu.tcl]] |
Changes to library/tcltest/tcltest.tcl.
| ︙ | ︙ | |||
1635 1636 1637 1638 1639 1640 1641 |
1 {
# Only the string to be printed is specified
append outData [lindex $args 0]\n
return
# return [Puts [lindex $args 0]]
}
2 {
| | | | 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 |
1 {
# Only the string to be printed is specified
append outData [lindex $args 0]\n
return
# return [Puts [lindex $args 0]]
}
2 {
# Either -nonewline or channel has been specified
if {[lindex $args 0] eq "-nonewline"} {
append outData [lindex $args end]
return
# return [Puts -nonewline [lindex $args end]]
} else {
set channel [lindex $args 0]
set newline \n
}
}
3 {
if {[lindex $args 0] eq "-nonewline"} {
# Both -nonewline and channel are specified, unless
# it's an error. -nonewline is supposed to be argv[0].
set channel [lindex $args 1]
set newline ""
}
}
}
|
| ︙ | ︙ |
Changes to tests-perf/chan.perf.tcl.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
namespace eval ::tclTestPerf-Chan {
namespace path {::tclTestPerf}
proc _get_test_chan {{bufSize 4096}} {
lassign [chan pipe] ch wch;
| | | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
namespace eval ::tclTestPerf-Chan {
namespace path {::tclTestPerf}
proc _get_test_chan {{bufSize 4096}} {
lassign [chan pipe] ch wch;
fconfigure $ch -translation lf -encoding utf-8 -buffersize $bufSize -buffering full
fconfigure $wch -translation lf -encoding utf-8 -buffersize $bufSize -buffering full
exec [info nameofexecutable] -- $bufSize >@$wch << {
set bufSize [lindex $::argv end]
fconfigure stdout -translation lf -encoding utf-8 -buffersize $bufSize -buffering full
set buf [string repeat test 1000]; # 4K
# write ~ 10*1M + 10*2M + 10*10M + 1*20M:
set i 0; while {$i < int((10*1e6 + 10*2e6 + 10*10e6 + 1*20e6)/4e3)} {
#puts -nonewline stdout $i\t
puts stdout $buf
#flush stdout; # don't flush to use full buffer
incr i
|
| ︙ | ︙ |
Changes to tests/assemble.test.
| ︙ | ︙ | |||
768 769 770 771 772 773 774 |
test assemble-7.43 {uplus} {
-body {
assemble {
push NaN; uplus
}
}
-returnCodes error
| | | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 |
test assemble-7.43 {uplus} {
-body {
assemble {
push NaN; uplus
}
}
-returnCodes error
-result {cannot use non-numeric floating-point value "NaN" as operand of "+"}
}
test assemble-7.43.1 {tryCvtToNumeric} {
-body {
assemble {
push NaN; tryCvtToNumeric
}
}
|
| ︙ | ︙ |
Changes to tests/chan.test.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 |
} -returnCodes error -result "wrong # args: should be \"chan subcommand ?arg ...?\""
test chan-1.2 {chan command general syntax} -body {
chan FOOBAR
} -returnCodes error -match glob -result "unknown or ambiguous subcommand \"FOOBAR\": must be *"
test chan-2.1 {chan command: blocked subcommand} -body {
chan blocked foo bar
| | | | | | | | | | | | | | > > > > > > > > > > | | | | 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 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 147 148 149 150 151 152 153 |
} -returnCodes error -result "wrong # args: should be \"chan subcommand ?arg ...?\""
test chan-1.2 {chan command general syntax} -body {
chan FOOBAR
} -returnCodes error -match glob -result "unknown or ambiguous subcommand \"FOOBAR\": must be *"
test chan-2.1 {chan command: blocked subcommand} -body {
chan blocked foo bar
} -returnCodes error -result "wrong # args: should be \"chan blocked channel\""
test chan-3.1 {chan command: close subcommand} -body {
chan close foo bar zet
} -returnCodes error -result "wrong # args: should be \"chan close channel ?direction?\""
test chan-3.2 {chan command: close subcommand} -setup {
set chan [open [info script] r]
} -body {
chan close $chan bar
} -cleanup {
close $chan
} -returnCodes error -result "bad direction \"bar\": must be read or write"
test chan-3.3 {chan command: close subcommand} -setup {
set chan [open [info script] r]
} -body {
chan close $chan write
} -cleanup {
close $chan
} -returnCodes error -result "Half-close of write-side not possible, side not opened or already closed"
test chan-4.1 {chan command: configure subcommand} -body {
chan configure
} -returnCodes error -result "wrong # args: should be \"chan configure channel ?-option value ...?\""
test chan-4.2 {chan command: [Bug 800753]} -body {
chan configure stdout -eofchar Ā
} -returnCodes error -result {bad value for -eofchar: must be non-NUL ASCII character}
test chan-4.3 {chan command: [Bug 800753]} -body {
chan configure stdout -eofchar \x00
} -returnCodes error -result {bad value for -eofchar: must be non-NUL ASCII character}
test chan-4.4 {chan command: check valid inValue, no outValue} -constraints deprecated -body {
chan configure stdout -eofchar [list \x27 {}]
} -result {}
test chan-4.5 {chan command: check valid inValue, invalid outValue} -body {
chan configure stdout -eofchar [list \x27 \x80]
} -returnCodes error -result {bad value for -eofchar: must be non-NUL ASCII character}
test chan-4.6 {chan command: check no inValue, valid outValue} -body {
chan configure stdout -eofchar [list {} \x27]
} -returnCodes error -result {bad value for -eofchar: must be non-NUL ASCII character}
test chan-5.1 {chan command: copy subcommand} -body {
chan copy foo
} -returnCodes error -result "wrong # args: should be \"chan copy input output ?-size size? ?-command callback?\""
test chan-6.1 {chan command: eof subcommand} -body {
chan eof foo bar
} -returnCodes error -result "wrong # args: should be \"chan eof channel\""
test chan-7.1 {chan command: event subcommand} -body {
chan event foo
} -returnCodes error -result "wrong # args: should be \"chan event channel event ?script?\""
test chan-8.1 {chan command: flush subcommand} -body {
chan flush foo bar
} -returnCodes error -result "wrong # args: should be \"chan flush channel\""
test chan-9.1 {chan command: gets subcommand} -body {
chan gets
} -returnCodes error -result "wrong # args: should be \"chan gets channel ?varName?\""
test chan-10.1 {chan command: names subcommand} -body {
chan names foo bar
} -returnCodes error -result "wrong # args: should be \"chan names ?pattern?\""
test chan-11.1 {chan command: puts subcommand} -body {
chan puts foo bar foo bar
} -returnCodes error -result "wrong # args: should be \"chan puts ?-nonewline? ?channel? string\""
test chan-12.1 {chan command: read subcommand} -body {
chan read
} -returnCodes error -result "wrong # args: should be \"chan read channel ?numChars?\" or \"chan read ?-nonewline? channel\""
test chan-13.1 {chan command: seek subcommand} -body {
chan seek foo bar foo bar
} -returnCodes error -result "wrong # args: should be \"chan seek channel offset ?origin?\""
test chan-14.1 {chan command: tell subcommand} -body {
chan tell foo bar
} -returnCodes error -result "wrong # args: should be \"chan tell channel\""
test chan-15.1 {chan command: truncate subcommand} -body {
chan truncate foo bar foo bar
} -returnCodes error -result "wrong \# args: should be \"chan truncate channel ?length?\""
test chan-15.2 {chan command: truncate subcommand} -setup {
set file [makeFile {} testTruncate]
set f [open $file w+]
fconfigure $f -translation binary
} -body {
seek $f 0
puts -nonewline $f 12345
seek $f 0
chan truncate $f 2
read $f
} -result 12 -cleanup {
catch {close $f}
catch {removeFile $file}
}
test chan-15.3 {chan command: isbinary subcommand} -setup {
set file [makeFile {} testIsBinary]
set f [open $file w+]
fconfigure $f -translation binary
} -body {
chan isbinary $f
} -result 1 -cleanup {
catch {close $f}
catch {removeFile $file}
}
# TIP 287: chan pending
test chan-16.1 {chan command: pending subcommand} -body {
chan pending
} -returnCodes error -result "wrong # args: should be \"chan pending mode channel\""
test chan-16.2 {chan command: pending subcommand} -body {
chan pending stdin
} -returnCodes error -result "wrong # args: should be \"chan pending mode channel\""
test chan-16.3 {chan command: pending subcommand} -body {
chan pending stdin stdout stderr
} -returnCodes error -result "wrong # args: should be \"chan pending mode channel\""
test chan-16.4 {chan command: pending subcommand} -body {
chan pending {input output} stdout
} -returnCodes error -result "bad mode \"input output\": must be input or output"
test chan-16.5 {chan command: pending input subcommand} -body {
chan pending input stdout
} -result -1
test chan-16.6 {chan command: pending input subcommand} -body {
|
| ︙ | ︙ |
Changes to tests/chanio.test.
| ︙ | ︙ | |||
65 66 67 68 69 70 71 |
testConstraint makeFileInHome [expr {![file exists $::env(HOME)/_test_] && [file writable $::env(HOME)]}]
# set up a long data file for some of the following tests
set path(longfile) [makeFile {} longfile]
set f [open $path(longfile) w]
| | | | | 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 |
testConstraint makeFileInHome [expr {![file exists $::env(HOME)/_test_] && [file writable $::env(HOME)]}]
# set up a long data file for some of the following tests
set path(longfile) [makeFile {} longfile]
set f [open $path(longfile) w]
chan configure $f -translation lf
for { set i 0 } { $i < 100 } { incr i} {
chan puts $f "#123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
\#123456789abcdef01
\#"
}
chan close $f
set path(cat) [makeFile {
set f stdin
if {$argv != ""} {
set f [open [lindex $argv 0]]
}
chan configure $f -translation binary -blocking 0 -eofchar \x1A
chan configure stdout -translation binary -buffering none
chan event $f readable "foo $f"
proc foo {f} {
set x [chan read $f]
catch {chan puts -nonewline $x}
if {[chan eof $f]} {
chan close $f
exit 0
|
| ︙ | ︙ | |||
113 114 115 116 117 118 119 |
test chan-io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
# no test, need to cause an async error.
} {}
set path(test1) [makeFile {} test1]
test chan-io-1.6 {Tcl_WriteChars: WriteBytes} {
set f [open $path(test1) w]
| | | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
test chan-io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
# no test, need to cause an async error.
} {}
set path(test1) [makeFile {} test1]
test chan-io-1.6 {Tcl_WriteChars: WriteBytes} {
set f [open $path(test1) w]
chan configure $f -translation binary
chan puts -nonewline $f "a\x4D\x00"
chan close $f
contents $path(test1)
} aM\x00
test chan-io-1.7 {Tcl_WriteChars: WriteChars} {
set f [open $path(test1) w]
chan configure $f -encoding shiftjis
|
| ︙ | ︙ | |||
182 183 184 185 186 187 188 |
chan close $f
lappend sizes [file size $path(test2)]
} {19 19 19 19 19}
test chan-io-2.1 {WriteBytes} {
# loop until all bytes are written
set f [open $path(test1) w]
| | | | | < | 182 183 184 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 220 221 222 223 224 |
chan close $f
lappend sizes [file size $path(test2)]
} {19 19 19 19 19}
test chan-io-2.1 {WriteBytes} {
# loop until all bytes are written
set f [open $path(test1) w]
chan configure $f -translation binary -buffersize 16 -translation crlf
chan puts $f "abcdefghijklmnopqrstuvwxyz"
chan close $f
contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test chan-io-2.2 {WriteBytes: savedLF > 0} {
# After flushing buffer, there was a \n left over from the last
# \n -> \r\n expansion. It gets stuck at beginning of this buffer.
set f [open $path(test1) w]
chan configure $f -translation binary -buffersize 16 -translation crlf
chan puts -nonewline $f "123456789012345\n12"
set x [list [contents $path(test1)]]
chan close $f
lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test chan-io-2.3 {WriteBytes: flush on line} -body {
# Tcl "line" buffering has weird behavior: if current buffer contains a
# \n, entire buffer gets flushed. Logical behavior would be to flush only
# up to the \n.
set f [open $path(test1) w]
chan configure $f -translation binary -buffering line -translation crlf
chan puts -nonewline $f "\n12"
contents $path(test1)
} -cleanup {
chan close $f
} -result "\r\n12"
test chan-io-2.4 {WriteBytes: reset sawLF after each buffer} {
set f [open $path(test1) w]
chan configure $f -translation binary -buffering line -buffersize 16
chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
set x [list [contents $path(test1)]]
chan close $f
lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
test chan-io-3.1 {WriteChars: compatibility with WriteBytes} {
|
| ︙ | ︙ | |||
365 366 367 368 369 370 371 |
chan puts -nonewline $f "12345678901\n456789012345678901234"
chan close $f
set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"
test chan-io-5.1 {CheckFlush: not full} {
set f [open $path(test1) w]
| < | 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
chan puts -nonewline $f "12345678901\n456789012345678901234"
chan close $f
set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"
test chan-io-5.1 {CheckFlush: not full} {
set f [open $path(test1) w]
chan puts -nonewline $f "12345678901234567890"
set x [list [contents $path(test1)]]
chan close $f
lappend x [contents $path(test1)]
} [list "" "12345678901234567890"]
test chan-io-5.2 {CheckFlush: full} {
set f [open $path(test1) w]
|
| ︙ | ︙ | |||
1077 1078 1079 1080 1081 1082 1083 |
chan gets $f
} -cleanup {
chan close $f
} -result "123456789012301234"
test chan-io-7.2 {FilterInputBytes: split up character in middle of buffer} -body {
# (bufPtr->nextAdded < bufPtr->bufLength)
set f [open $path(test1) w]
| | | | | | 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 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 |
chan gets $f
} -cleanup {
chan close $f
} -result "123456789012301234"
test chan-io-7.2 {FilterInputBytes: split up character in middle of buffer} -body {
# (bufPtr->nextAdded < bufPtr->bufLength)
set f [open $path(test1) w]
chan configure $f -translation binary
chan puts -nonewline $f "1234567890\n123\x82\x4F\x82\x50\x82"
chan close $f
set f [open $path(test1)]
chan configure $f -encoding shiftjis
list [chan gets $f line] $line [chan eof $f]
} -cleanup {
chan close $f
} -result {10 1234567890 0}
test chan-io-7.3 {FilterInputBytes: split up character at EOF} -setup {
set x ""
} -constraints {testchannel} -body {
set f [open $path(test1) w]
chan configure $f -translation binary
chan puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82"
chan close $f
set f [open $path(test1)]
chan configure $f -encoding shiftjis -profile tcl8
lappend x [chan gets $f line] $line
lappend x [chan tell $f] [testchannel inputbuffered $f] [chan eof $f]
lappend x [chan gets $f line] $line
} -cleanup {
chan close $f
} -result [list 16 "123456789012301\x82" 18 0 1 -1 ""]
test chan-io-7.4 {FilterInputBytes: recover from split up character} -setup {
variable x ""
} -constraints {stdio fileevent} -body {
set f [openpipe w+ $path(cat)]
chan configure $f -translation binary -buffering none
chan puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82"
chan configure $f -encoding shiftjis -blocking 0
chan event $f read [namespace code {
lappend x [chan gets $f line] $line [chan blocked $f]
}]
vwait [namespace which -variable x]
chan configure $f -translation binary -blocking 1
chan puts $f "\x51\x82\x52"
chan configure $f -encoding shiftjis
vwait [namespace which -variable x]
return $x
} -cleanup {
chan close $f
} -result [list -1 "" 1 17 "12345678901230123" 0]
|
| ︙ | ︙ | |||
1174 1175 1176 1177 1178 1179 1180 |
test chan-io-8.4 {PeekAhead: cached data available in this buffer} -body {
# not (bytesLeft == 0)
set f [open $path(test1) w+]
chan configure $f -translation binary
chan puts $f "${a}\r\nabcdef"
chan close $f
set f [open $path(test1)]
| | | 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 |
test chan-io-8.4 {PeekAhead: cached data available in this buffer} -body {
# not (bytesLeft == 0)
set f [open $path(test1) w+]
chan configure $f -translation binary
chan puts $f "${a}\r\nabcdef"
chan close $f
set f [open $path(test1)]
chan configure $f -translation binary -translation auto
# "${a}\r" was converted in one operation (because ENCODING_LINESIZE is
# 30). To check if "\n" follows, calls PeekAhead and determines that
# cached data is available in buffer w/o having to call driver.
chan gets $f
} -cleanup {
chan close $f
} -result $a
|
| ︙ | ︙ | |||
1279 1280 1281 1282 1283 1284 1285 |
test chan-io-11.1 {ReadBytes: want to read a lot} -body {
# ((unsigned) toRead > (unsigned) srcLen)
set f [open $path(test1) w]
chan puts -nonewline $f abcdefghijkl
chan close $f
set f [open $path(test1)]
| | | | | | 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 |
test chan-io-11.1 {ReadBytes: want to read a lot} -body {
# ((unsigned) toRead > (unsigned) srcLen)
set f [open $path(test1) w]
chan puts -nonewline $f abcdefghijkl
chan close $f
set f [open $path(test1)]
chan configure $f -translation binary
# here
chan read $f 1000
} -cleanup {
chan close $f
} -result {abcdefghijkl}
test chan-io-11.2 {ReadBytes: want to read all} -body {
# ((unsigned) toRead > (unsigned) srcLen)
set f [open $path(test1) w]
chan puts -nonewline $f abcdefghijkl
chan close $f
set f [open $path(test1)]
chan configure $f -translation binary
# here
chan read $f
} -cleanup {
chan close $f
} -result {abcdefghijkl}
test chan-io-11.3 {ReadBytes: allocate more space} -body {
# (toRead > length - offset - 1)
set f [open $path(test1) w]
chan puts -nonewline $f abcdefghijklmnopqrstuvwxyz
chan close $f
set f [open $path(test1)]
chan configure $f -buffersize 16 -translation binary
# here
chan read $f
} -cleanup {
chan close $f
} -result {abcdefghijklmnopqrstuvwxyz}
test chan-io-11.4 {ReadBytes: EOF char found} -body {
# (TranslateInputEOL() != 0)
set f [open $path(test1) w]
chan puts $f abcdefghijklmnopqrstuvwxyz
chan close $f
set f [open $path(test1)]
chan configure $f -translation binary -eofchar m
# here
list [chan read $f] [chan eof $f] [chan read $f] [chan eof $f]
} -cleanup {
chan close $f
} -result {abcdefghijkl 1 {} 1}
test chan-io-12.1 {ReadChars: want to read a lot} -body {
|
| ︙ | ︙ | |||
1361 1362 1363 1364 1365 1366 1367 |
chan close $f
} -result {abcdefghijklmnopqrstuvwxyz}
test chan-io-12.4 {ReadChars: split-up char} -setup {
variable x {}
} -constraints {stdio testchannel fileevent} -body {
# (srcRead == 0)
set f [openpipe w+ $path(cat)]
| | | | | 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 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 |
chan close $f
} -result {abcdefghijklmnopqrstuvwxyz}
test chan-io-12.4 {ReadChars: split-up char} -setup {
variable x {}
} -constraints {stdio testchannel fileevent} -body {
# (srcRead == 0)
set f [openpipe w+ $path(cat)]
chan configure $f -translation binary -buffering none -buffersize 16
chan puts -nonewline $f "123456789012345\x96"
chan configure $f -encoding shiftjis -blocking 0
chan event $f read [namespace code {
lappend x [chan read $f] [testchannel inputbuffered $f]
}]
chan configure $f -encoding shiftjis
vwait [namespace which -variable x]
chan configure $f -translation binary -blocking 1
chan puts -nonewline $f \x7B
after 500 ;# Give the cat process time to catch up
chan configure $f -encoding shiftjis -blocking 0
vwait [namespace which -variable x]
return $x
} -cleanup {
chan close $f
} -result [list "123456789012345" 1 本 0]
test chan-io-12.5 {ReadChars: chan events on partial characters} -setup {
variable x {}
} -constraints {stdio fileevent} -body {
set path(test1) [makeFile {
chan configure stdout -translation binary -buffering none
chan gets stdin; chan puts -nonewline \xE7
chan gets stdin; chan puts -nonewline \x89
chan gets stdin; chan puts -nonewline \xA6
} test1]
set f [openpipe r+ $path(test1)]
chan event $f readable [namespace code {
lappend x [chan read $f]
|
| ︙ | ︙ | |||
1949 1950 1951 1952 1953 1954 1955 |
chan close $f
} -result "file"
test chan-io-25.1 {Tcl_GetChannelHandle, input} -setup {
set l ""
} -constraints {testchannel} -body {
set f [open $path(test1) w]
| | | 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 |
chan close $f
} -result "file"
test chan-io-25.1 {Tcl_GetChannelHandle, input} -setup {
set l ""
} -constraints {testchannel} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f "1234567890\n098765432"
chan close $f
set f [open $path(test1) r]
chan gets $f
lappend l [testchannel inputbuffered $f]
lappend l [chan tell $f]
} -cleanup {
|
| ︙ | ︙ | |||
2001 2002 2003 2004 2005 2006 2007 |
chan close $f
} -result 0
test chan-io-27.2 {FlushChannel, some output buffered} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
| | | | | | | 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 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 2070 2071 2072 |
chan close $f
} -result 0
test chan-io-27.2 {FlushChannel, some output buffered} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f hello
lappend l [file size $path(test1)]
chan flush $f
lappend l [file size $path(test1)]
chan close $f
lappend l [file size $path(test1)]
} -result {0 6 6}
test chan-io-27.3 {FlushChannel, implicit flush on chan close} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f hello
lappend l [file size $path(test1)]
chan close $f
lappend l [file size $path(test1)]
} -result {0 6}
test chan-io-27.4 {FlushChannel, implicit flush when buffer fills} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan configure $f -buffersize 60
lappend l [file size $path(test1)]
for {set i 0} {$i < 12} {incr i} {
chan puts $f hello
}
lappend l [file size $path(test1)]
chan flush $f
lappend l [file size $path(test1)]
} -cleanup {
chan close $f
} -result {0 60 72}
test chan-io-27.5 {FlushChannel, implicit flush when buffer fills and on chan close} -setup {
file delete $path(test1)
set l ""
} -constraints {unixOrWin} -body {
set f [open $path(test1) w]
chan configure $f -translation lf -buffersize 60
lappend l [file size $path(test1)]
for {set i 0} {$i < 12} {incr i} {
chan puts $f hello
}
lappend l [file size $path(test1)]
chan close $f
lappend l [file size $path(test1)]
} -result {0 60 72}
set path(pipe) [makeFile {} pipe]
set path(output) [makeFile {} output]
test chan-io-27.6 {FlushChannel, async flushing, async chan close} -setup {
file delete $path(pipe)
file delete $path(output)
} -constraints {stdio asyncPipeChan Close} -body {
set f [open $path(pipe) w]
chan puts $f "set f \[[list open $path(output) w]]"
chan puts $f {
chan configure $f -translation lf -buffering none
while {![chan eof stdin]} {
after 20
chan puts -nonewline $f [chan read stdin 1024]
}
chan close $f
}
chan close $f
|
| ︙ | ︙ | |||
2129 2130 2131 2132 2133 2134 2135 |
} -result abcdef
test chan-io-28.3 {Chan CloseChannel, not called before output queue is empty} -setup {
file delete $path(pipe)
file delete $path(output)
} -constraints {stdio asyncPipeChan Close nonPortable} -body {
set f [open $path(pipe) w]
chan puts $f {
| < < < < < | | 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 |
} -result abcdef
test chan-io-28.3 {Chan CloseChannel, not called before output queue is empty} -setup {
file delete $path(pipe)
file delete $path(output)
} -constraints {stdio asyncPipeChan Close nonPortable} -body {
set f [open $path(pipe) w]
chan puts $f {
set f [open $path(output) w]
chan configure $f -translation lf -buffering none
for {set x 0} {$x < 20} {incr x} {
after 20
chan puts -nonewline $f [chan read stdin 1024]
}
chan close $f
}
chan close $f
set x 01234567890123456789012345678901
for {set i 0} {$i < 11} {incr i} {
set x "$x$x"
}
set f [open $path(output) w]
chan close $f
set f [openpipe r+ $path(pipe)]
chan configure $f -blocking off
chan puts -nonewline $f $x
chan close $f
set counter 0
while {([file size $path(output)] < 20480) && ($counter < 1000)} {
after 20 [list incr [namespace which -variable counter]]
vwait [namespace which -variable counter]
}
|
| ︙ | ︙ | |||
2267 2268 2269 2270 2271 2272 2273 |
test chan-io-29.1 {Tcl_WriteChars, channel not writable} -body {
chan puts stdin hello
} -returnCodes error -result {channel "stdin" wasn't opened for writing}
test chan-io-29.2 {Tcl_WriteChars, empty string} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
| < < | | | | | 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 |
test chan-io-29.1 {Tcl_WriteChars, channel not writable} -body {
chan puts stdin hello
} -returnCodes error -result {channel "stdin" wasn't opened for writing}
test chan-io-29.2 {Tcl_WriteChars, empty string} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan puts -nonewline $f ""
chan close $f
file size $path(test1)
} -result 0
test chan-io-29.3 {Tcl_WriteChars, nonempty string} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan puts -nonewline $f hello
chan close $f
file size $path(test1)
} -result 5
test chan-io-29.4 {Tcl_WriteChars, buffering in full buffering mode} -setup {
file delete $path(test1)
set l ""
} -constraints {testchannel} -body {
set f [open $path(test1) w]
chan configure $f -translation lf -buffering full
chan puts $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
chan flush $f
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
} -cleanup {
chan close $f
} -result {6 0 0 6}
test chan-io-29.5 {Tcl_WriteChars, buffering in line buffering mode} -setup {
file delete $path(test1)
set l ""
} -constraints {testchannel} -body {
set f [open $path(test1) w]
chan configure $f -translation lf -buffering line
chan puts -nonewline $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
chan puts $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
} -cleanup {
chan close $f
} -result {5 0 0 11}
test chan-io-29.6 {Tcl_WriteChars, buffering in no buffering mode} -setup {
file delete $path(test1)
set l ""
} -constraints {testchannel} -body {
set f [open $path(test1) w]
chan configure $f -translation lf -buffering none
chan puts -nonewline $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
chan puts $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
} -cleanup {
chan close $f
} -result {0 5 0 11}
test chan-io-29.7 {Tcl_Flush, full buffering} -setup {
file delete $path(test1)
set l ""
} -constraints {testchannel} -body {
set f [open $path(test1) w]
chan configure $f -translation lf -buffering full
chan puts -nonewline $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
chan puts $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
chan flush $f
|
| ︙ | ︙ | |||
2372 2373 2374 2375 2376 2377 2378 |
test chan-io-29.9 {Tcl_Flush, channel not writable} -body {
chan flush stdin
} -returnCodes error -result {channel "stdin" wasn't opened for writing}
test chan-io-29.10 {Tcl_WriteChars, looping and buffering} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
| | < | 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 |
test chan-io-29.9 {Tcl_Flush, channel not writable} -body {
chan flush stdin
} -returnCodes error -result {channel "stdin" wasn't opened for writing}
test chan-io-29.10 {Tcl_WriteChars, looping and buffering} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
set f2 [open $path(longfile) r]
for {set x 0} {$x < 10} {incr x} {
chan puts $f1 [chan gets $f2]
}
chan close $f2
chan close $f1
file size $path(test1)
} -result 387
test chan-io-29.11 {Tcl_WriteChars, no newline, implicit flush} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
set f2 [open $path(longfile) r]
for {set x 0} {$x < 10} {incr x} {
chan puts -nonewline $f1 [chan gets $f2]
}
chan close $f1
chan close $f2
file size $path(test1)
|
| ︙ | ︙ | |||
2519 2520 2521 2522 2523 2524 2525 |
} -cleanup {
chan close $f1
} -result {18 24 30}
test chan-io-29.19 {Explicit and implicit flushes} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
| | | | 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 |
} -cleanup {
chan close $f1
} -result {18 24 30}
test chan-io-29.19 {Explicit and implicit flushes} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
set x ""
chan puts $f1 hello
chan puts $f1 hello
chan puts $f1 hello
chan flush $f1
lappend x [file size $path(test1)]
chan puts $f1 hello
chan flush $f1
lappend x [file size $path(test1)]
chan puts $f1 hello
chan close $f1
lappend x [file size $path(test1)]
} -result {18 24 30}
test chan-io-29.20 {Implicit flush when buffer is full} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
set line "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
for {set x 0} {$x < 100} {incr x} {
chan puts $f1 $line
}
set z ""
lappend z [file size $path(test1)]
for {set x 0} {$x < 100} {incr x} {
|
| ︙ | ︙ | |||
2678 2679 2680 2681 2682 2683 2684 |
}
string tolower $x
} -match glob -result {1 {error flushing "*": broken pipe} {posix epipe {broken pipe}}}
test chan-io-29.28 {Tcl_WriteChars, lf mode} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
| | | | | 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 |
}
string tolower $x
} -match glob -result {1 {error flushing "*": broken pipe} {posix epipe {broken pipe}}}
test chan-io-29.28 {Tcl_WriteChars, lf mode} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f hello\nthere\nand\nhere
chan flush $f
file size $path(test1)
} -cleanup {
chan close $f
} -result 21
test chan-io-29.29 {Tcl_WriteChars, cr mode} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation cr
chan puts $f hello\nthere\nand\nhere
chan close $f
file size $path(test1)
} -result 21
test chan-io-29.30 {Tcl_WriteChars, crlf mode} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation crlf
chan puts $f hello\nthere\nand\nhere
chan close $f
file size $path(test1)
} -result 25
test chan-io-29.31 {Tcl_WriteChars, background flush} -setup {
file delete $path(pipe)
file delete $path(output)
|
| ︙ | ︙ | |||
3176 3177 3178 3179 3180 3181 3182 |
chan close $f
} -result {abc def 0 {} 1 {} 1}
test chan-io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
| | | | | | | | 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 |
chan close $f
} -result {abc def 0 {} 1 {} 1}
test chan-io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation lf
lappend l [chan gets $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
} -cleanup {
chan close $f
} -result "abc def 0 \x1Aghi 0 qrs 0 {} 1"
test chan-io-30.21 {Tcl_Write, ^Z in middle ignored, Tcl_Read cr} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation cr
set x [chan gets $f]
lappend l [string equal $x "abc\ndef\n\x1Aghi\nqrs\n"]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
} -cleanup {
chan close $f
} -result {1 1 {} 1}
test chan-io-30.22 {Tcl_Write, ^Z in middle ignored, Tcl_Read crlf} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f [format "abc\ndef\n%cghi\nqrs" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation crlf
set x [chan gets $f]
lappend l [string equal $x "abc\ndef\n\x1Aghi\nqrs\n"]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
} -cleanup {
chan close $f
|
| ︙ | ︙ | |||
3730 3731 3732 3733 3734 3735 3736 |
chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
| | | | | | | | 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 |
chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation lf
lappend l [chan gets $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
} -cleanup {
chan close $f
} -result "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test chan-io-31.23 {Tcl_Write, ^Z in middle ignored, Tcl_Gets cr} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation cr
chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation cr
lappend l [chan gets $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
} -cleanup {
chan close $f
} -result "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test chan-io-31.24 {Tcl_Write, ^Z in middle ignored, Tcl_Gets crlf} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation crlf
chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation crlf
lappend l [chan gets $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
|
| ︙ | ︙ | |||
3832 3833 3834 3835 3836 3837 3838 |
chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
| | | | | | 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 |
chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation cr
chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation auto -eofchar \x1A
lappend l [chan gets $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
} -cleanup {
chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.28 {Tcl_Write cr, ^Z in middle, Tcl_Gets cr} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation cr
chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation cr -eofchar \x1A
lappend l [chan gets $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
} -cleanup {
chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.29 {Tcl_Write crlf, ^Z in middle, Tcl_Gets auto} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation crlf
chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation auto -eofchar \x1A
lappend l [chan gets $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
} -cleanup {
chan close $f
} -result {abc def 0 {} 1}
test chan-io-31.30 {Tcl_Write crlf, ^Z in middle, Tcl_Gets crlf} -setup {
file delete $path(test1)
set l ""
} -body {
set f [open $path(test1) w]
chan configure $f -translation crlf
chan puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
chan close $f
set f [open $path(test1) r]
chan configure $f -translation crlf -eofchar \x1A
lappend l [chan gets $f]
lappend l [chan gets $f]
lappend l [chan eof $f]
|
| ︙ | ︙ | |||
4217 4218 4219 4220 4221 4222 4223 |
set x 24
chan gets $f x(0)
} -returnCodes error -cleanup {
chan close $f
} -result {can't set "x(0)": variable isn't array}
test chan-io-33.8 {Tcl_Gets, exercising double buffering} {
set f [open $path(test3) w]
| | | | | 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 |
set x 24
chan gets $f x(0)
} -returnCodes error -cleanup {
chan close $f
} -result {can't set "x(0)": variable isn't array}
test chan-io-33.8 {Tcl_Gets, exercising double buffering} {
set f [open $path(test3) w]
chan configure $f -translation lf
set x ""
for {set y 0} {$y < 99} {incr y} {set x "a$x"}
for {set y 0} {$y < 100} {incr y} {chan puts $f $x}
chan close $f
set f [open $path(test3) r]
chan configure $f -translation lf
for {set y 0} {$y < 100} {incr y} {chan gets $f}
chan close $f
set y
} 100
test chan-io-33.9 {Tcl_Gets, exercising double buffering} {
set f [open $path(test3) w]
chan configure $f -translation lf
set x ""
for {set y 0} {$y < 99} {incr y} {set x "a$x"}
for {set y 0} {$y < 200} {incr y} {chan puts $f $x}
chan close $f
set f [open $path(test3) r]
chan configure $f -translation lf
for {set y 0} {$y < 200} {incr y} {chan gets $f}
chan close $f
set y
} 200
test chan-io-33.10 {Tcl_Gets, exercising double buffering} {
set f [open $path(test3) w]
chan configure $f -translation lf
set x ""
for {set y 0} {$y < 99} {incr y} {set x "a$x"}
for {set y 0} {$y < 300} {incr y} {chan puts $f $x}
chan close $f
set f [open $path(test3) r]
chan configure $f -translation lf
for {set y 0} {$y < 300} {incr y} {chan gets $f}
|
| ︙ | ︙ | |||
4268 4269 4270 4271 4272 4273 4274 |
} -cleanup {
chan close $f1
} -result 0
test chan-io-34.2 {Tcl_Seek to offset from start} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
| | | | | | | | 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 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 |
} -cleanup {
chan close $f1
} -result 0
test chan-io-34.2 {Tcl_Seek to offset from start} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan close $f1
set f1 [open $path(test1) r]
chan seek $f1 10 start
chan tell $f1
} -cleanup {
chan close $f1
} -result 10
test chan-io-34.3 {Tcl_Seek to end of file} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan close $f1
set f1 [open $path(test1) r]
chan seek $f1 0 end
chan tell $f1
} -cleanup {
chan close $f1
} -result 54
test chan-io-34.4 {Tcl_Seek to offset from end of file} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan close $f1
set f1 [open $path(test1) r]
chan seek $f1 -10 end
chan tell $f1
} -cleanup {
chan close $f1
} -result 44
test chan-io-34.5 {Tcl_Seek to offset from current position} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan close $f1
set f1 [open $path(test1) r]
chan seek $f1 10 current
chan seek $f1 10 current
chan tell $f1
} -cleanup {
chan close $f1
} -result 20
test chan-io-34.6 {Tcl_Seek to offset from end of file} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan close $f1
set f1 [open $path(test1) r]
chan seek $f1 -10 end
list [chan tell $f1] [chan read $f1]
} -cleanup {
chan close $f1
} -result {44 {rstuvwxyz
}}
test chan-io-34.7 {Tcl_Seek to offset from end of file, then to current position} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan close $f1
set f1 [open $path(test1) r]
chan seek $f1 -10 end
set c1 [chan tell $f1]
set r1 [chan read $f1 5]
|
| ︙ | ︙ | |||
4364 4365 4366 4367 4368 4369 4370 |
} -returnCodes error -cleanup {
chan close $pipe
} -match glob -result {error during seek on "*": invalid argument}
test chan-io-34.9 {Tcl_Seek, testing buffered input flushing} -setup {
file delete $path(test3)
} -body {
set f [open $path(test3) w]
| < | 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 |
} -returnCodes error -cleanup {
chan close $pipe
} -match glob -result {error during seek on "*": invalid argument}
test chan-io-34.9 {Tcl_Seek, testing buffered input flushing} -setup {
file delete $path(test3)
} -body {
set f [open $path(test3) w]
chan puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
chan close $f
set f [open $path(test3) RDWR]
set x [chan read $f 1]
chan seek $f 3
lappend x [chan read $f 1]
chan seek $f 0 start
|
| ︙ | ︙ | |||
4412 4413 4414 4415 4416 4417 4418 |
chan seek $f 2
set x [chan gets $f]
chan close $f
list $x [viewFile test3]
} "zzy xyzzy"
test chan-io-34.12 {Tcl_Seek testing combination of write, seek back and read} {
set f [open $path(test3) w]
| | | | 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 |
chan seek $f 2
set x [chan gets $f]
chan close $f
list $x [viewFile test3]
} "zzy xyzzy"
test chan-io-34.12 {Tcl_Seek testing combination of write, seek back and read} {
set f [open $path(test3) w]
chan configure $f -translation lf
chan puts $f xyz\n123
chan close $f
set f [open $path(test3) a+]
chan configure $f -translation lf
chan puts $f xyzzy
chan flush $f
set x [chan tell $f]
chan seek $f -4 cur
set y [chan gets $f]
chan close $f
list $x [viewFile test3] $y
|
| ︙ | ︙ | |||
4439 4440 4441 4442 4443 4444 4445 |
} -cleanup {
chan close $f1
} -result 0
test chan-io-34.14 {Tcl_Tell after seek to end of file} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
| | | | 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 |
} -cleanup {
chan close $f1
} -result 0
test chan-io-34.14 {Tcl_Tell after seek to end of file} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan close $f1
set f1 [open $path(test1) r]
chan seek $f1 0 end
chan tell $f1
} -cleanup {
chan close $f1
} -result 54
test chan-io-34.15 {Tcl_Tell combined with seeking} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan puts $f1 "abcdefghijklmnopqrstuvwxyz"
chan close $f1
set f1 [open $path(test1) r]
chan seek $f1 10 start
set c1 [chan tell $f1]
chan seek $f1 10 current
|
| ︙ | ︙ | |||
4484 4485 4486 4487 4488 4489 4490 |
chan close $f1
set c
} -1
test chan-io-34.18 {Tcl_Tell combined with seeking and reading} -setup {
file delete $path(test2)
} -body {
set f [open $path(test2) w]
| | | | 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 |
chan close $f1
set c
} -1
test chan-io-34.18 {Tcl_Tell combined with seeking and reading} -setup {
file delete $path(test2)
} -body {
set f [open $path(test2) w]
chan configure $f -translation lf
chan puts -nonewline $f "line1\nline2\nline3\nline4\nline5\n"
chan close $f
set f [open $path(test2)]
chan configure $f -translation lf
set x [chan tell $f]
chan read $f 3
lappend x [chan tell $f]
chan seek $f 2
lappend x [chan tell $f]
chan seek $f 10 current
lappend x [chan tell $f]
chan seek $f 0 end
lappend x [chan tell $f]
} -cleanup {
chan close $f
} -result {0 3 2 12 30}
test chan-io-34.19 {Tcl_Tell combined with opening in append mode} -body {
set f [open $path(test3) w]
chan configure $f -translation lf
chan puts $f "abcdefghijklmnopqrstuvwxyz"
chan puts $f "abcdefghijklmnopqrstuvwxyz"
chan close $f
set f [open $path(test3) a]
chan tell $f
} -cleanup {
chan close $f
|
| ︙ | ︙ | |||
4533 4534 4535 4536 4537 4538 4539 |
chan close $f
} -result {29 39 40 447}
test chan-io-34.21 {Tcl_Seek and Tcl_Tell on large files} -setup {
file delete $path(test3)
set l ""
} -constraints {largefileSupport extensive} -body {
set f [open $path(test3) w]
| | | 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 |
chan close $f
} -result {29 39 40 447}
test chan-io-34.21 {Tcl_Seek and Tcl_Tell on large files} -setup {
file delete $path(test3)
set l ""
} -constraints {largefileSupport extensive} -body {
set f [open $path(test3) w]
chan configure $f -translation binary
lappend l [chan tell $f]
chan puts -nonewline $f abcdef
lappend l [chan tell $f]
chan flush $f
lappend l [chan tell $f]
# 4GB offset!
chan seek $f 0x100000000
|
| ︙ | ︙ | |||
4730 4731 4732 4733 4734 4735 4736 |
} -cleanup {
chan close $f
} -result {10 8 1}
test chan-io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
| | | | | | | | 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 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 |
} -cleanup {
chan close $f
} -result {10 8 1}
test chan-io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
chan close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
chan configure $f -translation auto -eofchar \x1A
list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
chan close $f
} -result {17 8 1}
test chan-io-35.13 {Tcl_Eof, eof char in middle, lf write, lf read} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation lf
chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
chan close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
chan configure $f -translation lf -eofchar \x1A
list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
chan close $f
} -result {17 8 1}
test chan-io-35.14 {Tcl_Eof, eof char in middle, cr write, auto read} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation cr
chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
chan close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
chan configure $f -translation auto -eofchar \x1A
list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
chan close $f
} -result {17 8 1}
test chan-io-35.15 {Tcl_Eof, eof char in middle, cr write, cr read} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation cr
chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
chan close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
chan configure $f -translation cr -eofchar \x1A
list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
chan close $f
} -result {17 8 1}
test chan-io-35.16 {Tcl_Eof, eof char in middle, crlf write, auto read} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation crlf
chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
chan close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
chan configure $f -translation auto -eofchar \x1A
list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
chan close $f
} -result {21 8 1}
test chan-io-35.17 {Tcl_Eof, eof char in middle, crlf write, crlf read} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation crlf
chan puts $f [format abc\ndef\n%cqrs\nuvw 26]
chan close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
chan configure $f -translation crlf -eofchar \x1A
list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
|
| ︙ | ︙ | |||
5074 5075 5076 5077 5078 5079 5080 |
chan close $f1
} -result {0 21}
test chan-io-39.8 {Tcl_SetChannelOption, different buffering options} -setup {
file delete $path(test1)
set l ""
} -body {
set f1 [open $path(test1) w]
| | | 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 |
chan close $f1
} -result {0 21}
test chan-io-39.8 {Tcl_SetChannelOption, different buffering options} -setup {
file delete $path(test1)
set l ""
} -body {
set f1 [open $path(test1) w]
chan configure $f1 -translation lf -buffering none
chan puts -nonewline $f1 hello
lappend l [file size $path(test1)]
chan puts -nonewline $f1 hello
lappend l [file size $path(test1)]
chan configure $f1 -buffering full
chan puts -nonewline $f1 hello
lappend l [file size $path(test1)]
|
| ︙ | ︙ | |||
5174 5175 5176 5177 5178 5179 5180 |
} -cleanup {
chan close $f
} -result 40000
test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
| | | | | | 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 |
} -cleanup {
chan close $f
} -result 40000
test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation binary
chan puts -nonewline $f \xE7\x89\xA6
chan close $f
set f [open $path(test1) r]
chan configure $f -encoding utf-8
chan read $f
} -cleanup {
chan close $f
} -result 牦
test chan-io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup {
file delete $path(test1)
} -body {
set f [open $path(test1) w]
chan configure $f -translation binary
chan puts -nonewline $f \xE7\x89\xA6
chan close $f
set f [open $path(test1) r]
chan configure $f -encoding utf-8
chan read $f
} -cleanup {
chan close $f
} -result 牦
test chan-io-39.16 {Tcl_SetChannelOption: -encoding, errors} -setup {
file delete $path(test1)
set f [open $path(test1) w]
} -body {
chan configure $f -encoding foobar
} -returnCodes error -cleanup {
chan close $f
} -result {unknown encoding "foobar"}
test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} -setup {
variable x {}
} -constraints {stdio fileevent} -body {
set f [openpipe r+ $path(cat)]
chan configure $f -encoding iso8859-1
chan puts -nonewline $f \xE7
chan flush $f
chan configure $f -encoding utf-8 -blocking 0
chan event $f readable [namespace code { lappend x [chan read $f] }]
vwait [namespace which -variable x]
after 300 [namespace code { lappend x timeout }]
vwait [namespace which -variable x]
chan configure $f -encoding utf-8
vwait [namespace which -variable x]
after 300 [namespace code { lappend x timeout }]
vwait [namespace which -variable x]
chan configure $f -encoding iso8859-1
vwait [namespace which -variable x]
after 300 [namespace code { lappend x timeout }]
vwait [namespace which -variable x]
return $x
} -cleanup {
chan close $f
} -result "{} timeout {} timeout \xE7 timeout"
|
| ︙ | ︙ | |||
5371 5372 5373 5374 5375 5376 5377 |
file stat $path(test3) stats
format 0o%03o [expr {$stats(mode) & 0o777}]
} -result [format 0o%03o [expr {0o666 & ~ $umaskValue}]]
test chan-io-40.4 {POSIX open access modes: CREAT} -setup {
file delete $path(test3)
} -body {
set f [open $path(test3) w]
| < < | | 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 |
file stat $path(test3) stats
format 0o%03o [expr {$stats(mode) & 0o777}]
} -result [format 0o%03o [expr {0o666 & ~ $umaskValue}]]
test chan-io-40.4 {POSIX open access modes: CREAT} -setup {
file delete $path(test3)
} -body {
set f [open $path(test3) w]
chan puts $f xyzzy
chan close $f
set f [open $path(test3) {WRONLY CREAT}]
chan puts -nonewline $f "ab"
chan close $f
set f [open $path(test3) r]
chan gets $f
} -cleanup {
chan close $f
} -result abzzy
test chan-io-40.5 {POSIX open access modes: APPEND} -setup {
file delete $path(test3)
set x ""
} -body {
set f [open $path(test3) w]
chan configure $f -translation lf
chan puts $f xyzzy
chan close $f
set f [open $path(test3) {WRONLY APPEND}]
chan configure $f -translation lf
chan puts $f "new line"
chan seek $f 0
chan puts $f "abc"
|
| ︙ | ︙ | |||
5417 5418 5419 5420 5421 5422 5423 |
chan close $f
open $path(test3) {WRONLY CREAT EXCL}
} -returnCodes error -result {(?i)couldn't open ".*test3": file (already )?exists}
test chan-io-40.7 {POSIX open access modes: EXCL} -setup {
file delete $path(test3)
} -body {
set f [open $path(test3) {WRONLY CREAT EXCL}]
| < | 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 |
chan close $f
open $path(test3) {WRONLY CREAT EXCL}
} -returnCodes error -result {(?i)couldn't open ".*test3": file (already )?exists}
test chan-io-40.7 {POSIX open access modes: EXCL} -setup {
file delete $path(test3)
} -body {
set f [open $path(test3) {WRONLY CREAT EXCL}]
chan puts $f "A test line"
chan close $f
viewFile test3
} -result {A test line}
test chan-io-40.8 {POSIX open access modes: TRUNC} -setup {
file delete $path(test3)
} -body {
|
| ︙ | ︙ | |||
5468 5469 5470 5471 5472 5473 5474 |
test chan-io-40.12 {POSIX open access modes: WRONLY} -match regexp -body {
file delete $path(test3)
open $path(test3) WRONLY
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test chan-io-40.13 {POSIX open access modes: WRONLY} -body {
makeFile xyzzy test3
set f [open $path(test3) WRONLY]
| < | 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 |
test chan-io-40.12 {POSIX open access modes: WRONLY} -match regexp -body {
file delete $path(test3)
open $path(test3) WRONLY
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test chan-io-40.13 {POSIX open access modes: WRONLY} -body {
makeFile xyzzy test3
set f [open $path(test3) WRONLY]
chan puts -nonewline $f "ab"
chan seek $f 0 current
set x [list [catch {chan gets $f} msg] $msg]
chan close $f
lappend x [viewFile test3]
} -match glob -result {1 {channel "*" wasn't opened for reading} abzzy}
test chan-io-40.14 {POSIX open access modes: RDWR} -match regexp -body {
|
| ︙ | ︙ | |||
5501 5502 5503 5504 5505 5506 5507 |
} -cleanup {
file delete ./~ ;# ./ because don't want to delete home in case of bugs!
cd $curdir
} -result 1
test chan-io-41.1 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
chan event foo
| | | | 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 |
} -cleanup {
file delete ./~ ;# ./ because don't want to delete home in case of bugs!
cd $curdir
} -result 1
test chan-io-41.1 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
chan event foo
} -returnCodes error -result {wrong # args: should be "chan event channel event ?script?"}
test chan-io-41.2 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
chan event foo bar baz q
} -returnCodes error -result {wrong # args: should be "chan event channel event ?script?"}
test chan-io-41.3 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
chan event gorp readable
} -returnCodes error -result {can not find channel named "gorp"}
test chan-io-41.4 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
chan event gorp writable
} -returnCodes error -result {can not find channel named "gorp"}
test chan-io-41.5 {Tcl_FileeventCmd: errors} -constraints fileevent -body {
|
| ︙ | ︙ | |||
6731 6732 6733 6734 6735 6736 6737 |
lappend result [file size $path(test1)]
} -result {0 0 40}
test chan-io-52.5 {TclCopyChannel, all} -constraints {fcopy} -setup {
file delete $path(test1)
} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
| | | | | | | | | | | | 6716 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 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 |
lappend result [file size $path(test1)]
} -result {0 0 40}
test chan-io-52.5 {TclCopyChannel, all} -constraints {fcopy} -setup {
file delete $path(test1)
} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation binary -blocking 0
chan configure $f2 -translation binary -blocking 0
chan copy $f1 $f2 -size -1 ;# -1 means 'copy all', same as if no -size specified.
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
chan close $f1
chan close $f2
if {[file size $thisScript] == [file size $path(test1)]} {
lappend result ok
}
return $result
} -result {0 0 ok}
test chan-io-52.5a {TclCopyChannel, all, other negative value} -setup {
file delete $path(test1)
} -constraints {fcopy} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation binary -blocking 0
chan configure $f2 -translation binary -blocking 0
chan copy $f1 $f2 -size -2 ;# < 0 behaves like -1, copy all
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
chan close $f1
chan close $f2
if {[file size $thisScript] == [file size $path(test1)]} {
lappend result ok
}
return $result
} -result {0 0 ok}
test chan-io-52.5b {TclCopyChannel, all, wrap to negative value} -setup {
file delete $path(test1)
} -constraints {fcopy} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation binary -blocking 0
chan configure $f2 -translation binary -blocking 0
chan copy $f1 $f2 -size 3221176172 ;# Wrapped to < 0, behaves like -1, copy all
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
chan close $f1
chan close $f2
if {[file size $thisScript] == [file size $path(test1)]} {
lappend result ok
}
return $result
} -result {0 0 ok}
test chan-io-52.6 {TclCopyChannel} -setup {
file delete $path(test1)
} -constraints {fcopy} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation binary -blocking 0
chan configure $f2 -translation binary -blocking 0
set s0 [chan copy $f1 $f2 -size [expr {[file size $thisScript] + 5}]]
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
chan close $f1
chan close $f2
set s1 [file size $thisScript]
set s2 [file size $path(test1)]
if {($s1 == $s2) && ($s0 == $s1)} {
lappend result ok
}
return $result
} -result {0 0 ok}
test chan-io-52.7 {TclCopyChannel} -constraints {fcopy} -setup {
file delete $path(test1)
} -body {
set f1 [open $thisScript]
set f2 [open $path(test1) w]
chan configure $f1 -translation binary -blocking 0
chan configure $f2 -translation binary -blocking 0
chan copy $f1 $f2
set result [list [chan configure $f1 -blocking] [chan configure $f2 -blocking]]
if {[file size $thisScript] == [file size $path(test1)]} {
lappend result ok
}
return $result
} -cleanup {
|
| ︙ | ︙ | |||
6870 6871 6872 6873 6874 6875 6876 |
[file size $path(utf8-fcopy.txt)] \
[file size $path(utf8-rp.txt)]
} {3 5 5}
test chan-io-52.10 {TclCopyChannel & encodings} -constraints {fcopy} -body {
set in [open $path(kyrillic.txt) r]
set out [open $path(utf8-fcopy.txt) w]
chan configure $in -encoding koi8-r -translation lf
| < < | 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 |
[file size $path(utf8-fcopy.txt)] \
[file size $path(utf8-rp.txt)]
} {3 5 5}
test chan-io-52.10 {TclCopyChannel & encodings} -constraints {fcopy} -body {
set in [open $path(kyrillic.txt) r]
set out [open $path(utf8-fcopy.txt) w]
chan configure $in -encoding koi8-r -translation lf
chan configure $out -translation binary
chan copy $in $out
file size $path(utf8-fcopy.txt)
} -cleanup {
chan close $in
chan close $out
unset in out
} -returnCodes 1 -match glob -result {error writing "*":\
invalid or incomplete multibyte or wide character}
test chan-io-52.11 {TclCopyChannel & encodings} -setup {
set f [open $path(utf8-fcopy.txt) w]
fconfigure $f -encoding utf-8 -translation lf
puts $f АА
close $f
} -constraints {fcopy} -body {
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
chan configure $in -translation binary
chan configure $out -encoding koi8-r -translation lf -profile strict
catch {chan copy $in $out} cres copts
return $cres
} -cleanup {
if {$in in [chan names]} {
close $in
|
| ︙ | ︙ |
Changes to tests/clock.test.
| ︙ | ︙ | |||
279 280 281 282 283 284 285 |
set i [interp create]; # because clock can be used somewhere, test it in new interp:
} -body {
$i eval {
lappend ret ens:[namespace ensemble exists ::clock]
clock seconds; # init ensemble (but not yet stubs, loading of clock.tcl retarded)
lappend ret ens:[namespace ensemble exists ::clock]
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
| | | | | | | 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 |
set i [interp create]; # because clock can be used somewhere, test it in new interp:
} -body {
$i eval {
lappend ret ens:[namespace ensemble exists ::clock]
clock seconds; # init ensemble (but not yet stubs, loading of clock.tcl retarded)
lappend ret ens:[namespace ensemble exists ::clock]
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
clock format now; # clock.tcl stubs expected
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
}
} -cleanup {
interp delete $i
} -result {ens:1 ens:1 stubs:0 stubs:1}
test clock-0.1a "initial: safe interpreter shares clock command with parent" -setup {
set i [interp create]
$i eval {set sci [interp create -safe]}
} -body {
$i eval {
lappend ret ens:[namespace ensemble exists ::clock]
$sci eval { clock seconds }; # init ensemble (but not yet stubs, loading of clock.tcl retarded)
lappend ret ens:[namespace ensemble exists ::clock]
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
$sci eval { clock format now }; # clock.tcl stubs expected
lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
}
} -cleanup {
interp delete $i
} -result {ens:1 ens:1 stubs:0 stubs:1}
test clock-0.2 "initial: loading of format/locale does not overwrite interp state (errorInfo)" -setup {
# be sure - we have no cached locale/msgcat, etc:
if {[namespace which -command ::tcl::clock::ClearCaches] ne ""} {
::tcl::clock::ClearCaches
}
} -body {
if {[catch {
return -level 0 -code error -errorcode {EXPERR TEST-ERROR} -errorinfo "ERROR expected error" test
}]} {
clock format now -locale de; # should not overwrite error code/info
list $::errorCode $::errorInfo
}
} -result {{EXPERR TEST-ERROR} {ERROR expected error}}
# Test some of the basics of [clock format]
set syntax "clockval|now ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?"
test clock-1.0 "clock format - wrong # args" {
list [catch {clock format} msg] $msg $::errorCode
} [subst {1 {wrong # args: should be "clock format $syntax"} {CLOCK wrongNumArgs}}]
test clock-1.0.1 "clock format - wrong # args (compiled ensemble with invalid syntax)" {
list [catch {clock format 0 -too-few-options-4-test} msg] $msg $::errorCode
} [subst {1 {wrong # args: should be "clock format $syntax"} {CLOCK wrongNumArgs}}]
test clock-1.1 "clock format - bad time" {
list [catch {clock format foo} msg opt] $msg [dict getd $opt -errorcode {}]
} {1 {bad seconds "foo": must be now or integer} {CLOCK badOption foo}}
test clock-1.2 "clock format - bad gmt val" {
list [catch {clock format 0 -gmt foo} msg] $msg
} {1 {expected boolean value but got "foo"}}
test clock-1.3 "clock format - empty val" {
clock format 0 -gmt 1 -format ""
|
| ︙ | ︙ | |||
363 364 365 366 367 368 369 |
clock format 0 -g true -f "%Y-%m-%d"
} 1970-01-01
test clock-1.7.1 "clock format - command abbreviations (compat regression test)" {
clock f 0 -g 1 -f "%Y-%m-%d"
} 1970-01-01
| | | | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
clock format 0 -g true -f "%Y-%m-%d"
} 1970-01-01
test clock-1.7.1 "clock format - command abbreviations (compat regression test)" {
clock f 0 -g 1 -f "%Y-%m-%d"
} 1970-01-01
test clock-1.8 "clock format now" {
# give one second more for test (if on boundary of the current second):
set n [clock format [clock seconds] -g 1 -f "%s"]
expr {[clock format now -g 1 -f "%s"] in [list $n [incr n]]}
} 1
test clock-1.9 "clock arguments: option doubly present" {
list [catch {clock format 0 -gmt 1 -gmt 0} result] $result
} {1 {bad option "-gmt": doubly present}}
test clock-1.10 {clock format: text with token (bug [a858d95f4bfddafb])} {
|
| ︙ | ︙ | |||
18700 18701 18702 18703 18704 18705 18706 |
test clock-6.8 {input of seconds} {
clock scan {9223372036854775807} -format %s -gmt true
} 9223372036854775807
test clock-6.8b "clock scan - bad base" {
list [catch {clock scan "" -base foo -gmt 1} msg opt] $msg [dict getd $opt -errorcode {}]
| | | 18700 18701 18702 18703 18704 18705 18706 18707 18708 18709 18710 18711 18712 18713 18714 |
test clock-6.8 {input of seconds} {
clock scan {9223372036854775807} -format %s -gmt true
} 9223372036854775807
test clock-6.8b "clock scan - bad base" {
list [catch {clock scan "" -base foo -gmt 1} msg opt] $msg [dict getd $opt -errorcode {}]
} {1 {bad seconds "foo": must be now or integer} {CLOCK badOption foo}}
test clock-6.9 {input of seconds - overflow} {
list [catch {clock scan -9223372036854775809 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}
test clock-6.10 {input of seconds - overflow} {
list [catch {clock scan 9223372036854775808 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}
|
| ︙ | ︙ | |||
37150 37151 37152 37153 37154 37155 37156 |
[clock scan "12:01 pm" -base 0 -gmt 1]
} -result {60 43260}
test clock-46.6 {freescan: regression test - bad time} -constraints valid_off \
-body {
# 13:00 am/pm are invalid input strings...
list [clock scan "13:00 am" -base 0 -gmt 1] \
[clock scan "13:00 pm" -base 0 -gmt 1]
| | > > > > > > > > > > > > > > > > > > > > > > | > | < > | | < < | > > > | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 37150 37151 37152 37153 37154 37155 37156 37157 37158 37159 37160 37161 37162 37163 37164 37165 37166 37167 37168 37169 37170 37171 37172 37173 37174 37175 37176 37177 37178 37179 37180 37181 37182 37183 37184 37185 37186 37187 37188 37189 37190 37191 37192 37193 37194 37195 37196 37197 37198 37199 37200 37201 37202 37203 37204 37205 37206 37207 37208 37209 37210 37211 37212 37213 37214 37215 37216 37217 37218 37219 37220 37221 37222 37223 37224 37225 37226 37227 37228 37229 37230 37231 37232 37233 37234 37235 37236 37237 37238 37239 37240 37241 37242 37243 37244 37245 37246 37247 37248 37249 37250 37251 37252 37253 37254 37255 37256 37257 37258 37259 37260 37261 37262 37263 37264 37265 37266 37267 37268 37269 37270 37271 37272 37273 37274 37275 37276 37277 37278 37279 37280 37281 37282 |
[clock scan "12:01 pm" -base 0 -gmt 1]
} -result {60 43260}
test clock-46.6 {freescan: regression test - bad time} -constraints valid_off \
-body {
# 13:00 am/pm are invalid input strings...
list [clock scan "13:00 am" -base 0 -gmt 1] \
[clock scan "13:00 pm" -base 0 -gmt 1]
} -result {3600 46800}
if {!$valid_mode} {
test clock-46.7a {regression test - switch day by large not-valid time, see bug [3ee8f1c2a785f4d8]} {valid_off} {
list [clock scan 23:59:59 -base 0 -gmt 1 -format %H:%M:%S] \
[clock scan 24:00:00 -base 0 -gmt 1 -format %H:%M:%S] \
[clock scan 48:00:00 -base 0 -gmt 1 -format %H:%M:%S]
} {86399 86400 172800}
test clock-46.7b {freescan: regression test - switch day by large not-valid time, see bug [3ee8f1c2a785f4d8]} {valid_off} {
list [clock scan 23:59:59 -base 0 -gmt 1] \
[clock scan 24:00:00 -base 0 -gmt 1] \
[clock scan 48:00:00 -base 0 -gmt 1]
} {86399 86400 172800}
} else {
test clock-46.8a {regression test - invalid time (hour)} {
list [catch {clock scan 24:00:00 -base 0 -gmt 1 -format %H:%M:%S} msg] $msg \
[catch {clock scan 48:00:00 -base 0 -gmt 1 -format %H:%M:%S} msg] $msg
} {1 {unable to convert input string: invalid time (hour)} 1 {unable to convert input string: invalid time (hour)}}
test clock-46.8b {freescan: regression test - invalid time (hour)} {
list [catch {clock scan 24:00:00 -base 0 -gmt 1} msg] $msg \
[catch {clock scan 48:00:00 -base 0 -gmt 1} msg] $msg
} {1 {unable to convert input string: invalid time (hour)} 1 {unable to convert input string: invalid time (hour)}}
}
proc _invalid_test {testtz scnargs args} {
global valid_mode
# ensure validation works TZ independently, since the conversion
# of local time to UTC may adjust date/time tokens, depending on TZ:
set res {}
if {$testtz eq ""} {
set testtz {:GMT :CET {} :Europe/Berlin :localtime}
}
if {!$valid_mode} { # globally -valid 0, so add it explicitely
lappend scnargs -valid 1
}
foreach tz $testtz {
foreach {v} $args {
lappend res [catch {clock scan $v {*}$scnargs -timezone $tz} msg] $msg
}
}
set res
}
# test without and with relative offsets:
foreach {idx relstr} {"" "" "+rel" "+ 15 month + 40 days + 30 hours + 80 minutes +9999 seconds"} {
test clock-46.10$idx {freescan: validation rules: invalid time} \
-body {
# 13:00 am/pm are invalid input strings...
_invalid_test {} {} "13:00 am$relstr" "13:00 pm$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid time (hour)}]
test clock-46.11$idx {freescan: validation rules: invalid time} \
-body {
# invalid minutes in input strings...
_invalid_test {} {} "23:70$relstr" "11:80 pm$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid time (minutes)}]
test clock-46.12$idx {freescan: validation rules: invalid time} \
-body {
# invalid seconds in input strings...
_invalid_test {} {} "23:00:70$relstr" "11:00:80 pm$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid time}]
test clock-46.13$idx {freescan: validation rules: invalid day} \
-body {
_invalid_test {} {} "29 Feb 2017$relstr" "30 Feb 2016$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.14$idx {freescan: validation rules: invalid day} \
-body {
_invalid_test {} {} "0 Feb 2017$relstr" "00 Feb 2017$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.15$idx {freescan: validation rules: invalid month} \
-body {
_invalid_test {} {} "13/13/2017$relstr" "00/00/2017$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid month}]
test clock-46.16$idx {freescan: validation rules: invalid day of week} \
-body {
_invalid_test {} {} "Sat Jan 02 00:00:00 1970$relstr" "Thu Jan 04 00:00:00 1970$relstr"
} -result [lrepeat 10 1 {unable to convert input string: invalid day of week}]
test clock-46.17$idx {scan: validation rules: invalid year} -setup {
set orgcfg [list -min-year [::tcl::unsupported::clock::configure -min-year] -max-year [::tcl::unsupported::clock::configure -max-year] \
-year-century [::tcl::unsupported::clock::configure -year-century] -century-switch [::tcl::unsupported::clock::configure -century-switch]]
::tcl::unsupported::clock::configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
} -body {
_invalid_test {} {} "70-01-01$relstr" "1870-01-01$relstr" "9570-01-01$relstr"
} -result [lrepeat 15 1 {unable to convert input string: invalid year}] -cleanup {
::tcl::unsupported::clock::configure {*}$orgcfg
unset -nocomplain orgcfg
}
}; # foreach
test clock-46.16-pos-fs {freescan: validation rules: valid day of week (must work for all weekdays)} \
-body {
_invalid_test {:GMT -12:00 +12:00} {} {Sat, 01 Jan 2000 00:00:00} {Sun, 02 Jan 2000 00:00:00} {Mon, 03 Jan 2000 00:00:00} {Tue, 04 Jan 2000 00:00:00} {Wed, 05 Jan 2000 00:00:00} {Thu, 06 Jan 2000 00:00:00} {Fri, 07 Jan 2000 00:00:00}
} -result [list \
0 946684800 0 946771200 0 946857600 0 946944000 0 947030400 0 947116800 0 947203200 \
0 946728000 0 946814400 0 946900800 0 946987200 0 947073600 0 947160000 0 947246400 \
0 946641600 0 946728000 0 946814400 0 946900800 0 946987200 0 947073600 0 947160000 \
]
test clock-46.16-pos-fmt1 {scan with format: validation rules: valid day of week (must work for all weekdays)} \
-body {
_invalid_test {:GMT -12:00 +12:00} {-format "%a, %d %b %Y %H:%M:%S"} {Sat, 01 Jan 2000 00:00:00} {Sun, 02 Jan 2000 00:00:00} {Mon, 03 Jan 2000 00:00:00} {Tue, 04 Jan 2000 00:00:00} {Wed, 05 Jan 2000 00:00:00} {Thu, 06 Jan 2000 00:00:00} {Fri, 07 Jan 2000 00:00:00}
} -result [list \
0 946684800 0 946771200 0 946857600 0 946944000 0 947030400 0 947116800 0 947203200 \
0 946728000 0 946814400 0 946900800 0 946987200 0 947073600 0 947160000 0 947246400 \
0 946641600 0 946728000 0 946814400 0 946900800 0 946987200 0 947073600 0 947160000 \
]
test clock-46.16-pos-fmt2 {scan with format: validation rules: valid day of week (must work for all weekdays)} \
-body {
_invalid_test {:GMT -12:00 +12:00} {-format "%u, %d %b %Y %H:%M:%S"} {6, 01 Jan 2000 00:00:00} {7, 02 Jan 2000 00:00:00} {1, 03 Jan 2000 00:00:00} {2, 04 Jan 2000 00:00:00} {3, 05 Jan 2000 00:00:00} {4, 06 Jan 2000 00:00:00} {5, 07 Jan 2000 00:00:00}
} -result [list \
0 946684800 0 946771200 0 946857600 0 946944000 0 947030400 0 947116800 0 947203200 \
0 946728000 0 946814400 0 946900800 0 946987200 0 947073600 0 947160000 0 947246400 \
0 946641600 0 946728000 0 946814400 0 946900800 0 946987200 0 947073600 0 947160000 \
]
test clock-46.16-pos-fmt3 {scan with format: validation rules: valid day of week (must work for all weekdays)} \
-body {
_invalid_test {:GMT -12:00 +12:00} {-format "%w, %d %b %Y %H:%M:%S"} {6, 01 Jan 2000 00:00:00} {0, 02 Jan 2000 00:00:00} {1, 03 Jan 2000 00:00:00} {2, 04 Jan 2000 00:00:00} {3, 05 Jan 2000 00:00:00} {4, 06 Jan 2000 00:00:00} {5, 07 Jan 2000 00:00:00}
} -result [list \
0 946684800 0 946771200 0 946857600 0 946944000 0 947030400 0 947116800 0 947203200 \
0 946728000 0 946814400 0 946900800 0 946987200 0 947073600 0 947160000 0 947246400 \
0 946641600 0 946728000 0 946814400 0 946900800 0 946987200 0 947073600 0 947160000 \
]
rename _invalid_test {}
unset -nocomplain idx relstr
set dst_hole_check {
{":Europe/Berlin"
"2017-03-26 01:59:59" "2017-03-26 02:00:00" "2017-03-26 02:59:59" "2017-03-26 03:00:00"
"2017-10-29 01:59:59" "2017-10-29 02:00:00"}
|
| ︙ | ︙ |
Changes to tests/cmdAH.test.
| ︙ | ︙ | |||
19 20 21 22 23 24 25 |
catch [list package require -exact tcl::test [info patchlevel]]
testConstraint testchmod [llength [info commands testchmod]]
testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testvolumetype [llength [info commands testvolumetype]]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint time64bit [expr {
| > | > > | > > > > > > > > > > > > > | 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 |
catch [list package require -exact tcl::test [info patchlevel]]
testConstraint testchmod [llength [info commands testchmod]]
testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testvolumetype [llength [info commands testvolumetype]]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint time64bit [expr {
([llength [info command testsize]] ?
[testsize st_mtime] : $::tcl_platform(pointerSize)) >= 8
}]
testConstraint filetime64bit [expr {
[testConstraint time64bit] && (
![testConstraint unix] || [apply {{} {
# check whether disk may have 2038 problem, see [fd91b0ca09cb171f]:
set fn [makeFile "" foo.text]
if {[catch {
exec sh -c "TZ=:UTC LC_TIME=en_US touch -ma -t '207006290000' '$fn' && TZ=:UTC LC_TIME=en_US ls -l '$fn'"
} res]} {
#puts "Check constraint failed:\t$res"
set res {}
}
removeFile $fn
regexp {\mJun\s+29\s+2070\M} $res
}}]
)
}]
testConstraint linkDirectory [expr {
![testConstraint win] ||
($::tcl_platform(osVersion) >= 5.0
&& [lindex [file system [temporaryDirectory]] 1] eq "NTFS")
}]
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]
|
| ︙ | ︙ | |||
1707 1708 1709 1710 1711 1712 1713 |
test cmdAH-24.14.1 {
Tcl_FileObjCmd: mtime (built-in Windows names with dir path and extension)
} -constraints {win} -body {
file mtime [file join [temporaryDirectory] CON.txt]
} -match regexp -result {could not (?:get modification time|read)} -returnCodes error
# 3155760000 is 64-bit Unix time, Wed Jan 01 00:00:00 GMT 2070:
| | | | 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 |
test cmdAH-24.14.1 {
Tcl_FileObjCmd: mtime (built-in Windows names with dir path and extension)
} -constraints {win} -body {
file mtime [file join [temporaryDirectory] CON.txt]
} -match regexp -result {could not (?:get modification time|read)} -returnCodes error
# 3155760000 is 64-bit Unix time, Wed Jan 01 00:00:00 GMT 2070:
test cmdAH-24.20.1 {Tcl_FileObjCmd: atime 64-bit time_t, bug [4718b41c56]} -constraints {time64bit filetime64bit} -setup {
set filename [makeFile "" foo.text]
} -body {
# This test may fail if your system does not have a 64-bit time_t.
# That is to be expected and is not a problem with Tcl.
list [file atime $filename 3155760000] [file atime $filename]
} -cleanup {
removeFile $filename
} -result {3155760000 3155760000}
test cmdAH-24.20.2 {Tcl_FileObjCmd: mtime 64-bit time_t, bug [4718b41c56]} -constraints {time64bit filetime64bit} -setup {
set filename [makeFile "" foo.text]
} -body {
# This test may fail if your system does not have a 64-bit time_t.
# That is to be expected and is not a problem with Tcl.
list [file mtime $filename 3155760000] [file mtime $filename]
} -cleanup {
file delete -force $filename
|
| ︙ | ︙ | |||
1796 1797 1798 1799 1800 1801 1802 |
# size
test cmdAH-27.1 {Tcl_FileObjCmd: size} -returnCodes error -body {
file size a b
} -result {wrong # args: should be "file size name"}
test cmdAH-27.2 {Tcl_FileObjCmd: size} {
set oldsize [file size $gorpfile]
set f [open $gorpfile a]
| | | 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 |
# size
test cmdAH-27.1 {Tcl_FileObjCmd: size} -returnCodes error -body {
file size a b
} -result {wrong # args: should be "file size name"}
test cmdAH-27.2 {Tcl_FileObjCmd: size} {
set oldsize [file size $gorpfile]
set f [open $gorpfile a]
fconfigure $f -translation lf
puts $f "More text"
close $f
expr {[file size $gorpfile] - $oldsize}
} {10}
test cmdAH-27.3 {Tcl_FileObjCmd: size} {
list [catch {file size _bogus_} msg] [string tolower $msg] $errorCode
} {1 {could not read "_bogus_": no such file or directory} {POSIX ENOENT {no such file or directory}}}
|
| ︙ | ︙ |
Changes to tests/compExpr-old.test.
| ︙ | ︙ | |||
272 273 274 275 276 277 278 |
expr 2***3|6
} -returnCodes error -match glob -result *
test compExpr-old-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
expr 2^x
} -returnCodes error -match glob -result *
test compExpr-old-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
list [catch {expr {24.0^3}} msg] $msg
| | | | | | 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 |
expr 2***3|6
} -returnCodes error -match glob -result *
test compExpr-old-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
expr 2^x
} -returnCodes error -match glob -result *
test compExpr-old-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
list [catch {expr {24.0^3}} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of "^"}}
test compExpr-old-6.10 {CompileBitXorExpr: runtime error in bitxor arm} {
list [catch {expr {"a"^"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "^"}}
test compExpr-old-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
test compExpr-old-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
test compExpr-old-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
test compExpr-old-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
test compExpr-old-7.5 {CompileBitAndExpr: error in equality expr} -body {
expr x==3
} -returnCodes error -match glob -result *
test compExpr-old-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
test compExpr-old-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
test compExpr-old-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
test compExpr-old-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
test compExpr-old-7.10 {CompileBitAndExpr: error compiling bitand arm} -body {
expr 2***3&6
} -returnCodes error -match glob -result *
test compExpr-old-7.11 {CompileBitAndExpr: error compiling bitand arm} -body {
expr 2&x
} -returnCodes error -match glob -result *
test compExpr-old-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
list [catch {expr {24.0&3}} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of "&"}}
test compExpr-old-7.13 {CompileBitAndExpr: runtime error in bitand arm} {
list [catch {expr {"a"&"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "&"}}
test compExpr-old-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
test compExpr-old-8.2 {CompileEqualityExpr: just relational expr} {expr 2<=2.1} 1
test compExpr-old-8.3 {CompileEqualityExpr: just relational expr} {expr 3.2>"2.2"} 1
test compExpr-old-8.4 {CompileEqualityExpr: just relational expr} {expr {"0y"<"0x12"}} 0
test compExpr-old-8.5 {CompileEqualityExpr: error in relational expr} -body {
expr x>3
|
| ︙ | ︙ | |||
357 358 359 360 361 362 363 |
expr 2***3>>6
} -returnCodes error -match glob -result *
test compExpr-old-10.9 {CompileShiftExpr: error compiling shift arm} -body {
expr 2<<x
} -returnCodes error -match glob -result *
test compExpr-old-10.10 {CompileShiftExpr: runtime error} {
list [catch {expr {24.0>>43}} msg] $msg
| | | | | | 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 |
expr 2***3>>6
} -returnCodes error -match glob -result *
test compExpr-old-10.9 {CompileShiftExpr: error compiling shift arm} -body {
expr 2<<x
} -returnCodes error -match glob -result *
test compExpr-old-10.10 {CompileShiftExpr: runtime error} {
list [catch {expr {24.0>>43}} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of ">>"}}
test compExpr-old-10.11 {CompileShiftExpr: runtime error} {
list [catch {expr {"a"<<"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "<<"}}
test compExpr-old-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
test compExpr-old-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
test compExpr-old-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
test compExpr-old-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0o123} 6
test compExpr-old-11.5 {CompileAddExpr: error in multiply expr} -body {
expr x*3
} -returnCodes error -match glob -result *
test compExpr-old-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
test compExpr-old-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
test compExpr-old-11.8 {CompileAddExpr: error compiling add arm} -body {
expr 2***3+6
} -returnCodes error -match glob -result *
test compExpr-old-11.9 {CompileAddExpr: error compiling add arm} -body {
expr 2-x
} -returnCodes error -match glob -result *
test compExpr-old-11.10 {CompileAddExpr: runtime error} {
list [catch {expr {24.0+"xx"}} msg] $msg
} {1 {cannot use non-numeric string "xx" as right operand of "+"}}
test compExpr-old-11.11 {CompileAddExpr: runtime error} {
list [catch {expr {"a"-"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "-"}}
test compExpr-old-11.12 {CompileAddExpr: runtime error} {
list [catch {expr {3/0}} msg] $msg
} {1 {divide by zero}}
test compExpr-old-11.13a {CompileAddExpr: runtime error} ieeeFloatingPoint {
list [catch {expr {2.3/0.0}} msg] $msg
} {0 Inf}
test compExpr-old-11.13b {CompileAddExpr: runtime error} !ieeeFloatingPoint {
|
| ︙ | ︙ | |||
410 411 412 413 414 415 416 |
expr 2*3%%6
} -returnCodes error -match glob -result *
test compExpr-old-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
expr 2*x
} -returnCodes error -match glob -result *
test compExpr-old-12.10 {CompileMultiplyExpr: runtime error} {
list [catch {expr {24.0*"xx"}} msg] $msg
| | | | | | 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 |
expr 2*3%%6
} -returnCodes error -match glob -result *
test compExpr-old-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
expr 2*x
} -returnCodes error -match glob -result *
test compExpr-old-12.10 {CompileMultiplyExpr: runtime error} {
list [catch {expr {24.0*"xx"}} msg] $msg
} {1 {cannot use non-numeric string "xx" as right operand of "*"}}
test compExpr-old-12.11 {CompileMultiplyExpr: runtime error} {
list [catch {expr {"a"/"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "/"}}
test compExpr-old-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
test compExpr-old-13.2 {CompileUnaryExpr: unary exprs} {expr +0o00123} 83
test compExpr-old-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
test compExpr-old-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
test compExpr-old-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
test compExpr-old-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
test compExpr-old-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
test compExpr-old-13.8 {CompileUnaryExpr: error compiling unary expr} -body {
expr ~x
} -returnCodes error -match glob -result *
test compExpr-old-13.9 {CompileUnaryExpr: error compiling unary expr} -body {
expr !1.x
set msg
} -returnCodes error -match glob -result *
test compExpr-old-13.10 {CompileUnaryExpr: runtime error} {
list [catch {expr {~"xx"}} msg] $msg
} {1 {cannot use non-numeric string "xx" as operand of "~"}}
test compExpr-old-13.11 {CompileUnaryExpr: runtime error} {
list [catch {expr ~4.0} msg] $msg
} {1 {cannot use floating-point value "4.0" as operand of "~"}}
test compExpr-old-13.12 {CompileUnaryExpr: just primary expr} {expr 0x123} 291
test compExpr-old-13.13 {CompileUnaryExpr: just primary expr} {
set a 27
expr $a
} 27
test compExpr-old-13.14 {CompileUnaryExpr: just primary expr} {
expr double(27)
|
| ︙ | ︙ |
Changes to tests/coroutine.test.
| ︙ | ︙ | |||
821 822 823 824 825 826 827 |
# c1. After the fix, that doesn't happen, so if c1 still exists call it
# one final time to allow it to finish and clean up
rename c1 {}
}
return [list $done0 $done1]
} -result {failure failure}
| < < < < < < < < < < < < < < < < | | | > | 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 |
# c1. After the fix, that doesn't happen, so if c1 still exists call it
# one final time to allow it to finish and clean up
rename c1 {}
}
return [list $done0 $done1]
} -result {failure failure}
test coroutine-8.1.1 {coro inject, ticket 42202ba1e5ff566e} -body {
interp create child
child eval {
coroutine demo apply {{} { while {1} yield }}
demo
coroinject demo set ::result inject-executed
}
interp delete child
} -result {}
test coroutine-8.1.2 {coro inject with result, ticket 42202ba1e5ff566e} -body {
interp create child
child eval {
coroutine demo apply {{} { while {1} yield }}
demo
coroinject demo lappend ::result inject-executed
}
child eval demo
set result [child eval {set ::result}]
interp delete child
set result
} -result {inject-executed yield {}}
test coroutine-9.1 {coroprobe with yield} -body {
coroutine demo apply {{} { foreach i {1 2} yield }}
list [coroprobe demo set i] [demo] [coroprobe demo set i] [demo]
} -cleanup {
catch {rename demo {}}
} -result {1 {} 2 {}}
|
| ︙ | ︙ | |||
1033 1034 1035 1036 1037 1038 1039 |
test coroutine-12.1 {coroutine general introspection} -setup {
set i [interp create]
} -body {
$i eval {
# Make the introspection code
namespace path tcl::unsupported
| | | | 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 |
test coroutine-12.1 {coroutine general introspection} -setup {
set i [interp create]
} -body {
$i eval {
# Make the introspection code
namespace path tcl::unsupported
proc probe {var type args} {
upvar 1 $var v
set f [info frame]
incr f -1
set result [list $v [dict get [info frame $f] proc]]
if {$type eq "yield"} {
tailcall yield $result
} else {
tailcall yieldto string cat $result
}
}
proc pokecoro {c var} {
coroinject $c probe $var
$c
}
# Coroutine implementations
proc cbody1 {} {
set val [info coroutine]
set accum {}
|
| ︙ | ︙ |
Changes to tests/encoding.test.
| ︙ | ︙ | |||
185 186 187 188 189 190 191 |
append a $a
set x [encoding convertfrom jis0208 $a]
list [string length $x] [string index $x 0]
} "512 乎"
test encoding-8.1 {Tcl_ExternalToUtf} {
set f [open [file join [temporaryDirectory] dummy] w]
| | | | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
append a $a
set x [encoding convertfrom jis0208 $a]
list [string length $x] [string index $x 0]
} "512 乎"
test encoding-8.1 {Tcl_ExternalToUtf} {
set f [open [file join [temporaryDirectory] dummy] w]
fconfigure $f -translation binary
puts -nonewline $f "ab\x8C\xC1g"
close $f
set f [open [file join [temporaryDirectory] dummy] r]
fconfigure $f -translation lf -encoding shiftjis
set x [read $f]
close $f
file delete [file join [temporaryDirectory] dummy]
return $x
} ab乎g
test encoding-9.1 {Tcl_UtfToExternalDString: small buffer} {
|
| ︙ | ︙ | |||
213 214 215 216 217 218 219 |
append a $a
set x [encoding convertto jis0208 $a]
list [string length $x] [string range $x 0 1]
} "1024 8C"
test encoding-10.1 {Tcl_UtfToExternal} {
set f [open [file join [temporaryDirectory] dummy] w]
| | | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
append a $a
set x [encoding convertto jis0208 $a]
list [string length $x] [string range $x 0 1]
} "1024 8C"
test encoding-10.1 {Tcl_UtfToExternal} {
set f [open [file join [temporaryDirectory] dummy] w]
fconfigure $f -translation lf -encoding shiftjis
puts -nonewline $f ab乎g
close $f
set f [open [file join [temporaryDirectory] dummy] r]
fconfigure $f -translation binary
set x [read $f]
close $f
file delete [file join [temporaryDirectory] dummy]
return $x
} "ab\x8C\xC1g"
test encoding-11.1 {LoadEncodingFile: unknown encoding} {testencoding} {
|
| ︙ | ︙ | |||
675 676 677 678 679 680 681 | 小切手送付先として使用しております。恐れ入りますが、正しい住所をご登録しなお お願いいたします。また、大変恐縮ですが、住所変更のあと、日本語サービス部( casino_japanese@___.com )までご住所変更済の連絡をいただけないで しょうか?" cd [temporaryDirectory] set fid [open iso2022.txt w] | | | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
小切手送付先として使用しております。恐れ入りますが、正しい住所をご登録しなお
お願いいたします。また、大変恐縮ですが、住所変更のあと、日本語サービス部(
casino_japanese@___.com )までご住所変更済の連絡をいただけないで
しょうか?"
cd [temporaryDirectory]
set fid [open iso2022.txt w]
fconfigure $fid -translation binary
puts -nonewline $fid $iso2022encData
close $fid
test encoding-23.1 {iso2022-jp escape encoding test} {
string equal $iso2022uniData $iso2022uniData2
} 1
test encoding-23.2 {iso2022-jp escape encoding test} {
|
| ︙ | ︙ | |||
990 991 992 993 994 995 996 |
return $diff
}
# Create char tables.
cd [temporaryDirectory]
foreach enc {cp932 euc-jp iso2022-jp} {
set f [open $enc.chars w]
| | | 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 |
return $diff
}
# Create char tables.
cd [temporaryDirectory]
foreach enc {cp932 euc-jp iso2022-jp} {
set f [open $enc.chars w]
fconfigure $f -encoding iso8859-1
foreach-jisx0208 code {
puts $f [format "%04X %s" $code [gen-jisx0208-$enc $code]]
}
close $f
}
# shiftjis == cp932 for jisx0208.
file copy -force cp932.chars shiftjis.chars
|
| ︙ | ︙ |
Changes to tests/execute.test.
| ︙ | ︙ | |||
174 175 176 177 178 179 180 |
test execute-3.5 {TclExecuteByteCode, INST_ADD, op1 is string double} {testobj} {
set x [teststringobj set 0 1.0]
expr {$x + 1}
} 2.0
test execute-3.6 {TclExecuteByteCode, INST_ADD, op1 is non-numeric} {testobj} {
set x [teststringobj set 0 foo]
list [catch {expr {$x + 1}} msg] $msg
| | | 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
test execute-3.5 {TclExecuteByteCode, INST_ADD, op1 is string double} {testobj} {
set x [teststringobj set 0 1.0]
expr {$x + 1}
} 2.0
test execute-3.6 {TclExecuteByteCode, INST_ADD, op1 is non-numeric} {testobj} {
set x [teststringobj set 0 foo]
list [catch {expr {$x + 1}} msg] $msg
} {1 {cannot use non-numeric string "foo" as left operand of "+"}}
test execute-3.7 {TclExecuteByteCode, INST_ADD, op2 is int} {testobj} {
set x [testintobj set 0 1]
expr {1 + $x}
} 2
test execute-3.8 {TclExecuteByteCode, INST_ADD, op2 is double} {testobj} {
set x [testdoubleobj set 0 1]
expr {1 + $x}
|
| ︙ | ︙ | |||
199 200 201 202 203 204 205 |
test execute-3.11 {TclExecuteByteCode, INST_ADD, op2 is string double} {testobj} {
set x [teststringobj set 0 1.0]
expr {1 + $x}
} 2.0
test execute-3.12 {TclExecuteByteCode, INST_ADD, op2 is non-numeric} {testobj} {
set x [teststringobj set 0 foo]
list [catch {expr {1 + $x}} msg] $msg
| | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
test execute-3.11 {TclExecuteByteCode, INST_ADD, op2 is string double} {testobj} {
set x [teststringobj set 0 1.0]
expr {1 + $x}
} 2.0
test execute-3.12 {TclExecuteByteCode, INST_ADD, op2 is non-numeric} {testobj} {
set x [teststringobj set 0 foo]
list [catch {expr {1 + $x}} msg] $msg
} {1 {cannot use non-numeric string "foo" as right operand of "+"}}
# INST_SUB is partially tested:
test execute-3.13 {TclExecuteByteCode, INST_SUB, op1 is int} {testobj} {
set x [testintobj set 0 1]
expr {$x - 1}
} 0
test execute-3.14 {TclExecuteByteCode, INST_SUB, op1 is double} {testobj} {
|
| ︙ | ︙ | |||
226 227 228 229 230 231 232 |
test execute-3.17 {TclExecuteByteCode, INST_SUB, op1 is string double} {testobj} {
set x [teststringobj set 0 1.0]
expr {$x - 1}
} 0.0
test execute-3.18 {TclExecuteByteCode, INST_SUB, op1 is non-numeric} {testobj} {
set x [teststringobj set 0 foo]
list [catch {expr {$x - 1}} msg] $msg
| | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
test execute-3.17 {TclExecuteByteCode, INST_SUB, op1 is string double} {testobj} {
set x [teststringobj set 0 1.0]
expr {$x - 1}
} 0.0
test execute-3.18 {TclExecuteByteCode, INST_SUB, op1 is non-numeric} {testobj} {
set x [teststringobj set 0 foo]
list [catch {expr {$x - 1}} msg] $msg
} {1 {cannot use non-numeric string "foo" as left operand of "-"}}
test execute-3.19 {TclExecuteByteCode, INST_SUB, op2 is int} {testobj} {
set x [testintobj set 0 1]
expr {1 - $x}
} 0
test execute-3.20 {TclExecuteByteCode, INST_SUB, op2 is double} {testobj} {
set x [testdoubleobj set 0 1]
expr {1 - $x}
|
| ︙ | ︙ | |||
251 252 253 254 255 256 257 |
test execute-3.23 {TclExecuteByteCode, INST_SUB, op2 is string double} {testobj} {
set x [teststringobj set 0 1.0]
expr {1 - $x}
} 0.0
test execute-3.24 {TclExecuteByteCode, INST_SUB, op2 is non-numeric} {testobj} {
set x [teststringobj set 0 foo]
list [catch {expr {1 - $x}} msg] $msg
| | | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
test execute-3.23 {TclExecuteByteCode, INST_SUB, op2 is string double} {testobj} {
set x [teststringobj set 0 1.0]
expr {1 - $x}
} 0.0
test execute-3.24 {TclExecuteByteCode, INST_SUB, op2 is non-numeric} {testobj} {
set x [teststringobj set 0 foo]
list [catch {expr {1 - $x}} msg] $msg
} {1 {cannot use non-numeric string "foo" as right operand of "-"}}
# INST_MULT is partially tested:
test execute-3.25 {TclExecuteByteCode, INST_MULT, op1 is int} {testobj} {
set x [testintobj set 1 1]
expr {$x * 1}
} 1
test execute-3.26 {TclExecuteByteCode, INST_MULT, op1 is double} {testobj} {
|
| ︙ | ︙ | |||
278 279 280 281 282 283 284 |
test execute-3.29 {TclExecuteByteCode, INST_MULT, op1 is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {$x * 1}
} 1.0
test execute-3.30 {TclExecuteByteCode, INST_MULT, op1 is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {$x * 1}} msg] $msg
| | | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
test execute-3.29 {TclExecuteByteCode, INST_MULT, op1 is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {$x * 1}
} 1.0
test execute-3.30 {TclExecuteByteCode, INST_MULT, op1 is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {$x * 1}} msg] $msg
} {1 {cannot use non-numeric string "foo" as left operand of "*"}}
test execute-3.31 {TclExecuteByteCode, INST_MULT, op2 is int} {testobj} {
set x [testintobj set 1 1]
expr {1 * $x}
} 1
test execute-3.32 {TclExecuteByteCode, INST_MULT, op2 is double} {testobj} {
set x [testdoubleobj set 1 2.0]
expr {1 * $x}
|
| ︙ | ︙ | |||
303 304 305 306 307 308 309 |
test execute-3.35 {TclExecuteByteCode, INST_MULT, op2 is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {1 * $x}
} 1.0
test execute-3.36 {TclExecuteByteCode, INST_MULT, op2 is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {1 * $x}} msg] $msg
| | | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
test execute-3.35 {TclExecuteByteCode, INST_MULT, op2 is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {1 * $x}
} 1.0
test execute-3.36 {TclExecuteByteCode, INST_MULT, op2 is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {1 * $x}} msg] $msg
} {1 {cannot use non-numeric string "foo" as right operand of "*"}}
# INST_DIV is partially tested:
test execute-3.37 {TclExecuteByteCode, INST_DIV, op1 is int} {testobj} {
set x [testintobj set 1 1]
expr {$x / 1}
} 1
test execute-3.38 {TclExecuteByteCode, INST_DIV, op1 is double} {testobj} {
|
| ︙ | ︙ | |||
330 331 332 333 334 335 336 |
test execute-3.41 {TclExecuteByteCode, INST_DIV, op1 is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {$x / 1}
} 1.0
test execute-3.42 {TclExecuteByteCode, INST_DIV, op1 is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {$x / 1}} msg] $msg
| | | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
test execute-3.41 {TclExecuteByteCode, INST_DIV, op1 is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {$x / 1}
} 1.0
test execute-3.42 {TclExecuteByteCode, INST_DIV, op1 is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {$x / 1}} msg] $msg
} {1 {cannot use non-numeric string "foo" as left operand of "/"}}
test execute-3.43 {TclExecuteByteCode, INST_DIV, op2 is int} {testobj} {
set x [testintobj set 1 1]
expr {2 / $x}
} 2
test execute-3.44 {TclExecuteByteCode, INST_DIV, op2 is double} {testobj} {
set x [testdoubleobj set 1 1.0]
expr {2 / $x}
|
| ︙ | ︙ | |||
355 356 357 358 359 360 361 |
test execute-3.47 {TclExecuteByteCode, INST_DIV, op2 is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {2 / $x}
} 2.0
test execute-3.48 {TclExecuteByteCode, INST_DIV, op2 is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {1 / $x}} msg] $msg
| | | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
test execute-3.47 {TclExecuteByteCode, INST_DIV, op2 is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {2 / $x}
} 2.0
test execute-3.48 {TclExecuteByteCode, INST_DIV, op2 is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {1 / $x}} msg] $msg
} {1 {cannot use non-numeric string "foo" as right operand of "/"}}
# INST_UPLUS is partially tested:
test execute-3.49 {TclExecuteByteCode, INST_UPLUS, op is int} {testobj} {
set x [testintobj set 1 1]
expr {+ $x}
} 1
test execute-3.50 {TclExecuteByteCode, INST_UPLUS, op is double} {testobj} {
|
| ︙ | ︙ | |||
382 383 384 385 386 387 388 |
test execute-3.53 {TclExecuteByteCode, INST_UPLUS, op is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {+ $x}
} 1.0
test execute-3.54 {TclExecuteByteCode, INST_UPLUS, op is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {+ $x}} msg] $msg
| | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
test execute-3.53 {TclExecuteByteCode, INST_UPLUS, op is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {+ $x}
} 1.0
test execute-3.54 {TclExecuteByteCode, INST_UPLUS, op is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {+ $x}} msg] $msg
} {1 {cannot use non-numeric string "foo" as operand of "+"}}
# INST_UMINUS is partially tested:
test execute-3.55 {TclExecuteByteCode, INST_UMINUS, op is int} {testobj} {
set x [testintobj set 1 1]
expr {- $x}
} -1
test execute-3.56 {TclExecuteByteCode, INST_UMINUS, op is double} {testobj} {
|
| ︙ | ︙ | |||
409 410 411 412 413 414 415 |
test execute-3.59 {TclExecuteByteCode, INST_UMINUS, op is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {- $x}
} -1.0
test execute-3.60 {TclExecuteByteCode, INST_UMINUS, op is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {- $x}} msg] $msg
| | | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
test execute-3.59 {TclExecuteByteCode, INST_UMINUS, op is string double} {testobj} {
set x [teststringobj set 1 1.0]
expr {- $x}
} -1.0
test execute-3.60 {TclExecuteByteCode, INST_UMINUS, op is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {- $x}} msg] $msg
} {1 {cannot use non-numeric string "foo" as operand of "-"}}
# INST_LNOT is partially tested:
test execute-3.61 {TclExecuteByteCode, INST_LNOT, op is int} {testobj} {
set x [testintobj set 1 2]
expr {! $x}
} 0
test execute-3.62 {TclExecuteByteCode, INST_LNOT, op is int} {testobj} {
|
| ︙ | ︙ | |||
457 458 459 460 461 462 463 |
test execute-3.70 {TclExecuteByteCode, INST_LNOT, op is string double} {testobj} {
set x [teststringobj set 1 0.0]
expr {! $x}
} 1
test execute-3.71 {TclExecuteByteCode, INST_LNOT, op is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {! $x}} msg] $msg
| | | 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
test execute-3.70 {TclExecuteByteCode, INST_LNOT, op is string double} {testobj} {
set x [teststringobj set 1 0.0]
expr {! $x}
} 1
test execute-3.71 {TclExecuteByteCode, INST_LNOT, op is non-numeric} {testobj} {
set x [teststringobj set 1 foo]
list [catch {expr {! $x}} msg] $msg
} {1 {cannot use non-numeric string "foo" as operand of "!"}}
# INST_TRY_CVT_TO_NUMERIC is partially tested:
test execute-3.72 {TclExecuteByteCode, INST_TRY_CVT_TO_NUMERIC, op is int} {testobj} {
set x [testintobj set 1 1]
expr {$x}
} 1
test execute-3.73 {TclExecuteByteCode, INST_TRY_CVT_TO_NUMERIC, op is double} {testobj} {
|
| ︙ | ︙ |
Changes to tests/expr-old.test.
| ︙ | ︙ | |||
189 190 191 192 193 194 195 |
list [catch {expr 028.1 + 09.2} msg] $msg
} {0 37.3}
# Operators that aren't legal on floating-point numbers
test expr-old-3.1 {illegal floating-point operations} {
list [catch {expr ~4.0} msg] $msg
| | | | | | | | | | | | 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 220 221 222 223 224 225 226 227 228 229 230 |
list [catch {expr 028.1 + 09.2} msg] $msg
} {0 37.3}
# Operators that aren't legal on floating-point numbers
test expr-old-3.1 {illegal floating-point operations} {
list [catch {expr ~4.0} msg] $msg
} {1 {cannot use floating-point value "4.0" as operand of "~"}}
test expr-old-3.2 {illegal floating-point operations} {
list [catch {expr 27%4.0} msg] $msg
} {1 {cannot use floating-point value "4.0" as right operand of "%"}}
test expr-old-3.3 {illegal floating-point operations} {
list [catch {expr 27.0%4} msg] $msg
} {1 {cannot use floating-point value "27.0" as left operand of "%"}}
test expr-old-3.4 {illegal floating-point operations} {
list [catch {expr 1.0<<3} msg] $msg
} {1 {cannot use floating-point value "1.0" as left operand of "<<"}}
test expr-old-3.5 {illegal floating-point operations} {
list [catch {expr 3<<1.0} msg] $msg
} {1 {cannot use floating-point value "1.0" as right operand of "<<"}}
test expr-old-3.6 {illegal floating-point operations} {
list [catch {expr 24.0>>3} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of ">>"}}
test expr-old-3.7 {illegal floating-point operations} {
list [catch {expr 24>>3.0} msg] $msg
} {1 {cannot use floating-point value "3.0" as right operand of ">>"}}
test expr-old-3.8 {illegal floating-point operations} {
list [catch {expr 24&3.0} msg] $msg
} {1 {cannot use floating-point value "3.0" as right operand of "&"}}
test expr-old-3.9 {illegal floating-point operations} {
list [catch {expr 24.0|3} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of "|"}}
test expr-old-3.10 {illegal floating-point operations} {
list [catch {expr 24.0^3} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of "^"}}
# Check the string operators individually.
test expr-old-4.1 {string operators} {expr {"abc" > "def"}} 0
test expr-old-4.2 {string operators} {expr {"def" > "def"}} 0
test expr-old-4.3 {string operators} {expr {"g" > "def"}} 1
test expr-old-4.4 {string operators} {expr {"abc" < "abd"}} 1
|
| ︙ | ︙ | |||
257 258 259 260 261 262 263 |
test expr-old-4.31 {string operators} {expr {1?"foo":"bar"}} foo
test expr-old-4.32 {string operators} {expr {0?"foo":"bar"}} bar
# Operators that aren't legal on string operands.
test expr-old-5.1 {illegal string operations} {
list [catch {expr {-"a"}} msg] $msg
| | | | | | | | | | | | | | | | 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 |
test expr-old-4.31 {string operators} {expr {1?"foo":"bar"}} foo
test expr-old-4.32 {string operators} {expr {0?"foo":"bar"}} bar
# Operators that aren't legal on string operands.
test expr-old-5.1 {illegal string operations} {
list [catch {expr {-"a"}} msg] $msg
} {1 {cannot use non-numeric string "a" as operand of "-"}}
test expr-old-5.2 {illegal string operations} {
list [catch {expr {+"a"}} msg] $msg
} {1 {cannot use non-numeric string "a" as operand of "+"}}
test expr-old-5.3 {illegal string operations} {
list [catch {expr {~"a"}} msg] $msg
} {1 {cannot use non-numeric string "a" as operand of "~"}}
test expr-old-5.4 {illegal string operations} {
list [catch {expr {!"a"}} msg] $msg
} {1 {cannot use non-numeric string "a" as operand of "!"}}
test expr-old-5.5 {illegal string operations} {
list [catch {expr {"a"*"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "*"}}
test expr-old-5.6 {illegal string operations} {
list [catch {expr {"a"/"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "/"}}
test expr-old-5.7 {illegal string operations} {
list [catch {expr {"a"%"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "%"}}
test expr-old-5.8 {illegal string operations} {
list [catch {expr {"a"+"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "+"}}
test expr-old-5.9 {illegal string operations} {
list [catch {expr {"a"-"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "-"}}
test expr-old-5.10 {illegal string operations} {
list [catch {expr {"a"<<"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "<<"}}
test expr-old-5.11 {illegal string operations} {
list [catch {expr {"a">>"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of ">>"}}
test expr-old-5.12 {illegal string operations} {
list [catch {expr {"a"&"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "&"}}
test expr-old-5.13 {illegal string operations} {
list [catch {expr {"a"^"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "^"}}
test expr-old-5.14 {illegal string operations} {
list [catch {expr {"a"|"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "|"}}
test expr-old-5.15 {illegal string operations} {
list [catch {expr {"a"&&"b"}} msg] $msg
} {1 {expected boolean value but got "a"}}
test expr-old-5.16 {illegal string operations} {
list [catch {expr {"a"||"b"}} msg] $msg
} {1 {expected boolean value but got "a"}}
test expr-old-5.17 {illegal string operations} {
|
| ︙ | ︙ | |||
485 486 487 488 489 490 491 |
test expr-old-25.19 {type conversions} {expr 2.0e15} 2000000000000000.0
test expr-old-25.20 {type conversions} {expr 10.0} 10.0
# Various error conditions.
test expr-old-26.1 {error conditions} {
list [catch {expr 2+"a"} msg] $msg
| | | | | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 |
test expr-old-25.19 {type conversions} {expr 2.0e15} 2000000000000000.0
test expr-old-25.20 {type conversions} {expr 10.0} 10.0
# Various error conditions.
test expr-old-26.1 {error conditions} {
list [catch {expr 2+"a"} msg] $msg
} {1 {cannot use non-numeric string "a" as right operand of "+"}}
test expr-old-26.2 {error conditions} -body {
expr 2+4*
} -returnCodes error -match glob -result *
test expr-old-26.3 {error conditions} -body {
expr 2+4*(
} -returnCodes error -match glob -result *
unset -nocomplain _non_existent_
test expr-old-26.4 {error conditions} {
list [catch {expr 2+$_non_existent_} msg] $msg
} {1 {can't read "_non_existent_": no such variable}}
set a xx
test expr-old-26.5 {error conditions} {
list [catch {expr {2+$a}} msg] $msg
} {1 {cannot use non-numeric string "xx" as right operand of "+"}}
test expr-old-26.6 {error conditions} {
list [catch {expr {2+[set a]}} msg] $msg
} {1 {cannot use non-numeric string "xx" as right operand of "+"}}
test expr-old-26.7 {error conditions} -body {
expr {2+(4}
} -returnCodes error -match glob -result *
test expr-old-26.8 {error conditions} {
list [catch {expr 2/0} msg] $msg $errorCode
} {1 {divide by zero} {ARITH DIVZERO {divide by zero}}}
test expr-old-26.9 {error conditions} {
|
| ︙ | ︙ | |||
526 527 528 529 530 531 532 |
expr 2`
} -returnCodes error -match glob -result *
test expr-old-26.12 {error conditions} -body {
expr a.b
} -returnCodes error -match glob -result *
test expr-old-26.13 {error conditions} {
list [catch {expr {"a"/"b"}} msg] $msg
| | | 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
expr 2`
} -returnCodes error -match glob -result *
test expr-old-26.12 {error conditions} -body {
expr a.b
} -returnCodes error -match glob -result *
test expr-old-26.13 {error conditions} {
list [catch {expr {"a"/"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "/"}}
test expr-old-26.14 {error conditions} -body {
expr 2:3
} -returnCodes error -match glob -result *
test expr-old-26.15 {error conditions} -body {
expr a@b
} -returnCodes error -match glob -result *
test expr-old-26.16 {error conditions} {
|
| ︙ | ︙ | |||
945 946 947 948 949 950 951 |
test expr-old-36.1 {ExprLooksLikeInt procedure} -body {
expr 0o289
} -returnCodes error -match glob -result {*invalid octal number*}
test expr-old-36.2 {ExprLooksLikeInt procedure} {
set x 0o289
list [catch {expr {$x+1}} msg] $msg
| | | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 |
test expr-old-36.1 {ExprLooksLikeInt procedure} -body {
expr 0o289
} -returnCodes error -match glob -result {*invalid octal number*}
test expr-old-36.2 {ExprLooksLikeInt procedure} {
set x 0o289
list [catch {expr {$x+1}} msg] $msg
} {1 {cannot use non-numeric string "0o289" as left operand of "+"}}
test expr-old-36.3 {ExprLooksLikeInt procedure} {
list [catch {expr 0289.1} msg] $msg
} {0 289.1}
test expr-old-36.4 {ExprLooksLikeInt procedure} {
set x 0289.1
list [catch {expr {$x+1}} msg] $msg
} {0 290.1}
|
| ︙ | ︙ | |||
985 986 987 988 989 990 991 |
expr {$x+1}
} 665802003400000000000001
# tests for [Bug #587140]
test expr-old-36.12 {ExprLooksLikeInt procedure} {
set x "10;"
list [catch {expr {$x+1}} msg] $msg
| | | | | 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 |
expr {$x+1}
} 665802003400000000000001
# tests for [Bug #587140]
test expr-old-36.12 {ExprLooksLikeInt procedure} {
set x "10;"
list [catch {expr {$x+1}} msg] $msg
} {1 {cannot use non-numeric string "10;" as left operand of "+"}}
test expr-old-36.13 {ExprLooksLikeInt procedure} {
set x " +"
list [catch {expr {$x+1}} msg] $msg
} {1 {cannot use non-numeric string " +" as left operand of "+"}}
test expr-old-36.14 {ExprLooksLikeInt procedure} {
set x "123456789012345678901234567890 "
expr {$x+1}
} 123456789012345678901234567891
test expr-old-36.15 {ExprLooksLikeInt procedure} {
set x "0o99 "
list [catch {expr {$x+1}} msg] $msg
} {1 {cannot use non-numeric string "0o99 " as left operand of "+"}}
test expr-old-36.16 {ExprLooksLikeInt procedure} {
set x " 0xffffffffffffffffffffffffffffffffffffff "
expr {$x+1}
} [expr 0x100000000000000000000000000000000000000]
test expr-old-37.1 {Check that Tcl_ExprLong doesn't modify interpreter result if no error} testexprlong {
testexprlong 4+1
|
| ︙ | ︙ |
Changes to tests/expr.test.
| ︙ | ︙ | |||
246 247 248 249 250 251 252 |
test expr-4.9 {CompileLorExpr: long lor arm} {
set a "abcdefghijkl"
set i 7
expr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]}
} 1
test expr-4.10 {CompileLorExpr: error compiling ! operand} {
list [catch {expr {!"a"}} msg] $msg
| | | 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
test expr-4.9 {CompileLorExpr: long lor arm} {
set a "abcdefghijkl"
set i 7
expr {[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]] || [string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]&&[string compare [format %c $i] [string index $a $i]]}
} 1
test expr-4.10 {CompileLorExpr: error compiling ! operand} {
list [catch {expr {!"a"}} msg] $msg
} {1 {cannot use non-numeric string "a" as operand of "!"}}
test expr-4.11 {CompileLorExpr: error compiling land arms} {
list [catch {expr {"a"||0}} msg] $msg
} {1 {expected boolean value but got "a"}}
test expr-4.12 {CompileLorExpr: error compiling land arms} {
list [catch {expr {0||"a"}} msg] $msg
} {1 {expected boolean value but got "a"}}
|
| ︙ | ︙ | |||
293 294 295 296 297 298 299 |
expr 2***3|6
} -returnCodes error -match glob -result *
test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
expr 2^x
} -returnCodes error -match glob -result *
test expr-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
list [catch {expr {24.0^3}} msg] $msg
| | | | | | 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 |
expr 2***3|6
} -returnCodes error -match glob -result *
test expr-6.8 {CompileBitXorExpr: error compiling bitxor arm} -body {
expr 2^x
} -returnCodes error -match glob -result *
test expr-6.9 {CompileBitXorExpr: runtime error in bitxor arm} {
list [catch {expr {24.0^3}} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of "^"}}
test expr-6.10 {CompileBitXorExpr: runtime error in bitxor arm} {
list [catch {expr {"a"^"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "^"}}
test expr-7.1 {CompileBitAndExpr: just equality expr} {expr 3==2} 0
test expr-7.2 {CompileBitAndExpr: just equality expr} {expr 2.0==2} 1
test expr-7.3 {CompileBitAndExpr: just equality expr} {expr 3.2!=2.2} 1
test expr-7.4 {CompileBitAndExpr: just equality expr} {expr {"abc" == "abd"}} 0
test expr-7.5 {CompileBitAndExpr: error in equality expr} -body {
expr x==3
} -returnCodes error -match glob -result *
test expr-7.6 {CompileBitAndExpr: simple bitand exprs} {expr 7&0x13} 3
test expr-7.7 {CompileBitAndExpr: simple bitand exprs} {expr 0xf2&0x53} 82
test expr-7.8 {CompileBitAndExpr: simple bitand exprs} {expr 3&6} 2
test expr-7.9 {CompileBitAndExpr: simple bitand exprs} {expr -1&-7} -7
test expr-7.10 {CompileBitAndExpr: error compiling bitand arm} -body {
expr 2***3&6
} -returnCodes error -match glob -result *
test expr-7.11 {CompileBitAndExpr: error compiling bitand arm} -body {
expr 2&x
} -returnCodes error -match glob -result *
test expr-7.12 {CompileBitAndExpr: runtime error in bitand arm} {
list [catch {expr {24.0&3}} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of "&"}}
test expr-7.13 {CompileBitAndExpr: runtime error in bitand arm} {
list [catch {expr {"a"&"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "&"}}
test expr-7.14 {CompileBitAndExpr: equality expr} {expr 3eq2} 0
test expr-7.18 {CompileBitAndExpr: equality expr} {expr {"abc" eq "abd"}} 0
test expr-7.20 {CompileBitAndExpr: error in equality expr} -body {
expr xne3
} -returnCodes error -match glob -result *
test expr-8.1 {CompileEqualityExpr: just relational expr} {expr 3>=2} 1
|
| ︙ | ︙ | |||
462 463 464 465 466 467 468 |
expr 2***3>>6
} -returnCodes error -match glob -result *
test expr-10.9 {CompileShiftExpr: error compiling shift arm} -body {
expr 2<<x
} -returnCodes error -match glob -result *
test expr-10.10 {CompileShiftExpr: runtime error} {
list [catch {expr {24.0>>43}} msg] $msg
| | | | | > > > > > > > > > | | | | | 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 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 549 550 551 552 553 554 555 556 557 558 559 560 561 |
expr 2***3>>6
} -returnCodes error -match glob -result *
test expr-10.9 {CompileShiftExpr: error compiling shift arm} -body {
expr 2<<x
} -returnCodes error -match glob -result *
test expr-10.10 {CompileShiftExpr: runtime error} {
list [catch {expr {24.0>>43}} msg] $msg
} {1 {cannot use floating-point value "24.0" as left operand of ">>"}}
test expr-10.11 {CompileShiftExpr: runtime error} {
list [catch {expr {"a"<<"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "<<"}}
test expr-11.1 {CompileAddExpr: just multiply expr} {expr 4*-2} -8
test expr-11.2 {CompileAddExpr: just multiply expr} {expr 0xff%2} 1
test expr-11.3 {CompileAddExpr: just multiply expr} {expr -1/2} -1
test expr-11.4 {CompileAddExpr: just multiply expr} {expr 7891%0o123} 6
test expr-11.5 {CompileAddExpr: error in multiply expr} -body {
expr x*3
} -returnCodes error -match glob -result *
test expr-11.6 {CompileAddExpr: simple add exprs} {expr 0xff++0x3} 258
test expr-11.7 {CompileAddExpr: simple add exprs} {expr -0xf2--0x3} -239
test expr-11.8 {CompileAddExpr: error compiling add arm} -body {
expr 2***3+6
} -returnCodes error -match glob -result *
test expr-11.9 {CompileAddExpr: error compiling add arm} -body {
expr 2-x
} -returnCodes error -match glob -result *
test expr-11.10 {CompileAddExpr: runtime error} {
list [catch {expr {24.0+"xx"}} msg] $msg
} {1 {cannot use non-numeric string "xx" as right operand of "+"}}
test expr-11.11 {CompileAddExpr: runtime error} {
list [catch {expr {"a"-"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "-"}}
test expr-11.12 {CompileAddExpr: runtime error} {
list [catch {expr {3/0}} msg] $msg
} {1 {divide by zero}}
test expr-11.13a {CompileAddExpr: runtime error} !ieeeFloatingPoint {
list [catch {expr {2.3/0.0}} msg] $msg
} {1 {divide by zero}}
test expr-11.13b {CompileAddExpr: runtime error} ieeeFloatingPoint {
list [catch {expr {2.3/0.0}} msg] $msg
} {0 Inf}
test expr-11.14 {CompileAddExpr: runtime error} {
list [catch {expr {24.0+[lseq 2 4]}} msg] $msg
} {1 {cannot use a list as right operand of "+"}}
test expr-11.15 {CompileAddExpr: runtime error} {
list [catch {expr {{1 2 3}+24.0}} msg] $msg
} {1 {cannot use a list as left operand of "+"}}
test expr-11.16 {CompileAddExpr: runtime error} {
list [catch {expr {~[dict create foo bar]}} msg] $msg
} {1 {cannot use a list as operand of "~"}}
test expr-12.1 {CompileMultiplyExpr: just unary expr} {expr ~4} -5
test expr-12.2 {CompileMultiplyExpr: just unary expr} {expr --5} 5
test expr-12.3 {CompileMultiplyExpr: just unary expr} {expr !27} 0
test expr-12.4 {CompileMultiplyExpr: just unary expr} {expr ~0xff00ff} -16711936
test expr-12.5 {CompileMultiplyExpr: error in unary expr} -body {
expr ~x
} -returnCodes error -match glob -result *
test expr-12.6 {CompileMultiplyExpr: simple multiply exprs} {expr 0xff*0x3} 765
test expr-12.7 {CompileMultiplyExpr: simple multiply exprs} {expr -0xf2%-0x3} -2
test expr-12.8 {CompileMultiplyExpr: error compiling multiply arm} -body {
expr 2*3%%6
} -returnCodes error -match glob -result *
test expr-12.9 {CompileMultiplyExpr: error compiling multiply arm} -body {
expr 2*x
} -returnCodes error -match glob -result *
test expr-12.10 {CompileMultiplyExpr: runtime error} {
list [catch {expr {24.0*"xx"}} msg] $msg
} {1 {cannot use non-numeric string "xx" as right operand of "*"}}
test expr-12.11 {CompileMultiplyExpr: runtime error} {
list [catch {expr {"a"/"b"}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "/"}}
test expr-13.1 {CompileUnaryExpr: unary exprs} {expr -0xff} -255
test expr-13.2 {CompileUnaryExpr: unary exprs} {expr +0o00123} 83
test expr-13.3 {CompileUnaryExpr: unary exprs} {expr +--++36} 36
test expr-13.4 {CompileUnaryExpr: unary exprs} {expr !2} 0
test expr-13.5 {CompileUnaryExpr: unary exprs} {expr +--+-62.0} -62.0
test expr-13.6 {CompileUnaryExpr: unary exprs} {expr !0.0} 1
test expr-13.7 {CompileUnaryExpr: unary exprs} {expr !0xef} 0
test expr-13.8 {CompileUnaryExpr: error compiling unary expr} -body {
expr ~x
} -returnCodes error -match glob -result *
test expr-13.9 {CompileUnaryExpr: error compiling unary expr} -body {
expr !1.x
} -returnCodes error -match glob -result *
test expr-13.10 {CompileUnaryExpr: runtime error} {
list [catch {expr {~"xx"}} msg] $msg
} {1 {cannot use non-numeric string "xx" as operand of "~"}}
test expr-13.11 {CompileUnaryExpr: runtime error} {
list [catch {expr ~4.0} msg] $msg
} {1 {cannot use floating-point value "4.0" as operand of "~"}}
test expr-13.12 {CompileUnaryExpr: just primary expr} {expr 0x123} 291
test expr-13.13 {CompileUnaryExpr: just primary expr} {
set a 27
expr $a
} 27
test expr-13.14 {CompileUnaryExpr: just primary expr} {
expr double(27)
|
| ︙ | ︙ | |||
815 816 817 818 819 820 821 |
test expr-21.11 {non-numeric boolean literals} {expr !no } 1
test expr-21.12 {non-numeric boolean literals} {expr !yes } 0
test expr-21.13 {non-numeric boolean literals} -body {
expr !truef
} -returnCodes error -match glob -result *
test expr-21.14 {non-numeric boolean literals} {
list [catch {expr !"truef"} err] $err
| | | | | | | | | | 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 |
test expr-21.11 {non-numeric boolean literals} {expr !no } 1
test expr-21.12 {non-numeric boolean literals} {expr !yes } 0
test expr-21.13 {non-numeric boolean literals} -body {
expr !truef
} -returnCodes error -match glob -result *
test expr-21.14 {non-numeric boolean literals} {
list [catch {expr !"truef"} err] $err
} {1 {cannot use non-numeric string "truef" as operand of "!"}}
test expr-21.15 {non-numeric boolean variables} {
set v truef
list [catch {expr {!$v}} err] $err
} {1 {cannot use non-numeric string "truef" as operand of "!"}}
test expr-21.16 {non-numeric boolean variables} {
set v "true "
list [catch {expr {!$v}} err] $err
} {1 {cannot use non-numeric string "true " as operand of "!"}}
test expr-21.17 {non-numeric boolean variables} {
set v "tru"
list [catch {expr {!$v}} err] $err
} {0 0}
test expr-21.18 {non-numeric boolean variables} {
set v "fal"
list [catch {expr {!$v}} err] $err
} {0 1}
test expr-21.19 {non-numeric boolean variables} {
set v "y"
list [catch {expr {!$v}} err] $err
} {0 0}
test expr-21.20 {non-numeric boolean variables} {
set v "of"
list [catch {expr {!$v}} err] $err
} {0 1}
test expr-21.21 {non-numeric boolean variables} {
set v "o"
list [catch {expr {!$v}} err] $err
} {1 {cannot use non-numeric string "o" as operand of "!"}}
test expr-21.22 {non-numeric boolean variables} {
set v ""
list [catch {expr {!$v}} err] $err
} {1 {cannot use non-numeric string "" as operand of "!"}}
# Test for non-numeric float handling.
test expr-22.1 {non-numeric floats} {
list [catch {expr {NaN + 1}} msg] $msg
} {1 {cannot use non-numeric floating-point value "NaN" as left operand of "+"}}
test expr-22.2 {non-numeric floats} !ieeeFloatingPoint {
list [catch {expr {Inf + 1}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "+"}}
test expr-22.3 {non-numeric floats} {
set nan NaN
list [catch {expr {$nan + 1}} msg] $msg
} {1 {cannot use non-numeric floating-point value "NaN" as left operand of "+"}}
test expr-22.4 {non-numeric floats} !ieeeFloatingPoint {
set inf Inf
list [catch {expr {$inf + 1}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "+"}}
test expr-22.5 {non-numeric floats} {
list [catch {expr NaN} msg] $msg
} {1 {domain error: argument not in valid range}}
test expr-22.6 {non-numeric floats} !ieeeFloatingPoint {
list [catch {expr Inf} msg] $msg
} {1 {floating-point value too large to represent}}
test expr-22.7 {non-numeric floats} {
list [catch {expr {1 / NaN}} msg] $msg
} {1 {cannot use non-numeric floating-point value "NaN" as right operand of "/"}}
test expr-22.8 {non-numeric floats} !ieeeFloatingPoint {
list [catch {expr {1 / Inf}} msg] $msg
} {1 {can't use infinite floating-point value as operand of "/"}}
# Make sure [Bug 761471] stays fixed.
test expr-22.9 {non-numeric floats: shared object equality and NaN} {
set x NaN
expr {$x == $x}
|
| ︙ | ︙ | |||
908 909 910 911 912 913 914 |
expr (-3-)**6
} -returnCodes error -match glob -result *
test expr-23.8 {CompileExponentialExpr: error compiling expo arm} -body {
expr 2**x
} -returnCodes error -match glob -result *
test expr-23.9 {CompileExponentialExpr: runtime error} {
list [catch {expr {24.0**"xx"}} msg] $msg
| | | | 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 |
expr (-3-)**6
} -returnCodes error -match glob -result *
test expr-23.8 {CompileExponentialExpr: error compiling expo arm} -body {
expr 2**x
} -returnCodes error -match glob -result *
test expr-23.9 {CompileExponentialExpr: runtime error} {
list [catch {expr {24.0**"xx"}} msg] $msg
} {1 {cannot use non-numeric string "xx" as right operand of "**"}}
test expr-23.10 {CompileExponentialExpr: runtime error} {
list [catch {expr {"a"**2}} msg] $msg
} {1 {cannot use non-numeric string "a" as left operand of "**"}}
test expr-23.11 {CompileExponentialExpr: runtime error} {
list [catch {expr {0**-1}} msg] $msg
} {1 {exponentiation of zero by negative power}}
test expr-23.12 {CompileExponentialExpr: runtime error} {
list [catch {expr {0.0**-1.0}} msg] $msg
} {1 {exponentiation of zero by negative power}}
test expr-23.13 {CompileExponentialExpr: runtime error} {
|
| ︙ | ︙ | |||
5838 5839 5840 5841 5842 5843 5844 |
[expr {$max_long_str + 0}] \
[expr {$max_long + 0}] \
[expr {2147483647 + 0}] \
[expr {$max_long == $max_long_hex}] \
[expr {int(2147483647 + 1) > 0}] \
} {2147483647 2147483647 2147483647 2147483647 1 1}
| | | 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 |
[expr {$max_long_str + 0}] \
[expr {$max_long + 0}] \
[expr {2147483647 + 0}] \
[expr {$max_long == $max_long_hex}] \
[expr {int(2147483647 + 1) > 0}] \
} {2147483647 2147483647 2147483647 2147483647 1 1}
test expr-33.2 {parse smallest long value} {
set min_long_str -2147483648
set min_long_hex "-0x80000000 "
set min_long -2147483648
# This will convert to integer (not wide) internal rep
string is integer $min_long
|
| ︙ | ︙ | |||
7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 |
if {$k != (1<<28)+1} {
append trouble "i = $i, k = $k\n"
incr faults
}
}
set trouble
} {}
test expr-48.1 {Bug 1770224} {
expr {-0x8000000000000001 >> 0x8000000000000000}
} -1
test expr-49.1 {Bug 2823282} {
coroutine foo apply {{} {set expr expr; $expr {[yield]}}}
| > > > > > > > > > | 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 |
if {$k != (1<<28)+1} {
append trouble "i = $i, k = $k\n"
incr faults
}
}
set trouble
} {}
test expr-47.14 {isqrt() - lseq} {
list [catch {expr {isqrt([lseq 1 3])}} result] $result
} {1 {expected number but got a list}}
test expr-47.15 {isqrt() - lseq} {
list [catch {expr {isqrt({1 2 3})}} result] $result
} {1 {expected number but got a list}}
test expr-47.16 {isqrt() - lseq} {
list [catch {expr {isqrt([dict create foo bar])}} result] $result
} {1 {expected number but got a list}}
test expr-48.1 {Bug 1770224} {
expr {-0x8000000000000001 >> 0x8000000000000000}
} -1
test expr-49.1 {Bug 2823282} {
coroutine foo apply {{} {set expr expr; $expr {[yield]}}}
|
| ︙ | ︙ |
Changes to tests/format.test.
| ︙ | ︙ | |||
11 12 13 14 15 16 17 |
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
| | < < < | < < < | < < < | < < < | < < < | < < < | < < < | 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 |
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
# %z/%t/%p output depends on pointerSize, so some tests are not portable.
testConstraint pointerIs64bit [expr {$tcl_platform(pointerSize) >= 8}]
# MSVC uses a broken libc that gets sprintf("%g") wrong. This is a pain
# particularly in Continuous Integration, and there isn't anything much we can
# do about it.
testConstraint knownMsvcBug [expr {![string match msvc-* [tcl::build-info compiler]]}]
test format-1.1 {integer formatting} {
format "%*d %d %d %d" 6 34 16923 -12 -1
} { 34 16923 -12 -1}
test format-1.2 {integer formatting} {
format "%4d %4d %4d %4d %d %#x %#X" 6 34 16923 -12 -1 14 12
} { 6 34 16923 -12 -1 0xe 0xC}
test format-1.3 {integer formatting} {
format "%4u %4u %4u %4u %d %#o" 6 34 16923 -12 -1 0
} { 6 34 16923 4294967284 -1 0}
test format-1.4 {integer formatting} {
format "%-4d %-4i %-4d %-4ld" 6 34 16923 -12 -1
} {6 34 16923 -12 }
test format-1.5 {integer formatting} {
format "%04d %04d %04d %04i" 6 34 16923 -12 -1
} {0006 0034 16923 -012}
test format-1.6 {integer formatting} {
format "%00*d" 6 34
} {000034}
# Printing negative numbers in hex or octal format depends on word
# length, so these tests are not portable.
test format-1.7 {integer formatting} {
format "%4x %4x %4x %4x" 6 34 16923 -12 -1
} { 6 22 421b fffffff4}
test format-1.8 {integer formatting} {
format "%#x %#x %#X %#X %#x" 0 6 34 16923 -12 -1
} {0 0x6 0x22 0x421B 0xfffffff4}
test format-1.9 {integer formatting} {
format "%#5x %#20x %#20x %#20x %#20x" 0 6 34 16923 -12 -1
} { 0 0x6 0x22 0x421b 0xfffffff4}
test format-1.10 {integer formatting} {
format "%-#5x %-#20x %-#20x %-#20x %-#20x" 0 6 34 16923 -12 -1
} {0 0x6 0x22 0x421b 0xfffffff4 }
test format-1.11 {integer formatting} {
format "%-#5o %-#20o %#-20o %#-20o %#-20o" 0 6 34 16923 -12 -1
} {0 0o6 0o42 0o41033 0o37777777764 }
test format-1.12 {integer formatting} {
format "%b %#b %#b %llb" 5 0 5 [expr {2**100}]
} {101 0 0b101 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}
test format-1.13 {integer formatting} {
format "%#0d %#0d %#0d %#0d %#0d" 0 6 34 16923 -12 -1
} {0 0d6 0d34 0d16923 -0d12}
test format-1.14 {integer formatting} {
|
| ︙ | ︙ | |||
552 553 554 555 556 557 558 |
for {set i 290} {$i < 400} {incr i} {
test format-16.[expr {$i -289}] {testing MAX_FLOAT_SIZE} {
format {%s} $b
} $b
append b "x"
}
| | | | | 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 |
for {set i 290} {$i < 400} {incr i} {
test format-16.[expr {$i -289}] {testing MAX_FLOAT_SIZE} {
format {%s} $b
} $b
append b "x"
}
test format-17.1 {testing %d with wide} {
format %d 7810179016327718216
} 1819043144
test format-17.2 {testing %ld with wide} {
format %ld 7810179016327718216
} 7810179016327718216
test format-17.3 {testing %ld with non-wide} {
format %ld 42
} 42
test format-17.4 {testing %l with non-integer} {
format %lf 1
} 1.000000
test format-17.5 {testing %llu with positive bignum} -body {
format %llu 0xabcdef0123456789abcdef
|
| ︙ | ︙ | |||
585 586 587 588 589 590 591 |
lappend result [expr {$a == $b}]
set b 0xaaaa
append b aaaa
lappend result [expr {$a == $b}]
format %08x $b
lappend result [expr {$a == $b}]
} {1 1 1 1}
| | | < | 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 |
lappend result [expr {$a == $b}]
set b 0xaaaa
append b aaaa
lappend result [expr {$a == $b}]
format %08x $b
lappend result [expr {$a == $b}]
} {1 1 1 1}
test format-18.2 {do not demote existing numeric values} {
set a [expr {0xaaaaaaaaaa + 1}]
set b 0xaaaaaaaaab
list [format %08x $a] [expr {$a == $b}]
} {aaaaaaab 1}
test format-19.1 {regression test - tcl-core message by Brian Griffin on 26 0ctober 2004} -body {
set x 0x8fedc654
list [expr { ~ $x }] [format %08x [expr { ~$x }]]
} -match regexp -result {-2414724693 f*701239ab}
test format-19.2 {Bug 1867855} {
format %llx 0
} 0
test format-19.3 {Bug 2830354} {
string length [format %340f 0]
} 340
test format-19.4.1 {Bug d498578df4: width overflow should cause limit exceeded} -body {
# in case of overflow into negative, it produces width -2 (and limit exceeded),
# in case of width will be unsigned, it will be outside limit (2GB for 32bit)...
# and it don't throw an error in case the bug is not fixed (and probably no segfault).
format %[expr {0xffffffff - 1}]g 0
} -returnCodes error -result "max size for a Tcl value exceeded"
test format-19.4.2 {Bug d498578df4: width overflow should cause limit exceeded} -body {
|
| ︙ | ︙ |
Added tests/icu.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
# Tests for tcl::unsupported::icu
if {"::tcltest" ni [namespace children]} {
package require tcltest
namespace import -force ::tcltest::*
}
# Force late loading of ICU if present
catch {::tcl::unsupported::icu}
testConstraint icu [expr {[info commands ::tcl::unsupported::icu::detect] ne ""}]
namespace eval icu {
test icu-detect-0 {Return list of ICU encodings} -constraints icu -body {
set encoders [::tcl::unsupported::icu detect]
list [::tcl::mathop::in UTF-8 $encoders] [::tcl::mathop::in ISO-8859-1 $encoders]
} -result {1 1}
test icu-detect-1 {Guess encoding} -constraints icu -body {
::tcl::unsupported::icu detect [readFile [info script]]
} -result ISO-8859-1
test icu-detect-2 {Get all possible encodings} -constraints icu -body {
set encodings [::tcl::unsupported::icu detect [readFile [info script]] -all]
list [::tcl::mathop::in UTF-8 $encodings] [::tcl::mathop::in ISO-8859-1 $encodings]
} -result {1 1}
test icu-tclToIcu-0 {Map Tcl encoding} -constraints icu -body {
# tis-620 because it is ambiguous in ICU on some platforms
# but should return the preferred encoding
list [::tcl::unsupported::icu tclToIcu utf-8] [::tcl::unsupported::icu tclToIcu tis-620] [::tcl::unsupported::icu tclToIcu shiftjis]
} -result {UTF-8 TIS-620 ibm-943_P15A-2003}
test icu-tclToIcu-1 {Map Tcl encoding - no map} -constraints icu -body {
# Should not raise an error
::tcl::unsupported::icu tclToIcu dummy
} -result {}
test icu-icuToTcl-0 {Map ICU encoding} -constraints icu -body {
list [::tcl::unsupported::icu icuToTcl UTF-8] [::tcl::unsupported::icu icuToTcl TIS-620] [::tcl::unsupported::icu icuToTcl ibm-943_P15A-2003]
} -result {utf-8 tis-620 cp932}
test icu-icuToTcl-1 {Map ICU encoding - no map} -constraints icu -body {
# Should not raise an error
::tcl::unsupported::icu icuToTcl dummy
} -result {}
}
namespace delete icu
::tcltest::cleanupTests
|
Changes to tests/info.test.
| ︙ | ︙ | |||
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 |
test info-33.35 {{*}, literal, simple, bytecompiled} -body {
reduce [foo::bar]
} -cleanup {
namespace delete foo
} -result {type source line 2389 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
namespace eval ::testinfocmdtype {
apply {cmds {
foreach c $cmds {rename $c {}}
} ::testinfocmdtype} [info commands ::testinfocmdtype::*]
}
test info-40.1 {info cmdtype: syntax} -body {
info cmdtype
| > | 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 |
test info-33.35 {{*}, literal, simple, bytecompiled} -body {
reduce [foo::bar]
} -cleanup {
namespace delete foo
} -result {type source line 2389 file info.test cmd {info frame 0} proc ::foo::bar level 0}
# -------------------------------------------------------------------------
namespace eval ::testinfocmdtype {
apply {cmds {
foreach c $cmds {rename $c {}}
} ::testinfocmdtype} [info commands ::testinfocmdtype::*]
}
test info-40.1 {info cmdtype: syntax} -body {
info cmdtype
|
| ︙ | ︙ | |||
2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 |
} -returnCodes error -cleanup {
interp delete $safe
} -result {not allowed to invoke subcommand cmdtype of info}
namespace delete ::testinfocmdtype
# -------------------------------------------------------------------------
unset -nocomplain res
test info-39.2 {Bug 4b61afd660} -setup {
proc probe {} {
return [dict get [info frame -1] line]
}
set body {
set cmd probe
$cmd
}
proc demo {} $body
} -body {
demo
} -cleanup {
unset -nocomplain body
rename demo {}
rename probe {}
} -result 3
# cleanup
catch {namespace delete test_ns_info1 test_ns_info2}
::tcltest::cleanupTests
return
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 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 |
} -returnCodes error -cleanup {
interp delete $safe
} -result {not allowed to invoke subcommand cmdtype of info}
namespace delete ::testinfocmdtype
# -------------------------------------------------------------------------
unset -nocomplain res
test info-19.7 {info vars: bug [0e4b7fce57], TIP #278 - no global vars resolve} -setup {
catch {namespace delete x}
} -body {
namespace eval x {info vars}
} -cleanup {
namespace delete x
} -result {}
test info-19.8 {info vars: bug [0e4b7fce57], TIP #278 - no global vars resolve} -setup {
catch {namespace delete x}
} -body {
namespace eval x {info vars tcl_platform}
} -cleanup {
namespace delete x
} -result {}
test info-19.9 {info vars: global vars resolved by pattern} -setup {
catch {namespace delete x}
} -body {
namespace eval x {info vars ::tcl_platform}
} -cleanup {
namespace delete x
} -result {::tcl_platform}
test info-39.2 {Bug 4b61afd660} -setup {
proc probe {} {
return [dict get [info frame -1] line]
}
set body {
set cmd probe
$cmd
}
proc demo {} $body
} -body {
demo
} -cleanup {
unset -nocomplain body
rename demo {}
rename probe {}
} -result 3
test info-41.0 {Bug 0de6c1d79c crash} -setup {
interp create child
child hide info
} -body {
list [child invokehidden info frame] \
[child invokehidden info frame 0] \
[child invokehidden info frame 1] \
[catch {child invokehidden info frame -1} msg] $msg \
[catch {child invokehidden info frame 2} msg] $msg
} -cleanup {
interp delete child
unset -nocomplain msg
} -result {1 {type precompiled} {type precompiled} 1 {bad level "-1"} 1 {bad level "2"}}
test info-41.1 {Bug 0de6c1d79c crash} -setup {
interp create child
child hide info
} -cleanup {
interp delete child
} -body {
child invokehidden info frame
} -result 1
# cleanup
catch {namespace delete test_ns_info1 test_ns_info2}
::tcltest::cleanupTests
return
|
Changes to tests/io.test.
| ︙ | ︙ | |||
63 64 65 66 67 68 69 |
testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]
# set up a long data file for some of the following tests
set path(longfile) [makeFile {} longfile]
set f [open $path(longfile) w]
| | | | | 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 |
testConstraint makeFileInHome [expr {![file exists ~/_test_] && [file writable ~]}]
# set up a long data file for some of the following tests
set path(longfile) [makeFile {} longfile]
set f [open $path(longfile) w]
fconfigure $f -translation lf
for { set i 0 } { $i < 100 } { incr i} {
puts $f "#123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
\#123456789abcdef01
\#"
}
close $f
set path(cat) [makeFile {
set f stdin
if {$argv != ""} {
set f [open [lindex $argv 0]]
}
fconfigure $f -translation binary -blocking 0 -eofchar \x1A
fconfigure stdout -translation binary -buffering none
fileevent $f readable "foo $f"
proc foo {f} {
set x [read $f]
catch {puts -nonewline $x}
if {[eof $f]} {
close $f
exit 0
|
| ︙ | ︙ | |||
106 107 108 109 110 111 112 |
test io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
# no test, need to cause an async error.
} {}
set path(test1) [makeFile {} test1]
test io-1.6 {Tcl_WriteChars: WriteBytes} {
set f [open $path(test1) w]
| | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
test io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} {
# no test, need to cause an async error.
} {}
set path(test1) [makeFile {} test1]
test io-1.6 {Tcl_WriteChars: WriteBytes} {
set f [open $path(test1) w]
fconfigure $f -translation binary
puts -nonewline $f "a\x4D\x00"
close $f
contents $path(test1)
} "a\x4D\x00"
test io-1.7 {Tcl_WriteChars: WriteChars} {
set f [open $path(test1) w]
fconfigure $f -encoding shiftjis
|
| ︙ | ︙ | |||
242 243 244 245 246 247 248 |
testreadwrite 0xffffffff
} -result 1
test io-2.1 {WriteBytes} {
# loop until all bytes are written
set f [open $path(test1) w]
| | | | | < | 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 |
testreadwrite 0xffffffff
} -result 1
test io-2.1 {WriteBytes} {
# loop until all bytes are written
set f [open $path(test1) w]
fconfigure $f -translation binary -buffersize 16 -translation crlf
puts $f "abcdefghijklmnopqrstuvwxyz"
close $f
contents $path(test1)
} "abcdefghijklmnopqrstuvwxyz\r\n"
test io-2.2 {WriteBytes: savedLF > 0} {
# After flushing buffer, there was a \n left over from the last
# \n -> \r\n expansion. It gets stuck at beginning of this buffer.
set f [open $path(test1) w]
fconfigure $f -translation binary -buffersize 16 -translation crlf
puts -nonewline $f "123456789012345\n12"
set x [list [contents $path(test1)]]
close $f
lappend x [contents $path(test1)]
} [list "123456789012345\r" "123456789012345\r\n12"]
test io-2.3 {WriteBytes: flush on line} {
# Tcl "line" buffering has weird behavior: if current buffer contains
# a \n, entire buffer gets flushed. Logical behavior would be to flush
# only up to the \n.
set f [open $path(test1) w]
fconfigure $f -translation binary -buffering line -translation crlf
puts -nonewline $f "\n12"
set x [contents $path(test1)]
close $f
set x
} "\r\n12"
test io-2.4 {WriteBytes: reset sawLF after each buffer} {
set f [open $path(test1) w]
fconfigure $f -translation binary -buffering line -buffersize 16
puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz"
set x [list [contents $path(test1)]]
close $f
lappend x [contents $path(test1)]
} [list "abcdefg\nhijklmno" "abcdefg\nhijklmnopqrstuvwxyz"]
test io-2.5 {WriteBytes: large file (> INT_MAX). Bug 3d01d51bc4} -constraints {
pointerIs64bit perf
|
| ︙ | ︙ | |||
463 464 465 466 467 468 469 |
puts -nonewline $f "12345678901\n456789012345678901234"
close $f
set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"
test io-5.1 {CheckFlush: not full} {
set f [open $path(test1) w]
| < | 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
puts -nonewline $f "12345678901\n456789012345678901234"
close $f
set x [contents $path(test1)]
} "12345678901\r\n456789012345678901234"
test io-5.1 {CheckFlush: not full} {
set f [open $path(test1) w]
puts -nonewline $f "12345678901234567890"
set x [list [contents $path(test1)]]
close $f
lappend x [contents $path(test1)]
} [list "" "12345678901234567890"]
test io-5.2 {CheckFlush: full} {
set f [open $path(test1) w]
|
| ︙ | ︙ | |||
1176 1177 1178 1179 1180 1181 1182 |
close $f
set x
} "123456789012301234"
test io-7.2 {FilterInputBytes: split up character in middle of buffer} {
# (bufPtr->nextAdded < bufPtr->bufLength)
set f [open $path(test1) w]
| | | | | | 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 |
close $f
set x
} "123456789012301234"
test io-7.2 {FilterInputBytes: split up character in middle of buffer} {
# (bufPtr->nextAdded < bufPtr->bufLength)
set f [open $path(test1) w]
fconfigure $f -translation binary
puts -nonewline $f "1234567890\n123\x82\x4F\x82\x50\x82"
close $f
set f [open $path(test1)]
fconfigure $f -encoding shiftjis -profile tcl8
set x [list [gets $f line] $line [eof $f]]
close $f
set x
} [list 10 "1234567890" 0]
test io-7.3 {FilterInputBytes: split up character at EOF} {testchannel} {
set f [open $path(test1) w]
fconfigure $f -translation binary
puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82"
close $f
set f [open $path(test1)]
fconfigure $f -encoding shiftjis -profile tcl8
set x [list [gets $f line] $line]
lappend x [tell $f] [testchannel inputbuffered $f] [eof $f]
lappend x [gets $f line] $line
close $f
set x
} [list 16 "123456789012301\x82" 18 0 1 -1 ""]
test io-7.4 {FilterInputBytes: recover from split up character} {stdio fileevent} {
set f [open "|[list [interpreter] $path(cat)]" w+]
fconfigure $f -translation binary -buffering none
puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82"
fconfigure $f -encoding shiftjis -blocking 0
fileevent $f read [namespace code "ready $f"]
variable x {}
proc ready {f} {
variable x
lappend x [gets $f line] $line [fblocked $f]
}
vwait [namespace which -variable x]
fconfigure $f -translation binary -blocking 1
puts $f "\x51\x82\x52"
fconfigure $f -encoding shiftjis
vwait [namespace which -variable x]
close $f
set x
} [list -1 "" 1 17 "12345678901230123" 0]
|
| ︙ | ︙ | |||
1275 1276 1277 1278 1279 1280 1281 |
# not (bytesLeft == 0)
set f [open $path(test1) w+]
fconfigure $f -translation binary
puts $f "${a}\r\nabcdef"
close $f
set f [open $path(test1)]
| | | 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 |
# not (bytesLeft == 0)
set f [open $path(test1) w+]
fconfigure $f -translation binary
puts $f "${a}\r\nabcdef"
close $f
set f [open $path(test1)]
fconfigure $f -translation binary -translation auto
# "${a}\r" was converted in one operation (because ENCODING_LINESIZE
# is 30). To check if "\n" follows, calls PeekAhead and determines
# that cached data is available in buffer w/o having to call driver.
set x [gets $f]
close $f
|
| ︙ | ︙ | |||
1392 1393 1394 1395 1396 1397 1398 |
test io-11.1 {ReadBytes: want to read a lot} {
# ((unsigned) toRead > (unsigned) srcLen)
set f [open $path(test1) w]
puts -nonewline $f abcdefghijkl
close $f
set f [open $path(test1)]
| | | | | | 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 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 1435 1436 1437 1438 1439 1440 1441 1442 1443 |
test io-11.1 {ReadBytes: want to read a lot} {
# ((unsigned) toRead > (unsigned) srcLen)
set f [open $path(test1) w]
puts -nonewline $f abcdefghijkl
close $f
set f [open $path(test1)]
fconfigure $f -translation binary
# here
set x [read $f 1000]
close $f
set x
} {abcdefghijkl}
test io-11.2 {ReadBytes: want to read all} {
# ((unsigned) toRead > (unsigned) srcLen)
set f [open $path(test1) w]
puts -nonewline $f abcdefghijkl
close $f
set f [open $path(test1)]
fconfigure $f -translation binary
# here
set x [read $f]
close $f
set x
} {abcdefghijkl}
test io-11.3 {ReadBytes: allocate more space} {
# (toRead > length - offset - 1)
set f [open $path(test1) w]
puts -nonewline $f abcdefghijklmnopqrstuvwxyz
close $f
set f [open $path(test1)]
fconfigure $f -buffersize 16 -translation binary
# here
set x [read $f]
close $f
set x
} {abcdefghijklmnopqrstuvwxyz}
test io-11.4 {ReadBytes: EOF char found} {
# (TranslateInputEOL() != 0)
set f [open $path(test1) w]
puts $f abcdefghijklmnopqrstuvwxyz
close $f
set f [open $path(test1)]
fconfigure $f -translation binary -eofchar m
# here
set x [list [read $f] [eof $f] [read $f] [eof $f]]
close $f
set x
} [list "abcdefghijkl" 1 "" 1]
test io-12.1 {ReadChars: want to read a lot} {
|
| ︙ | ︙ | |||
1479 1480 1481 1482 1483 1484 1485 |
close $f
set x
} {abcdefghijklmnopqrstuvwxyz}
test io-12.4 {ReadChars: split-up char} {stdio testchannel fileevent} {
# (srcRead == 0)
set f [open "|[list [interpreter] $path(cat)]" w+]
| | | | | 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 |
close $f
set x
} {abcdefghijklmnopqrstuvwxyz}
test io-12.4 {ReadChars: split-up char} {stdio testchannel fileevent} {
# (srcRead == 0)
set f [open "|[list [interpreter] $path(cat)]" w+]
fconfigure $f -translation binary -buffering none -buffersize 16
puts -nonewline $f "123456789012345\x96"
fconfigure $f -encoding shiftjis -blocking 0
fileevent $f read [namespace code "ready $f"]
proc ready {f} {
variable x
lappend x [read $f] [testchannel inputbuffered $f]
}
variable x {}
fconfigure $f -encoding shiftjis
vwait [namespace which -variable x]
fconfigure $f -translation binary -blocking 1
puts -nonewline $f "\x7B"
after 500 ;# Give the cat process time to catch up
fconfigure $f -encoding shiftjis -blocking 0
vwait [namespace which -variable x]
close $f
set x
} [list "123456789012345" 1 "本" 0]
test io-12.5 {ReadChars: fileevents on partial characters} {stdio fileevent} {
set path(test1) [makeFile {
fconfigure stdout -translation binary -buffering none
gets stdin; puts -nonewline "\xE7"
gets stdin; puts -nonewline "\x89"
gets stdin; puts -nonewline "\xA6"
} test1]
set f [open "|[list [interpreter] $path(test1)]" r+]
fileevent $f readable [namespace code {
lappend x [read $f]
|
| ︙ | ︙ | |||
2225 2226 2227 2228 2229 2230 2231 |
set t [testchannel type $f]
close $f
string compare $t file
} 0
test io-25.1 {Tcl_GetChannelHandle, input} {testchannel} {
set f [open $path(test1) w]
| | | 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 |
set t [testchannel type $f]
close $f
string compare $t file
} 0
test io-25.1 {Tcl_GetChannelHandle, input} {testchannel} {
set f [open $path(test1) w]
fconfigure $f -translation lf
puts $f "1234567890\n098765432"
close $f
set f [open $path(test1) r]
gets $f
set l ""
lappend l [testchannel inputbuffered $f]
lappend l [tell $f]
|
| ︙ | ︙ | |||
2274 2275 2276 2277 2278 2279 2280 |
set s [file size $path(test1)]
close $f
set s
} 0
test io-27.2 {FlushChannel, some output buffered} {
file delete $path(test1)
set f [open $path(test1) w]
| | | | | | 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 |
set s [file size $path(test1)]
close $f
set s
} 0
test io-27.2 {FlushChannel, some output buffered} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
set l ""
puts $f hello
lappend l [file size $path(test1)]
flush $f
lappend l [file size $path(test1)]
close $f
lappend l [file size $path(test1)]
set l
} {0 6 6}
test io-27.3 {FlushChannel, implicit flush on close} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
set l ""
puts $f hello
lappend l [file size $path(test1)]
close $f
lappend l [file size $path(test1)]
set l
} {0 6}
test io-27.4 {FlushChannel, implicit flush when buffer fills} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
fconfigure $f -buffersize 60
set l ""
lappend l [file size $path(test1)]
for {set i 0} {$i < 12} {incr i} {
puts $f hello
}
lappend l [file size $path(test1)]
flush $f
lappend l [file size $path(test1)]
close $f
set l
} {0 60 72}
test io-27.5 {FlushChannel, implicit flush when buffer fills and on close} \
{unixOrWin} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf -buffersize 60
set l ""
lappend l [file size $path(test1)]
for {set i 0} {$i < 12} {incr i} {
puts $f hello
}
lappend l [file size $path(test1)]
close $f
|
| ︙ | ︙ | |||
2337 2338 2339 2340 2341 2342 2343 |
# This test may fail on old Unix systems (seen on IRIX64 6.5) with
# obsolete gettimeofday() calls. See Tcl Bugs 3530533, 1942197.
file delete $path(pipe)
file delete $path(output)
set f [open $path(pipe) w]
puts $f "set f \[[list open $path(output) w]]"
puts $f {
| | | 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 |
# This test may fail on old Unix systems (seen on IRIX64 6.5) with
# obsolete gettimeofday() calls. See Tcl Bugs 3530533, 1942197.
file delete $path(pipe)
file delete $path(output)
set f [open $path(pipe) w]
puts $f "set f \[[list open $path(output) w]]"
puts $f {
fconfigure $f -translation lf -buffering none
while {![eof stdin]} {
after 20
puts -nonewline $f [read stdin 1024]
}
close $f
}
close $f
|
| ︙ | ︙ | |||
2404 2405 2406 2407 2408 2409 2410 |
test io-28.3 {CloseChannel, not called before output queue is empty} \
{stdio asyncPipeClose nonPortable} {
file delete $path(pipe)
file delete $path(output)
set f [open $path(pipe) w]
puts $f {
| < < < < < < < | | 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 |
test io-28.3 {CloseChannel, not called before output queue is empty} \
{stdio asyncPipeClose nonPortable} {
file delete $path(pipe)
file delete $path(output)
set f [open $path(pipe) w]
puts $f {
set f [open $path(output) w]
fconfigure $f -translation lf -buffering none
for {set x 0} {$x < 20} {incr x} {
after 20
puts -nonewline $f [read stdin 1024]
}
close $f
}
close $f
set x 01234567890123456789012345678901
for {set i 0} {$i < 11} {incr i} {
set x "$x$x"
}
set f [open $path(output) w]
close $f
set f [open "|[list [interpreter] pipe]" r+]
fconfigure $f -blocking off
puts -nonewline $f $x
close $f
set counter 0
while {([file size $path(output)] < 20480) && ($counter < 1000)} {
after 20 [list incr [namespace which -variable counter]]
vwait [namespace which -variable counter]
|
| ︙ | ︙ | |||
2560 2561 2562 2563 2564 2565 2566 |
test io-29.1 {Tcl_WriteChars, channel not writable} {
list [catch {puts stdin hello} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}
test io-29.2 {Tcl_WriteChars, empty string} {
file delete $path(test1)
set f [open $path(test1) w]
| < < | | | | | 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 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 |
test io-29.1 {Tcl_WriteChars, channel not writable} {
list [catch {puts stdin hello} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}
test io-29.2 {Tcl_WriteChars, empty string} {
file delete $path(test1)
set f [open $path(test1) w]
puts -nonewline $f ""
close $f
file size $path(test1)
} 0
test io-29.3 {Tcl_WriteChars, nonempty string} {
file delete $path(test1)
set f [open $path(test1) w]
puts -nonewline $f hello
close $f
file size $path(test1)
} 5
test io-29.4 {Tcl_WriteChars, buffering in full buffering mode} {testchannel} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf -buffering full
puts $f hello
set l ""
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
flush $f
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
close $f
set l
} {6 0 0 6}
test io-29.5 {Tcl_WriteChars, buffering in line buffering mode} {testchannel} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf -buffering line
puts -nonewline $f hello
set l ""
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
puts $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
close $f
set l
} {5 0 0 11}
test io-29.6 {Tcl_WriteChars, buffering in no buffering mode} {testchannel} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf -buffering none
puts -nonewline $f hello
set l ""
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
puts $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
close $f
set l
} {0 5 0 11}
test io-29.7 {Tcl_Flush, full buffering} {testchannel} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf -buffering full
puts -nonewline $f hello
set l ""
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
puts $f hello
lappend l [testchannel outputbuffered $f]
lappend l [file size $path(test1)]
|
| ︙ | ︙ | |||
2658 2659 2660 2661 2662 2663 2664 |
} {5 0 0 5 0 11 0 11}
test io-29.9 {Tcl_Flush, channel not writable} {
list [catch {flush stdin} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}
test io-29.10 {Tcl_WriteChars, looping and buffering} {
file delete $path(test1)
set f1 [open $path(test1) w]
| | < | 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 |
} {5 0 0 5 0 11 0 11}
test io-29.9 {Tcl_Flush, channel not writable} {
list [catch {flush stdin} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}
test io-29.10 {Tcl_WriteChars, looping and buffering} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
set f2 [open $path(longfile) r]
for {set x 0} {$x < 10} {incr x} {
puts $f1 [gets $f2]
}
close $f2
close $f1
file size $path(test1)
} 387
test io-29.11 {Tcl_WriteChars, no newline, implicit flush} {
file delete $path(test1)
set f1 [open $path(test1) w]
set f2 [open $path(longfile) r]
for {set x 0} {$x < 10} {incr x} {
puts -nonewline $f1 [gets $f2]
}
close $f1
close $f2
file size $path(test1)
|
| ︙ | ︙ | |||
2796 2797 2798 2799 2800 2801 2802 |
lappend x [file size $path(test1)]
close $f1
set x
} {18 24 30}
test io-29.19 {Explicit and implicit flushes} {
file delete $path(test1)
set f1 [open $path(test1) w]
| | | | 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 |
lappend x [file size $path(test1)]
close $f1
set x
} {18 24 30}
test io-29.19 {Explicit and implicit flushes} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
set x ""
puts $f1 hello
puts $f1 hello
puts $f1 hello
flush $f1
lappend x [file size $path(test1)]
puts $f1 hello
flush $f1
lappend x [file size $path(test1)]
puts $f1 hello
close $f1
lappend x [file size $path(test1)]
set x
} {18 24 30}
test io-29.20 {Implicit flush when buffer is full} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
set line "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
for {set x 0} {$x < 100} {incr x} {
puts $f1 $line
}
set z ""
lappend z [file size $path(test1)]
for {set x 0} {$x < 100} {incr x} {
|
| ︙ | ︙ | |||
2952 2953 2954 2955 2956 2957 2958 |
}
regsub {".*":} $x {"":} x
string tolower $x
} {1 {error flushing "": broken pipe} {posix epipe {broken pipe}}}
test io-29.28 {Tcl_WriteChars, lf mode} {
file delete $path(test1)
set f [open $path(test1) w]
| | | | | 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 |
}
regsub {".*":} $x {"":} x
string tolower $x
} {1 {error flushing "": broken pipe} {posix epipe {broken pipe}}}
test io-29.28 {Tcl_WriteChars, lf mode} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
puts $f hello\nthere\nand\nhere
flush $f
set s [file size $path(test1)]
close $f
set s
} 21
test io-29.29 {Tcl_WriteChars, cr mode} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation cr
puts $f hello\nthere\nand\nhere
close $f
file size $path(test1)
} 21
test io-29.30 {Tcl_WriteChars, crlf mode} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation crlf
puts $f hello\nthere\nand\nhere
close $f
file size $path(test1)
} 25
test io-29.31 {Tcl_WriteChars, background flush} stdio {
# This test may fail on old Unix systems (seen on IRIX64 6.5) with
# obsolete gettimeofday() calls. See Tcl Bugs 3530533, 1942197.
|
| ︙ | ︙ | |||
3544 3545 3546 3547 3548 3549 3550 |
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1 {} 1}
test io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} {
file delete $path(test1)
set f [open $path(test1) w]
| | | | | | | | 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 |
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1 {} 1}
test io-30.20 {Tcl_Write, ^Z in middle ignored, Tcl_Read lf} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
set s [format "abc\ndef\n%cghi\nqrs" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation lf
set l ""
lappend l [gets $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
close $f
set l
} "abc def 0 \x1Aghi 0 qrs 0 {} 1"
test io-30.21 {Tcl_Write, ^Z in middle ignored, Tcl_Read cr} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
set s [format "abc\ndef\n%cghi\nqrs" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation cr
set l ""
set x [gets $f]
lappend l [string compare $x "abc\ndef\n\x1Aghi\nqrs\n"]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
close $f
set l
} {0 1 {} 1}
test io-30.22 {Tcl_Write, ^Z in middle ignored, Tcl_Read crlf} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
set s [format "abc\ndef\n%cghi\nqrs" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation crlf
set l ""
set x [gets $f]
lappend l [string compare $x "abc\ndef\n\x1Aghi\nqrs\n"]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
close $f
|
| ︙ | ︙ | |||
4080 4081 4082 4083 4084 4085 4086 |
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1}
test io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} {
file delete $path(test1)
set f [open $path(test1) w]
| | | | | | | | 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 |
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1}
test io-31.22 {Tcl_Write, ^Z in middle ignored, Tcl_Gets lf} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
set s [format "abc\ndef\n%cqrs\ntuv" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation lf
set l ""
lappend l [gets $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
close $f
set l
} "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test io-31.23 {Tcl_Write, ^Z in middle ignored, Tcl_Gets cr} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation cr
set s [format "abc\ndef\n%cqrs\ntuv" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation cr
set l ""
lappend l [gets $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
close $f
set l
} "abc def 0 \x1Aqrs 0 tuv 0 {} 1"
test io-31.24 {Tcl_Write, ^Z in middle ignored, Tcl_Gets crlf} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation crlf
set s [format "abc\ndef\n%cqrs\ntuv" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation crlf
set l ""
lappend l [gets $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
|
| ︙ | ︙ | |||
4182 4183 4184 4185 4186 4187 4188 |
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1}
test io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} {
file delete $path(test1)
set f [open $path(test1) w]
| | | | | | 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 |
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1}
test io-31.27 {Tcl_Write cr, ^Z in middle, Tcl_Gets auto} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation cr
set s [format "abc\ndef\n%cqrs\ntuv" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation auto -eofchar \x1A
set l ""
lappend l [gets $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1}
test io-31.28 {Tcl_Write cr, ^Z in middle, Tcl_Gets cr} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation cr
set s [format "abc\ndef\n%cqrs\ntuv" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation cr -eofchar \x1A
set l ""
lappend l [gets $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1}
test io-31.29 {Tcl_Write crlf, ^Z in middle, Tcl_Gets auto} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation crlf
set s [format "abc\ndef\n%cqrs\ntuv" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation auto -eofchar \x1A
set l ""
lappend l [gets $f]
lappend l [gets $f]
lappend l [eof $f]
lappend l [gets $f]
lappend l [eof $f]
close $f
set l
} {abc def 0 {} 1}
test io-31.30 {Tcl_Write crlf, ^Z in middle, Tcl_Gets crlf} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation crlf
set s [format "abc\ndef\n%cqrs\ntuv" 26]
puts $f $s
close $f
set f [open $path(test1) r]
fconfigure $f -translation crlf -eofchar \x1A
set l ""
lappend l [gets $f]
|
| ︙ | ︙ | |||
4605 4606 4607 4608 4609 4610 4611 |
set f [open $path(test3) r]
set result [list [catch {gets $f x(0)} msg] $msg]
close $f
set result
} {1 {can't set "x(0)": variable isn't array}}
test io-33.8 {Tcl_Gets, exercising double buffering} {
set f [open $path(test3) w]
| | | | | 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 |
set f [open $path(test3) r]
set result [list [catch {gets $f x(0)} msg] $msg]
close $f
set result
} {1 {can't set "x(0)": variable isn't array}}
test io-33.8 {Tcl_Gets, exercising double buffering} {
set f [open $path(test3) w]
fconfigure $f -translation lf
set x ""
for {set y 0} {$y < 99} {incr y} {set x "a$x"}
for {set y 0} {$y < 100} {incr y} {puts $f $x}
close $f
set f [open $path(test3) r]
fconfigure $f -translation lf
for {set y 0} {$y < 100} {incr y} {gets $f}
close $f
set y
} 100
test io-33.9 {Tcl_Gets, exercising double buffering} {
set f [open $path(test3) w]
fconfigure $f -translation lf
set x ""
for {set y 0} {$y < 99} {incr y} {set x "a$x"}
for {set y 0} {$y < 200} {incr y} {puts $f $x}
close $f
set f [open $path(test3) r]
fconfigure $f -translation lf
for {set y 0} {$y < 200} {incr y} {gets $f}
close $f
set y
} 200
test io-33.10 {Tcl_Gets, exercising double buffering} {
set f [open $path(test3) w]
fconfigure $f -translation lf
set x ""
for {set y 0} {$y < 99} {incr y} {set x "a$x"}
for {set y 0} {$y < 300} {incr y} {puts $f $x}
close $f
set f [open $path(test3) r]
fconfigure $f -translation lf
for {set y 0} {$y < 300} {incr y} {gets $f}
|
| ︙ | ︙ | |||
4759 4760 4761 4762 4763 4764 4765 |
set c [tell $f1]
close $f1
set c
} 0
test io-34.2 {Tcl_Seek to offset from start} {
file delete $path(test1)
set f1 [open $path(test1) w]
| | | | | | | | 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 |
set c [tell $f1]
close $f1
set c
} 0
test io-34.2 {Tcl_Seek to offset from start} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
puts $f1 "abcdefghijklmnopqrstuvwxyz"
puts $f1 "abcdefghijklmnopqrstuvwxyz"
close $f1
set f1 [open $path(test1) r]
seek $f1 10 start
set c [tell $f1]
close $f1
set c
} 10
test io-34.3 {Tcl_Seek to end of file} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
puts $f1 "abcdefghijklmnopqrstuvwxyz"
puts $f1 "abcdefghijklmnopqrstuvwxyz"
close $f1
set f1 [open $path(test1) r]
seek $f1 0 end
set c [tell $f1]
close $f1
set c
} 54
test io-34.4 {Tcl_Seek to offset from end of file} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
puts $f1 "abcdefghijklmnopqrstuvwxyz"
puts $f1 "abcdefghijklmnopqrstuvwxyz"
close $f1
set f1 [open $path(test1) r]
seek $f1 -10 end
set c [tell $f1]
close $f1
set c
} 44
test io-34.5 {Tcl_Seek to offset from current position} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
puts $f1 "abcdefghijklmnopqrstuvwxyz"
puts $f1 "abcdefghijklmnopqrstuvwxyz"
close $f1
set f1 [open $path(test1) r]
seek $f1 10 current
seek $f1 10 current
set c [tell $f1]
close $f1
set c
} 20
test io-34.6 {Tcl_Seek to offset from end of file} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
puts $f1 "abcdefghijklmnopqrstuvwxyz"
puts $f1 "abcdefghijklmnopqrstuvwxyz"
close $f1
set f1 [open $path(test1) r]
seek $f1 -10 end
set c [tell $f1]
set r [read $f1]
close $f1
list $c $r
} {44 {rstuvwxyz
}}
test io-34.7 {Tcl_Seek to offset from end of file, then to current position} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
puts $f1 "abcdefghijklmnopqrstuvwxyz"
puts $f1 "abcdefghijklmnopqrstuvwxyz"
close $f1
set f1 [open $path(test1) r]
seek $f1 -10 end
set c1 [tell $f1]
set r1 [read $f1 5]
|
| ︙ | ︙ | |||
4850 4851 4852 4853 4854 4855 4856 |
close $f1
regsub {".*":} $x {"":} x
string tolower $x
} {1 {error during seek on "": invalid argument}}
test io-34.9 {Tcl_Seek, testing buffered input flushing} {
file delete $path(test3)
set f [open $path(test3) w]
| < | 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 |
close $f1
regsub {".*":} $x {"":} x
string tolower $x
} {1 {error during seek on "": invalid argument}}
test io-34.9 {Tcl_Seek, testing buffered input flushing} {
file delete $path(test3)
set f [open $path(test3) w]
puts -nonewline $f "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
close $f
set f [open $path(test3) RDWR]
set x [read $f 1]
seek $f 3
lappend x [read $f 1]
seek $f 0 start
|
| ︙ | ︙ | |||
4898 4899 4900 4901 4902 4903 4904 |
seek $f 2
set x [gets $f]
close $f
list $x [viewFile test3]
} "zzy xyzzy"
test io-34.12 {Tcl_Seek testing combination of write, seek back and read} {
set f [open $path(test3) w]
| | | | | | 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 |
seek $f 2
set x [gets $f]
close $f
list $x [viewFile test3]
} "zzy xyzzy"
test io-34.12 {Tcl_Seek testing combination of write, seek back and read} {
set f [open $path(test3) w]
fconfigure $f -translation lf
puts $f xyz\n123
close $f
set f [open $path(test3) a+]
fconfigure $f -translation lf
puts $f xyzzy
flush $f
set x [tell $f]
seek $f -4 cur
set y [gets $f]
close $f
list $x [viewFile test3] $y
} {14 {xyz
123
xyzzy} zzy}
test io-34.13 {Tcl_Tell at start of file} {
file delete $path(test1)
set f1 [open $path(test1) w]
set p [tell $f1]
close $f1
set p
} 0
test io-34.14 {Tcl_Tell after seek to end of file} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
puts $f1 "abcdefghijklmnopqrstuvwxyz"
puts $f1 "abcdefghijklmnopqrstuvwxyz"
close $f1
set f1 [open $path(test1) r]
seek $f1 0 end
set c1 [tell $f1]
close $f1
set c1
} 54
test io-34.15 {Tcl_Tell combined with seeking} {
file delete $path(test1)
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf
puts $f1 "abcdefghijklmnopqrstuvwxyz"
puts $f1 "abcdefghijklmnopqrstuvwxyz"
close $f1
set f1 [open $path(test1) r]
seek $f1 10 start
set c1 [tell $f1]
seek $f1 10 current
|
| ︙ | ︙ | |||
4966 4967 4968 4969 4970 4971 4972 |
gets $f1
close $f1
set c
} -1
test io-34.18 {Tcl_Tell combined with seeking and reading} {
file delete $path(test2)
set f [open $path(test2) w]
| | | | 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 |
gets $f1
close $f1
set c
} -1
test io-34.18 {Tcl_Tell combined with seeking and reading} {
file delete $path(test2)
set f [open $path(test2) w]
fconfigure $f -translation lf
puts -nonewline $f "line1\nline2\nline3\nline4\nline5\n"
close $f
set f [open $path(test2)]
fconfigure $f -translation lf
set x [tell $f]
read $f 3
lappend x [tell $f]
seek $f 2
lappend x [tell $f]
seek $f 10 current
lappend x [tell $f]
seek $f 0 end
lappend x [tell $f]
close $f
set x
} {0 3 2 12 30}
test io-34.19 {Tcl_Tell combined with opening in append mode} {
set f [open $path(test3) w]
fconfigure $f -translation lf
puts $f "abcdefghijklmnopqrstuvwxyz"
puts $f "abcdefghijklmnopqrstuvwxyz"
close $f
set f [open $path(test3) a]
set c [tell $f]
close $f
set c
|
| ︙ | ︙ | |||
5012 5013 5014 5015 5016 5017 5018 |
lappend l [tell $f]
close $f
set l
} {29 39 40 447}
test io-34.21 {Tcl_Seek and Tcl_Tell on large files} {largefileSupport extensive} {
file delete $path(test3)
set f [open $path(test3) w]
| | | 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 |
lappend l [tell $f]
close $f
set l
} {29 39 40 447}
test io-34.21 {Tcl_Seek and Tcl_Tell on large files} {largefileSupport extensive} {
file delete $path(test3)
set f [open $path(test3) w]
fconfigure $f -translation binary
set l ""
lappend l [tell $f]
puts -nonewline $f abcdef
lappend l [tell $f]
flush $f
lappend l [tell $f]
# 4GB offset!
|
| ︙ | ︙ | |||
5206 5207 5208 5209 5210 5211 5212 |
set e [eof $f]
close $f
list $s $l $e
} {10 8 1}
test io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} {
file delete $path(test1)
set f [open $path(test1) w]
| | | | | | | | 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 |
set e [eof $f]
close $f
list $s $l $e
} {10 8 1}
test io-35.12 {Tcl_Eof, eof char in middle, lf write, auto read} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
set i [format abc\ndef\n%cqrs\nuvw 26]
puts $f $i
close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
fconfigure $f -translation auto -eofchar \x1A
set l [string length [read $f]]
set e [eof $f]
close $f
list $c $l $e
} {17 8 1}
test io-35.13 {Tcl_Eof, eof char in middle, lf write, lf read} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation lf
set i [format abc\ndef\n%cqrs\nuvw 26]
puts $f $i
close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
fconfigure $f -translation lf -eofchar \x1A
set l [string length [read $f]]
set e [eof $f]
close $f
list $c $l $e
} {17 8 1}
test io-35.14 {Tcl_Eof, eof char in middle, cr write, auto read} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation cr
set i [format abc\ndef\n%cqrs\nuvw 26]
puts $f $i
close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
fconfigure $f -translation auto -eofchar \x1A
set l [string length [read $f]]
set e [eof $f]
close $f
list $c $l $e
} {17 8 1}
test io-35.15 {Tcl_Eof, eof char in middle, cr write, cr read} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation cr
set i [format abc\ndef\n%cqrs\nuvw 26]
puts $f $i
close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
fconfigure $f -translation cr -eofchar \x1A
set l [string length [read $f]]
set e [eof $f]
close $f
list $c $l $e
} {17 8 1}
test io-35.16 {Tcl_Eof, eof char in middle, crlf write, auto read} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation crlf
set i [format abc\ndef\n%cqrs\nuvw 26]
puts $f $i
close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
fconfigure $f -translation auto -eofchar \x1A
set l [string length [read $f]]
set e [eof $f]
close $f
list $c $l $e
} {21 8 1}
test io-35.17 {Tcl_Eof, eof char in middle, crlf write, crlf read} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation crlf
set i [format abc\ndef\n%cqrs\nuvw 26]
puts $f $i
close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
fconfigure $f -translation crlf -eofchar \x1A
set l [string length [read $f]]
|
| ︙ | ︙ | |||
5352 5353 5354 5355 5356 5357 5358 |
set e [eof $f]
close $f
list $s $l $e [scan [string index $in end] %c]
} -result {1 1 1 13}
test io-35.19 {Tcl_Eof, eof char in middle, cr write, crlf read} -body {
file delete $path(test1)
set f [open $path(test1) w]
| | | | 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 |
set e [eof $f]
close $f
list $s $l $e [scan [string index $in end] %c]
} -result {1 1 1 13}
test io-35.19 {Tcl_Eof, eof char in middle, cr write, crlf read} -body {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation cr
set i [format abc\ndef\n%cqrs\nuvw 26]
puts $f $i
close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
fconfigure $f -translation crlf -eofchar \x1A
set l [string length [set in [read $f]]]
set e [eof $f]
close $f
list $c $l $e [scan [string index $in end] %c]
} -result {17 8 1 13}
test io-35.20 {Tcl_Eof, eof char in middle, cr write, crlf read} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation cr
set i [format \n%cqrsuvw 26]
puts $f $i
close $f
set c [file size $path(test1)]
set f [open $path(test1) r]
fconfigure $f -translation crlf -eofchar \x1A
set l [string length [set in [read $f]]]
|
| ︙ | ︙ | |||
5403 5404 5405 5406 5407 5408 5409 |
lappend x [gets $f1]
lappend x [fblocked $f1]
close $f1
set x
} {{} 1 hello 0 {} 1}
test io-36.1.1 {Tcl_InputBlocked on nonblocking binary pipe} stdio {
set f1 [open "|[list [interpreter]]" r+]
| | | | 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 |
lappend x [gets $f1]
lappend x [fblocked $f1]
close $f1
set x
} {{} 1 hello 0 {} 1}
test io-36.1.1 {Tcl_InputBlocked on nonblocking binary pipe} stdio {
set f1 [open "|[list [interpreter]]" r+]
chan configure $f1 -translation binary
puts $f1 {
chan configure stdout -translation binary
puts hello_from_pipe
}
flush $f1
gets $f1
fconfigure $f1 -blocking off -buffering full
puts $f1 {puts hello}
set x ""
|
| ︙ | ︙ | |||
5653 5654 5655 5656 5657 5658 5659 |
close $f1
set x
} {0 21}
test io-39.8 {Tcl_SetChannelOption, different buffering options} {
file delete $path(test1)
set f1 [open $path(test1) w]
set l ""
| | | 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 |
close $f1
set x
} {0 21}
test io-39.8 {Tcl_SetChannelOption, different buffering options} {
file delete $path(test1)
set f1 [open $path(test1) w]
set l ""
fconfigure $f1 -translation lf -buffering none
puts -nonewline $f1 hello
lappend l [file size $path(test1)]
puts -nonewline $f1 hello
lappend l [file size $path(test1)]
fconfigure $f1 -buffering full
puts -nonewline $f1 hello
lappend l [file size $path(test1)]
|
| ︙ | ︙ | |||
5748 5749 5750 5751 5752 5753 5754 |
set x [fconfigure $f -buffersize]
close $f
set x
} 40000
test io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
file delete $path(test1)
set f [open $path(test1) w]
| | | | 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 |
set x [fconfigure $f -buffersize]
close $f
set x
} 40000
test io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation binary
puts -nonewline $f \xE7\x89\xA6
close $f
set f [open $path(test1) r]
fconfigure $f -encoding utf-8
set x [read $f]
close $f
set x
} 牦
test io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} {
file delete $path(test1)
set f [open $path(test1) w]
fconfigure $f -translation binary
puts -nonewline $f \xE7\x89\xA6
close $f
set f [open $path(test1) r]
fconfigure $f -encoding utf-8
set x [read $f]
close $f
set x
|
| ︙ | ︙ | |||
5785 5786 5787 5788 5789 5790 5791 |
set f [open $path(test1) w]
fconfigure $f -e foobar
} -cleanup {
close $f
} -returnCodes 1 -match glob -result {bad option "-e": should be one of *}
test io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} {stdio fileevent} {
set f [open "|[list [interpreter] $path(cat)]" r+]
| | | | 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 |
set f [open $path(test1) w]
fconfigure $f -e foobar
} -cleanup {
close $f
} -returnCodes 1 -match glob -result {bad option "-e": should be one of *}
test io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} {stdio fileevent} {
set f [open "|[list [interpreter] $path(cat)]" r+]
fconfigure $f -encoding iso8859-1
puts -nonewline $f "\xE7"
flush $f
fconfigure $f -encoding utf-8 -blocking 0
variable x {}
fileevent $f readable [namespace code { lappend x [read $f] }]
vwait [namespace which -variable x]
after 300 [namespace code { lappend x timeout }]
vwait [namespace which -variable x]
fconfigure $f -encoding utf-8
vwait [namespace which -variable x]
after 300 [namespace code { lappend x timeout }]
vwait [namespace which -variable x]
fconfigure $f -translation binary
vwait [namespace which -variable x]
after 300 [namespace code { lappend x timeout }]
vwait [namespace which -variable x]
close $f
set x
} "{} timeout {} timeout \xE7 timeout"
test io-39.18 {Tcl_SetChannelOption, setting read mode independently} \
|
| ︙ | ︙ | |||
5937 5938 5939 5940 5941 5942 5943 |
close $f
file stat $path(test3) stats
format 0o%03o [expr {$stats(mode)&0o777}]
} [format 0o%03o [expr {0o666 & ~ $umaskValue}]]
test io-40.4 {POSIX open access modes: CREAT} {
file delete $path(test3)
set f [open $path(test3) w]
| < < | | 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 |
close $f
file stat $path(test3) stats
format 0o%03o [expr {$stats(mode)&0o777}]
} [format 0o%03o [expr {0o666 & ~ $umaskValue}]]
test io-40.4 {POSIX open access modes: CREAT} {
file delete $path(test3)
set f [open $path(test3) w]
puts $f xyzzy
close $f
set f [open $path(test3) {WRONLY CREAT}]
puts -nonewline $f "ab"
close $f
set f [open $path(test3) r]
set x [gets $f]
close $f
set x
} abzzy
test io-40.5 {POSIX open access modes: APPEND} {
file delete $path(test3)
set f [open $path(test3) w]
fconfigure $f -translation lf
puts $f xyzzy
close $f
set f [open $path(test3) {WRONLY APPEND}]
fconfigure $f -translation lf
puts $f "new line"
seek $f 0
puts $f "abc"
|
| ︙ | ︙ | |||
5980 5981 5982 5983 5984 5985 5986 |
puts $f xyzzy
close $f
open $path(test3) {WRONLY CREAT EXCL}
} -returnCodes error -result {(?i)couldn't open ".*test3": file (already )?exists}
test io-40.7 {POSIX open access modes: EXCL} {
file delete $path(test3)
set f [open $path(test3) {WRONLY CREAT EXCL}]
| < | 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 |
puts $f xyzzy
close $f
open $path(test3) {WRONLY CREAT EXCL}
} -returnCodes error -result {(?i)couldn't open ".*test3": file (already )?exists}
test io-40.7 {POSIX open access modes: EXCL} {
file delete $path(test3)
set f [open $path(test3) {WRONLY CREAT EXCL}]
puts $f "A test line"
close $f
viewFile test3
} {A test line}
test io-40.8 {POSIX open access modes: TRUNC} {
file delete $path(test3)
set f [open $path(test3) w]
|
| ︙ | ︙ | |||
6031 6032 6033 6034 6035 6036 6037 |
test io-40.12 {POSIX open access modes: WRONLY} -match regexp -body {
file delete $path(test3)
open $path(test3) WRONLY
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test io-40.13 {POSIX open access modes: WRONLY} {
makeFile xyzzy test3
set f [open $path(test3) WRONLY]
| < | 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 |
test io-40.12 {POSIX open access modes: WRONLY} -match regexp -body {
file delete $path(test3)
open $path(test3) WRONLY
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
test io-40.13 {POSIX open access modes: WRONLY} {
makeFile xyzzy test3
set f [open $path(test3) WRONLY]
puts -nonewline $f "ab"
seek $f 0 current
set x [list [catch {gets $f} msg] $msg]
close $f
lappend x [viewFile test3]
string compare [string tolower $x] \
[list 1 "channel \"$f\" wasn't opened for reading" abzzy]
|
| ︙ | ︙ | |||
6070 6071 6072 6073 6074 6075 6076 |
set x [list [catch {open ~/foo} msg] $msg]
set ::env(HOME) $home
set x
} {1 {couldn't open "~/foo": no such file or directory}}
test io-41.1 {Tcl_FileeventCmd: errors} {fileevent} {
list [catch {fileevent foo} msg] $msg
| | | | 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 |
set x [list [catch {open ~/foo} msg] $msg]
set ::env(HOME) $home
set x
} {1 {couldn't open "~/foo": no such file or directory}}
test io-41.1 {Tcl_FileeventCmd: errors} {fileevent} {
list [catch {fileevent foo} msg] $msg
} {1 {wrong # args: should be "fileevent channel event ?script?"}}
test io-41.2 {Tcl_FileeventCmd: errors} {fileevent} {
list [catch {fileevent foo bar baz q} msg] $msg
} {1 {wrong # args: should be "fileevent channel event ?script?"}}
test io-41.3 {Tcl_FileeventCmd: errors} {fileevent} {
list [catch {fileevent gorp readable} msg] $msg
} {1 {can not find channel named "gorp"}}
test io-41.4 {Tcl_FileeventCmd: errors} {fileevent} {
list [catch {fileevent gorp writable} msg] $msg
} {1 {can not find channel named "gorp"}}
test io-41.5 {Tcl_FileeventCmd: errors} {fileevent} {
|
| ︙ | ︙ | |||
7601 7602 7603 7604 7605 7606 7607 |
[file size $path(utf8-rp.txt)]
} {3 5 5}
test io-52.10 {TclCopyChannel & encodings} -constraints fcopy -body {
set in [open $path(kyrillic.txt) r]
set out [open $path(utf8-fcopy.txt) w]
fconfigure $in -encoding koi8-r -translation lf
| < < | 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 |
[file size $path(utf8-rp.txt)]
} {3 5 5}
test io-52.10 {TclCopyChannel & encodings} -constraints fcopy -body {
set in [open $path(kyrillic.txt) r]
set out [open $path(utf8-fcopy.txt) w]
fconfigure $in -encoding koi8-r -translation lf
fconfigure $out -translation binary
fcopy $in $out
file size $path(utf8-fcopy.txt)
} -cleanup {
close $in
close $out
} -returnCodes 1 -match glob -result {error writing "*":\
invalid or incomplete multibyte or wide character}
test io-52.11 {TclCopyChannel & encodings} -setup {
set out [open $path(utf8-fcopy.txt) w]
fconfigure $out -encoding utf-8 -translation lf -profile strict
puts $out АА
close $out
} -constraints {fcopy} -body {
set in [open $path(utf8-fcopy.txt) r]
set out [open $path(kyrillic.txt) w]
fconfigure $in -translation binary
fconfigure $out -encoding koi8-r -translation lf -profile strict
catch {fcopy $in $out} cres copts
return $cres
} -cleanup {
if {$in in [chan names]} {
close $in
|
| ︙ | ︙ | |||
9326 9327 9328 9329 9330 9331 9332 |
testobj freeallvars
removeFile io-74.1
} -returnCodes error -match glob -result {can not find channel named "*"}
test io-75.1 {multibyte encoding error read results in raw bytes (-profile tcl8)} -setup {
set fn [makeFile {} io-75.1]
set f [open $fn w+]
| | | 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 |
testobj freeallvars
removeFile io-74.1
} -returnCodes error -match glob -result {can not find channel named "*"}
test io-75.1 {multibyte encoding error read results in raw bytes (-profile tcl8)} -setup {
set fn [makeFile {} io-75.1]
set f [open $fn w+]
fconfigure $f -translation binary
# In UTF-8, a byte 0xCx starts a multibyte sequence and must be followed
# by a byte > 0x7F. This is violated to get an invalid sequence.
puts -nonewline $f A\xC0\x40
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -profile tcl8 -buffering none
} -body {
|
| ︙ | ︙ | |||
9362 9363 9364 9365 9366 9367 9368 |
# Incomplete sequence test.
# This error may IMHO only be detected with the close.
# But the read already returns the incomplete sequence.
test io-75.3 {incomplete multibyte encoding read is ignored (-profile tcl8)} -setup {
set fn [makeFile {} io-75.3]
set f [open $fn w+]
| | | | | | | | | | | | | | | | | | | 9343 9344 9345 9346 9347 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 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 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 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 |
# Incomplete sequence test.
# This error may IMHO only be detected with the close.
# But the read already returns the incomplete sequence.
test io-75.3 {incomplete multibyte encoding read is ignored (-profile tcl8)} -setup {
set fn [makeFile {} io-75.3]
set f [open $fn w+]
fconfigure $f -translation binary
puts -nonewline $f "A\xC0"
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -profile tcl8
} -body {
set d [read $f]
binary scan $d H* hd
set hd
} -cleanup {
close $f
removeFile io-75.3
} -result 41c0
# As utf-8 has a special treatment in multi-byte decoding, also test another
# one.
test io-75.4 {shiftjis encoding error read results in raw bytes (-profile tcl8)} -setup {
set fn [makeFile {} io-75.4]
set f [open $fn w+]
fconfigure $f -translation binary
# In shiftjis, \x81 starts a two-byte sequence.
# But 2nd byte \xFF is not allowed
puts -nonewline $f A\x81\xFFA
flush $f
seek $f 0
fconfigure $f -encoding shiftjis -buffering none -eofchar "" -translation lf -profile tcl8
} -body {
set d [read $f]
binary scan $d H* hd
set hd
} -cleanup {
close $f
removeFile io-75.4
} -result 4181ff41
test io-75.5 {invalid utf-8 encoding read is ignored (-profile tcl8)} -setup {
set fn [makeFile {} io-75.5]
set f [open $fn w+]
fconfigure $f -translation binary
puts -nonewline $f A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar "" -translation lf -profile tcl8
} -body {
set d [read $f]
binary scan $d H* hd
set hd
} -cleanup {
close $f
removeFile io-75.5
} -result 4181
test io-75.6 {incomplete utf-8 encoding, blocking gets is not ignored (-profile strict)} -setup {
set fn [makeFile {} io-75.6]
set f [open $fn w+]
fconfigure $f -translation 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 \
-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.6.1 {invalid utf-8 encoding, blocking gets is not ignored (-profile strict)} -setup {
set fn [makeFile {} io-75.6.1]
set f [open $fn w+]
fconfigure $f -translation binary
# utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
puts -nonewline $f A\xC3B
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none \
-translation lf -profile strict
} -body {
gets $f
} -cleanup {
close $f
removeFile io-75.6.1
} -match glob -returnCodes 1 -result {error reading "file*":\
invalid or incomplete multibyte or wide character}
test io-75.6.2 {invalid utf-8 encoding, blocking gets is not ignored (-profile strict), recover functionality} -setup {
set fn [makeFile {} io-75.6.2]
set f [open $fn w+]
fconfigure $f -translation binary
# utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
puts -nonewline $f A\xC3B
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none \
-translation lf -profile strict
} -body {
set l {}
lappend l [catch {gets $f}]
lappend l [tell $f]
fconfigure $f -translation binary
lappend l [expr {[gets $f] eq "A\xC3B"}]
} -cleanup {
close $f
removeFile io-75.6.2
} -match glob -returnCodes 0 -result {1 0 1}
# TCL ticket c4eb46a196: non blocking case had endless loop, so test it
test io-75.6.3 {invalid utf-8 encoding, non blocking gets is not ignored (-profile strict)} -setup {
set fn [makeFile {} io-75.6.3]
set f [open $fn w+]
fconfigure $f -translation binary
# utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
puts -nonewline $f A\xC3B
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none \
-translation lf -profile strict -blocking 0
} -body {
gets $f
} -cleanup {
close $f
removeFile io-75.6.3
} -match glob -returnCodes 1 -result {error reading "file*":\
invalid or incomplete multibyte or wide character}
test io-75.6.4 {incomplete utf-8 encoding, non blocking gets is not ignored (-profile strict)} -setup {
set fn [makeFile {} io-75.6.4]
set f [open $fn w+]
fconfigure $f -translation 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 \
-translation lf -profile strict -blocking 0
} -body {
gets $f
# only the 2nd gets returns the error
gets $f
} -cleanup {
close $f
removeFile io-75.6.4
} -match glob -returnCodes 1 -result {error reading "file*":\
invalid or incomplete multibyte or wide character}
test io-75.7 {
invalid utf-8 encoding read is not ignored (-profile strict)
} -setup {
set fn [makeFile {} io-75.7]
set f [open $fn w+]
fconfigure $f -translation binary
# \x81 is invalid in utf-8
puts -nonewline $f A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -translation lf \
-profile strict
} -body {
list [catch {read $f} msg data] $msg [dict get $data -data]
} -cleanup {
close $f
removeFile io-75.7
unset msg data f fn
} -match glob -result {1 {error reading "file*":\
invalid or incomplete multibyte or wide character} A}
test io-75.8 {invalid utf-8 encoding eof first handling (-profile strict)} -setup {
set fn [makeFile {} io-75.8]
set f [open $fn w+]
fconfigure $f -translation binary
# \x81 is invalid in utf-8, but since \x1A comes first, -eofchar takes
# precedence.
puts -nonewline $f A\x1A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -eofchar \x1A \
-translation lf -profile strict
|
| ︙ | ︙ | |||
9558 9559 9560 9561 9562 9563 9564 |
unset f d hd
} -result {41 1 {}}
test io-75.8.eoflater {invalid utf-8 encoding eof after handling (-profile strict)} -setup {
set fn [makeFile {} io-75.8]
set f [open $fn w+]
# This also configures the channel encoding profile as strict.
| | | 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 |
unset f d hd
} -result {41 1 {}}
test io-75.8.eoflater {invalid utf-8 encoding eof after 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 -translation 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 {
|
| ︙ | ︙ | |||
9585 9586 9587 9588 9589 9590 9591 |
test io-strict-multibyte-eof {
incomplete utf-8 sequence immediately prior to eof character
See issue 25cdcb7e8fb381fb
} -setup {
set chan [file tempfile];
| | | 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 |
test io-strict-multibyte-eof {
incomplete utf-8 sequence immediately prior to eof character
See issue 25cdcb7e8fb381fb
} -setup {
set chan [file tempfile];
fconfigure $chan -translation 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} msg data] $msg [dict get $data -data]
} -cleanup {
|
| ︙ | ︙ | |||
9621 9622 9623 9624 9625 9626 9627 |
test io-75.10 {
incomplete multibyte encoding read is not ignored because "binary" sets
profile to strict
} -setup {
set res {}
set fn [makeFile {} io-75.10]
set f [open $fn w+]
| | | 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 |
test io-75.10 {
incomplete multibyte encoding read is not ignored because "binary" sets
profile to strict
} -setup {
set res {}
set fn [makeFile {} io-75.10]
set f [open $fn w+]
fconfigure $f -translation binary
puts -nonewline $f A\xC0
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none
} -body {
catch {read $f} errmsg
lappend res $errmsg
|
| ︙ | ︙ | |||
9650 9651 9652 9653 9654 9655 9656 |
# This may be expected due to special utf-8 handling.
# As utf-8 has a special treatment in multi-byte decoding, also test another
# one.
test io-75.11 {shiftjis encoding error read results in error (strict profile)} -setup {
set fn [makeFile {} io-75.11]
set f [open $fn w+]
| | | | | | 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675 |
# This may be expected due to special utf-8 handling.
# As utf-8 has a special treatment in multi-byte decoding, also test another
# one.
test io-75.11 {shiftjis encoding error read results in error (strict profile)} -setup {
set fn [makeFile {} io-75.11]
set f [open $fn w+]
fconfigure $f -translation binary
# In shiftjis, \x81 starts a two-byte sequence.
# But 2nd byte \xFF is not allowed
puts -nonewline $f A\x81\xFFA
flush $f
seek $f 0
fconfigure $f -encoding shiftjis -blocking 0 -translation lf \
-profile strict
} -body {
set d [read $f]
binary scan $d H* hd
lappend hd [catch {set d [read $f]} msg data] $msg [dict exists $data -data]
} -cleanup {
close $f
removeFile io-75.11
unset d hd msg data f
} -match glob -result {41 1 {error reading "file*":\
invalid or incomplete multibyte or wide character} 0}
test io-75.12 {
invalid utf-8 encoding read is not ignored because setting the encoding to
"binary" also set the profile to strict
} -setup {
set res {}
set fn [makeFile {} io-75.12]
set f [open $fn w+]
fconfigure $f -translation binary
puts -nonewline $f A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -buffering none -translation lf
} -body {
catch {read $f} errmsg
lappend res $errmsg
chan configure $f -profile tcl8
seek $f 0
set d [read $f]
binary scan $d H* hd
|
| ︙ | ︙ | |||
9703 9704 9705 9706 9707 9708 9709 |
test io-75.13 {
In nonblocking mode when there is an encoding error the data that has been
successfully read so far is returned first and then the error is returned
on the next call to [read].
} -setup {
set fn [makeFile {} io-75.13]
set f [open $fn w+]
| | | | | | 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 |
test io-75.13 {
In nonblocking mode when there is an encoding error the data that has been
successfully read so far is returned first and then the error is returned
on the next call to [read].
} -setup {
set fn [makeFile {} io-75.13]
set f [open $fn w+]
fconfigure $f -translation binary
# \x81 is invalid in utf-8
puts -nonewline $f A\x81
flush $f
seek $f 0
fconfigure $f -encoding utf-8 -blocking 0 -translation lf \
-profile strict
} -body {
set d [read $f]
binary scan $d H* hd
lappend hd [catch {read $f} msg data] $msg [dict exists $data -data]
} -cleanup {
close $f
removeFile io-75.13
unset d hd msg data f fn
} -match glob -result {41 1 {error reading "file*":\
invalid or incomplete multibyte or wide character} 0}
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 -translation 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 \
-translation auto -profile strict
} -body {
set res [gets $chan]
lappend res [gets $chan]
lappend res [catch {gets $chan} msg data] $msg [dict exists $data -data]
chan configure $chan -profile tcl8
lappend res [gets $chan]
|
| ︙ | ︙ | |||
9755 9756 9757 9758 9759 9760 9761 |
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]
| | | 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 |
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 -translation 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]
|
| ︙ | ︙ |
Changes to tests/ioCmd.test.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 |
# Custom constraints used in this file
testConstraint testchannel [llength [info commands testchannel]]
#----------------------------------------------------------------------
test iocmd-1.1 {puts command} {
list [catch {puts} msg] $msg
| | | | | | | | | | | | | | | | 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 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 |
# Custom constraints used in this file
testConstraint testchannel [llength [info commands testchannel]]
#----------------------------------------------------------------------
test iocmd-1.1 {puts command} {
list [catch {puts} msg] $msg
} {1 {wrong # args: should be "puts ?-nonewline? ?channel? string"}}
test iocmd-1.2 {puts command} {
list [catch {puts a b c d e f g} msg] $msg
} {1 {wrong # args: should be "puts ?-nonewline? ?channel? string"}}
test iocmd-1.3 {puts command} {
list [catch {puts froboz -nonewline kablooie} msg] $msg
} {1 {wrong # args: should be "puts ?-nonewline? ?channel? string"}}
test iocmd-1.4 {puts command} {
list [catch {puts froboz hello} msg] $msg
} {1 {can not find channel named "froboz"}}
test iocmd-1.5 {puts command} {
list [catch {puts stdin hello} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}
set path(test1) [makeFile {} test1]
test iocmd-1.6 {puts command} {
set f [open $path(test1) w]
fconfigure $f -translation lf
puts -nonewline $f foobar
close $f
file size $path(test1)
} 6
test iocmd-1.7 {puts command} {
set f [open $path(test1) w]
fconfigure $f -translation lf
puts $f foobar
close $f
file size $path(test1)
} 7
test iocmd-1.8 {puts command} {
set f [open $path(test1) w]
fconfigure $f -translation binary
puts -nonewline $f [binary format a4a5 foo bar]
close $f
file size $path(test1)
} 9
test iocmd-2.1 {flush command} {
list [catch {flush} msg] $msg
} {1 {wrong # args: should be "flush channel"}}
test iocmd-2.2 {flush command} {
list [catch {flush a b c d e} msg] $msg
} {1 {wrong # args: should be "flush channel"}}
test iocmd-2.3 {flush command} {
list [catch {flush foo} msg] $msg
} {1 {can not find channel named "foo"}}
test iocmd-2.4 {flush command} {
list [catch {flush stdin} msg] $msg
} {1 {channel "stdin" wasn't opened for writing}}
test iocmd-3.1 {gets command} {
list [catch {gets} msg] $msg
} {1 {wrong # args: should be "gets channel ?varName?"}}
test iocmd-3.2 {gets command} {
list [catch {gets a b c d e f g} msg] $msg
} {1 {wrong # args: should be "gets channel ?varName?"}}
test iocmd-3.3 {gets command} {
list [catch {gets aaa} msg] $msg
} {1 {can not find channel named "aaa"}}
test iocmd-3.4 {gets command} {
list [catch {gets stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test iocmd-3.5 {gets command} {
set f [open $path(test1) w]
puts $f [binary format a4a5 foo bar]
close $f
set f [open $path(test1) r]
set result [gets $f]
close $f
set x foo\x00
set x "${x}bar\x00\x00"
string compare $x $result
} 0
test iocmd-4.1 {read command} {
list [catch {read} msg] $msg
} {1 {wrong # args: should be "read channel ?numChars?" or "read ?-nonewline? channel"}}
test iocmd-4.2 {read command} {
list [catch {read a b c d e f g h} msg] $msg
} {1 {wrong # args: should be "read channel ?numChars?" or "read ?-nonewline? channel"}}
test iocmd-4.3 {read command} {
list [catch {read aaa} msg] $msg
} {1 {can not find channel named "aaa"}}
test iocmd-4.4 {read command} {
list [catch {read -nonewline} msg] $msg
} {1 {wrong # args: should be "read channel ?numChars?" or "read ?-nonewline? channel"}}
test iocmd-4.5 {read command} {
list [catch {read -nonew file4} msg] $msg $::errorCode
} {1 {can not find channel named "-nonew"} {TCL LOOKUP CHANNEL -nonew}}
test iocmd-4.6 {read command} {
list [catch {read stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test iocmd-4.7 {read command} {
list [catch {read -nonewline stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test iocmd-4.8 {read command with incorrect combination of arguments} {
file delete $path(test1)
set f [open $path(test1) w]
puts $f "Two lines: this one"
puts $f "and this one"
close $f
set f [open $path(test1)]
set x [list [catch {read -nonewline $f 20 z} msg] $msg $::errorCode]
close $f
set x
} {1 {wrong # args: should be "read channel ?numChars?" or "read ?-nonewline? channel"} {TCL WRONGARGS}}
test iocmd-4.9 {read command} {
list [catch {read stdin foo} msg] $msg $::errorCode
} {1 {expected non-negative integer but got "foo"} {TCL VALUE NUMBER}}
test iocmd-4.10 {read command} {
list [catch {read file107} msg] $msg $::errorCode
} {1 {can not find channel named "file107"} {TCL LOOKUP CHANNEL file107}}
set path(test3) [makeFile {} test3]
|
| ︙ | ︙ | |||
157 158 159 160 161 162 163 |
read $f 12z
} -cleanup {
close $f
} -result {expected non-negative integer but got "12z"} -errorCode {TCL VALUE NUMBER}
test iocmd-5.1 {seek command} -returnCodes error -body {
seek
| | | | | | | | 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 |
read $f 12z
} -cleanup {
close $f
} -result {expected non-negative integer but got "12z"} -errorCode {TCL VALUE NUMBER}
test iocmd-5.1 {seek command} -returnCodes error -body {
seek
} -result {wrong # args: should be "seek channel offset ?origin?"}
test iocmd-5.2 {seek command} -returnCodes error -body {
seek a b c d e f g
} -result {wrong # args: should be "seek channel offset ?origin?"}
test iocmd-5.3 {seek command} -returnCodes error -body {
seek stdin gugu
} -result {expected integer but got "gugu"}
test iocmd-5.4 {seek command} -returnCodes error -body {
seek stdin 100 gugu
} -result {bad origin "gugu": must be start, current, or end}
test iocmd-6.1 {tell command} {
list [catch {tell} msg] $msg
} {1 {wrong # args: should be "tell channel"}}
test iocmd-6.2 {tell command} {
list [catch {tell a b c d e} msg] $msg
} {1 {wrong # args: should be "tell channel"}}
test iocmd-6.3 {tell command} {
list [catch {tell aaa} msg] $msg
} {1 {can not find channel named "aaa"}}
test iocmd-7.1 {close command} {
list [catch {close} msg] $msg
} {1 {wrong # args: should be "close channel ?direction?"}}
test iocmd-7.2 {close command} {
list [catch {close a b c d e} msg] $msg
} {1 {wrong # args: should be "close channel ?direction?"}}
test iocmd-7.3 {close command} {
list [catch {close aaa} msg] $msg
} {1 {can not find channel named "aaa"}}
test iocmd-7.4 {close command} -setup {
set chan [open [info script] r]
} -body {
chan close $chan bar
|
| ︙ | ︙ | |||
212 213 214 215 216 217 218 |
}
set opts [list {*}$basicOpts {*}$extra]
lset opts end [string cat "or " [lindex $opts end]]
return [format {bad option "%s": should be one of %s} $got [join $opts ", "]]
}
test iocmd-8.1 {fconfigure command} -returnCodes error -body {
fconfigure
| | | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
}
set opts [list {*}$basicOpts {*}$extra]
lset opts end [string cat "or " [lindex $opts end]]
return [format {bad option "%s": should be one of %s} $got [join $opts ", "]]
}
test iocmd-8.1 {fconfigure command} -returnCodes error -body {
fconfigure
} -result {wrong # args: should be "fconfigure channel ?-option value ...?"}
test iocmd-8.2 {fconfigure command} -returnCodes error -body {
fconfigure a b c d e f
} -result {wrong # args: should be "fconfigure channel ?-option value ...?"}
test iocmd-8.3 {fconfigure command} -returnCodes error -body {
fconfigure a b
} -result {can not find channel named "a"}
test iocmd-8.4 {fconfigure command} -setup {
file delete $path(test1)
set f1 [open $path(test1) w]
} -body {
|
| ︙ | ︙ | |||
237 238 239 240 241 242 243 |
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 {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
| | | | < | 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 |
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 {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf -encoding utf-16
fconfigure $f1
} -cleanup {
catch {close $f1}
} -result {-blocking 1 -buffering full -buffersize 4096 -encoding utf-16 -eofchar {} -profile strict -translation lf}
test iocmd-8.8 {fconfigure command} -setup {
file delete $path(test1)
set x {}
} -body {
set f1 [open $path(test1) w]
fconfigure $f1 -translation lf -buffering line -buffersize 3030 \
-encoding utf-16 -profile tcl8
lappend x [fconfigure $f1 -buffering]
lappend x [fconfigure $f1]
} -cleanup {
catch {close $f1}
} -result {line {-blocking 1 -buffering line -buffersize 3030 -encoding utf-16 -eofchar {} -profile tcl8 -translation lf}}
test iocmd-8.9 {fconfigure command} -setup {
file delete $path(test1)
} -body {
set f1 [open $path(test1) w]
fconfigure $f1 -translation binary -buffering none -buffersize 4040
fconfigure $f1
} -cleanup {
catch {close $f1}
} -result {-blocking 1 -buffering none -buffersize 4040 -encoding iso8859-1 -eofchar {} -profile strict -translation lf}
test iocmd-8.10 {fconfigure command} -returnCodes error -body {
fconfigure a b
} -result {can not find channel named "a"}
|
| ︙ | ︙ | |||
372 373 374 375 376 377 378 |
test iocmd-8.23 {fconfigure -profile badprofile} -body {
fconfigure stdin -profile froboz
} -returnCodes error -result {bad profile name "froboz": must be replace, strict, or tcl8}
test iocmd-9.1 {eof command} {
list [catch {eof} msg] $msg $::errorCode
| | | | | | 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 |
test iocmd-8.23 {fconfigure -profile badprofile} -body {
fconfigure stdin -profile froboz
} -returnCodes error -result {bad profile name "froboz": must be replace, strict, or tcl8}
test iocmd-9.1 {eof command} {
list [catch {eof} msg] $msg $::errorCode
} {1 {wrong # args: should be "eof channel"} {TCL WRONGARGS}}
test iocmd-9.2 {eof command} {
list [catch {eof a b} msg] $msg $::errorCode
} {1 {wrong # args: should be "eof channel"} {TCL WRONGARGS}}
test iocmd-9.3 {eof command} {
catch {close file100}
list [catch {eof file100} msg] $msg $::errorCode
} {1 {can not find channel named "file100"} {TCL LOOKUP CHANNEL file100}}
# The tests for Tcl_ExecObjCmd are in exec.test
test iocmd-10.1 {fblocked command} {
list [catch {fblocked} msg] $msg
} {1 {wrong # args: should be "fblocked channel"}}
test iocmd-10.2 {fblocked command} {
list [catch {fblocked a b c d e f g} msg] $msg
} {1 {wrong # args: should be "fblocked channel"}}
test iocmd-10.3 {fblocked command} {
list [catch {fblocked file1000} msg] $msg
} {1 {can not find channel named "file1000"}}
test iocmd-10.4 {fblocked command} {
list [catch {fblocked stdout} msg] $msg
} {1 {channel "stdout" wasn't opened for reading}}
test iocmd-10.5 {fblocked command} {
|
| ︙ | ︙ | |||
443 444 445 446 447 448 449 |
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
#
# Test 13.4 relies on assigning the same channel name twice.
#
test iocmd-12.4 {POSIX open access modes: WRONLY} {unix} {
file delete $path(test3)
set f [open $path(test3) w]
| < < < | 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 |
} -returnCodes error -result {(?i)couldn't open ".*test3": no such file or directory}
#
# Test 13.4 relies on assigning the same channel name twice.
#
test iocmd-12.4 {POSIX open access modes: WRONLY} {unix} {
file delete $path(test3)
set f [open $path(test3) w]
puts $f xyzzy
close $f
set f [open $path(test3) WRONLY]
puts -nonewline $f "ab"
seek $f 0 current
set x [list [catch {gets $f} msg] $msg]
close $f
set f [open $path(test3) r]
lappend x [gets $f]
close $f
set y [list 1 [format "channel \"%s\" wasn't opened for reading" $f] abzzy]
string compare $x $y
} 0
test iocmd-12.5 {POSIX open access modes: RDWR} -match regexp -body {
file delete $path(test3)
|
| ︙ | ︙ | |||
1389 1390 1391 1392 1393 1394 1395 |
set res {}
proc foo args {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
set c [chan create {r w} foo]
note [fconfigure $c]
close $c
rename foo {}
set res
| | | | | 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 |
set res {}
proc foo args {oninit; onfinal; track; note MUST_NOT_HAPPEN; return}
set c [chan create {r w} foo]
note [fconfigure $c]
close $c
rename foo {}
set res
} -result {{-blocking 1 -buffering full -buffersize 4096 -encoding * -profile * -translation {auto *}}}
test iocmd-25.2 {chan configure, cgetall, no options} -match glob -body {
set res {}
proc foo args {oninit cget cgetall; onfinal; track; return ""}
set c [chan create {r w} foo]
note [fconfigure $c]
close $c
rename foo {}
set res
} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -profile * -translation {auto *}}}
test iocmd-25.3 {chan configure, cgetall, regular result} -match glob -body {
set res {}
proc foo args {
oninit cget cgetall; onfinal; track
return {-bar foo -snarf x}
}
set c [chan create {r w} foo]
note [fconfigure $c]
close $c
rename foo {}
set res
} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -profile * -translation {auto *} -bar foo -snarf x}}
test iocmd-25.4 {chan configure, cgetall, bad result, list of uneven length} -match glob -body {
set res {}
proc foo {args} {
oninit cget cgetall; onfinal; track
return "-bar"
}
set c [chan create {r w} foo]
|
| ︙ | ︙ | |||
2974 2975 2976 2977 2978 2979 2980 |
note [fconfigure $c]
close $c
notes
} c]
rename foo {}
set res
} -constraints {testchannel thread} \
| | | | | 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 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 |
note [fconfigure $c]
close $c
notes
} c]
rename foo {}
set res
} -constraints {testchannel thread} \
-result {{-blocking 1 -buffering full -buffersize 4096 -encoding * * -translation {auto *}}}
test iocmd.tf-25.2 {chan configure, cgetall, no options} -match glob -body {
set res {}
proc foo {args} {oninit cget cgetall; onfinal; track; return ""}
set c [chan create {r w} foo]
notes [inthread $c {
note [fconfigure $c]
close $c
notes
} c]
rename foo {}
set res
} -constraints {testchannel thread} \
-result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * * -translation {auto *}}}
test iocmd.tf-25.3 {chan configure, cgetall, regular result} -match glob -body {
set res {}
proc foo {args} {
oninit cget cgetall; onfinal; track
return "-bar foo -snarf x"
}
set c [chan create {r w} foo]
notes [inthread $c {
note [fconfigure $c]
close $c
notes
} c]
rename foo {}
set res
} -constraints {testchannel thread} \
-result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * * -translation {auto *} -bar foo -snarf x}}
test iocmd.tf-25.4 {chan configure, cgetall, bad result, list of uneven length} -match glob -body {
set res {}
proc foo {args} {
oninit cget cgetall; onfinal; track
return "-bar"
}
set c [chan create {r w} foo]
|
| ︙ | ︙ |
Changes to tests/macOSXFCmd.test.
| ︙ | ︙ | |||
100 101 102 103 104 105 106 |
[file delete -force -- foo.test]
} {0 {} 0 1 {}}
test macOSXFCmd-2.7 {MacOSXSetFileAttribute - rsrclength} {macosxFileAttr notRoot nonPortable} {
catch {file delete -force -- foo.test}
close [open foo.test w]
catch {
set f [open foo.test/..namedfork/rsrc w]
| | | | 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 |
[file delete -force -- foo.test]
} {0 {} 0 1 {}}
test macOSXFCmd-2.7 {MacOSXSetFileAttribute - rsrclength} {macosxFileAttr notRoot nonPortable} {
catch {file delete -force -- foo.test}
close [open foo.test w]
catch {
set f [open foo.test/..namedfork/rsrc w]
fconfigure $f -translation lf
puts -nonewline $f "foo"
close $f
}
list [catch {file attributes foo.test -rsrclength} msg] $msg \
[catch {file attributes foo.test -rsrclength 0} msg] $msg \
[catch {file attributes foo.test -rsrclength} msg] $msg \
[file delete -force -- foo.test]
} {0 3 0 {} 0 0 {}}
test macOSXFCmd-3.1 {MacOSXCopyFileAttributes} {macosxFileAttr notRoot} {
catch {file delete -force -- foo.test}
catch {file delete -force -- bar.test}
close [open foo.test w]
catch {
file attributes foo.test -creator FOOC -type FOOT -hidden 1
set f [open foo.test/..namedfork/rsrc w]
fconfigure $f -translation lf
puts -nonewline $f "foo"
close $f
file copy foo.test bar.test
}
list [catch {file attributes bar.test -creator} msg] $msg \
[catch {file attributes bar.test -type} msg] $msg \
[catch {file attributes bar.test -hidden} msg] $msg \
|
| ︙ | ︙ |
Changes to tests/mathop.test.
| ︙ | ︙ | |||
110 111 112 113 114 115 116 |
test mathop-1.6 {compiled +} { + 1 2 3.0 } 6.0
test mathop-1.7 {compiled +} { + 100000000000 2 3 } 100000000005
test mathop-1.8 {compiled +} { + 1 2 300000000000 } 300000000003
test mathop-1.9 {compiled +} { + 1000000000000000000000 2 3 } 1000000000000000000005
test mathop-1.10 {compiled +} { + 1 2 3000000000000000000000 } 3000000000000000000003
test mathop-1.11 {compiled +: errors} -returnCodes error -body {
+ x 0
| | | | | | | | 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 |
test mathop-1.6 {compiled +} { + 1 2 3.0 } 6.0
test mathop-1.7 {compiled +} { + 100000000000 2 3 } 100000000005
test mathop-1.8 {compiled +} { + 1 2 300000000000 } 300000000003
test mathop-1.9 {compiled +} { + 1000000000000000000000 2 3 } 1000000000000000000005
test mathop-1.10 {compiled +} { + 1 2 3000000000000000000000 } 3000000000000000000003
test mathop-1.11 {compiled +: errors} -returnCodes error -body {
+ x 0
} -result {cannot use non-numeric string "x" as left operand of "+"}
test mathop-1.12 {compiled +: errors} -returnCodes error -body {
+ nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "+"}
test mathop-1.13 {compiled +: errors} -returnCodes error -body {
+ 0 x
} -result {cannot use non-numeric string "x" as right operand of "+"}
test mathop-1.14 {compiled +: errors} -returnCodes error -body {
+ 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "+"}
test mathop-1.15 {compiled +: errors} -returnCodes error -body {
+ 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "+"}
test mathop-1.16 {compiled +: errors} -returnCodes error -body {
+ 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "+"}
test mathop-1.17 {compiled +: errors} -returnCodes error -body {
+ 0 [error expectedError]
} -result expectedError
test mathop-1.18 {compiled +: argument processing order} -body {
# Bytecode compilation known hard for 3+ arguments
list [catch {
+ [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
|
| ︙ | ︙ | |||
148 149 150 151 152 153 154 |
test mathop-1.24 {interpreted +} { $op 1 2 3.0 } 6.0
test mathop-1.25 {interpreted +} { $op 100000000000 2 3 } 100000000005
test mathop-1.26 {interpreted +} { $op 1 2 300000000000 } 300000000003
test mathop-1.27 {interpreted +} { $op 1000000000000000000000 2 3 } 1000000000000000000005
test mathop-1.28 {interpreted +} { $op 1 2 3000000000000000000000 } 3000000000000000000003
test mathop-1.29 {interpreted +: errors} -returnCodes error -body {
$op x 0
| | | | | | | | 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 |
test mathop-1.24 {interpreted +} { $op 1 2 3.0 } 6.0
test mathop-1.25 {interpreted +} { $op 100000000000 2 3 } 100000000005
test mathop-1.26 {interpreted +} { $op 1 2 300000000000 } 300000000003
test mathop-1.27 {interpreted +} { $op 1000000000000000000000 2 3 } 1000000000000000000005
test mathop-1.28 {interpreted +} { $op 1 2 3000000000000000000000 } 3000000000000000000003
test mathop-1.29 {interpreted +: errors} -returnCodes error -body {
$op x 0
} -result {cannot use non-numeric string "x" as left operand of "+"}
test mathop-1.30 {interpreted +: errors} -returnCodes error -body {
$op nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "+"}
test mathop-1.31 {interpreted +: errors} -returnCodes error -body {
$op 0 x
} -result {cannot use non-numeric string "x" as right operand of "+"}
test mathop-1.32 {interpreted +: errors} -returnCodes error -body {
$op 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "+"}
test mathop-1.33 {interpreted +: errors} -returnCodes error -body {
$op 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "+"}
test mathop-1.34 {interpreted +: errors} -returnCodes error -body {
$op 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "+"}
test mathop-1.35 {interpreted +: errors} -returnCodes error -body {
$op 0 [error expectedError]
} -result expectedError
test mathop-1.36 {interpreted +: argument processing order} -body {
list [catch {
$op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
} msg] $msg $x
|
| ︙ | ︙ | |||
185 186 187 188 189 190 191 |
test mathop-2.6 {compiled *} { * 1 2 3.0 } 6.0
test mathop-2.7 {compiled *} { * 100000000000 2 3 } 600000000000
test mathop-2.8 {compiled *} { * 1 2 300000000000 } 600000000000
test mathop-2.9 {compiled *} { * 1000000000000000000000 2 3 } 6000000000000000000000
test mathop-2.10 {compiled *} { * 1 2 3000000000000000000000 } 6000000000000000000000
test mathop-2.11 {compiled *: errors} -returnCodes error -body {
* x 0
| | | | | | | | 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 |
test mathop-2.6 {compiled *} { * 1 2 3.0 } 6.0
test mathop-2.7 {compiled *} { * 100000000000 2 3 } 600000000000
test mathop-2.8 {compiled *} { * 1 2 300000000000 } 600000000000
test mathop-2.9 {compiled *} { * 1000000000000000000000 2 3 } 6000000000000000000000
test mathop-2.10 {compiled *} { * 1 2 3000000000000000000000 } 6000000000000000000000
test mathop-2.11 {compiled *: errors} -returnCodes error -body {
* x 0
} -result {cannot use non-numeric string "x" as left operand of "*"}
test mathop-2.12 {compiled *: errors} -returnCodes error -body {
* nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "*"}
test mathop-2.13 {compiled *: errors} -returnCodes error -body {
* 0 x
} -result {cannot use non-numeric string "x" as right operand of "*"}
test mathop-2.14 {compiled *: errors} -returnCodes error -body {
* 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "*"}
test mathop-2.15 {compiled *: errors} -returnCodes error -body {
* 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "*"}
test mathop-2.16 {compiled *: errors} -returnCodes error -body {
* 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "*"}
test mathop-2.17 {compiled *: errors} -returnCodes error -body {
* 0 [error expectedError]
} -result expectedError
test mathop-2.18 {compiled *: argument processing order} -body {
# Bytecode compilation known hard for 3+ arguments
list [catch {
* [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
|
| ︙ | ︙ | |||
223 224 225 226 227 228 229 |
test mathop-2.24 {interpreted *} { $op 1 2 3.0 } 6.0
test mathop-2.25 {interpreted *} { $op 100000000000 2 3 } 600000000000
test mathop-2.26 {interpreted *} { $op 1 2 300000000000 } 600000000000
test mathop-2.27 {interpreted *} { $op 1000000000000000000000 2 3 } 6000000000000000000000
test mathop-2.28 {interpreted *} { $op 1 2 3000000000000000000000 } 6000000000000000000000
test mathop-2.29 {interpreted *: errors} -returnCodes error -body {
$op x 0
| | | | | | | | | | | | | | | | | | 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 |
test mathop-2.24 {interpreted *} { $op 1 2 3.0 } 6.0
test mathop-2.25 {interpreted *} { $op 100000000000 2 3 } 600000000000
test mathop-2.26 {interpreted *} { $op 1 2 300000000000 } 600000000000
test mathop-2.27 {interpreted *} { $op 1000000000000000000000 2 3 } 6000000000000000000000
test mathop-2.28 {interpreted *} { $op 1 2 3000000000000000000000 } 6000000000000000000000
test mathop-2.29 {interpreted *: errors} -returnCodes error -body {
$op x 0
} -result {cannot use non-numeric string "x" as left operand of "*"}
test mathop-2.30 {interpreted *: errors} -returnCodes error -body {
$op nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "*"}
test mathop-2.31 {interpreted *: errors} -returnCodes error -body {
$op 0 x
} -result {cannot use non-numeric string "x" as right operand of "*"}
test mathop-2.32 {interpreted *: errors} -returnCodes error -body {
$op 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "*"}
test mathop-2.33 {interpreted *: errors} -returnCodes error -body {
$op 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "*"}
test mathop-2.34 {interpreted *: errors} -returnCodes error -body {
$op 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "*"}
test mathop-2.35 {interpreted *: errors} -returnCodes error -body {
$op 0 [error expectedError]
} -result expectedError
test mathop-2.36 {interpreted *: argument processing order} -body {
list [catch {
$op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
} msg] $msg $x
} -result {1 expected 2}
test mathop-3.1 {compiled !} {! 0} 1
test mathop-3.2 {compiled !} {! 1} 0
test mathop-3.3 {compiled !} {! false} 1
test mathop-3.4 {compiled !} {! true} 0
test mathop-3.5 {compiled !} {! 0.0} 1
test mathop-3.6 {compiled !} {! 10000000000} 0
test mathop-3.7 {compiled !} {! 10000000000000000000000000} 0
test mathop-3.8 {compiled !: errors} -body {
! foobar
} -returnCodes error -result {cannot use non-numeric string "foobar" as operand of "!"}
test mathop-3.9 {compiled !: errors} -body {
! 0 0
} -returnCodes error -result "wrong # args: should be \"! boolean\""
test mathop-3.10 {compiled !: errors} -body {
!
} -returnCodes error -result "wrong # args: should be \"! boolean\""
set op !
test mathop-3.11 {interpreted !} {$op 0} 1
test mathop-3.12 {interpreted !} {$op 1} 0
test mathop-3.13 {interpreted !} {$op false} 1
test mathop-3.14 {interpreted !} {$op true} 0
test mathop-3.15 {interpreted !} {$op 0.0} 1
test mathop-3.16 {interpreted !} {$op 10000000000} 0
test mathop-3.17 {interpreted !} {$op 10000000000000000000000000} 0
test mathop-3.18 {interpreted !: errors} -body {
$op foobar
} -returnCodes error -result {cannot use non-numeric string "foobar" as operand of "!"}
test mathop-3.19 {interpreted !: errors} -body {
$op 0 0
} -returnCodes error -result "wrong # args: should be \"! boolean\""
test mathop-3.20 {interpreted !: errors} -body {
$op
} -returnCodes error -result "wrong # args: should be \"! boolean\""
test mathop-3.21 {compiled !: error} -returnCodes error -body {
! NaN
} -result {cannot use non-numeric floating-point value "NaN" as operand of "!"}
test mathop-3.22 {interpreted !: error} -returnCodes error -body {
$op NaN
} -result {cannot use non-numeric floating-point value "NaN" as operand of "!"}
test mathop-4.1 {compiled ~} {~ 0} -1
test mathop-4.2 {compiled ~} {~ 1} -2
test mathop-4.3 {compiled ~} {~ 31} -32
test mathop-4.4 {compiled ~} {~ -127} 126
test mathop-4.5 {compiled ~} {~ -0} -1
test mathop-4.6 {compiled ~} {~ 10000000000} -10000000001
test mathop-4.7 {compiled ~} {~ 10000000000000000000000000} -10000000000000000000000001
test mathop-4.8 {compiled ~: errors} -body {
~ foobar
} -returnCodes error -result {cannot use non-numeric string "foobar" as operand of "~"}
test mathop-4.9 {compiled ~: errors} -body {
~ 0 0
} -returnCodes error -result "wrong # args: should be \"~ integer\""
test mathop-4.10 {compiled ~: errors} -body {
~
} -returnCodes error -result "wrong # args: should be \"~ integer\""
test mathop-4.11 {compiled ~: errors} -returnCodes error -body {
~ 0.0
} -result {cannot use floating-point value "0.0" as operand of "~"}
test mathop-4.12 {compiled ~: errors} -returnCodes error -body {
~ NaN
} -result {cannot use non-numeric floating-point value "NaN" as operand of "~"}
set op ~
test mathop-4.13 {interpreted ~} {$op 0} -1
test mathop-4.14 {interpreted ~} {$op 1} -2
test mathop-4.15 {interpreted ~} {$op 31} -32
test mathop-4.16 {interpreted ~} {$op -127} 126
test mathop-4.17 {interpreted ~} {$op -0} -1
test mathop-4.18 {interpreted ~} {$op 10000000000} -10000000001
test mathop-4.19 {interpreted ~} {$op 10000000000000000000000000} -10000000000000000000000001
test mathop-4.20 {interpreted ~: errors} -body {
$op foobar
} -returnCodes error -result {cannot use non-numeric string "foobar" as operand of "~"}
test mathop-4.21 {interpreted ~: errors} -body {
$op 0 0
} -returnCodes error -result "wrong # args: should be \"~ integer\""
test mathop-4.22 {interpreted ~: errors} -body {
$op
} -returnCodes error -result "wrong # args: should be \"~ integer\""
test mathop-4.23 {interpreted ~: errors} -returnCodes error -body {
$op 0.0
} -result {cannot use floating-point value "0.0" as operand of "~"}
test mathop-4.24 {interpreted ~: errors} -returnCodes error -body {
$op NaN
} -result {cannot use non-numeric floating-point value "NaN" as operand of "~"}
test mathop-5.1 {compiled eq} {eq {} a} 0
test mathop-5.2 {compiled eq} {eq a a} 1
test mathop-5.3 {compiled eq} {eq a {}} 0
test mathop-5.4 {compiled eq} {eq a b} 0
test mathop-5.5 {compiled eq} { eq } 1
test mathop-5.6 {compiled eq} {eq a} 1
|
| ︙ | ︙ | |||
373 374 375 376 377 378 379 |
test mathop-6.1 {compiled &} { & } -1
test mathop-6.2 {compiled &} { & 1 } 1
test mathop-6.3 {compiled &} { & 1 2 } 0
test mathop-6.4 {compiled &} { & 3 7 6 } 2
test mathop-6.5 {compiled &} -returnCodes error -body {
& 1.0 2 3
| | | | | | | | | | | | | | | | | | 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 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 |
test mathop-6.1 {compiled &} { & } -1
test mathop-6.2 {compiled &} { & 1 } 1
test mathop-6.3 {compiled &} { & 1 2 } 0
test mathop-6.4 {compiled &} { & 3 7 6 } 2
test mathop-6.5 {compiled &} -returnCodes error -body {
& 1.0 2 3
} -result {cannot use floating-point value "1.0" as right operand of "&"}
test mathop-6.6 {compiled &} -returnCodes error -body {
& 1 2 3.0
} -result {cannot use floating-point value "3.0" as left operand of "&"}
test mathop-6.7 {compiled &} { & 100000000002 18 -126 } 2
test mathop-6.8 {compiled &} { & 0xff 0o377 333333333333 } 85
test mathop-6.9 {compiled &} { & 1000000000000000000002 18 -126 } 2
test mathop-6.10 {compiled &} { & 0xff 0o377 3333333333333333333333 } 85
test mathop-6.11 {compiled &: errors} -returnCodes error -body {
& x 0
} -result {cannot use non-numeric string "x" as left operand of "&"}
test mathop-6.12 {compiled &: errors} -returnCodes error -body {
& nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "&"}
test mathop-6.13 {compiled &: errors} -returnCodes error -body {
& 0 x
} -result {cannot use non-numeric string "x" as right operand of "&"}
test mathop-6.14 {compiled &: errors} -returnCodes error -body {
& 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "&"}
test mathop-6.15 {compiled &: errors} -returnCodes error -body {
& 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "&"}
test mathop-6.16 {compiled &: errors} -returnCodes error -body {
& 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "&"}
test mathop-6.17 {compiled &: errors} -returnCodes error -body {
& 0 [error expectedError]
} -result expectedError
test mathop-6.18 {compiled &: argument processing order} -body {
# Bytecode compilation known hard for 3+ arguments
list [catch {
& [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
} msg] $msg $x
} -result {1 expected 2}
set op &
test mathop-6.19 {interpreted &} { $op } -1
test mathop-6.20 {interpreted &} { $op 1 } 1
test mathop-6.21 {interpreted &} { $op 1 2 } 0
test mathop-6.22 {interpreted &} { $op 3 7 6 } 2
test mathop-6.23 {interpreted &} -returnCodes error -body {
$op 1.0 2 3
} -result {cannot use floating-point value "1.0" as left operand of "&"}
test mathop-6.24 {interpreted &} -returnCodes error -body {
$op 1 2 3.0
} -result {cannot use floating-point value "3.0" as right operand of "&"}
test mathop-6.25 {interpreted &} { $op 100000000002 18 -126 } 2
test mathop-6.26 {interpreted &} { $op 0xff 0o377 333333333333 } 85
test mathop-6.27 {interpreted &} { $op 1000000000000000000002 18 -126 } 2
test mathop-6.28 {interpreted &} { $op 0xff 0o377 3333333333333333333333 } 85
test mathop-6.29 {interpreted &: errors} -returnCodes error -body {
$op x 0
} -result {cannot use non-numeric string "x" as left operand of "&"}
test mathop-6.30 {interpreted &: errors} -returnCodes error -body {
$op nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "&"}
test mathop-6.31 {interpreted &: errors} -returnCodes error -body {
$op 0 x
} -result {cannot use non-numeric string "x" as right operand of "&"}
test mathop-6.32 {interpreted &: errors} -returnCodes error -body {
$op 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "&"}
test mathop-6.33 {interpreted &: errors} -returnCodes error -body {
$op 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "&"}
test mathop-6.34 {interpreted &: errors} -returnCodes error -body {
$op 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "&"}
test mathop-6.35 {interpreted &: errors} -returnCodes error -body {
$op 0 [error expectedError]
} -result expectedError
test mathop-6.36 {interpreted &: argument processing order} -body {
list [catch {
$op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
} msg] $msg $x
|
| ︙ | ︙ | |||
483 484 485 486 487 488 489 |
test mathop-7.1 {compiled |} { | } 0
test mathop-7.2 {compiled |} { | 1 } 1
test mathop-7.3 {compiled |} { | 1 2 } 3
test mathop-7.4 {compiled |} { | 3 7 6 } 7
test mathop-7.5 {compiled |} -returnCodes error -body {
| 1.0 2 3
| | | | | | | | | | | | | | | | | | 483 484 485 486 487 488 489 490 491 492 493 494 495 496 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 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 |
test mathop-7.1 {compiled |} { | } 0
test mathop-7.2 {compiled |} { | 1 } 1
test mathop-7.3 {compiled |} { | 1 2 } 3
test mathop-7.4 {compiled |} { | 3 7 6 } 7
test mathop-7.5 {compiled |} -returnCodes error -body {
| 1.0 2 3
} -result {cannot use floating-point value "1.0" as right operand of "|"}
test mathop-7.6 {compiled |} -returnCodes error -body {
| 1 2 3.0
} -result {cannot use floating-point value "3.0" as left operand of "|"}
test mathop-7.7 {compiled |} { | 100000000002 18 -126 } -110
test mathop-7.8 {compiled |} { | 0xff 0o377 333333333333 } 333333333503
test mathop-7.9 {compiled |} { | 1000000000000000000002 18 -126 } -110
test mathop-7.10 {compiled |} { | 0xff 0o377 3333333333333333333333 } 3333333333333333333503
test mathop-7.11 {compiled |: errors} -returnCodes error -body {
| x 0
} -result {cannot use non-numeric string "x" as left operand of "|"}
test mathop-7.12 {compiled |: errors} -returnCodes error -body {
| nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "|"}
test mathop-7.13 {compiled |: errors} -returnCodes error -body {
| 0 x
} -result {cannot use non-numeric string "x" as right operand of "|"}
test mathop-7.14 {compiled |: errors} -returnCodes error -body {
| 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "|"}
test mathop-7.15 {compiled |: errors} -returnCodes error -body {
| 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "|"}
test mathop-7.16 {compiled |: errors} -returnCodes error -body {
| 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "|"}
test mathop-7.17 {compiled |: errors} -returnCodes error -body {
| 0 [error expectedError]
} -result expectedError
test mathop-7.18 {compiled |: argument processing order} -body {
# Bytecode compilation known hard for 3+ arguments
list [catch {
| [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
} msg] $msg $x
} -result {1 expected 2}
set op |
test mathop-7.19 {interpreted |} { $op } 0
test mathop-7.20 {interpreted |} { $op 1 } 1
test mathop-7.21 {interpreted |} { $op 1 2 } 3
test mathop-7.22 {interpreted |} { $op 3 7 6 } 7
test mathop-7.23 {interpreted |} -returnCodes error -body {
$op 1.0 2 3
} -result {cannot use floating-point value "1.0" as left operand of "|"}
test mathop-7.24 {interpreted |} -returnCodes error -body {
$op 1 2 3.0
} -result {cannot use floating-point value "3.0" as right operand of "|"}
test mathop-7.25 {interpreted |} { $op 100000000002 18 -126 } -110
test mathop-7.26 {interpreted |} { $op 0xff 0o377 333333333333 } 333333333503
test mathop-7.27 {interpreted |} { $op 1000000000000000000002 18 -126 } -110
test mathop-7.28 {interpreted |} { $op 0xff 0o377 3333333333333333333333 } 3333333333333333333503
test mathop-7.29 {interpreted |: errors} -returnCodes error -body {
$op x 0
} -result {cannot use non-numeric string "x" as left operand of "|"}
test mathop-7.30 {interpreted |: errors} -returnCodes error -body {
$op nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "|"}
test mathop-7.31 {interpreted |: errors} -returnCodes error -body {
$op 0 x
} -result {cannot use non-numeric string "x" as right operand of "|"}
test mathop-7.32 {interpreted |: errors} -returnCodes error -body {
$op 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "|"}
test mathop-7.33 {interpreted |: errors} -returnCodes error -body {
$op 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "|"}
test mathop-7.34 {interpreted |: errors} -returnCodes error -body {
$op 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "|"}
test mathop-7.35 {interpreted |: errors} -returnCodes error -body {
$op 0 [error expectedError]
} -result expectedError
test mathop-7.36 {interpreted |: argument processing order} -body {
list [catch {
$op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
} msg] $msg $x
|
| ︙ | ︙ | |||
593 594 595 596 597 598 599 |
test mathop-8.1 {compiled ^} { ^ } 0
test mathop-8.2 {compiled ^} { ^ 1 } 1
test mathop-8.3 {compiled ^} { ^ 1 2 } 3
test mathop-8.4 {compiled ^} { ^ 3 7 6 } 2
test mathop-8.5 {compiled ^} -returnCodes error -body {
^ 1.0 2 3
| | | | | | | | | | | | | | | | | | 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 |
test mathop-8.1 {compiled ^} { ^ } 0
test mathop-8.2 {compiled ^} { ^ 1 } 1
test mathop-8.3 {compiled ^} { ^ 1 2 } 3
test mathop-8.4 {compiled ^} { ^ 3 7 6 } 2
test mathop-8.5 {compiled ^} -returnCodes error -body {
^ 1.0 2 3
} -result {cannot use floating-point value "1.0" as right operand of "^"}
test mathop-8.6 {compiled ^} -returnCodes error -body {
^ 1 2 3.0
} -result {cannot use floating-point value "3.0" as left operand of "^"}
test mathop-8.7 {compiled ^} { ^ 100000000002 18 -126 } -100000000110
test mathop-8.8 {compiled ^} { ^ 0xff 0o377 333333333333 } 333333333333
test mathop-8.9 {compiled ^} { ^ 1000000000000000000002 18 -126 } -1000000000000000000110
test mathop-8.10 {compiled ^} { ^ 0xff 0o377 3333333333333333333333 } 3333333333333333333333
test mathop-8.11 {compiled ^: errors} -returnCodes error -body {
^ x 0
} -result {cannot use non-numeric string "x" as left operand of "^"}
test mathop-8.12 {compiled ^: errors} -returnCodes error -body {
^ nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "^"}
test mathop-8.13 {compiled ^: errors} -returnCodes error -body {
^ 0 x
} -result {cannot use non-numeric string "x" as right operand of "^"}
test mathop-8.14 {compiled ^: errors} -returnCodes error -body {
^ 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "^"}
test mathop-8.15 {compiled ^: errors} -returnCodes error -body {
^ 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "^"}
test mathop-8.16 {compiled ^: errors} -returnCodes error -body {
^ 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "^"}
test mathop-8.17 {compiled ^: errors} -returnCodes error -body {
^ 0 [error expectedError]
} -result expectedError
test mathop-8.18 {compiled ^: argument processing order} -body {
# Bytecode compilation known hard for 3+ arguments
list [catch {
^ [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
} msg] $msg $x
} -result {1 expected 2}
set op ^
test mathop-8.19 {interpreted ^} { $op } 0
test mathop-8.20 {interpreted ^} { $op 1 } 1
test mathop-8.21 {interpreted ^} { $op 1 2 } 3
test mathop-8.22 {interpreted ^} { $op 3 7 6 } 2
test mathop-8.23 {interpreted ^} -returnCodes error -body {
$op 1.0 2 3
} -result {cannot use floating-point value "1.0" as left operand of "^"}
test mathop-8.24 {interpreted ^} -returnCodes error -body {
$op 1 2 3.0
} -result {cannot use floating-point value "3.0" as right operand of "^"}
test mathop-8.25 {interpreted ^} { $op 100000000002 18 -126 } -100000000110
test mathop-8.26 {interpreted ^} { $op 0xff 0o377 333333333333 } 333333333333
test mathop-8.27 {interpreted ^} { $op 1000000000000000000002 18 -126 } -1000000000000000000110
test mathop-8.28 {interpreted ^} { $op 0xff 0o377 3333333333333333333333 } 3333333333333333333333
test mathop-8.29 {interpreted ^: errors} -returnCodes error -body {
$op x 0
} -result {cannot use non-numeric string "x" as left operand of "^"}
test mathop-8.30 {interpreted ^: errors} -returnCodes error -body {
$op nan 0
} -result {cannot use non-numeric floating-point value "nan" as left operand of "^"}
test mathop-8.31 {interpreted ^: errors} -returnCodes error -body {
$op 0 x
} -result {cannot use non-numeric string "x" as right operand of "^"}
test mathop-8.32 {interpreted ^: errors} -returnCodes error -body {
$op 0 nan
} -result {cannot use non-numeric floating-point value "nan" as right operand of "^"}
test mathop-8.33 {interpreted ^: errors} -returnCodes error -body {
$op 0o8 0
} -result {cannot use non-numeric string "0o8" as left operand of "^"}
test mathop-8.34 {interpreted ^: errors} -returnCodes error -body {
$op 0 0o8
} -result {cannot use non-numeric string "0o8" as right operand of "^"}
test mathop-8.35 {interpreted ^: errors} -returnCodes error -body {
$op 0 [error expectedError]
} -result expectedError
test mathop-8.36 {interpreted ^: argument processing order} -body {
list [catch {
$op [set x 0] [incr x] NaN [incr x] [error expected] [incr x]
} msg] $msg $x
|
| ︙ | ︙ | |||
770 771 772 773 774 775 776 |
} {0 0 0 0 0 0 0}
test mathop-20.6 { one arg, error } {
set res {}
set exp {}
foreach vals {x {1 x} {1 1 x} {1 x 1}} {
# skipping - for now, knownbug...
foreach op {+ * / & | ^ **} {
| | | | | | | 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 |
} {0 0 0 0 0 0 0}
test mathop-20.6 { one arg, error } {
set res {}
set exp {}
foreach vals {x {1 x} {1 1 x} {1 x 1}} {
# skipping - for now, knownbug...
foreach op {+ * / & | ^ **} {
#lappend res [TestOp $op {*}$vals]
#lappend exp "cannot use non-numeric string \"x\" as right operand of \"$op\"\
#ARITH DOMAIN {non-numeric string}"
}
}
foreach op {+ * / & | ^ **} {
lappend res [TestOp $op NaN 1]
lappend exp "cannot use non-numeric floating-point value \"NaN\" as left operand of \"$op\"\
ARITH DOMAIN {non-numeric floating-point value}"
}
expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0
test mathop-20.7 { multi arg } {
set res {}
foreach vals {{1 2} {3 4 5} {4 3 2 1}} {
foreach op {+ - * /} {
lappend res [TestOp $op {*}$vals]
}
|
| ︙ | ︙ | |||
846 847 848 849 850 851 852 |
set res
} [list 1.0 0.2 0.17857142857142858 -0.125 \
2.8196218755553604e-15 8.10000006561e-27]
test mathop-21.5 { unary ops, bad values } {
set res {}
set exp {}
lappend res [TestOp / x]
| | | | | | | | | 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 |
set res
} [list 1.0 0.2 0.17857142857142858 -0.125 \
2.8196218755553604e-15 8.10000006561e-27]
test mathop-21.5 { unary ops, bad values } {
set res {}
set exp {}
lappend res [TestOp / x]
lappend exp "cannot use non-numeric string \"x\" as right operand of \"/\" ARITH DOMAIN {non-numeric string}"
#lappend res [TestOp - x]
#lappend exp "cannot use non-numeric string \"x\" as operand of \"-\" ARITH DOMAIN {non-numeric string}"
lappend res [TestOp ~ x]
lappend exp "cannot use non-numeric string \"x\" as operand of \"~\" ARITH DOMAIN {non-numeric string}"
lappend res [TestOp ! x]
lappend exp "cannot use non-numeric string \"x\" as operand of \"!\" ARITH DOMAIN {non-numeric string}"
lappend res [TestOp ~ 5.0]
lappend exp "cannot use floating-point value \"5.0\" as operand of \"~\" ARITH DOMAIN {floating-point value}"
expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0
test mathop-21.6 { unary ops, too many } {
set exp {}
foreach op {~ !} {
set res [TestOp $op 7 8]
if {[string match "wrong # args: should be * TCL WRONGARGS" $res]} {
lappend exp 0
|
| ︙ | ︙ | |||
961 962 963 964 965 966 967 |
70720 \
]
test mathop-22.4 { unary ops, bad values } {
set res {}
set exp {}
foreach op {& | ^} {
lappend res [TestOp $op x 5]
| | | | | 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 |
70720 \
]
test mathop-22.4 { unary ops, bad values } {
set res {}
set exp {}
foreach op {& | ^} {
lappend res [TestOp $op x 5]
lappend exp "cannot use non-numeric string \"x\" as left operand of \"$op\" ARITH DOMAIN {non-numeric string}"
lappend res [TestOp $op 5 x]
lappend exp "cannot use non-numeric string \"x\" as right operand of \"$op\" ARITH DOMAIN {non-numeric string}"
}
expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0
test mathop-23.1 { comparison ops, numerical } {
set res {}
set todo {5 {1 6} {1 2 2 3} {4 3 2 1} {5.0 5.0} {6 3 3 1} {5.0 5}}
lappend todo [list 2342476234762482734623842342 234827463876473 3434]
lappend todo [list 2653 453735910264536 453735910264537 2384762472634982746239847637]
|
| ︙ | ︙ | |||
1076 1077 1078 1079 1080 1081 1082 |
0 \
]
test mathop-24.3 { binary ops, bad values } {
set res {}
set exp {}
foreach op {% << >>} {
lappend res [TestOp $op x 1]
| | | | | | | 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 1105 1106 1107 1108 1109 1110 1111 1112 |
0 \
]
test mathop-24.3 { binary ops, bad values } {
set res {}
set exp {}
foreach op {% << >>} {
lappend res [TestOp $op x 1]
lappend exp "cannot use non-numeric string \"x\" as left operand of \"$op\" ARITH DOMAIN {non-numeric string}"
lappend res [TestOp $op 1 x]
lappend exp "cannot use non-numeric string \"x\" as right operand of \"$op\" ARITH DOMAIN {non-numeric string}"
}
foreach op {% << >>} {
lappend res [TestOp $op 5.0 1]
lappend exp "cannot use floating-point value \"5.0\" as left operand of \"$op\" ARITH DOMAIN {floating-point value}"
lappend res [TestOp $op 1 5.0]
lappend exp "cannot use floating-point value \"5.0\" as right operand of \"$op\" ARITH DOMAIN {floating-point value}"
}
foreach op {in ni} {
lappend res [TestOp $op 5 "a b \{ c"]
lappend exp "unmatched open brace in list TCL VALUE LIST BRACE"
}
lappend res [TestOp % 5 0]
lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
lappend res [TestOp % 9838923468297346238478737647637375 0]
lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
lappend res [TestOp / 5 0]
lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
lappend res [TestOp / 9838923468297346238478737647637375 0]
lappend exp "divide by zero ARITH DIVZERO {divide by zero}"
expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0
test mathop-24.4 { binary ops, negative shift } {
set res {}
set big -12135435435354435435342423948763867876
set wide -12345678912345
set small -1
|
| ︙ | ︙ | |||
1262 1263 1264 1265 1266 1267 1268 |
lappend res [TestOp ** $small $wide]
lappend exp "exponent too large NONE"
lappend res [TestOp ** 2 $big]
lappend exp "exponent too large NONE"
lappend res [TestOp ** $huge 2.1]
lappend exp "Inf"
lappend res [TestOp ** 2 foo]
| | | | | 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 |
lappend res [TestOp ** $small $wide]
lappend exp "exponent too large NONE"
lappend res [TestOp ** 2 $big]
lappend exp "exponent too large NONE"
lappend res [TestOp ** $huge 2.1]
lappend exp "Inf"
lappend res [TestOp ** 2 foo]
lappend exp "cannot use non-numeric string \"foo\" as right operand of \"**\" ARITH DOMAIN {non-numeric string}"
lappend res [TestOp ** foo 2]
lappend exp "cannot use non-numeric string \"foo\" as left operand of \"**\" ARITH DOMAIN {non-numeric string}"
expr {$res eq $exp ? 0 : "$res\n$exp"}
} 0
test mathop-26.1 { misc ops, size combinations } {
set big1 12135435435354435435342423948763867876
set big2 2746237174783836746262564892918327847
set wide1 87321847232215
set wide2 12345678912345
|
| ︙ | ︙ |
Changes to tests/msgcat.test.
| ︙ | ︙ | |||
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 |
namespace eval bar {::msgcat::mcforgetpackage}
namespace eval baz {::msgcat::mcforgetpackage}
namespace delete bar baz
} -body {
bar::ObjCur method1
} -result con2baz
# Test msgcat-16.*: command mcpackagenamespaceget
test msgcat-16.1 {mcpackagenamespaceget in namespace procedure} -body {
namespace eval baz {msgcat::mcpackagenamespaceget}
} -result ::msgcat::test::baz
test msgcat-16.2 {mcpackagenamespaceget in class setup} -setup {
| > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
namespace eval bar {::msgcat::mcforgetpackage}
namespace eval baz {::msgcat::mcforgetpackage}
namespace delete bar baz
} -body {
bar::ObjCur method1
} -result con2baz
# HaO 2024-07-15 fix me
# Ticket 91b3a5bb: I have no idea what the following case should do.
# But currently, it raises an error and that should not happen.
# The background is the tklib tooltip package.
# This package captures the caller namespace to later invoke msgcat with current data.
# If the caller namespace is a method, it currently fails.
test msgcat-15.5 {ticket 91b3a5bb: method namespace recorded and evaluated gives error}\
-setup {
oo::class create App {}
oo::define App {
constructor {} { my add_one }
method add_one {} { recordMsgcat }
}
proc ::recordMsgcat {} { set ::nscaller [uplevel 1 {namespace current}] }
set application [App new]
} -cleanup {
$application destroy
App destroy
unset -nocomplain ::nscaller
rename ::recordMsgcat ""
} -body {
namespace eval $::nscaller [list ::msgcat::mc "Test"]
} -returnCodes ok -result Test
# Test msgcat-16.*: command mcpackagenamespaceget
test msgcat-16.1 {mcpackagenamespaceget in namespace procedure} -body {
namespace eval baz {msgcat::mcpackagenamespaceget}
} -result ::msgcat::test::baz
test msgcat-16.2 {mcpackagenamespaceget in class setup} -setup {
|
| ︙ | ︙ |
Changes to tests/namespace.test.
| ︙ | ︙ | |||
3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 |
rename getbytes {}
unset i ns start end
} -result 0
test namespace-55.1 {compiled ensembles inside compiled ensembles: Bug 6d2f249a01} {
info class [format %s constructor] oo::object
} ""
test namespace-56.1 {bug f97d4ee020: mutually-entangled deletion} {
namespace eval ::testing {
proc abc {} {}
proc def {} {}
trace add command abc delete "rename ::testing::def {}; #"
trace add command def delete "rename ::testing::abc {}; #"
| > > > > > > > > > > > > > > > > | 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 |
rename getbytes {}
unset i ns start end
} -result 0
test namespace-55.1 {compiled ensembles inside compiled ensembles: Bug 6d2f249a01} {
info class [format %s constructor] oo::object
} ""
test namespace-55.2 {compiled ensembles inside safe interpreters (for safe sub-commands), bug [1095bf7f756f9aed]} -setup {
interp create -safe si
set code {
proc test_comp_dict d { dict for {k v} $d {expr $v} }
regexp -inline {Command 1:(?:[^\n]*\n){1,5}} [::tcl::unsupported::disassemble proc test_comp_dict]
}
} -body {
set a [ eval $code]
set b [si eval $code]
list [expr {$a eq $b}] [regexp { dictFirst } $a] [regexp { dictFirst } $b] $a $b
} -cleanup {
rename test_comp_dict {}
unset -nocomplain code a b
interp delete si
} -match glob -result {1 1 1 *}
test namespace-56.1 {bug f97d4ee020: mutually-entangled deletion} {
namespace eval ::testing {
proc abc {} {}
proc def {} {}
trace add command abc delete "rename ::testing::def {}; #"
trace add command def delete "rename ::testing::abc {}; #"
|
| ︙ | ︙ |
Changes to tests/obj.test.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 |
namespace import -force ::tcltest::*
}
::tcltest::loadTestedCommands
catch [list package require -exact tcl::test [info patchlevel]]
testConstraint testobj [llength [info commands testobj]]
| < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
namespace import -force ::tcltest::*
}
::tcltest::loadTestedCommands
catch [list package require -exact tcl::test [info patchlevel]]
testConstraint testobj [llength [info commands testobj]]
testConstraint wideIs64bit [expr {wide(0x8000000000000000) < 0}]
test obj-1.1 {Tcl_AppendAllObjTypes, and InitTypeTable, Tcl_RegisterObjType} testobj {
set r 1
foreach {t} {
bytecode
cmdName
|
| ︙ | ︙ | |||
543 544 545 546 547 548 549 |
set x {}
for {set i 0} {$i<100000} {incr i} {
set x [list $x {}]
}
unset x
} {}
| | | | | | | 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 |
set x {}
for {set i 0} {$i<100000} {incr i} {
set x [list $x {}]
}
unset x
} {}
test obj-33.1 {integer overflow on input} {wideIs64bit} {
set x 0x8000; append x 0000
list [string is integer $x] [expr { wide($x) }]
} {1 2147483648}
test obj-33.2 {integer overflow on input} {wideIs64bit} {
set x 0xffff; append x ffff
list [string is integer $x] [expr { wide($x) }]
} {1 4294967295}
test obj-33.3 {integer overflow on input} {
set x 0x10000; append x 0000
list [string is integer $x] [expr { wide($x) }]
} {1 4294967296}
test obj-33.4 {integer overflow on input} {wideIs64bit} {
set x -0x8000; append x 0000
list [string is integer $x] [expr { wide($x) }]
} {1 -2147483648}
test obj-33.5 {integer overflow on input} {wideIs64bit} {
set x -0x8000; append x 0001
list [string is integer $x] [expr { wide($x) }]
} {1 -2147483649}
test obj-33.6 {integer overflow on input} {wideIs64bit} {
set x -0xffff; append x ffff
list [string is integer $x] [expr { wide($x) }]
} {1 -4294967295}
test obj-33.7 {integer overflow on input} {
set x -0x10000; append x 0000
list [string is integer $x] [expr { wide($x) }]
} {1 -4294967296}
|
| ︙ | ︙ |
Changes to tests/oo.test.
| ︙ | ︙ | |||
3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 |
parent destroy
} -result {this command cannot be called when the object has been deleted
while executing
"self {error foobar}"
(in definition script for class "::foo" line 1)
invoked from within
"oo::define foo {rename ::foo {}; self {error foobar}}"}
test oo-19.1 {OO: varname method} -setup {
oo::object create inst
oo::objdefine inst export eval
set result {}
inst eval { variable x }
} -body {
| > > > > > > > > > > | 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 |
parent destroy
} -result {this command cannot be called when the object has been deleted
while executing
"self {error foobar}"
(in definition script for class "::foo" line 1)
invoked from within
"oo::define foo {rename ::foo {}; self {error foobar}}"}
test oo-18.12 {OO: self callable via eval method} -setup {
oo::class create parent {
export eval
}
parent create ::foo
} -body {
foo eval { self }
} -cleanup {
parent destroy
} -result ::foo
test oo-19.1 {OO: varname method} -setup {
oo::object create inst
oo::objdefine inst export eval
set result {}
inst eval { variable x }
} -body {
|
| ︙ | ︙ | |||
3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 |
} -body {
testClass create A
testClass create B
lsearch [list [A varname foo] [B varname foo]] [B bar A]
} -cleanup {
testClass destroy
} -result 0
test oo-20.1 {OO: variable method} -body {
oo::class create testClass {
constructor {} {
my variable ok
set ok {}
}
| > > > > > > > > > > > > > > | 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 |
} -body {
testClass create A
testClass create B
lsearch [list [A varname foo] [B varname foo]] [B bar A]
} -cleanup {
testClass destroy
} -result 0
test oo-19.4 {OO: varname ghosts [Bug 74b6110204]} -setup {
oo::class create testClass {
export varname
self export createWithNamespace
}
set obj [testClass createWithNamespace testoo19_4 testoo19_4]
set ns [info object namespace $obj]
} -body {
set v [$obj varname foo]
list [namespace which -variable $v] \
[info exists $v] [namespace which -variable $v]
} -cleanup {
testClass destroy
} -result {::testoo19_4::foo 0 ::testoo19_4::foo}
test oo-20.1 {OO: variable method} -body {
oo::class create testClass {
constructor {} {
my variable ok
set ok {}
}
|
| ︙ | ︙ |
Changes to tests/pid.test.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
close $f
set pids
} -cleanup {
removeFile test1
} -result {}
test pid-1.4 {pid command} pidDefined {
list [catch {pid a b} msg] $msg
| | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
close $f
set pids
} -cleanup {
removeFile test1
} -result {}
test pid-1.4 {pid command} pidDefined {
list [catch {pid a b} msg] $msg
} {1 {wrong # args: should be "pid ?channel?"}}
test pid-1.5 {pid command} pidDefined {
list [catch {pid gorp} msg] $msg
} {1 {can not find channel named "gorp"}}
# cleanup
::tcltest::cleanupTests
return
|
Changes to tests/scan.test.
| ︙ | ︙ | |||
78 79 80 81 82 83 84 |
default {
return 0
}
}
}
testConstraint ieeeFloatingPoint [testIEEE]
| < | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
default {
return 0
}
}
}
testConstraint ieeeFloatingPoint [testIEEE]
test scan-1.1 {BuildCharSet, CharInSet} {
list [scan foo {%[^o]} x] $x
} {1 f}
test scan-1.2 {BuildCharSet, CharInSet} {
list [scan \]foo {%[]f]} x] $x
} {1 \]f}
|
| ︙ | ︙ | |||
513 514 515 516 517 518 519 |
#
test scan-5.11 {integer scanning} -constraints {nonPortable} -setup {
set a {}; set b {}
} -body {
list [scan "4294967280 4294967280" "%u %d" a b] $a \
[expr {$b == -16 || $b == 0x7fffffff}]
} -result {2 4294967280 1}
| | | 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
#
test scan-5.11 {integer scanning} -constraints {nonPortable} -setup {
set a {}; set b {}
} -body {
list [scan "4294967280 4294967280" "%u %d" a b] $a \
[expr {$b == -16 || $b == 0x7fffffff}]
} -result {2 4294967280 1}
test scan-5.12 {integer scanning} -setup {
set a {}; set b {}; set c {}
} -body {
list [scan "7810179016327718216,6c63546f6c6c6548,661432506755433062510" \
%ld,%lx,%lo a b c] $a $b $c
} -result {3 7810179016327718216 7810179016327718216 7810179016327718216}
test scan-5.13 {integer scanning and overflow} {
# This test used to fail on some 64-bit systems. [Bug 1011860]
|
| ︙ | ︙ |
Changes to tests/trace.test.
| ︙ | ︙ | |||
1691 1692 1693 1694 1695 1696 1697 |
set {*}$args
}
test trace-21.12 {bug 2438181} -setup {
trace add execution set2 leave {puts one two three #;}
} -body {
set2 a hello
| | | 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 |
set {*}$args
}
test trace-21.12 {bug 2438181} -setup {
trace add execution set2 leave {puts one two three #;}
} -body {
set2 a hello
} -returnCodes 1 -result {wrong # args: should be "puts ?-nonewline? ?channel? string"}
proc factorial {n} {
if {$n != 1} { return [expr {$n * [factorial [expr {$n -1 }]]}] }
return 1
}
test trace-22.1 {recursive(1) trace execution: enter} {
|
| ︙ | ︙ |
Changes to tests/while-old.test.
| ︙ | ︙ | |||
88 89 90 91 92 93 94 |
test while-old-4.3 {errors in while loops} {
set err [catch {while 1 2 3} msg]
list $err $msg
} {1 {wrong # args: should be "while test command"}}
test while-old-4.4 {errors in while loops} {
set err [catch {while {"a"+"b"} {error "loop aborted"}} msg]
list $err $msg
| | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
test while-old-4.3 {errors in while loops} {
set err [catch {while 1 2 3} msg]
list $err $msg
} {1 {wrong # args: should be "while test command"}}
test while-old-4.4 {errors in while loops} {
set err [catch {while {"a"+"b"} {error "loop aborted"}} msg]
list $err $msg
} {1 {cannot use non-numeric string "a" as left operand of "+"}}
test while-old-4.5 {errors in while loops} {
catch {unset x}
set x 1
set err [catch {while {$x} {set x foo}} msg]
list $err $msg
} {1 {expected boolean value but got "foo"}}
test while-old-4.6 {errors in while loops} {
|
| ︙ | ︙ |
Changes to tests/while.test.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 |
catch {while {$i<} break}
return $::errorInfo
} -cleanup {
unset i
} -match glob -result {*"while {$i<} break"}
test while-1.3 {TclCompileWhileCmd: error in test expression} -body {
while {"a"+"b"} {error "loop aborted"}
| | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
catch {while {$i<} break}
return $::errorInfo
} -cleanup {
unset i
} -match glob -result {*"while {$i<} break"}
test while-1.3 {TclCompileWhileCmd: error in test expression} -body {
while {"a"+"b"} {error "loop aborted"}
} -returnCodes error -result {cannot use non-numeric string "a" as left operand of "+"}
test while-1.4 {TclCompileWhileCmd: multiline test expr} -body {
set value 1
while {($tcl_platform(platform) != "foobar1") && \
($tcl_platform(platform) != "foobar2")} {
incr value
break
}
|
| ︙ | ︙ | |||
339 340 341 342 343 344 345 |
return $::errorInfo
} -match glob -cleanup {
unset i z
} -result {*"$z {$i<} {set x 1}"}
test while-4.4 {while (not compiled): error in test expression} -body {
set z while
$z {"a"+"b"} {error "loop aborted"}
| | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
return $::errorInfo
} -match glob -cleanup {
unset i z
} -result {*"$z {$i<} {set x 1}"}
test while-4.4 {while (not compiled): error in test expression} -body {
set z while
$z {"a"+"b"} {error "loop aborted"}
} -returnCodes error -result {cannot use non-numeric string "a" as left operand of "+"}
test while-4.5 {while (not compiled): multiline test expr} -body {
set value 1
set z while
$z {($tcl_platform(platform) != "foobar1") && \
($tcl_platform(platform) != "foobar2")} {
incr value
break
|
| ︙ | ︙ |
Changes to tests/zipfs.test.
| ︙ | ︙ | |||
1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 |
thread
} -body {
set before [lsort [zipfs mount]]
thread::release [thread::create]
after 100; # Needed to allow the spawned thread to exit to trigger bug
string equal $before [lsort [zipfs mount]]
} -result 1
}
::tcltest::cleanupTests
return
# Local Variables:
| > > > > > > > > > > > > > > > > | 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 |
thread
} -body {
set before [lsort [zipfs mount]]
thread::release [thread::create]
after 100; # Needed to allow the spawned thread to exit to trigger bug
string equal $before [lsort [zipfs mount]]
} -result 1
test bug-7d5f1c1308 "zipfs error on dotfiles" -setup {
set basename bug-7d5f1c1308
set mt //zipfs:/$basename-mt
set zipfile $basename.zip
set dir [makeDirectory $basename]
close [open [file join $dir .ext] w]
} -cleanup {
zipfs unmount $mt
file delete $zipfile
removeDirectory $basename
} -body {
zipfs mkzip $zipfile $dir [file dirname $dir]
zipfs mount $zipfile $mt
lsort [zipfs list $mt/*]
} -result {//zipfs:/bug-7d5f1c1308-mt/bug-7d5f1c1308 //zipfs:/bug-7d5f1c1308-mt/bug-7d5f1c1308/.ext}
}
::tcltest::cleanupTests
return
# Local Variables:
|
| ︙ | ︙ |
Changes to tests/zlib.test.
| ︙ | ︙ | |||
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 |
lappend result $size $size2 ->$size3
}
return $result
} -cleanup {
chan close $src
chan close $dst
} -result {5 5 ->5 5 5 ->5 5 5 ->5}
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
| > > > > > > > > > > | 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 |
lappend result $size $size2 ->$size3
}
return $result
} -cleanup {
chan close $src
chan close $dst
} -result {5 5 ->5 5 5 ->5 5 5 ->5}
test zlib-15.1 {Bug cfdf80a2efc6 - negative checksums} -setup {
set compressor [zlib stream gzip -header {comment "A zlib demo"}]
$compressor put abcd
$compressor finalize
} -body {
$compressor checksum
} -cleanup {
$compressor close
} -result 3984772369
::tcltest::cleanupTests
return
# Local Variables:
# mode: tcl
|
| ︙ | ︙ |
Added tools/ucm2tests.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 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 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 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 351 352 |
# ucm2tests.tcl
#
# Parses given ucm files (from ICU) to generate test data
# for encodings.
#
# tclsh ucm2tests.tcl PATH_TO_ICU_UCM_DIRECTORY ?OUTPUTPATH?
#
namespace eval ucm {
# No means to change these currently but ...
variable outputPath
variable outputChan
variable errorChan stderr
variable verbose 0
# Map Tcl encoding name to ICU UCM file name
variable encNameMap
array set encNameMap {
cp1250 glibc-CP1250-2.1.2
cp1251 glibc-CP1251-2.1.2
cp1252 glibc-CP1252-2.1.2
cp1253 glibc-CP1253-2.1.2
cp1254 glibc-CP1254-2.1.2
cp1255 glibc-CP1255-2.1.2
cp1256 glibc-CP1256-2.1.2
cp1257 glibc-CP1257-2.1.2
cp1258 glibc-CP1258-2.1.2
gb1988 glibc-GB_1988_80-2.3.3
iso8859-1 glibc-ISO_8859_1-2.1.2
iso8859-2 glibc-ISO_8859_2-2.1.2
iso8859-3 glibc-ISO_8859_3-2.1.2
iso8859-4 glibc-ISO_8859_4-2.1.2
iso8859-5 glibc-ISO_8859_5-2.1.2
iso8859-6 glibc-ISO_8859_6-2.1.2
iso8859-7 glibc-ISO_8859_7-2.3.3
iso8859-8 glibc-ISO_8859_8-2.3.3
iso8859-9 glibc-ISO_8859_9-2.1.2
iso8859-10 glibc-ISO_8859_10-2.1.2
iso8859-11 glibc-ISO_8859_11-2.1.2
iso8859-13 glibc-ISO_8859_13-2.3.3
iso8859-14 glibc-ISO_8859_14-2.1.2
iso8859-15 glibc-ISO_8859_15-2.1.2
iso8859-16 glibc-ISO_8859_16-2.3.3
}
# Array keyed by Tcl encoding name. Each element contains mapping of
# Unicode code point -> byte sequence for that encoding as a flat list
# (or dictionary). Both are stored as hex strings
variable charMap
# Array keyed by Tcl encoding name. List of invalid code sequences
# each being a hex string.
variable invalidCodeSequences
# Array keyed by Tcl encoding name. List of unicode code points that are
# not mapped, each being a hex string.
variable unmappedCodePoints
# The fallback character per encoding
variable encSubchar
}
proc ucm::abort {msg} {
variable errorChan
puts $errorChan $msg
exit 1
}
proc ucm::warn {msg} {
variable errorChan
puts $errorChan $msg
}
proc ucm::log {msg} {
variable verbose
if {$verbose} {
variable errorChan
puts $errorChan $msg
}
}
proc ucm::print {s} {
variable outputChan
puts $outputChan $s
}
proc ucm::parse_SBCS {encName fd} {
variable charMap
variable invalidCodeSequences
variable unmappedCodePoints
set result {}
while {[gets $fd line] >= 0} {
if {[string match #* $line]} {
continue
}
if {[string equal "END CHARMAP" [string trim $line]]} {
break
}
if {![regexp {^\s*<U([[:xdigit:]]{4})>\s*((\\x[[:xdigit:]]{2})+)\s*(\|(0|1|2|3|4))} $line -> unichar bytes - - precision]} {
error "Unexpected line parsing SBCS: $line"
}
set bytes [string map {\\x {}} $bytes]; # \xNN -> NN
if {$precision eq "" || $precision eq "0"} {
lappend result $unichar $bytes
} else {
# It is a fallback mapping - ignore
}
}
set charMap($encName) $result
# Find out invalid code sequences and unicode code points that are not mapped
set valid {}
set mapped {}
foreach {unich bytes} $result {
lappend mapped $unich
lappend valid $bytes
}
set invalidCodeSequences($encName) {}
for {set i 0} {$i <= 255} {incr i} {
set hex [format %.2X $i]
if {[lsearch -exact $valid $hex] < 0} {
lappend invalidCodeSequences($encName) $hex
}
}
set unmappedCodePoints($encName) {}
for {set i 0} {$i <= 65535} {incr i} {
set hex [format %.4X $i]
if {[lsearch -exact $mapped $hex] < 0} {
lappend unmappedCodePoints($encName) $hex
# Only look for (at most) one below 256 and one above 1024
if {$i < 255} {
# Found one so jump past 8 bits
set i 255
} else {
break
}
}
if {$i == 255} {
set i 1023
}
}
lappend unmappedCodePoints($encName) D800 DC00 10000 10FFFF
}
proc ucm::generate_boilerplate {} {
# Common procedures
print {
# This file is automatically generated by ucm2tests.tcl.
# Edits will be overwritten on next generation.
#
# Generates tests comparing Tcl encodings to ICU.
# The generated file is NOT standalone. It should be sourced into a test script.
proc ucmConvertfromMismatches {enc map} {
set mismatches {}
foreach {unihex hex} $map {
set unihex [string range 00000000$unihex end-7 end]; # Make 8 digits
set unich [subst "\\U$unihex"]
if {[encoding convertfrom -profile strict $enc [binary decode hex $hex]] ne $unich} {
lappend mismatches "<[printable $unich],$hex>"
}
}
return $mismatches
}
proc ucmConverttoMismatches {enc map} {
set mismatches {}
foreach {unihex hex} $map {
set unihex [string range 00000000$unihex end-7 end]; # Make 8 digits
set unich [subst "\\U$unihex"]
if {[encoding convertto -profile strict $enc $unich] ne [binary decode hex $hex]} {
lappend mismatches "<[printable $unich],$hex>"
}
}
return $mismatches
}
if {[info commands printable] eq ""} {
proc printable {s} {
set print ""
foreach c [split $s ""] {
set i [scan $c %c]
if {[string is print $c] && ($i <= 127)} {
append print $c
} elseif {$i <= 0xff} {
append print \\x[format %02X $i]
} elseif {$i <= 0xffff} {
append print \\u[format %04X $i]
} else {
append print \\U[format %08X $i]
}
}
return $print
}
}
}
} ; # generate_boilerplate
proc ucm::generate_tests {} {
variable encNameMap
variable charMap
variable invalidCodeSequences
variable unmappedCodePoints
variable outputPath
variable outputChan
variable encSubchar
if {[info exists outputPath]} {
set outputChan [open $outputPath w]
fconfigure $outputChan -translation lf
} else {
set outputChan stdout
}
array set tclNames {}
foreach encName [encoding names] {
set tclNames($encName) ""
}
generate_boilerplate
foreach encName [lsort -dictionary [array names encNameMap]] {
if {![info exists charMap($encName)]} {
warn "No character map read for $encName"
continue
}
unset tclNames($encName)
# Print the valid tests
print "\n#\n# $encName (generated from $encNameMap($encName))"
print "\ntest encoding-convertfrom-ucmCompare-$encName {Compare against ICU UCM} -body \{"
print " ucmConvertfromMismatches $encName {$charMap($encName)}"
print "\} -result {}"
print "\ntest encoding-convertto-ucmCompare-$encName {Compare against ICU UCM} -body \{"
print " ucmConverttoMismatches $encName {$charMap($encName)}"
print "\} -result {}"
if {0} {
# This will generate individual tests for every char
# and test in lead, tail, middle, solo configurations
# but takes considerable time
print "lappend encValidStrings \{*\}\{"
foreach {unich hex} $charMap($encName) {
print " $encName \\u$unich $hex {} {}"
}
print "\}; # $encName"
}
# Generate the invalidity checks
print "\n# $encName - invalid byte sequences"
print "lappend encInvalidBytes \{*\}\{"
foreach hex $invalidCodeSequences($encName) {
# Map XXXX... to \xXX\xXX...
set uhex [regsub -all .. $hex {\\x\0}]
set uhex \\U[string range 00000000$hex end-7 end]
print " $encName $hex tcl8 $uhex -1 {} {}"
print " $encName $hex replace \\uFFFD -1 {} {}"
print " $encName $hex strict {} 0 {} {}"
}
print "\}; # $encName"
print "\n# $encName - invalid byte sequences"
print "lappend encUnencodableStrings \{*\}\{"
if {[info exists encSubchar($encName)]} {
set subchar $encSubchar($encName)
} else {
set subchar "3F"; # Tcl uses ? by default
}
foreach hex $unmappedCodePoints($encName) {
set uhex \\U[string range 00000000$hex end-7 end]
print " $encName $uhex tcl8 $subchar -1 {} {}"
print " $encName $uhex replace $subchar -1 {} {}"
print " $encName $uhex strict {} 0 {} {}"
}
print "\}; # $encName"
}
if {[array size tclNames]} {
warn "Missing encoding: [lsort [array names tclNames]]"
}
if {[info exists outputPath]} {
close $outputChan
unset outputChan
}
}
proc ucm::parse_file {encName ucmPath} {
variable charMap
variable encSubchar
set fd [open $ucmPath]
try {
# Parse the metadata
unset -nocomplain state
while {[gets $fd line] >= 0} {
if {[regexp {<(code_set_name|mb_cur_max|mb_cur_min|uconv_class|subchar)>\s+(\S+)} $line -> key val]} {
set state($key) $val
} elseif {[regexp {^\s*CHARMAP\s*$} $line]} {
set state(charmap) ""
break
} else {
# Skip all else
}
}
if {![info exists state(charmap)]} {
abort "Error: $ucmPath has No CHARMAP line."
}
foreach key {code_set_name uconv_class} {
if {[info exists state($key)]} {
set state($key) [string trim $state($key) {"}]
}
}
if {[info exists charMap($encName)]} {
abort "Duplicate file for $encName ($path)"
}
if {![info exists state(uconv_class)]} {
abort "Error: $ucmPath has no uconv_class definition."
}
if {[info exists state(subchar)]} {
# \xNN\xNN.. -> NNNN..
set encSubchar($encName) [string map {\\x {}} $state(subchar)]
}
switch -exact -- $state(uconv_class) {
SBCS {
if {[catch {
parse_SBCS $encName $fd
} result]} {
abort "Could not process $ucmPath. $result"
}
}
default {
log "Skipping $ucmPath -- not SBCS encoding."
return
}
}
} finally {
close $fd
}
}
proc ucm::run {} {
variable encNameMap
variable outputPath
switch [llength $::argv] {
2 {set outputPath [lindex $::argv 1]}
1 {}
default {
abort "Usage: [info nameofexecutable] $::argv0 path/to/icu/ucm/data ?outputfile?"
}
}
foreach {encName fname} [array get encNameMap] {
ucm::parse_file $encName [file join [lindex $::argv 0] ${fname}.ucm]
}
generate_tests
}
ucm::run
|
Changes to unix/Makefile.in.
| ︙ | ︙ | |||
303 304 305 306 307 308 309 | tclArithSeries.o tclAssembly.o tclAsync.o tclBasic.o tclBinary.o \ tclBrodnik.o \ tclCkalloc.o tclClock.o tclClockFmt.o tclCmdAH.o tclCmdIL.o tclCmdMZ.o \ tclCompCmds.o tclCompCmdsGR.o tclCompCmdsSZ.o tclCompExpr.o \ tclCompile.o tclConfig.o tclDate.o tclDictObj.o tclDisassemble.o \ tclEncoding.o tclEnsemble.o tclHAMT.o tclHAMTObj.o \ tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \ | > | | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | tclArithSeries.o tclAssembly.o tclAsync.o tclBasic.o tclBinary.o \ tclBrodnik.o \ tclCkalloc.o tclClock.o tclClockFmt.o tclCmdAH.o tclCmdIL.o tclCmdMZ.o \ tclCompCmds.o tclCompCmdsGR.o tclCompCmdsSZ.o tclCompExpr.o \ tclCompile.o tclConfig.o tclDate.o tclDictObj.o tclDisassemble.o \ tclEncoding.o tclEnsemble.o tclHAMT.o tclHAMTObj.o \ tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \ tclHash.o tclHistory.o \ tclIcu.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \ tclIORChan.o tclIORTrans.o tclIOGT.o tclIOSock.o tclIOUtil.o \ tclLink.o tclListObj.o \ tclLiteral.o tclLoad.o tclMain.o tclNamesp.o tclNotify.o \ tclObj.o tclOptimize.o tclPanic.o tclParse.o tclPathObj.o tclPipe.o \ tclPkg.o tclPkgConfig.o tclPosixStr.o \ tclPreserve.o tclProc.o tclProcess.o tclRegexp.o \ tclResolve.o tclResult.o tclScan.o tclStringObj.o tclStrIdxTree.o \ |
| ︙ | ︙ | |||
434 435 436 437 438 439 440 441 442 443 444 445 446 447 | $(GENERIC_DIR)/tclFCmd.c \ $(GENERIC_DIR)/tclFileName.c \ $(GENERIC_DIR)/tclGet.c \ $(GENERIC_DIR)/tclHAMT.c \ $(GENERIC_DIR)/tclHAMTObj.c \ $(GENERIC_DIR)/tclHash.c \ $(GENERIC_DIR)/tclHistory.c \ $(GENERIC_DIR)/tclIndexObj.c \ $(GENERIC_DIR)/tclInterp.c \ $(GENERIC_DIR)/tclIO.c \ $(GENERIC_DIR)/tclIOCmd.c \ $(GENERIC_DIR)/tclIOGT.c \ $(GENERIC_DIR)/tclIOSock.c \ $(GENERIC_DIR)/tclIOUtil.c \ | > | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | $(GENERIC_DIR)/tclFCmd.c \ $(GENERIC_DIR)/tclFileName.c \ $(GENERIC_DIR)/tclGet.c \ $(GENERIC_DIR)/tclHAMT.c \ $(GENERIC_DIR)/tclHAMTObj.c \ $(GENERIC_DIR)/tclHash.c \ $(GENERIC_DIR)/tclHistory.c \ $(GENERIC_DIR)/tclIcu.c \ $(GENERIC_DIR)/tclIndexObj.c \ $(GENERIC_DIR)/tclInterp.c \ $(GENERIC_DIR)/tclIO.c \ $(GENERIC_DIR)/tclIOCmd.c \ $(GENERIC_DIR)/tclIOGT.c \ $(GENERIC_DIR)/tclIOSock.c \ $(GENERIC_DIR)/tclIOUtil.c \ |
| ︙ | ︙ | |||
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 | tclHash.o: $(GENERIC_DIR)/tclHash.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclHash.c tclHistory.o: $(GENERIC_DIR)/tclHistory.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclHistory.c tclIndexObj.o: $(GENERIC_DIR)/tclIndexObj.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIndexObj.c tclInterp.o: $(GENERIC_DIR)/tclInterp.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclInterp.c tclIO.o: $(GENERIC_DIR)/tclIO.c $(IOHDR) | > > > | 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 | tclHash.o: $(GENERIC_DIR)/tclHash.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclHash.c tclHistory.o: $(GENERIC_DIR)/tclHistory.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclHistory.c tclIcu.o: $(GENERIC_DIR)/tclIcu.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIcu.c tclIndexObj.o: $(GENERIC_DIR)/tclIndexObj.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclIndexObj.c tclInterp.o: $(GENERIC_DIR)/tclInterp.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclInterp.c tclIO.o: $(GENERIC_DIR)/tclIO.c $(IOHDR) |
| ︙ | ︙ |
Changes to unix/installManPage.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
Sym=""
Loc=""
Gz=""
Suffix=""
while true; do
case $1 in
| | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Sym=""
Loc=""
Gz=""
Suffix=""
while true; do
case $1 in
-s | --symlinks ) Sym="-s " ;;
-z | --compress ) Gzip=$2; shift ;;
-e | --extension ) Gz=$2; shift ;;
-x | --suffix ) Suffix=$2; shift ;;
-*) cat <<EOF
Unknown option "$1". Supported options:
-s Use symbolic links for manpages with multiple names.
-z PROG Use PROG to compress manual pages.
-e EXT Defines the extension added by -z PROG when compressing.
|
| ︙ | ︙ |
Changes to unix/tclEpollNotfy.c.
| ︙ | ︙ | |||
203 204 205 206 207 208 209 |
if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) {
newEvent.events |= EPOLLIN;
}
if (filePtr->mask & TCL_WRITABLE) {
newEvent.events |= EPOLLOUT;
}
if (isNew) {
| | | | | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) {
newEvent.events |= EPOLLIN;
}
if (filePtr->mask & TCL_WRITABLE) {
newEvent.events |= EPOLLOUT;
}
if (isNew) {
newPedPtr = (struct PlatformEventData *)
Tcl_Alloc(sizeof(struct PlatformEventData));
newPedPtr->filePtr = filePtr;
newPedPtr->tsdPtr = tsdPtr;
filePtr->pedPtr = newPedPtr;
}
newEvent.data.ptr = filePtr->pedPtr;
/*
* N.B. As discussed in Tcl_WaitForEvent(), epoll(7) does not support
* regular files (S_IFREG). Therefore, filePtr is in these cases simply
|
| ︙ | ︙ | |||
363 364 365 366 367 368 369 |
tsdPtr->triggerFilePtr = filePtr;
if ((tsdPtr->eventsFd = epoll_create1(EPOLL_CLOEXEC)) == -1) {
Tcl_Panic("epoll_create1: %s", strerror(errno));
}
filePtr->mask = TCL_READABLE;
PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_ADD, 1);
if (!tsdPtr->readyEvents) {
| | | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
tsdPtr->triggerFilePtr = filePtr;
if ((tsdPtr->eventsFd = epoll_create1(EPOLL_CLOEXEC)) == -1) {
Tcl_Panic("epoll_create1: %s", strerror(errno));
}
filePtr->mask = TCL_READABLE;
PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_ADD, 1);
if (!tsdPtr->readyEvents) {
tsdPtr->maxReadyEvents = 512;
tsdPtr->readyEvents = (struct epoll_event *) Tcl_Alloc(
tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0]));
}
LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
}
/*
|
| ︙ | ︙ |
Changes to unix/tclLoadOSF.c.
| ︙ | ︙ | |||
124 125 126 127 128 129 130 |
* impossible to get a package name given a module.
*
* I build loadable modules with a makefile rule like
* ld ... -export $@: -o $@ $(OBJS)
*/
if ((pkg = strrchr(fileName, '/')) == NULL) {
| | | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
* impossible to get a package name given a module.
*
* I build loadable modules with a makefile rule like
* ld ... -export $@: -o $@ $(OBJS)
*/
if ((pkg = strrchr(fileName, '/')) == NULL) {
pkg = fileName;
} else {
pkg++;
}
newHandle = (Tcl_LoadHandle)Tcl_Alloc(sizeof(*newHandle));
newHandle->clientData = pkg;
newHandle->findSymbolProcPtr = &FindSymbol;
newHandle->unloadFileProcPtr = &UnloadFile;
|
| ︙ | ︙ |
Changes to unix/tclUnixCompat.c.
| ︙ | ︙ | |||
990 991 992 993 994 995 996 |
int *regsPtr) /* Registers after the CPUID. */
{
int status = TCL_ERROR;
/* See: <http://en.wikipedia.org/wiki/CPUID> */
#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
__asm__ __volatile__("movq %%rbx, %%rsi \n\t" /* save %rbx */
| | | | | | | | | | 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 |
int *regsPtr) /* Registers after the CPUID. */
{
int status = TCL_ERROR;
/* See: <http://en.wikipedia.org/wiki/CPUID> */
#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
__asm__ __volatile__("movq %%rbx, %%rsi \n\t" /* save %rbx */
"cpuid \n\t"
"xchgq %%rsi, %%rbx \n\t" /* restore the old %rbx */
: "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
: "a"(index));
status = TCL_OK;
#elif defined(__i386__) || defined(_M_IX86)
__asm__ __volatile__("mov %%ebx, %%esi \n\t" /* save %ebx */
"cpuid \n\t"
"xchg %%esi, %%ebx \n\t" /* restore the old %ebx */
: "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3])
: "a"(index));
status = TCL_OK;
#else
(void)index;
(void)regsPtr;
#endif
return status;
}
|
| ︙ | ︙ |
Changes to unix/tclUnixInit.c.
| ︙ | ︙ | |||
50 51 52 53 54 55 56 |
static const char *const processors[NUMPROCESSORS] = {
"i686", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
"x86_64", "ia32_on_win64", "neutral", "arm64", "arm32_on_win64", "ia32_on_arm64"
};
typedef struct {
union {
| | | | | | | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
static const char *const processors[NUMPROCESSORS] = {
"i686", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
"x86_64", "ia32_on_win64", "neutral", "arm64", "arm32_on_win64", "ia32_on_arm64"
};
typedef struct {
union {
unsigned int dwOemId;
struct {
int wProcessorArchitecture;
int wReserved;
};
};
unsigned int dwPageSize;
void *lpMinimumApplicationAddress;
void *lpMaximumApplicationAddress;
void *dwActiveProcessorMask;
unsigned int dwNumberOfProcessors;
unsigned int dwProcessorType;
|
| ︙ | ︙ | |||
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 |
static const char *
SearchKnownEncodings(
const char *encoding)
{
int left = 0;
int right = sizeof(localeTable)/sizeof(LocaleTable);
while (left < right) {
int test = (left + right)/2;
int code = strcmp(localeTable[test].lang, encoding);
if (code == 0) {
return localeTable[test].encoding;
}
if (code < 0) {
left = test+1;
} else {
| > > > > | | 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 |
static const char *
SearchKnownEncodings(
const char *encoding)
{
int left = 0;
int right = sizeof(localeTable)/sizeof(LocaleTable);
/* Here, search for i in the interval left <= i < right. */
while (left < right) {
int test = (left + right)/2;
int code = strcmp(localeTable[test].lang, encoding);
if (code == 0) {
/* Found it at i == test. */
return localeTable[test].encoding;
}
if (code < 0) {
/* Restrict the search to the interval test < i < right. */
left = test+1;
} else {
/* Restrict the search to the interval left <= i < test. */
right = test;
}
}
return NULL;
}
const char *
Tcl_GetEncodingNameFromEnvironment(
|
| ︙ | ︙ | |||
856 857 858 859 860 861 862 |
p = q+1;
}
if (*p) {
Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(p, -1));
}
Tcl_ObjSetVar2(interp, Tcl_NewStringObj("tcl_pkgPath", -1), NULL, pkgListObj, TCL_GLOBAL_ONLY);
{
| | | | | | | | | | 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 |
p = q+1;
}
if (*p) {
Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(p, -1));
}
Tcl_ObjSetVar2(interp, Tcl_NewStringObj("tcl_pkgPath", -1), NULL, pkgListObj, TCL_GLOBAL_ONLY);
{
/* Some platforms build configure scripts expect ~ expansion so do that */
Tcl_Obj *origPaths;
Tcl_Obj *resolvedPaths;
origPaths = Tcl_GetVar2Ex(interp, "tcl_pkgPath", NULL, TCL_GLOBAL_ONLY);
resolvedPaths = TclResolveTildePathList(origPaths);
if (resolvedPaths != origPaths && resolvedPaths != NULL) {
Tcl_SetVar2Ex(interp, "tcl_pkgPath", NULL, resolvedPaths, TCL_GLOBAL_ONLY);
}
}
#ifdef DJGPP
Tcl_SetVar2(interp, "tcl_platform", "platform", "dos", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "tcl_platform", "platform", "unix", TCL_GLOBAL_ONLY);
#endif
|
| ︙ | ︙ |
Changes to unix/tclUnixPipe.c.
| ︙ | ︙ | |||
424 425 426 427 428 429 430 |
Tcl_Pid *pidPtr) /* If this function is successful, pidPtr is
* filled with the process id of the child
* process. */
{
TclFile errPipeIn, errPipeOut;
int count, status, fd;
char errSpace[200 + TCL_INTEGER_SPACE];
| | | | 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
Tcl_Pid *pidPtr) /* If this function is successful, pidPtr is
* filled with the process id of the child
* process. */
{
TclFile errPipeIn, errPipeOut;
int count, status, fd;
char errSpace[200 + TCL_INTEGER_SPACE];
Tcl_DString *volatile dsArray;
char **volatile newArgv;
int pid;
size_t i;
#if defined(HAVE_POSIX_SPAWNP)
int childErrno;
static int use_spawn = -1;
#endif
|
| ︙ | ︙ | |||
1376 1377 1378 1379 1380 1381 1382 |
{
Tcl_Channel chan;
PipeState *pipePtr;
size_t i;
Tcl_Obj *resultPtr;
if (objc > 2) {
| | | 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 |
{
Tcl_Channel chan;
PipeState *pipePtr;
size_t i;
Tcl_Obj *resultPtr;
if (objc > 2) {
Tcl_WrongNumArgs(interp, 1, objv, "?channel?");
return TCL_ERROR;
}
if (objc == 1) {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(getpid()));
} else {
/*
|
| ︙ | ︙ |
Changes to unix/tclUnixSock.c.
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
TcpFdList fds; /* The file descriptors of the sockets. */
int interest; /* Event types of interest */
/*
* Only needed for server sockets
*/
| | < | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
TcpFdList fds; /* The file descriptors of the sockets. */
int interest; /* Event types of interest */
/*
* Only needed for server sockets
*/
Tcl_TcpAcceptProc *acceptProc; /* Proc to call on accept. */
void *acceptProcData; /* The data for the accept proc. */
/*
* Only needed for client sockets
*/
struct addrinfo *addrlist; /* Addresses to connect to. */
|
| ︙ | ︙ | |||
223 224 225 226 227 228 229 |
#ifndef NO_UNAME
struct utsname u;
struct hostent *hp;
memset(&u, (int) 0, sizeof(struct utsname));
if (uname(&u) >= 0) { /* INTL: Native. */
| | | | | | 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 |
#ifndef NO_UNAME
struct utsname u;
struct hostent *hp;
memset(&u, (int) 0, sizeof(struct utsname));
if (uname(&u) >= 0) { /* INTL: Native. */
hp = TclpGetHostByName(u.nodename); /* INTL: Native. */
if (hp == NULL) {
/*
* Sometimes the nodename is fully qualified, but gets truncated
* as it exceeds SYS_NMLN. See if we can just get the immediate
* nodename and get a proper answer that way.
*/
char *dot = strchr(u.nodename, '.');
if (dot != NULL) {
char *node = (char *)Tcl_Alloc(dot - u.nodename + 1);
memcpy(node, u.nodename, dot - u.nodename);
node[dot - u.nodename] = '\0';
hp = TclpGetHostByName(node);
Tcl_Free(node);
}
}
if (hp != NULL) {
native = hp->h_name;
} else {
native = u.nodename;
}
}
#else /* !NO_UNAME */
/*
* Uname doesn't exist; try gethostname instead.
*
* There is no portable macro for the maximum length of host names
* returned by gethostbyname(). We should only trust SYS_NMLN if it is at
|
| ︙ | ︙ | |||
366 367 368 369 370 371 372 |
if (mode == TCL_MODE_BLOCKING) {
CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING);
} else {
SET_BITS(statePtr->flags, TCP_NONBLOCKING);
}
if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
| | | | 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
if (mode == TCL_MODE_BLOCKING) {
CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING);
} else {
SET_BITS(statePtr->flags, TCP_NONBLOCKING);
}
if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
statePtr->cachedBlocking = mode;
return 0;
}
if (TclUnixSetBlockingMode(statePtr->fds.fd, mode) < 0) {
return errno;
}
return 0;
}
|
| ︙ | ︙ | |||
439 440 441 442 443 444 445 |
* In socket test mode do not continue with the connect.
* Exceptions are:
* - Call by recv/send and blocking socket
* (errorCodePtr != NULL && !GOT_BITS(flags, TCP_NONBLOCKING))
*/
if (GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE)
| | | | | | | | | | | | | | | | | | | | | 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 482 |
* In socket test mode do not continue with the connect.
* Exceptions are:
* - Call by recv/send and blocking socket
* (errorCodePtr != NULL && !GOT_BITS(flags, TCP_NONBLOCKING))
*/
if (GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE)
&& !(errorCodePtr != NULL
&& !GOT_BITS(statePtr->flags, TCP_NONBLOCKING))) {
*errorCodePtr = EWOULDBLOCK;
return -1;
}
if (errorCodePtr == NULL || GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
timeout = 0;
} else {
timeout = -1;
}
do {
if (TclUnixWaitForFile(statePtr->fds.fd,
TCL_WRITABLE | TCL_EXCEPTION, timeout) != 0) {
TcpConnect(NULL, statePtr);
}
/*
* Do this only once in the nonblocking case and repeat it until the
* socket is final when blocking.
*/
} while (timeout == -1 && GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT));
if (errorCodePtr != NULL) {
if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
*errorCodePtr = EAGAIN;
return -1;
} else if (statePtr->connectError != 0) {
*errorCodePtr = ENOTCONN;
return -1;
}
}
return 0;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
623 624 625 626 627 628 629 |
while (fds != NULL) {
TcpFdList *next = fds->next;
Tcl_Free(fds);
fds = next;
}
if (statePtr->addrlist != NULL) {
| | | | 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 |
while (fds != NULL) {
TcpFdList *next = fds->next;
Tcl_Free(fds);
fds = next;
}
if (statePtr->addrlist != NULL) {
freeaddrinfo(statePtr->addrlist);
}
if (statePtr->myaddrlist != NULL) {
freeaddrinfo(statePtr->myaddrlist);
}
Tcl_Free(statePtr);
return errorCode;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ | |||
702 703 704 705 706 707 708 |
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
static inline int
IPv6AddressNeedsNumericRendering(
struct in6_addr addr)
{
if (IN6_ARE_ADDR_EQUAL(&addr, &in6addr_any)) {
| | | | | | | | | | | | | | | | | | | | | | | 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 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 |
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
static inline int
IPv6AddressNeedsNumericRendering(
struct in6_addr addr)
{
if (IN6_ARE_ADDR_EQUAL(&addr, &in6addr_any)) {
return 1;
}
/*
* The IN6_IS_ADDR_V4MAPPED macro has a problem with aliasing warnings on
* at least some versions of OSX.
*/
if (!IN6_IS_ADDR_V4MAPPED(&addr)) {
return 0;
}
return (addr.s6_addr[12] == 0 && addr.s6_addr[13] == 0
&& addr.s6_addr[14] == 0 && addr.s6_addr[15] == 0);
}
#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic pop
#endif
#endif /* NEED_FAKE_RFC2553 */
static void
TcpHostPortList(
Tcl_Interp *interp,
Tcl_DString *dsPtr,
address addr,
socklen_t salen)
{
#define SUPPRESS_RDNS_VAR "::tcl::unsupported::noReverseDNS"
char host[NI_MAXHOST], nhost[NI_MAXHOST], nport[NI_MAXSERV];
int flags = 0;
getnameinfo(&addr.sa, salen, nhost, sizeof(nhost), nport, sizeof(nport),
NI_NUMERICHOST | NI_NUMERICSERV);
Tcl_DStringAppendElement(dsPtr, nhost);
/*
* We don't want to resolve INADDR_ANY and sin6addr_any; they can
* sometimes cause problems (and never have a name).
*/
if (addr.sa.sa_family == AF_INET) {
if (addr.sa4.sin_addr.s_addr == INADDR_ANY) {
flags |= NI_NUMERICHOST;
}
#ifndef NEED_FAKE_RFC2553
} else if (addr.sa.sa_family == AF_INET6) {
if (IPv6AddressNeedsNumericRendering(addr.sa6.sin6_addr)) {
flags |= NI_NUMERICHOST;
}
#endif /* NEED_FAKE_RFC2553 */
}
/*
* Check if reverse DNS has been switched off globally.
*/
if (interp != NULL &&
Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
flags |= NI_NUMERICHOST;
}
if (getnameinfo(&addr.sa, salen, host, sizeof(host), NULL, 0,
flags) == 0) {
/*
* Reverse mapping worked.
*/
Tcl_DStringAppendElement(dsPtr, host);
} else {
/*
* Reverse mapping failed - use the numeric rep once more.
*/
Tcl_DStringAppendElement(dsPtr, nhost);
}
Tcl_DStringAppendElement(dsPtr, nport);
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
903 904 905 906 907 908 909 |
}
if ((len > 1) && (optionName[1] == 'e') &&
(strncmp(optionName, "-error", len) == 0)) {
socklen_t optlen = sizeof(int);
WaitForConnect(statePtr, NULL);
| | | | | | | | | | | | | | | | | | | | | 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 |
}
if ((len > 1) && (optionName[1] == 'e') &&
(strncmp(optionName, "-error", len) == 0)) {
socklen_t optlen = sizeof(int);
WaitForConnect(statePtr, NULL);
if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
/*
* Suppress errors as long as we are not done.
*/
errno = 0;
} else if (statePtr->connectError != 0) {
errno = statePtr->connectError;
statePtr->connectError = 0;
} else {
int err;
getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &err,
&optlen);
errno = err;
}
if (errno != 0) {
Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(errno), TCL_INDEX_NONE);
}
return TCL_OK;
}
if ((len > 1) && (optionName[1] == 'c') &&
(strncmp(optionName, "-connecting", len) == 0)) {
WaitForConnect(statePtr, NULL);
Tcl_DStringAppend(dsPtr,
GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT) ? "1" : "0", TCL_INDEX_NONE);
return TCL_OK;
}
if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
(strncmp(optionName, "-peername", len) == 0))) {
address peername;
socklen_t size = sizeof(peername);
WaitForConnect(statePtr, NULL);
if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
/*
* In async connect output an empty string
*/
|
| ︙ | ︙ | |||
959 960 961 962 963 964 965 |
* Peername fetch succeeded - output list
*/
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-peername");
Tcl_DStringStartSublist(dsPtr);
}
| | | | | | | 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 |
* Peername fetch succeeded - output list
*/
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-peername");
Tcl_DStringStartSublist(dsPtr);
}
TcpHostPortList(interp, dsPtr, peername, size);
if (len) {
return TCL_OK;
}
Tcl_DStringEndSublist(dsPtr);
} else {
/*
* getpeername failed - but if we were asked for all the options
* (len==0), don't flag an error at that point because it could be
* an fconfigure request on a server socket (which have no peer).
* Same must be done on win&mac.
*/
if (len) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't get peername: %s",
Tcl_PosixError(interp)));
}
return TCL_ERROR;
}
}
}
|
| ︙ | ︙ | |||
1000 1001 1002 1003 1004 1005 1006 |
Tcl_DStringStartSublist(dsPtr);
}
if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
/*
* In async connect output an empty string
*/
| | | | | | | | | | | | | 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 |
Tcl_DStringStartSublist(dsPtr);
}
if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
/*
* In async connect output an empty string
*/
found = 1;
} else {
for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
size = sizeof(sockname);
if (getsockname(fds->fd, &(sockname.sa), &size) >= 0) {
found = 1;
TcpHostPortList(interp, dsPtr, sockname, size);
}
}
}
if (found) {
if (len) {
return TCL_OK;
}
Tcl_DStringEndSublist(dsPtr);
} else {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't get sockname: %s", Tcl_PosixError(interp)));
}
return TCL_ERROR;
}
}
if ((len == 0) || ((len > 1) && (optionName[1] == 'k') &&
(strncmp(optionName, "-keepalive", len) == 0))) {
int opt = 0;
|
| ︙ | ︙ | |||
1066 1067 1068 1069 1070 1071 1072 |
if (len > 0) {
return TCL_OK;
}
}
if (len > 0) {
return Tcl_BadChannelOption(interp, optionName,
| | | 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 |
if (len > 0) {
return TCL_OK;
}
}
if (len > 0) {
return Tcl_BadChannelOption(interp, optionName,
"connecting keepalive nodelay peername sockname");
}
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
|
| ︙ | ︙ | |||
1173 1174 1175 1176 1177 1178 1179 |
int mask) /* Events of interest; an OR-ed combination of
* TCL_READABLE, TCL_WRITABLE and
* TCL_EXCEPTION. */
{
TcpState *statePtr = (TcpState *)instanceData;
if (statePtr->acceptProc != NULL) {
| | | | | | | | | | | | 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 |
int mask) /* Events of interest; an OR-ed combination of
* TCL_READABLE, TCL_WRITABLE and
* TCL_EXCEPTION. */
{
TcpState *statePtr = (TcpState *)instanceData;
if (statePtr->acceptProc != NULL) {
/*
* Make sure we don't mess with server sockets since they will never
* be readable or writable at the Tcl level. This keeps Tcl scripts
* from interfering with the -accept behavior (bug #3394732).
*/
return;
}
if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
/*
* Async sockets use a FileHandler internally while connecting, so we
* need to cache this request until the connection has succeeded.
*/
statePtr->filehandlers = mask;
} else if (mask) {
/*
* Whether it is a bug or feature or otherwise, it is a fact of life
* that on at least some Linux kernels select() fails to report that a
* socket file descriptor is writable when the other end of the socket
* is closed. This is in contrast to the guarantees Tcl makes that
|
| ︙ | ︙ | |||
1310 1311 1312 1313 1314 1315 1316 |
socklen_t optlen;
int async_callback = GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING);
int ret = -1, error = EHOSTUNREACH;
int async = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
static const int reuseaddr = 1;
if (async_callback) {
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 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 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 |
socklen_t optlen;
int async_callback = GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING);
int ret = -1, error = EHOSTUNREACH;
int async = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
static const int reuseaddr = 1;
if (async_callback) {
goto reenter;
}
for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL;
statePtr->addr = statePtr->addr->ai_next) {
for (statePtr->myaddr = statePtr->myaddrlist;
statePtr->myaddr != NULL;
statePtr->myaddr = statePtr->myaddr->ai_next) {
/*
* No need to try combinations of local and remote addresses of
* different families.
*/
if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) {
continue;
}
/*
* Close the socket if it is still open from the last unsuccessful
* iteration.
*/
if (statePtr->fds.fd >= 0) {
close(statePtr->fds.fd);
statePtr->fds.fd = -1;
errno = 0;
}
statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM,
0);
if (statePtr->fds.fd < 0) {
continue;
}
/*
* Set the close-on-exec flag so that the socket will not get
* inherited by child processes.
*/
fcntl(statePtr->fds.fd, F_SETFD, FD_CLOEXEC);
/*
* Set kernel space buffering
*/
TclSockMinimumBuffers(INT2PTR(statePtr->fds.fd), SOCKET_BUFSIZE);
if (async) {
ret = TclUnixSetBlockingMode(statePtr->fds.fd,
TCL_MODE_NONBLOCKING);
if (ret < 0) {
continue;
}
}
/*
* Must reset the error variable here, before we use it for the
* first time in this iteration.
*/
error = 0;
(void) setsockopt(statePtr->fds.fd, SOL_SOCKET, SO_REUSEADDR,
(char *) &reuseaddr, sizeof(reuseaddr));
ret = bind(statePtr->fds.fd, statePtr->myaddr->ai_addr,
statePtr->myaddr->ai_addrlen);
if (ret < 0) {
error = errno;
continue;
}
/*
* Attempt to connect. The connect may fail at present with an
* EINPROGRESS but at a later time it will complete. The caller
* will set up a file handler on the socket if she is interested
* in being informed when the connect completes.
*/
ret = connect(statePtr->fds.fd, statePtr->addr->ai_addr,
statePtr->addr->ai_addrlen);
if (ret < 0) {
error = errno;
}
if (ret < 0 && errno == EINPROGRESS) {
Tcl_CreateFileHandler(statePtr->fds.fd,
TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback,
statePtr);
errno = EWOULDBLOCK;
SET_BITS(statePtr->flags, TCP_ASYNC_PENDING);
return TCL_OK;
reenter:
CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING);
Tcl_DeleteFileHandler(statePtr->fds.fd);
/*
* Read the error state from the socket to see if the async
* connection has succeeded or failed. As this clears the
* error condition, we cache the status in the socket state
* struct for later retrieval by [fconfigure -error].
*/
optlen = sizeof(int);
getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR,
(char *) &error, &optlen);
errno = error;
}
if (error == 0) {
goto out;
}
}
}
out:
statePtr->connectError = error;
CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
if (async_callback) {
/*
* An asynchonous connection has finally succeeded or failed.
*/
TcpWatchProc(statePtr, statePtr->filehandlers);
TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);
if (error != 0) {
SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
}
/*
* We need to forward the writable event that brought us here, because
* upon reading of getsockopt(SO_ERROR), at least some OSes clear the
* writable state from the socket, and so a subsequent select() on
* behalf of a script level [fileevent] would not fire. It doesn't
* hurt that this is also called in the successful case and will save
* the event mechanism one roundtrip through select().
*/
if (statePtr->cachedBlocking == TCL_MODE_NONBLOCKING) {
Tcl_NotifyChannel(statePtr->channel, TCL_WRITABLE);
}
}
if (error != 0) {
/*
* Failure for either a synchronous connection, or an async one that
* failed before it could enter background mode, e.g. because an
* invalid -myaddr was given.
*/
if (interp != NULL) {
errno = error;
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't open socket: %s", Tcl_PosixError(interp)));
}
return TCL_ERROR;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
1507 1508 1509 1510 1511 1512 1513 |
char channelName[SOCK_CHAN_LENGTH];
/*
* Do the name lookups for the local and remote addresses.
*/
if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg)
| | | | | | | | | | | | | | | 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 |
char channelName[SOCK_CHAN_LENGTH];
/*
* Do the name lookups for the local and remote addresses.
*/
if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg)
|| !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
&errorMsg)) {
if (addrlist != NULL) {
freeaddrinfo(addrlist);
}
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"couldn't open socket: %s", errorMsg));
}
return NULL;
}
/*
* Allocate a new TcpState for this socket.
*/
statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
statePtr->flags = async ? TCP_ASYNC_CONNECT : 0;
statePtr->cachedBlocking = TCL_MODE_BLOCKING;
statePtr->addrlist = addrlist;
statePtr->myaddrlist = myaddrlist;
statePtr->fds.fd = -1;
/*
* Create a new client socket and wrap it in a channel.
*/
if (TcpConnect(interp, statePtr) != TCL_OK) {
TcpCloseProc(statePtr, NULL);
return NULL;
}
snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(statePtr));
statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
statePtr, TCL_READABLE | TCL_WRITABLE);
if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation",
"auto crlf") == TCL_ERROR) {
Tcl_CloseEx(NULL, statePtr->channel, 0);
return NULL;
}
return statePtr->channel;
}
|
| ︙ | ︙ | |||
1573 1574 1575 1576 1577 1578 1579 |
*/
Tcl_Channel
Tcl_MakeTcpClientChannel(
void *sock) /* The socket to wrap up into a channel. */
{
return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock,
| | | 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 |
*/
Tcl_Channel
Tcl_MakeTcpClientChannel(
void *sock) /* The socket to wrap up into a channel. */
{
return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock,
TCL_READABLE | TCL_WRITABLE);
}
/*
*----------------------------------------------------------------------
*
* TclpMakeTcpClientChannelMode --
*
|
| ︙ | ︙ | |||
1680 1681 1682 1683 1684 1685 1686 |
*/
int retry = 0;
#define MAXRETRY 10
repeat:
if (retry > 0) {
| | | | | | | | | | | | | | | 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 |
*/
int retry = 0;
#define MAXRETRY 10
repeat:
if (retry > 0) {
if (statePtr != NULL) {
TcpCloseProc(statePtr, NULL);
statePtr = NULL;
}
if (addrlist != NULL) {
freeaddrinfo(addrlist);
addrlist = NULL;
}
if (retry >= MAXRETRY) {
goto error;
}
}
retry++;
chosenport = 0;
if (TclSockGetPort(interp, service, "tcp", &port) != TCL_OK) {
errorMsg = "invalid port number";
goto error;
}
if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1,
&errorMsg)) {
my_errno = errno;
goto error;
}
for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) {
sock = socket(addrPtr->ai_family, addrPtr->ai_socktype,
addrPtr->ai_protocol);
if (sock == -1) {
if (howfar < SOCKET) {
howfar = SOCKET;
my_errno = errno;
}
continue;
}
|
| ︙ | ︙ | |||
1756 1757 1758 1759 1760 1761 1762 | #else optvalue = 1; (void) setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *) &optvalue, sizeof(optvalue)); #endif } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 |
#else
optvalue = 1;
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
(char *) &optvalue, sizeof(optvalue));
#endif
}
/*
* Make sure we use the same port number when opening two server
* sockets for IPv4 and IPv6 on a random port.
*
* As sockaddr_in6 uses the same offset and size for the port member
* as sockaddr_in, we can handle both through the IPv4 API.
*/
if (port == 0 && chosenport != 0) {
((struct sockaddr_in *) addrPtr->ai_addr)->sin_port =
htons(chosenport);
}
#ifdef IPV6_V6ONLY
/*
* Missing on: Solaris 2.8
*/
if (addrPtr->ai_family == AF_INET6) {
int v6only = 1;
(void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
&v6only, sizeof(v6only));
}
#endif /* IPV6_V6ONLY */
status = bind(sock, addrPtr->ai_addr, addrPtr->ai_addrlen);
if (status == -1) {
if (howfar < BIND) {
howfar = BIND;
my_errno = errno;
}
close(sock);
sock = -1;
if (port == 0 && errno == EADDRINUSE) {
goto repeat;
}
continue;
}
if (port == 0 && chosenport == 0) {
address sockname;
socklen_t namelen = sizeof(sockname);
/*
* Synchronize port numbers when binding to port 0 of multiple
* addresses.
*/
if (getsockname(sock, &sockname.sa, &namelen) >= 0) {
chosenport = ntohs(sockname.sa4.sin_port);
}
}
if (backlog < 0) {
backlog = SOMAXCONN;
}
status = listen(sock, backlog);
if (status < 0) {
if (howfar < LISTEN) {
howfar = LISTEN;
my_errno = errno;
}
close(sock);
sock = -1;
if (port == 0 && errno == EADDRINUSE) {
goto repeat;
}
continue;
}
if (statePtr == NULL) {
/*
* Allocate a new TcpState for this socket.
*/
statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState));
memset(statePtr, 0, sizeof(TcpState));
statePtr->acceptProc = acceptProc;
statePtr->acceptProcData = acceptProcData;
snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(statePtr));
newfds = &statePtr->fds;
} else {
newfds = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
memset(newfds, (int) 0, sizeof(TcpFdList));
fds->next = newfds;
}
newfds->fd = sock;
newfds->statePtr = statePtr;
fds = newfds;
/*
* Set up the callback mechanism for accepting connections from new
* clients.
*/
Tcl_CreateFileHandler(sock, TCL_READABLE, TcpAccept, fds);
}
error:
if (addrlist != NULL) {
freeaddrinfo(addrlist);
}
if (statePtr != NULL) {
statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
statePtr, 0);
return statePtr->channel;
}
if (interp != NULL) {
Tcl_Obj *errorObj = Tcl_NewStringObj("couldn't open socket: ", TCL_INDEX_NONE);
if (errorMsg == NULL) {
errno = my_errno;
Tcl_AppendToObj(errorObj, Tcl_PosixError(interp), TCL_INDEX_NONE);
} else {
Tcl_AppendToObj(errorObj, errorMsg, TCL_INDEX_NONE);
}
Tcl_SetObjResult(interp, errorObj);
}
if (sock != -1) {
close(sock);
}
return NULL;
}
|
| ︙ | ︙ | |||
1934 1935 1936 1937 1938 1939 1940 |
newSockState, TCL_READABLE | TCL_WRITABLE);
Tcl_SetChannelOption(NULL, newSockState->channel, "-translation",
"auto crlf");
if (fds->statePtr->acceptProc != NULL) {
getnameinfo(&addr.sa, len, host, sizeof(host), port, sizeof(port),
| | | | 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 |
newSockState, TCL_READABLE | TCL_WRITABLE);
Tcl_SetChannelOption(NULL, newSockState->channel, "-translation",
"auto crlf");
if (fds->statePtr->acceptProc != NULL) {
getnameinfo(&addr.sa, len, host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST|NI_NUMERICSERV);
fds->statePtr->acceptProc(fds->statePtr->acceptProcData,
newSockState->channel, host, atoi(port));
}
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* tab-width: 8
* indent-tabs-mode: nil
* End:
*/
|
Changes to win/Makefile.in.
| ︙ | ︙ | |||
315 316 317 318 319 320 321 322 323 324 325 326 327 328 | tclFCmd.$(OBJEXT) \ tclFileName.$(OBJEXT) \ tclGet.$(OBJEXT) \ tclHAMT.$(OBJEXT) \ tclHAMTObj.$(OBJEXT) \ tclHash.$(OBJEXT) \ tclHistory.$(OBJEXT) \ tclIndexObj.$(OBJEXT) \ tclInterp.$(OBJEXT) \ tclIO.$(OBJEXT) \ tclIOCmd.$(OBJEXT) \ tclIOGT.$(OBJEXT) \ tclIORChan.$(OBJEXT) \ tclIORTrans.$(OBJEXT) \ | > | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | tclFCmd.$(OBJEXT) \ tclFileName.$(OBJEXT) \ tclGet.$(OBJEXT) \ tclHAMT.$(OBJEXT) \ tclHAMTObj.$(OBJEXT) \ tclHash.$(OBJEXT) \ tclHistory.$(OBJEXT) \ tclIcu.$(OBJEXT) \ tclIndexObj.$(OBJEXT) \ tclInterp.$(OBJEXT) \ tclIO.$(OBJEXT) \ tclIOCmd.$(OBJEXT) \ tclIOGT.$(OBJEXT) \ tclIORChan.$(OBJEXT) \ tclIORTrans.$(OBJEXT) \ |
| ︙ | ︙ |
Changes to win/makefile.vc.
| ︙ | ︙ | |||
276 277 278 279 280 281 282 283 284 285 286 287 288 289 | $(TMP_DIR)\tclFCmd.obj \ $(TMP_DIR)\tclFileName.obj \ $(TMP_DIR)\tclGet.obj \ $(TMP_DIR)\tclHash.obj \ $(TMP_DIR)\tclHAMT.obj \ $(TMP_DIR)\tclHAMTObj.obj \ $(TMP_DIR)\tclHistory.obj \ $(TMP_DIR)\tclIndexObj.obj \ $(TMP_DIR)\tclInterp.obj \ $(TMP_DIR)\tclIO.obj \ $(TMP_DIR)\tclIOCmd.obj \ $(TMP_DIR)\tclIOGT.obj \ $(TMP_DIR)\tclIOSock.obj \ $(TMP_DIR)\tclIOUtil.obj \ | > | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | $(TMP_DIR)\tclFCmd.obj \ $(TMP_DIR)\tclFileName.obj \ $(TMP_DIR)\tclGet.obj \ $(TMP_DIR)\tclHash.obj \ $(TMP_DIR)\tclHAMT.obj \ $(TMP_DIR)\tclHAMTObj.obj \ $(TMP_DIR)\tclHistory.obj \ $(TMP_DIR)\tclIcu.obj \ $(TMP_DIR)\tclIndexObj.obj \ $(TMP_DIR)\tclInterp.obj \ $(TMP_DIR)\tclIO.obj \ $(TMP_DIR)\tclIOCmd.obj \ $(TMP_DIR)\tclIOGT.obj \ $(TMP_DIR)\tclIOSock.obj \ $(TMP_DIR)\tclIOUtil.obj \ |
| ︙ | ︙ |
Changes to win/nmakehlp.c.
| ︙ | ︙ | |||
86 87 88 89 90 91 92 |
SetEnvironmentVariable("LINK", "");
if (argc > 1 && *argv[1] == '-') {
switch (*(argv[1]+1)) {
case 'c':
if (argc != 3) {
chars = snprintf(msg, sizeof(msg) - 1,
| | | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
SetEnvironmentVariable("LINK", "");
if (argc > 1 && *argv[1] == '-') {
switch (*(argv[1]+1)) {
case 'c':
if (argc != 3) {
chars = snprintf(msg, sizeof(msg) - 1,
"usage: %s -c <compiler option>\n"
"Tests for whether cl.exe supports an option\n"
"exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars,
&dwWritten, NULL);
return 2;
}
return CheckForCompilerFeature(argv[2]);
|
| ︙ | ︙ | |||
267 268 269 270 271 272 273 |
NULL, /* Use parent's starting directory. */
&si, /* Pointer to STARTUPINFO structure. */
&pi); /* Pointer to PROCESS_INFORMATION structure. */
if (!ok) {
DWORD err = GetLastError();
int chars = snprintf(msg, sizeof(msg) - 1,
| | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
NULL, /* Use parent's starting directory. */
&si, /* Pointer to STARTUPINFO structure. */
&pi); /* Pointer to PROCESS_INFORMATION structure. */
if (!ok) {
DWORD err = GetLastError();
int chars = snprintf(msg, sizeof(msg) - 1,
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
(300-chars), 0);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
return 2;
}
|
| ︙ | ︙ | |||
314 315 316 317 318 319 320 |
/*
* Look for the commandline warning code in both streams.
* - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
*/
return !(strstr(Out.buffer, "D4002") != NULL
| | | | | | | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
/*
* Look for the commandline warning code in both streams.
* - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002.
*/
return !(strstr(Out.buffer, "D4002") != NULL
|| strstr(Err.buffer, "D4002") != NULL
|| strstr(Out.buffer, "D9002") != NULL
|| strstr(Err.buffer, "D9002") != NULL
|| strstr(Out.buffer, "D2021") != NULL
|| strstr(Err.buffer, "D2021") != NULL);
}
static int
CheckForLinkerFeature(
char **options,
int count)
{
|
| ︙ | ︙ | |||
401 402 403 404 405 406 407 |
NULL, /* Use parent's starting directory. */
&si, /* Pointer to STARTUPINFO structure. */
&pi); /* Pointer to PROCESS_INFORMATION structure. */
if (!ok) {
DWORD err = GetLastError();
int chars = snprintf(msg, sizeof(msg) - 1,
| | | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
NULL, /* Use parent's starting directory. */
&si, /* Pointer to STARTUPINFO structure. */
&pi); /* Pointer to PROCESS_INFORMATION structure. */
if (!ok) {
DWORD err = GetLastError();
int chars = snprintf(msg, sizeof(msg) - 1,
"Tried to launch: \"%s\", but got error [%u]: ", cmdline, err);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPSTR)&msg[chars],
(300-chars), 0);
WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL);
return 2;
}
|
| ︙ | ︙ | |||
596 597 598 599 600 601 602 | * option here to handle autoconf style substitutions. * The substitution file is whitespace and line delimited. The file should * consist of lines matching the regular expression: * \s*\S+\s+\S*$ * * Usage is something like: * nmakehlp -S << $** > $@ | | | | | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
* option here to handle autoconf style substitutions.
* The substitution file is whitespace and line delimited. The file should
* consist of lines matching the regular expression:
* \s*\S+\s+\S*$
*
* Usage is something like:
* nmakehlp -S << $** > $@
* @PACKAGE_NAME@ $(PACKAGE_NAME)
* @PACKAGE_VERSION@ $(PACKAGE_VERSION)
* <<
*/
static int
SubstituteFile(
const char *substitutions,
const char *filename)
{
|
| ︙ | ︙ | |||
726 727 728 729 730 731 732 |
int keylen, ret;
WIN32_FIND_DATA finfo;
if (dir == NULL || keypath == NULL) {
return 2; /* Have no real error reporting mechanism into nmake */
}
dirlen = strlen(dir);
| | | > | > | > | | | | | | | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 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 |
int keylen, ret;
WIN32_FIND_DATA finfo;
if (dir == NULL || keypath == NULL) {
return 2; /* Have no real error reporting mechanism into nmake */
}
dirlen = strlen(dir);
if ((dirlen + 3) > sizeof(path)) {
return 2;
}
strncpy(path, dir, dirlen);
strncpy(path+dirlen, "\\*", 3); /* Including terminating \0 */
keylen = strlen(keypath);
#if 0 /* This function is not available in Visual C++ 6 */
/*
* Use numerics 0 -> FindExInfoStandard,
* 1 -> FindExSearchLimitToDirectories,
* as these are not defined in Visual C++ 6
*/
hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0);
#else
hSearch = FindFirstFile(path, &finfo);
#endif
if (hSearch == INVALID_HANDLE_VALUE) {
return 1; /* Not found */
}
/* Loop through all subdirs checking if the keypath is under there */
ret = 1; /* Assume not found */
do {
int sublen;
/*
* We need to check it is a directory despite the
* FindExSearchLimitToDirectories in the above call. See SDK docs
*/
if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
continue;
}
sublen = strlen(finfo.cFileName);
if ((dirlen+1+sublen+1+keylen+1) > sizeof(path)) {
continue; /* Path does not fit, assume not matched */
}
strncpy(path+dirlen+1, finfo.cFileName, sublen);
path[dirlen+1+sublen] = '\\';
strncpy(path+dirlen+1+sublen+1, keypath, keylen+1);
if (FileExists(path)) {
/* Found a match, print to stdout */
path[dirlen+1+sublen] = '\0';
QualifyPath(path);
ret = 0;
break;
}
} while (FindNextFile(hSearch, &finfo));
FindClose(hSearch);
return ret;
}
/*
* LocateDependency --
*
* Locates a dependency for a package.
* keypath - a relative path within the package directory
* that is used to confirm it is the correct directory.
* The search path for the package directory is currently only
* the parent and grandparent of the current working directory.
* If found, the command prints
* name_DIRPATH=<full path of located directory>
* and returns 0. If not found, does not print anything and returns 1.
*/
static int LocateDependency(const char *keypath)
{
size_t i;
int ret;
static const char *paths[] = {"..", "..\\..", "..\\..\\.."};
|
| ︙ | ︙ |
Changes to win/rules.vc.
| ︙ | ︙ | |||
1131 1132 1133 1134 1135 1136 1137 | STUBPREFIX = $(PROJECT)stub # # Set up paths to various Tcl executables and libraries needed by extensions # # TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc | > | > | 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 | STUBPREFIX = $(PROJECT)stub # # Set up paths to various Tcl executables and libraries needed by extensions # # TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc # TCLSCRIPTZIPNAME maintained for historical reasons TCL_ZIP_FILE = libtcl$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)$(TCL_PATCH_LETTER)$(TCL_RELEASE_SERIAL).zip TCLSCRIPTZIPNAME = $(TCL_ZIP_FILE) TKSCRIPTZIPNAME = libtk$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)$(TK_PATCH_LETTER)$(TK_RELEASE_SERIAL).zip !if $(DOING_TCL) TCLSHNAME = $(PROJECT)sh$(VERSION)$(SUFX).exe TCLSH = $(OUT_DIR)\$(TCLSHNAME) TCLIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib TCLLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) |
| ︙ | ︙ |
Changes to win/tclWinDde.c.
| ︙ | ︙ | |||
1320 1321 1322 1323 1324 1325 1326 |
enum DdeSrvOptions {
DDE_SERVERNAME_EXACT, DDE_SERVERNAME_HANDLER, DDE_SERVERNAME_LAST,
};
static const char *const ddeExecOptions[] = {
"-async", "-binary", NULL
};
enum DdeExecOptions {
| | | 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 |
enum DdeSrvOptions {
DDE_SERVERNAME_EXACT, DDE_SERVERNAME_HANDLER, DDE_SERVERNAME_LAST,
};
static const char *const ddeExecOptions[] = {
"-async", "-binary", NULL
};
enum DdeExecOptions {
DDE_EXEC_ASYNC, DDE_EXEC_BINARY
};
static const char *const ddeEvalOptions[] = {
"-async", NULL
};
static const char *const ddeReqOptions[] = {
"-binary", NULL
};
|
| ︙ | ︙ |
Changes to win/tclWinFCmd.c.
| ︙ | ︙ | |||
1707 1708 1709 1710 1711 1712 1713 | * fprintf(stderr, "%d\n", ((WCHAR *) nativeName)[0]); */ Tcl_DStringInit(&dsTemp); Tcl_WCharToUtfDString(nativeName, TCL_INDEX_NONE, &dsTemp); Tcl_DStringFree(&ds); | | | | 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 |
* fprintf(stderr, "%d\n", ((WCHAR *) nativeName)[0]);
*/
Tcl_DStringInit(&dsTemp);
Tcl_WCharToUtfDString(nativeName, TCL_INDEX_NONE, &dsTemp);
Tcl_DStringFree(&ds);
tempPath = Tcl_DStringToObj(&dsTemp);
Tcl_ListObjReplace(NULL, splitPath, i, 1, 1, &tempPath);
FindClose(handle);
}
}
*attributePtrPtr = Tcl_FSJoinPath(splitPath, TCL_INDEX_NONE);
if (splitPath != NULL) {
|
| ︙ | ︙ |
Changes to win/tclWinFile.c.
| ︙ | ︙ | |||
1434 1435 1436 1437 1438 1439 1440 |
Tcl_DStringInit(bufferPtr);
wDomain = NULL;
domain = Tcl_UtfFindFirst(name, '@');
if (domain == NULL) {
const char *ptr;
| | | | | | | | | | | | | | | | | | | 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 |
Tcl_DStringInit(bufferPtr);
wDomain = NULL;
domain = Tcl_UtfFindFirst(name, '@');
if (domain == NULL) {
const char *ptr;
/*
* Treat the current user as a special case because the general case
* below does not properly retrieve the path. The NetUserGetInfo
* call returns an empty path and the code defaults to the user's
* name in the profiles directory. On modern Windows systems, this
* is generally wrong as when the account is a Microsoft account,
* for example abcdefghi@outlook.com, the directory name is
* abcde and not abcdefghi.
*
* Note we could have just used env(USERPROFILE) here but
* the intent is to retrieve (as on Unix) the system's view
* of the home irrespective of environment settings of HOME
* and USERPROFILE.
*
* Fixing this for the general user needs more investigating but
* at least for the current user we can use a direct call.
*/
ptr = TclpGetUserName(&ds);
if (ptr != NULL && strcasecmp(name, ptr) == 0) {
HANDLE hProcess;
WCHAR buf[MAX_PATH];
DWORD nChars = sizeof(buf) / sizeof(buf[0]);
/* Sadly GetCurrentProcessToken not in Win 7 so slightly longer */
hProcess = GetCurrentProcess(); /* Need not be closed */
|
| ︙ | ︙ | |||
2050 2051 2052 2053 2054 2055 2056 |
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (fileHandle != INVALID_HANDLE_VALUE) {
BY_HANDLE_FILE_INFORMATION data;
if (GetFileInformationByHandle(fileHandle,&data) != TRUE) {
| | | | | | | | | | | | | | | | | | | 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 |
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (fileHandle != INVALID_HANDLE_VALUE) {
BY_HANDLE_FILE_INFORMATION data;
if (GetFileInformationByHandle(fileHandle,&data) != TRUE) {
fileType = GetFileType(fileHandle);
CloseHandle(fileHandle);
if (fileType != FILE_TYPE_CHAR && fileType != FILE_TYPE_DISK) {
Tcl_SetErrno(ENOENT);
return -1;
}
/*
* Mock up the expected structure
*/
memset(&data, 0, sizeof(data));
statPtr->st_atime = 0;
statPtr->st_mtime = 0;
statPtr->st_ctime = 0;
} else {
CloseHandle(fileHandle);
statPtr->st_atime = ToCTime(data.ftLastAccessTime);
statPtr->st_mtime = ToCTime(data.ftLastWriteTime);
statPtr->st_ctime = ToCTime(data.ftCreationTime);
}
attr = data.dwFileAttributes;
statPtr->st_size = ((long long) data.nFileSizeLow) |
(((long long) data.nFileSizeHigh) << 32);
/*
* On Unix, for directories, nlink apparently depends on the number of
* files in the directory. We could calculate that, but it would be a
|
| ︙ | ︙ | |||
2130 2131 2132 2133 2134 2135 2136 |
statPtr->st_mtime = ToCTime(data.ftLastWriteTime);
statPtr->st_ctime = ToCTime(data.ftCreationTime);
}
dev = NativeDev(nativePath);
mode = NativeStatMode(attr, checkLinks, NativeIsExec(nativePath));
if (fileType == FILE_TYPE_CHAR) {
| | | | | | 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 |
statPtr->st_mtime = ToCTime(data.ftLastWriteTime);
statPtr->st_ctime = ToCTime(data.ftCreationTime);
}
dev = NativeDev(nativePath);
mode = NativeStatMode(attr, checkLinks, NativeIsExec(nativePath));
if (fileType == FILE_TYPE_CHAR) {
mode &= ~S_IFMT;
mode |= S_IFCHR;
} else if (fileType == FILE_TYPE_DISK) {
mode &= ~S_IFMT;
mode |= S_IFBLK;
}
statPtr->st_dev = (dev_t) dev;
statPtr->st_ino = inode;
statPtr->st_mode = mode;
statPtr->st_nlink = nlink;
statPtr->st_uid = 0;
|
| ︙ | ︙ | |||
3276 3277 3278 3279 3280 3281 3282 |
int owned = 0;
native = (const WCHAR *)Tcl_FSGetNativePath(pathPtr);
if (GetNamedSecurityInfoW((LPWSTR) native, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION, &ownerSid, NULL, NULL, NULL,
&secd) != ERROR_SUCCESS) {
| | | | | | | | | | | | | | | | 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 |
int owned = 0;
native = (const WCHAR *)Tcl_FSGetNativePath(pathPtr);
if (GetNamedSecurityInfoW((LPWSTR) native, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION, &ownerSid, NULL, NULL, NULL,
&secd) != ERROR_SUCCESS) {
/*
* Either not a file, or we do not have access to it in which case we
* are in all likelihood not the owner.
*/
return 0;
}
/*
* Getting the current process SID is a multi-step process. We make the
* assumption that if a call fails, this process is so underprivileged it
* could not possibly own anything. Normally a process can *always* look
* up its own token.
*/
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
/*
* Find out how big the buffer needs to be.
*/
bufsz = 0;
GetTokenInformation(token, TokenUser, NULL, 0, &bufsz);
if (bufsz) {
buf = (LPBYTE)Tcl_Alloc(bufsz);
if (GetTokenInformation(token, TokenUser, buf, bufsz, &bufsz)) {
owned = EqualSid(ownerSid, ((PTOKEN_USER) buf)->User.Sid);
}
}
CloseHandle(token);
}
/*
* Free allocations and be done.
*/
if (secd) {
LocalFree(secd); /* Also frees ownerSid */
}
if (buf) {
Tcl_Free(buf);
}
return (owned != 0); /* Convert non-0 to 1 */
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
*/
|
Changes to win/tclWinInit.c.
| ︙ | ︙ | |||
512 513 514 515 516 517 518 |
if (ptr != NULL) {
Tcl_DStringAppend(&ds, ptr, TCL_INDEX_NONE);
}
if (Tcl_DStringLength(&ds) > 0) {
Tcl_SetVar2(interp, "env", "HOME", Tcl_DStringValue(&ds),
TCL_GLOBAL_ONLY);
} else {
| | | | | | | | | | 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 |
if (ptr != NULL) {
Tcl_DStringAppend(&ds, ptr, TCL_INDEX_NONE);
}
if (Tcl_DStringLength(&ds) > 0) {
Tcl_SetVar2(interp, "env", "HOME", Tcl_DStringValue(&ds),
TCL_GLOBAL_ONLY);
} else {
/* None of HOME, HOMEDRIVE, HOMEPATH exists. Try USERPROFILE */
ptr = Tcl_GetVar2(interp, "env", "USERPROFILE", TCL_GLOBAL_ONLY);
if (ptr != NULL && ptr[0]) {
Tcl_SetVar2(interp, "env", "HOME", ptr, TCL_GLOBAL_ONLY);
} else {
/* Last resort */
Tcl_SetVar2(interp, "env", "HOME", "c:\\", TCL_GLOBAL_ONLY);
}
}
}
/*
* Initialize the user name from the environment first, since this is much
* faster than asking the system.
* Note: cchUserNameLen is number of characters including nul terminator.
|
| ︙ | ︙ |
Changes to win/tclWinLoad.c.
| ︙ | ︙ | |||
86 87 88 89 90 91 92 | * Let the OS loader examine the binary search path for whatever * string the user gave us which hopefully refers to a file on the * binary path. */ Tcl_DString ds; | | | | | | | | | | | | | | | | | | 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 |
* Let the OS loader examine the binary search path for whatever
* string the user gave us which hopefully refers to a file on the
* binary path.
*/
Tcl_DString ds;
/*
* Remember the first error on load attempt to be used if the
* second load attempt below also fails.
*/
firstError = (nativeName == NULL) ?
ERROR_MOD_NOT_FOUND : GetLastError();
Tcl_DStringInit(&ds);
nativeName = Tcl_UtfToWCharDString(TclGetString(pathPtr), TCL_INDEX_NONE, &ds);
hInstance = LoadLibraryExW(nativeName, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
Tcl_DStringFree(&ds);
}
if (hInstance == NULL) {
DWORD lastError;
Tcl_Obj *errMsg;
/*
* We choose to only use the error from the second call if the first
* call failed due to the file not being found. Else stick to the
* first error for reporting purposes.
*/
if (firstError == ERROR_MOD_NOT_FOUND ||
firstError == ERROR_DLL_NOT_FOUND) {
lastError = GetLastError();
} else {
lastError = firstError;
}
errMsg = Tcl_ObjPrintf("couldn't load library \"%s\": ",
TclGetString(pathPtr));
/*
* Check for possible DLL errors. This doesn't work quite right,
* because Windows seems to only return ERROR_MOD_NOT_FOUND for just
|
| ︙ | ︙ | |||
153 154 155 156 157 158 159 | " is damaged", TCL_INDEX_NONE); break; case ERROR_DLL_INIT_FAILED: Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_INIT_FAILED", (char *)NULL); Tcl_AppendToObj(errMsg, "the library initialization" " routine failed", TCL_INDEX_NONE); break; | | | | | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
" is damaged", TCL_INDEX_NONE);
break;
case ERROR_DLL_INIT_FAILED:
Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_INIT_FAILED", (char *)NULL);
Tcl_AppendToObj(errMsg, "the library initialization"
" routine failed", TCL_INDEX_NONE);
break;
case ERROR_BAD_EXE_FORMAT:
Tcl_SetErrorCode(interp, "WIN_LOAD", "BAD_EXE_FORMAT", (char *)NULL);
Tcl_AppendToObj(errMsg, "Bad exe format. Possibly a 32/64-bit mismatch.", TCL_INDEX_NONE);
break;
default:
Tcl_WinConvertError(lastError);
Tcl_AppendToObj(errMsg, Tcl_PosixError(interp), TCL_INDEX_NONE);
}
Tcl_SetObjResult(interp, errMsg);
}
return TCL_ERROR;
}
|
| ︙ | ︙ |
Changes to win/tclWinPipe.c.
| ︙ | ︙ | |||
2758 2759 2760 2761 2762 2763 2764 |
Tcl_Channel chan;
const Tcl_ChannelType *chanTypePtr;
PipeInfo *pipePtr;
size_t i;
Tcl_Obj *resultPtr;
if (objc > 2) {
| | | 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 |
Tcl_Channel chan;
const Tcl_ChannelType *chanTypePtr;
PipeInfo *pipePtr;
size_t i;
Tcl_Obj *resultPtr;
if (objc > 2) {
Tcl_WrongNumArgs(interp, 1, objv, "?channel?");
return TCL_ERROR;
}
if (objc == 1) {
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(getpid()));
} else {
chan = Tcl_GetChannel(interp, TclGetString(objv[1]),
NULL);
|
| ︙ | ︙ |