From 5b000e5e2a256686ce691a99c2c5700a5a924346 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 21 Jun 2024 11:53:27 +0000 Subject: Eliminate "-encoding binary" in favour of "-translation binary". Meant for investigation what would happen. --- doc/chan.n | 4 +-- generic/tclIO.c | 6 +++- tests/chanio.test | 54 ++++++++++++++-------------- tests/encoding.test | 4 +-- tests/io.test | 100 ++++++++++++++++++++++++++-------------------------- tests/ioCmd.test | 3 +- 6 files changed, 87 insertions(+), 84 deletions(-) diff --git a/doc/chan.n b/doc/chan.n index c08c7e3..06108a2 100644 --- a/doc/chan.n +++ b/doc/chan.n @@ -166,7 +166,7 @@ million, allowing buffers of up to one million bytes in size. . This option is used to specify the encoding of the channel as one of the named encodings returned by \fBencoding names\fR or the special -value \fBbinary\fR, so that the data can be converted to and from +value \fB{}\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. @@ -177,7 +177,7 @@ 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 \fBbinary\fR. Tcl +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 diff --git a/generic/tclIO.c b/generic/tclIO.c index 75a9025..1aee501 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -8225,7 +8225,11 @@ Tcl_SetChannelOption( Tcl_Encoding encoding; int profile; - if ((newValue[0] == '\0') || (strcmp(newValue, "binary") == 0)) { + if (!strcmp(newValue, "binary")) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("\"-encoding binary\" is no longer supported.\n" + "please use either \"-translation binary\" or \"-encoding {}\"", TCL_INDEX_NONE)); + return TCL_ERROR; + } else if (newValue[0] == '\0') { encoding = Tcl_GetEncoding(NULL, "iso8859-1"); } else { encoding = Tcl_GetEncoding(interp, newValue); diff --git a/tests/chanio.test b/tests/chanio.test index e95a0ca..1c7f6f6 100644 --- a/tests/chanio.test +++ b/tests/chanio.test @@ -82,8 +82,8 @@ namespace eval ::tcl::test::io { if {$argv != ""} { set f [open [lindex $argv 0]] } - chan configure $f -encoding binary -translation lf -blocking 0 -eofchar \x1A - chan configure stdout -encoding binary -translation lf -buffering none + chan configure $f -encoding {} -translation lf -blocking 0 -eofchar \x1A + chan configure stdout -encoding {} -translation lf -buffering none chan event $f readable "foo $f" proc foo {f} { set x [chan read $f] @@ -117,7 +117,7 @@ test chan-io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} { set path(test1) [makeFile {} test1] test chan-io-1.6 {Tcl_WriteChars: WriteBytes} { set f [open $path(test1) w] - chan configure $f -encoding binary + chan configure $f -encoding {} chan puts -nonewline $f "a\x4D\x00" chan close $f contents $path(test1) @@ -186,7 +186,7 @@ test chan-io-1.9 {Tcl_WriteChars: WriteChars} { test chan-io-2.1 {WriteBytes} { # loop until all bytes are written set f [open $path(test1) w] - chan configure $f -encoding binary -buffersize 16 -translation crlf + chan configure $f -encoding {} -buffersize 16 -translation crlf chan puts $f "abcdefghijklmnopqrstuvwxyz" chan close $f contents $path(test1) @@ -195,7 +195,7 @@ 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 -encoding binary -buffersize 16 -translation crlf + chan configure $f -encoding {} -buffersize 16 -translation crlf chan puts -nonewline $f "123456789012345\n12" set x [list [contents $path(test1)]] chan close $f @@ -206,7 +206,7 @@ test chan-io-2.3 {WriteBytes: flush on line} -body { # \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 -encoding binary -buffering line -translation crlf + chan configure $f -encoding {} -buffering line -translation crlf chan puts -nonewline $f "\n12" contents $path(test1) } -cleanup { @@ -214,7 +214,7 @@ test chan-io-2.3 {WriteBytes: flush on line} -body { } -result "\r\n12" test chan-io-2.4 {WriteBytes: reset sawLF after each buffer} { set f [open $path(test1) w] - chan configure $f -encoding binary -buffering line -translation lf \ + chan configure $f -encoding {} -buffering line -translation lf \ -buffersize 16 chan puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz" set x [list [contents $path(test1)]] @@ -1081,7 +1081,7 @@ test chan-io-7.1 {FilterInputBytes: split up character at end of buffer} -body { 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 -encoding binary + chan configure $f -encoding {} chan puts -nonewline $f "1234567890\n123\x82\x4F\x82\x50\x82" chan close $f set f [open $path(test1)] @@ -1094,7 +1094,7 @@ 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 -encoding binary + chan configure $f -encoding {} chan puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82" chan close $f set f [open $path(test1)] @@ -1109,14 +1109,14 @@ 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 -encoding binary -buffering none + chan configure $f -encoding {} -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 -encoding binary -blocking 1 + chan configure $f -encoding {} -blocking 1 chan puts $f "\x51\x82\x52" chan configure $f -encoding shiftjis vwait [namespace which -variable x] @@ -1178,7 +1178,7 @@ test chan-io-8.4 {PeekAhead: cached data available in this buffer} -body { chan puts $f "${a}\r\nabcdef" chan close $f set f [open $path(test1)] - chan configure $f -encoding binary -translation auto + chan configure $f -encoding {} -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. @@ -1283,7 +1283,7 @@ test chan-io-11.1 {ReadBytes: want to read a lot} -body { chan puts -nonewline $f abcdefghijkl chan close $f set f [open $path(test1)] - chan configure $f -encoding binary + chan configure $f -encoding {} # here chan read $f 1000 } -cleanup { @@ -1295,7 +1295,7 @@ test chan-io-11.2 {ReadBytes: want to read all} -body { chan puts -nonewline $f abcdefghijkl chan close $f set f [open $path(test1)] - chan configure $f -encoding binary + chan configure $f -encoding {} # here chan read $f } -cleanup { @@ -1307,7 +1307,7 @@ test chan-io-11.3 {ReadBytes: allocate more space} -body { chan puts -nonewline $f abcdefghijklmnopqrstuvwxyz chan close $f set f [open $path(test1)] - chan configure $f -buffersize 16 -encoding binary + chan configure $f -buffersize 16 -encoding {} # here chan read $f } -cleanup { @@ -1319,7 +1319,7 @@ test chan-io-11.4 {ReadBytes: EOF char found} -body { chan puts $f abcdefghijklmnopqrstuvwxyz chan close $f set f [open $path(test1)] - chan configure $f -eofchar m -encoding binary + chan configure $f -eofchar m -encoding {} # here list [chan read $f] [chan eof $f] [chan read $f] [chan eof $f] } -cleanup { @@ -1365,7 +1365,7 @@ test chan-io-12.4 {ReadChars: split-up char} -setup { } -constraints {stdio testchannel fileevent} -body { # (srcRead == 0) set f [openpipe w+ $path(cat)] - chan configure $f -encoding binary -buffering none -buffersize 16 + chan configure $f -encoding {} -buffering none -buffersize 16 chan puts -nonewline $f "123456789012345\x96" chan configure $f -encoding shiftjis -blocking 0 chan event $f read [namespace code { @@ -1373,7 +1373,7 @@ test chan-io-12.4 {ReadChars: split-up char} -setup { }] chan configure $f -encoding shiftjis vwait [namespace which -variable x] - chan configure $f -encoding binary -blocking 1 + chan configure $f -encoding {} -blocking 1 chan puts -nonewline $f \x7B after 500 ;# Give the cat process time to catch up chan configure $f -encoding shiftjis -blocking 0 @@ -1386,7 +1386,7 @@ 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 -encoding binary -buffering none + chan configure stdout -encoding {} -buffering none chan gets stdin; chan puts -nonewline \xE7 chan gets stdin; chan puts -nonewline \x89 chan gets stdin; chan puts -nonewline \xA6 @@ -4537,7 +4537,7 @@ test chan-io-34.21 {Tcl_Seek and Tcl_Tell on large files} -setup { set l "" } -constraints {largefileSupport extensive} -body { set f [open $path(test3) w] - chan configure $f -encoding binary + chan configure $f -encoding {} lappend l [chan tell $f] chan puts -nonewline $f abcdef lappend l [chan tell $f] @@ -5174,7 +5174,7 @@ test chan-io-39.13 {Tcl_SetChannelOption, Tcl_GetChannelOption, buffer size} -se } -cleanup { chan close $f } -result 40000 -test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup { +test chan-io-39.14 {Tcl_SetChannelOption: -encoding {} & utf-8} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] @@ -5187,11 +5187,11 @@ test chan-io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup { } -cleanup { chan close $f } -result 牦 -test chan-io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} -setup { +test chan-io-39.15 {Tcl_SetChannelOption: -encoding {} & utf-8} -setup { file delete $path(test1) } -body { set f [open $path(test1) w] - chan configure $f -encoding binary + chan configure $f -encoding {} chan puts -nonewline $f \xE7\x89\xA6 chan close $f set f [open $path(test1) r] @@ -5212,7 +5212,7 @@ test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_ variable x {} } -constraints {stdio fileevent} -body { set f [openpipe r+ $path(cat)] - chan configure $f -encoding binary + chan configure $f -encoding {} chan puts -nonewline $f \xE7 chan flush $f chan configure $f -encoding utf-8 -blocking 0 @@ -5224,7 +5224,7 @@ test chan-io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_ vwait [namespace which -variable x] after 300 [namespace code { lappend x timeout }] vwait [namespace which -variable x] - chan configure $f -encoding binary + chan configure $f -encoding {} vwait [namespace which -variable x] after 300 [namespace code { lappend x timeout }] vwait [namespace which -variable x] @@ -6874,7 +6874,7 @@ 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 - # -translation binary is also -encoding binary + # -translation binary is also -encoding iso8859-1 chan configure $out -translation binary chan copy $in $out file size $path(utf8-fcopy.txt) @@ -6892,7 +6892,7 @@ test chan-io-52.11 {TclCopyChannel & encodings} -setup { } -constraints {fcopy} -body { set in [open $path(utf8-fcopy.txt) r] set out [open $path(kyrillic.txt) w] - # -translation binary is also -encoding binary + # -translation binary is also -encoding iso8859-1 chan configure $in -translation binary chan configure $out -encoding koi8-r -translation lf -profile strict catch {chan copy $in $out} cres copts diff --git a/tests/encoding.test b/tests/encoding.test index 10a7400..957f949 100644 --- a/tests/encoding.test +++ b/tests/encoding.test @@ -679,7 +679,7 @@ casino_japanese@___.com )までご住所変更済の連絡をいただけな cd [temporaryDirectory] set fid [open iso2022.txt w] -fconfigure $fid -encoding binary +fconfigure $fid -encoding {} puts -nonewline $fid $iso2022encData close $fid @@ -994,7 +994,7 @@ proc channel-diff {fa fb} { cd [temporaryDirectory] foreach enc {cp932 euc-jp iso2022-jp} { set f [open $enc.chars w] - fconfigure $f -encoding binary + fconfigure $f -encoding {} foreach-jisx0208 code { puts $f [format "%04X %s" $code [gen-jisx0208-$enc $code]] } diff --git a/tests/io.test b/tests/io.test index d550352..f73b88d 100644 --- a/tests/io.test +++ b/tests/io.test @@ -80,8 +80,8 @@ set path(cat) [makeFile { if {$argv != ""} { set f [open [lindex $argv 0]] } - fconfigure $f -encoding binary -translation lf -blocking 0 -eofchar \x1A - fconfigure stdout -encoding binary -translation lf -buffering none + fconfigure $f -encoding {} -translation lf -blocking 0 -eofchar \x1A + fconfigure stdout -encoding {} -translation lf -buffering none fileevent $f readable "foo $f" proc foo {f} { set x [read $f] @@ -110,7 +110,7 @@ test io-1.5 {Tcl_WriteChars: CheckChannelErrors} {emptyTest} { set path(test1) [makeFile {} test1] test io-1.6 {Tcl_WriteChars: WriteBytes} { set f [open $path(test1) w] - fconfigure $f -encoding binary + fconfigure $f -encoding {} puts -nonewline $f "a\x4D\x00" close $f contents $path(test1) @@ -246,7 +246,7 @@ test io-2.1 {WriteBytes} { # loop until all bytes are written set f [open $path(test1) w] - fconfigure $f -encoding binary -buffersize 16 -translation crlf + fconfigure $f -encoding {} -buffersize 16 -translation crlf puts $f "abcdefghijklmnopqrstuvwxyz" close $f contents $path(test1) @@ -256,7 +256,7 @@ test io-2.2 {WriteBytes: savedLF > 0} { # \n -> \r\n expansion. It gets stuck at beginning of this buffer. set f [open $path(test1) w] - fconfigure $f -encoding binary -buffersize 16 -translation crlf + fconfigure $f -encoding {} -buffersize 16 -translation crlf puts -nonewline $f "123456789012345\n12" set x [list [contents $path(test1)]] close $f @@ -268,7 +268,7 @@ test io-2.3 {WriteBytes: flush on line} { # only up to the \n. set f [open $path(test1) w] - fconfigure $f -encoding binary -buffering line -translation crlf + fconfigure $f -encoding {} -buffering line -translation crlf puts -nonewline $f "\n12" set x [contents $path(test1)] close $f @@ -276,7 +276,7 @@ test io-2.3 {WriteBytes: flush on line} { } "\r\n12" test io-2.4 {WriteBytes: reset sawLF after each buffer} { set f [open $path(test1) w] - fconfigure $f -encoding binary -buffering line -translation lf \ + fconfigure $f -encoding {} -buffering line -translation lf \ -buffersize 16 puts -nonewline $f "abcdefg\nhijklmnopqrstuvwxyz" set x [list [contents $path(test1)]] @@ -1180,7 +1180,7 @@ test io-7.2 {FilterInputBytes: split up character in middle of buffer} { # (bufPtr->nextAdded < bufPtr->bufLength) set f [open $path(test1) w] - fconfigure $f -encoding binary + fconfigure $f -encoding {} puts -nonewline $f "1234567890\n123\x82\x4F\x82\x50\x82" close $f set f [open $path(test1)] @@ -1191,7 +1191,7 @@ test io-7.2 {FilterInputBytes: split up character in middle of buffer} { } [list 10 "1234567890" 0] test io-7.3 {FilterInputBytes: split up character at EOF} {testchannel} { set f [open $path(test1) w] - fconfigure $f -encoding binary + fconfigure $f -encoding {} puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82" close $f set f [open $path(test1)] @@ -1204,7 +1204,7 @@ test io-7.3 {FilterInputBytes: split up character at EOF} {testchannel} { } [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 -encoding binary -buffering none + fconfigure $f -encoding {} -buffering none puts -nonewline $f "1234567890123\x82\x4F\x82\x50\x82" fconfigure $f -encoding shiftjis -blocking 0 fileevent $f read [namespace code "ready $f"] @@ -1214,7 +1214,7 @@ test io-7.4 {FilterInputBytes: recover from split up character} {stdio fileevent lappend x [gets $f line] $line [fblocked $f] } vwait [namespace which -variable x] - fconfigure $f -encoding binary -blocking 1 + fconfigure $f -encoding {} -blocking 1 puts $f "\x51\x82\x52" fconfigure $f -encoding shiftjis vwait [namespace which -variable x] @@ -1279,7 +1279,7 @@ test io-8.4 {PeekAhead: cached data available in this buffer} { puts $f "${a}\r\nabcdef" close $f set f [open $path(test1)] - fconfigure $f -encoding binary -translation auto + fconfigure $f -encoding {} -translation auto # "${a}\r" was converted in one operation (because ENCODING_LINESIZE # is 30). To check if "\n" follows, calls PeekAhead and determines @@ -1396,7 +1396,7 @@ test io-11.1 {ReadBytes: want to read a lot} { puts -nonewline $f abcdefghijkl close $f set f [open $path(test1)] - fconfigure $f -encoding binary + fconfigure $f -encoding {} # here set x [read $f 1000] close $f @@ -1409,7 +1409,7 @@ test io-11.2 {ReadBytes: want to read all} { puts -nonewline $f abcdefghijkl close $f set f [open $path(test1)] - fconfigure $f -encoding binary + fconfigure $f -encoding {} # here set x [read $f] close $f @@ -1422,7 +1422,7 @@ test io-11.3 {ReadBytes: allocate more space} { puts -nonewline $f abcdefghijklmnopqrstuvwxyz close $f set f [open $path(test1)] - fconfigure $f -buffersize 16 -encoding binary + fconfigure $f -buffersize 16 -encoding {} # here set x [read $f] close $f @@ -1435,7 +1435,7 @@ test io-11.4 {ReadBytes: EOF char found} { puts $f abcdefghijklmnopqrstuvwxyz close $f set f [open $path(test1)] - fconfigure $f -eofchar m -encoding binary + fconfigure $f -eofchar m -encoding {} # here set x [list [read $f] [eof $f] [read $f] [eof $f]] close $f @@ -1483,7 +1483,7 @@ test io-12.4 {ReadChars: split-up char} {stdio testchannel fileevent} { # (srcRead == 0) set f [open "|[list [interpreter] $path(cat)]" w+] - fconfigure $f -encoding binary -buffering none -buffersize 16 + fconfigure $f -encoding {} -buffering none -buffersize 16 puts -nonewline $f "123456789012345\x96" fconfigure $f -encoding shiftjis -blocking 0 @@ -1496,7 +1496,7 @@ test io-12.4 {ReadChars: split-up char} {stdio testchannel fileevent} { fconfigure $f -encoding shiftjis vwait [namespace which -variable x] - fconfigure $f -encoding binary -blocking 1 + fconfigure $f -encoding {} -blocking 1 puts -nonewline $f "\x7B" after 500 ;# Give the cat process time to catch up fconfigure $f -encoding shiftjis -blocking 0 @@ -1506,7 +1506,7 @@ test io-12.4 {ReadChars: split-up char} {stdio testchannel fileevent} { } [list "123456789012345" 1 "本" 0] test io-12.5 {ReadChars: fileevents on partial characters} {stdio fileevent} { set path(test1) [makeFile { - fconfigure stdout -encoding binary -buffering none + fconfigure stdout -encoding {} -buffering none gets stdin; puts -nonewline "\xE7" gets stdin; puts -nonewline "\x89" gets stdin; puts -nonewline "\xA6" @@ -5016,7 +5016,7 @@ test io-34.20 {Tcl_Tell combined with writing} { 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 -encoding binary + fconfigure $f -encoding {} set l "" lappend l [tell $f] puts -nonewline $f abcdef @@ -5407,9 +5407,9 @@ test io-36.1 {Tcl_InputBlocked on nonblocking pipe} stdio { } {{} 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 -encoding binary -translation lf -eofchar {} + chan configure $f1 -encoding {} -translation lf -eofchar {} puts $f1 { - chan configure stdout -encoding binary -translation lf -eofchar {} + chan configure stdout -encoding {} -translation lf -eofchar {} puts hello_from_pipe } flush $f1 @@ -5749,7 +5749,7 @@ test io-39.13 {Tcl_SetChannelOption, Tcl_GetChannelOption, buffer size} { close $f set x } 40000 -test io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} { +test io-39.14 {Tcl_SetChannelOption: -encoding {} & utf-8} { file delete $path(test1) set f [open $path(test1) w] fconfigure $f -encoding {} @@ -5761,10 +5761,10 @@ test io-39.14 {Tcl_SetChannelOption: -encoding, binary & utf-8} { close $f set x } 牦 -test io-39.15 {Tcl_SetChannelOption: -encoding, binary & utf-8} { +test io-39.15 {Tcl_SetChannelOption: -encoding {} & utf-8} { file delete $path(test1) set f [open $path(test1) w] - fconfigure $f -encoding binary + fconfigure $f -encoding {} puts -nonewline $f \xE7\x89\xA6 close $f set f [open $path(test1) r] @@ -5789,7 +5789,7 @@ test io-39.16a {Tcl_SetChannelOption: -encoding (invalid shortening to "-e"), er } -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 binary + fconfigure $f -encoding {} puts -nonewline $f "\xE7" flush $f fconfigure $f -encoding utf-8 -blocking 0 @@ -5802,7 +5802,7 @@ test io-39.17 {Tcl_SetChannelOption: -encoding, clearing CHANNEL_NEED_MORE_DATA} vwait [namespace which -variable x] after 300 [namespace code { lappend x timeout }] vwait [namespace which -variable x] - fconfigure $f -encoding binary + fconfigure $f -encoding {} vwait [namespace which -variable x] after 300 [namespace code { lappend x timeout }] vwait [namespace which -variable x] @@ -7605,7 +7605,7 @@ test io-52.10 {TclCopyChannel & encodings} -constraints fcopy -body { set out [open $path(utf8-fcopy.txt) w] fconfigure $in -encoding koi8-r -translation lf - # -translation binary is also -encoding binary + # -translation binary is also -encoding iso8859-1 fconfigure $out -translation binary fcopy $in $out @@ -7624,7 +7624,7 @@ test io-52.11 {TclCopyChannel & encodings} -setup { } -constraints {fcopy} -body { set in [open $path(utf8-fcopy.txt) r] set out [open $path(kyrillic.txt) w] - # -translation binary is also -encoding binary + # -translation binary is also -encoding iso8859-1 fconfigure $in -translation binary fconfigure $out -encoding koi8-r -translation lf -profile strict catch {fcopy $in $out} cres copts @@ -8426,7 +8426,7 @@ test io-53.10 {Bug 1350564, multi-directional fcopy} -setup { test io-53.11 {Bug 2895565} -setup { set in [makeFile {} in] set f [open $in w] - fconfigure $f -encoding utf-8 -translation binary + fconfigure $f -encoding utf-8 -translation lf puts -nonewline $f [string repeat "Ho hum\n" 11] close $f set inChan [open $in r] @@ -9330,7 +9330,7 @@ test io-74.1 {[104f2885bb] improper cache validity check} -setup { 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 -encoding binary + fconfigure $f -encoding {} # 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 @@ -9366,7 +9366,7 @@ test io-75.2 {unrepresentable character write passes and is replaced by ? (-prof 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 -encoding binary + fconfigure $f -encoding {} puts -nonewline $f "A\xC0" flush $f seek $f 0 @@ -9385,7 +9385,7 @@ test io-75.3 {incomplete multibyte encoding read is ignored (-profile tcl8)} -se 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 -encoding binary + fconfigure $f -encoding {} # In shiftjis, \x81 starts a two-byte sequence. # But 2nd byte \xFF is not allowed puts -nonewline $f A\x81\xFFA @@ -9404,7 +9404,7 @@ test io-75.4 {shiftjis encoding error read results in raw bytes (-profile tcl8)} 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 -encoding binary + fconfigure $f -encoding {} puts -nonewline $f A\x81 flush $f seek $f 0 @@ -9421,7 +9421,7 @@ test io-75.5 {invalid utf-8 encoding read is ignored (-profile tcl8)} -setup { 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 -encoding binary + fconfigure $f -encoding {} # \x81 is an incomplete byte sequence in utf-8 puts -nonewline $f A\x81 flush $f @@ -9439,7 +9439,7 @@ test io-75.6 {incomplete utf-8 encoding, blocking gets is not ignored (-profile 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 -encoding binary + fconfigure $f -encoding {} # utf-8: \xC3 requires a 2nd byte > x80, but x80, but x80, but Date: Sun, 23 Jun 2024 20:26:43 +0000 Subject: Add "chan isbinary" for checking whether a _channel_ is binary. --- doc/chan.n | 8 ++++++++ generic/tclIO.c | 28 ++++++++++++++++++++++++++++ generic/tclIOCmd.c | 41 +++++++++++++++++++++++++++++++++++++++++ generic/tclInt.h | 1 + tests/chan.test | 10 ++++++++++ 5 files changed, 88 insertions(+) diff --git a/doc/chan.n b/doc/chan.n index c08c7e3..8c35fee 100644 --- a/doc/chan.n +++ b/doc/chan.n @@ -527,6 +527,14 @@ 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 cr. .\" METHOD: names .TP \fBchan names\fR ?\fIpattern\fR? diff --git a/generic/tclIO.c b/generic/tclIO.c index 75a9025..2df5da5 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -7537,6 +7537,34 @@ CheckChannelErrors( /* *---------------------------------------------------------------------- * + * 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. diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c index 0357471..a31b64f 100644 --- a/generic/tclIOCmd.c +++ b/generic/tclIOCmd.c @@ -837,6 +837,46 @@ Tcl_EofObjCmd( 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; +} /* *---------------------------------------------------------------------- @@ -2033,6 +2073,7 @@ TclInitChanCmd( {"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 */ diff --git a/generic/tclInt.h b/generic/tclInt.h index 7f0e842..da8581a 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3291,6 +3291,7 @@ 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); diff --git a/tests/chan.test b/tests/chan.test index ea85e45..bbb9ec5 100644 --- a/tests/chan.test +++ b/tests/chan.test @@ -123,6 +123,16 @@ test chan-15.2 {chan command: truncate subcommand} -setup { 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 { -- cgit v0.12 From 0015fdd61a457d1292bd92f62ccdfad6bebb8e8a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 28 Jun 2024 16:10:01 +0000 Subject: Add "chan isbinary" command. Part of TIP #699, meant for 8.7 --- doc/chan.n | 8 ++++++++ generic/tclIO.c | 28 ++++++++++++++++++++++++++++ generic/tclIOCmd.c | 41 +++++++++++++++++++++++++++++++++++++++++ generic/tclInt.h | 1 + tests/chan.test | 10 ++++++++++ tests/cmdAH.test | 2 +- 6 files changed, 89 insertions(+), 1 deletion(-) diff --git a/doc/chan.n b/doc/chan.n index 6387bfb..d6cde99 100644 --- a/doc/chan.n +++ b/doc/chan.n @@ -540,6 +540,14 @@ 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 cr. .\" METHOD: names .TP \fBchan names\fR ?\fIpattern\fR? diff --git a/generic/tclIO.c b/generic/tclIO.c index caf0e3a..cd925b5 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -7628,6 +7628,34 @@ CheckChannelErrors( /* *---------------------------------------------------------------------- * + * 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 || (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. diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c index 71dc54e..68e79bd 100644 --- a/generic/tclIOCmd.c +++ b/generic/tclIOCmd.c @@ -864,6 +864,46 @@ Tcl_EofObjCmd( 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; +} /* *---------------------------------------------------------------------- @@ -2055,6 +2095,7 @@ TclInitChanCmd( {"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 */ diff --git a/generic/tclInt.h b/generic/tclInt.h index 9e956dc..c2f52b3 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3126,6 +3126,7 @@ 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); diff --git a/tests/chan.test b/tests/chan.test index d818a62..700df87 100644 --- a/tests/chan.test +++ b/tests/chan.test @@ -120,6 +120,16 @@ test chan-15.2 {chan command: truncate subcommand} -setup { 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 { diff --git a/tests/cmdAH.test b/tests/cmdAH.test index ed55c24..6432ad4 100644 --- a/tests/cmdAH.test +++ b/tests/cmdAH.test @@ -23,7 +23,7 @@ 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]] ? + ([llength [info command testsize]] ? [testsize st_mtime] : $::tcl_platform(pointerSize)) >= 8 }] testConstraint linkDirectory [expr { -- cgit v0.12 From 2b28072dd391c88f488e67a345e7eb92ddcb1afe Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 28 Jun 2024 16:13:57 +0000 Subject: Fix "chan isbinary" documentation for 8.7 --- doc/chan.n | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/chan.n b/doc/chan.n index d6cde99..ef965e5 100644 --- a/doc/chan.n +++ b/doc/chan.n @@ -546,8 +546,8 @@ changing the encoding in use. See \fBENCODING ERROR EXAMPLES\fR later. . 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 cr. +a channel with iso8859-1 or binary encoding, -eofchar set to {} and +-translation set to lf. .\" METHOD: names .TP \fBchan names\fR ?\fIpattern\fR? -- cgit v0.12