TIP 183: Add a Binary Flag to [open]

Author:         Andreas Leitgeb <[email protected]>
Author:         Don Porter <[email protected]>
State:          Final
Type:           Project
Vote:           Done
Created:        24-Mar-2004
Keywords:       Tcl
Tcl-Version:    8.5
Tcl-Ticket:     577093


To handle binary files, one currently has to open the file, and then in a second step fconfigure it with -translation binary. This TIP proposes to add a flag "b" to open's access-argument to set initial translation to binary (rather than auto).


ANSI-C fopen() supports an additional flag "b" in the mode parameter especially for non-POSIX platforms, where it makes sure that no conversion takes place at reading or writing. The manual page for open mentions that fconfigure should be used as a substitute for the missing "b"-flag but I don't see anything wrong with a "b" flag as a possible shortcut for this fconfigure-call, so this TIP proposes that the access argument to open should support b as an additional letter (anywhere within the argument when used in the first form documented on the manual page) which will cause the initial configuration of the channel to be suitable for reading and/or writing binary data.

Thus, for an expectedly very little implementation effort, we can simplify:

  set fd [open $fname "w"]; fconfigure $fd -translation binary


  set fd [open $fname "wb"]

which looks much more concise for such a common task.

This extra flag would only affect the initial translation state.


Tcl's open also tries to adopt the POSIX open() parameters (i.e. the second form documented for the access parameter on the manual page.) POSIX's open() doesn't know about binary or non-binary files, but Tcl does, so a new keyword "BINARY" could be introduced to offer this feature also to those who prefer list-of-flags syntax.


A patch attached to Tcl Feature Request 577093 implements this proposal. The public Tcl C routine Tcl_FSOpenFileChannel is amended to accept the b and BINARY substrings in its parsing of the modeString argument. If this proposal is accepted, additional work will be performed to add the required test and documentation changes to the patch.


Any remaining callers of the obsolete private interface TclOpenFileChannelInsertProc need to be aware that the (TclOpenFileChannelProc_ *) function(s) it registers will now possibly be passed a modeString argument that includes the newly supported b and BINARY substrings. Some updating will be required to handle this situation. Ideally, the updating will take the form of leaving behind use of this obsolete, unsupported, private interface, and migrating to the public support for virtual filesystems.

Other than that, this proposal is a completely compatible extension of existing interfaces.


There have been comments that the C-like version of access is just legacy, hard to grok/remember and other general bad things about even the existing things. Those who don't like/use "r","w", "r+", anyway, (and who always use {WRITE CREAT TRUNC} instead of just "w") are not affected by any additional "b". There is no need to use it that way. fconfigure still remains. (Partially I agree with them, the "r+" and "w+" are indeed lousy, and "a" is just a legacy design-bug -- seeks to end just once instead of before each write. Using that is like begging for race-conditions to bite. -- On the other hand "r" and "w", with or without "b" are unbeatably concise and still self-explaining.)

Some proposed adding -options for all kinds of things. Specifying the access-options as -read or -write ... My comment to this: If you like it verbose, use list-syntax for access-flags. This TIP is not about getting rid of legacy-C-syntax for flags.

Some said, that if "b" (BINARY) is added, then sooner or later every fconfigure option would have to be added to "open", (and some even proposed that). Thats beside the point. Does anybody really doubt that "-translation binary" is by far the most common option used with fconfigure? And open does really ask for that but not for any other one (at least not as loudly :-).

Another comment was about difficulties to implement "b", because lower-level functions (Tcl_FSOpenFileChannelProc was mentioned) would have to be changed for that. That is not true, because the "b" could be recognized at top level (Tcl_OpenObjCmd) and trigger the call to Tcl_SetChannelOption after returning from the lower levels. ("b" is valid already, just currently ignored at all levels).

"open binaryfile r -translation binary" is not really any convenience. It's almost as verbose as calling fconfigure explicitly.

Two positive comments appeared: First by Vince Darley: Having the Tcl C-Api for open accept the "b" makes it easier for foreign libraries (that open binary files) to be integrated as far as exposing them to Tcl's VFS, by #define'ing fopen to the Tcl-C-Api function.

Another, by DKF: The reasons of the current status quo are historical: the flags-argument for open was defined when Tcl was only (officially) available on Unix-platforms (where "b" is ignored) and didn't even support binary data (nor any translations). Both of these historical reasons are obsolete by now.

To sum up: yes, "b" is a C-ism, but open is, too. Also it's not a feature that someone would be required to use.


This document has been placed in the public domain.