#2700 public routines need private #define's

obsolete: 8.5a2
Don Porter
Don Porter

For C functions that are part of Tcl's
documented public interface, a
#include <tcl.h> should be all
that's needed to make use of them.
However, several of the filesystem
routines require additional #include's.

Tcl_FSAccess() needs the values
F_OK, R_OK, etc. for passing in as
the "mode" argument. tcl.h does not
define them; callers are required to
either #include <tclPort.h> or figure
out for themselves what system header
(if any) will fill the gap.

Tcl_FSSeek() needs the values
SEEK_SET, etc. tcl.h does not
define them (see Tcl Bug 926486);
callers are required to #include <stdio.h>
or figure out configure for the platform.

Tcl_FSStat() takes a (Tcl_StatBuf *)
argument, and then the caller needs
declarations about the struct and its
fields to do anything with the result.
This may include the time_t and mode_t
types, and various values and macros
like S_IFREG and S_ISREG(). This
all requires extra configuration to be sure
suitable header files (such as
sys/stat.h and/or sys/types.h) are included.

The Tcl_FSOpenFileChannelProc() of
a Tcl_FIlesystem is passed a "mode"
argument that requires values like
O_RDONLY, O_EXCL, etc for
decoding. tcl.h does not #define these
values; callers are required to
either #include <fcntl.h> or figure
out for themselves what system
header to use.

It appears that a better solution for all
these interfaces would be for tcl.h
itself to #define the values needed
by its public interfaces.


  • Vince Darley
    Vince Darley

    Logged In: YES

    This sounds like a good idea, although I have no idea how
    hard it would be to accomplish this in practice. Do you
    have a patch in mind?

  • Vince Darley
    Vince Darley

    • assigned_to: vincentdarley --> dgp
  • Don Porter
    Don Porter

    Logged In: YES

    Note that stdio.h has been restored
    to tcl.h (926486 rejected) so Tcl_FSSeek()
    is ok again. The other routines listed
    here still fail to define symbols they need.

  • Logged In: YES

    here, here.. same for the POSIX error #defines hidden in

  • Jan Nijtmans
    Jan Nijtmans

    The problem with including those in tcl.h is that extensions who
    include <tcl.h> first and after that <unistd.h>/<stdio.h>/<fcntl.h>
    will break because of the re-define.

    My suggestion would be simply to document which includes
    are needed, it's not that difficult. Not so many extensions
    use those API's, the fact that this issue is already open for
    8 years proves that.

  • Christophe


    I would like to propose as the safest solution IMHO for TCL to have its own defines. In the example of Tcl_FSAccess this could be:
    #define TCL_FEXISTS 0
    #define TCL_FEXECUTABLE 1
    #define TCL_FWRITEABLE 2
    #define TCL_FREADABLE 4

    This would have the advantage:
    - to be system-independant, for compatibility
    - to provide a clearer name...
    - ...and less prone to clash

    On the TCL's internal implementation, I would suggest something like:
    if ((TCL_FEXISTS == F_OK) && (TCL_FREADABLE == R_OK) && (...)) {
    type_for_syscall = type_arg & (TCL_FREADABLE | TCL_FWRITEABLE | ...);
    // to avoid potential misused bits
    } else {
    type_for_syscall = 0;
    if (type_arg & TCL_FREADABLE) type_for_syscal |= R_OK;

    Leting, of course, the compiler optimise the first if, so we'd have:
    - a code that is portable
    - a code potentially optimised if the defines matches the sys defs

    On a side note, I'd like to remind the note I raised in #3517838 about describing F_OK/TCL_FEXISTS as being actually 0, to prevent potential developper's headache with tests like "if (type & TCL_FEXISTS)".
    Talking about this bug, I also take the opportunity to thank you for the help.