MJ: We can extend the Tcl
chan command to have a new subcommand
chan mode that returns a list of the access modes of a file handle (r for readable, w for writable) with the small extension below.
To register the new subcommand in the
namespace ensemble the ensemble map needs to be updated.
examples edit
% package require chanmode
0.1
% chan mode stderr
w
% chan mode stdin
r
% set f [open c:/temp.txt w+]
filee1f908
% chan mode $f
r w
pkgIndex.tcl edit
package ifneeded chanmode 0.1 \
[list source [file join [file dirname [info script]] chanmode.tcl]]
chanmode.tcl edit
load [file dirname [info script]]/chanmode0.1[info sharedlibextension]
set map [namespace ensemble configure ::chan -map]
dict set map mode ::chanmode::mode
namespace ensemble configure ::chan -map $map
chanmode.c edit
#include <tcl.h>
#include <stdio.h>
int
Chanmode_ModeObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan; /* The channel to get the mode from. */
const char *channelId; /* Name of channel to get the mode from. */
int mode; /* Mode in which channel is opened. */
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId");
return TCL_ERROR;
}
channelId = Tcl_GetString(objv[1]);
chan = Tcl_GetChannel(interp, channelId, &mode);
if (chan == (Tcl_Channel)NULL) {
return TCL_ERROR;
}
if (mode & TCL_READABLE) {
Tcl_AppendElement(interp, "r");
}
if (mode & TCL_WRITABLE) {
Tcl_AppendElement(interp, "w");
}
return TCL_OK;
}
int DLLEXPORT
Chanmode_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, "8.5", 0) == 0) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "chanmode::mode", Chanmode_ModeObjCmd,
NULL, NULL);
Tcl_PkgProvide(interp, "chanmode", "0.1");
return TCL_OK;
}