summaryrefslogtreecommitdiffstats
path: root/generic/tclIOCmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclIOCmd.c')
-rw-r--r--generic/tclIOCmd.c572
1 files changed, 244 insertions, 328 deletions
diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c
index c9b1b2e..db1150d 100644
--- a/generic/tclIOCmd.c
+++ b/generic/tclIOCmd.c
@@ -16,8 +16,8 @@
*/
typedef struct AcceptCallback {
- char *script; /* Script to invoke. */
- Tcl_Interp *interp; /* Interpreter in which to run it. */
+ char *script; /* Script to invoke. */
+ Tcl_Interp *interp; /* Interpreter in which to run it. */
} AcceptCallback;
/*
@@ -39,8 +39,12 @@ static Tcl_ThreadDataKey dataKey;
static void FinalizeIOCmdTSD(ClientData clientData);
static void AcceptCallbackProc(ClientData callbackData,
Tcl_Channel chan, char *address, int port);
-static Tcl_ObjCmdProc ChanPendingObjCmd;
-static Tcl_ObjCmdProc ChanTruncateObjCmd;
+static int ChanPendingObjCmd(ClientData unused,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+static int ChanTruncateObjCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
static void RegisterTcpServerInterpCleanup(Tcl_Interp *interp,
AcceptCallback *acceptCallbackPtr);
static void TcpAcceptCallbacksDeleteProc(ClientData clientData,
@@ -101,23 +105,24 @@ int
Tcl_PutsObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan; /* The channel to puts on. */
Tcl_Obj *string; /* String to write. */
Tcl_Obj *chanObjPtr = NULL; /* channel object. */
int newline; /* Add a newline at end? */
+ int result; /* Result of puts operation. */
int mode; /* Mode in which channel is opened. */
ThreadSpecificData *tsdPtr;
switch (objc) {
- case 2: /* [puts $x] */
+ case 2: /* [puts $x] */
string = objv[1];
newline = 1;
break;
- case 3: /* [puts -nonewline $x] or [puts $chan $x] */
+ case 3: /* [puts -nonewline $x] or [puts $chan $x] */
if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) {
newline = 0;
} else {
@@ -127,17 +132,27 @@ Tcl_PutsObjCmd(
string = objv[2];
break;
- case 4: /* [puts -nonewline $chan $x] or
- * [puts $chan $x nonewline] */
+ case 4: /* [puts -nonewline $chan $x] or [puts $chan $x nonewline] */
newline = 0;
if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) {
chanObjPtr = objv[2];
string = objv[3];
break;
+ } else if (strcmp(TclGetString(objv[3]), "nonewline") == 0) {
+ /*
+ * The code below provides backwards compatibility with an old
+ * form of the command that is no longer recommended or
+ * documented. See also [Bug #3151675]. Will be removed in Tcl 9,
+ * maybe even earlier.
+ */
+
+ chanObjPtr = objv[1];
+ string = objv[2];
+ break;
}
/* Fall through */
- default: /* [puts] or
- * [puts some bad number of arguments...] */
+ default:
+ /* [puts] or [puts some bad number of arguments...] */
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channelId? string");
return TCL_ERROR;
}
@@ -156,21 +171,24 @@ Tcl_PutsObjCmd(
if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
- if (!(mode & TCL_WRITABLE)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "channel \"%s\" wasn't opened for writing",
- TclGetString(chanObjPtr)));
+ if ((mode & TCL_WRITABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", TclGetString(chanObjPtr),
+ "\" wasn't opened for writing", NULL);
return TCL_ERROR;
}
- if (Tcl_WriteObj(chan, string) < 0) {
+ TclChannelPreserve(chan);
+ result = Tcl_WriteObj(chan, string);
+ if (result < 0) {
goto error;
}
if (newline != 0) {
- if (Tcl_WriteChars(chan, "\n", 1) < 0) {
+ result = Tcl_WriteChars(chan, "\n", 1);
+ if (result < 0) {
goto error;
}
}
+ TclChannelRelease(chan);
return TCL_OK;
/*
@@ -182,9 +200,11 @@ Tcl_PutsObjCmd(
error:
if (!TclChanCaughtErrorBypass(interp, chan)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf("error writing \"%s\": %s",
- TclGetString(chanObjPtr), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "error writing \"",
+ TclGetString(chanObjPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
}
+ TclChannelRelease(chan);
return TCL_ERROR;
}
@@ -210,7 +230,7 @@ int
Tcl_FlushObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Obj *chanObjPtr;
@@ -225,13 +245,13 @@ Tcl_FlushObjCmd(
if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
- if (!(mode & TCL_WRITABLE)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "channel \"%s\" wasn't opened for writing",
- TclGetString(chanObjPtr)));
+ if ((mode & TCL_WRITABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", TclGetString(chanObjPtr),
+ "\" wasn't opened for writing", NULL);
return TCL_ERROR;
}
+ TclChannelPreserve(chan);
if (Tcl_Flush(chan) != TCL_OK) {
/*
* TIP #219.
@@ -241,12 +261,14 @@ Tcl_FlushObjCmd(
*/
if (!TclChanCaughtErrorBypass(interp, chan)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "error flushing \"%s\": %s",
- TclGetString(chanObjPtr), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "error flushing \"",
+ TclGetString(chanObjPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
}
+ TclChannelRelease(chan);
return TCL_ERROR;
}
+ TclChannelRelease(chan);
return TCL_OK;
}
@@ -272,13 +294,14 @@ int
Tcl_GetsObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan; /* The channel to read from. */
int 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, "channelId ?varName?");
@@ -288,13 +311,13 @@ Tcl_GetsObjCmd(
if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
- if (!(mode & TCL_READABLE)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "channel \"%s\" wasn't opened for reading",
- TclGetString(chanObjPtr)));
+ if ((mode & TCL_READABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", TclGetString(chanObjPtr),
+ "\" wasn't opened for reading", NULL);
return TCL_ERROR;
}
+ TclChannelPreserve(chan);
linePtr = Tcl_NewObj();
lineLen = Tcl_GetsObj(chan, linePtr);
if (lineLen < 0) {
@@ -302,31 +325,36 @@ Tcl_GetsObjCmd(
Tcl_DecrRefCount(linePtr);
/*
- * TIP #219.
- * Capture error messages put by the driver into the bypass area
- * and put them into the regular interpreter result. Fall back to
- * the regular message if nothing was found in the bypass.
+ * TIP #219. Capture error messages put by the driver into the
+ * bypass area and put them into the regular interpreter result.
+ * Fall back to the regular message if nothing was found in the
+ * bypass.
*/
if (!TclChanCaughtErrorBypass(interp, chan)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "error reading \"%s\": %s",
- TclGetString(chanObjPtr), Tcl_PosixError(interp)));
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "error reading \"",
+ TclGetString(chanObjPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
}
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
lineLen = -1;
}
if (objc == 3) {
if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr,
TCL_LEAVE_ERR_MSG) == NULL) {
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(lineLen));
} else {
Tcl_SetObjResult(interp, linePtr);
}
- return TCL_OK;
+ done:
+ TclChannelRelease(chan);
+ return code;
}
/*
@@ -351,15 +379,13 @@ int
Tcl_ReadObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan; /* The channel to read from. */
int newline, i; /* Discard newline at end? */
- // TODO Allow larger reads on 64-bit
int toRead; /* How many bytes to read? */
- size_t realToRead;
- ssize_t charactersRead; /* How many characters were read? */
+ int charactersRead; /* How many characters were read? */
int mode; /* Mode in which channel is opened. */
Tcl_Obj *resultPtr, *chanObjPtr;
@@ -377,6 +403,7 @@ Tcl_ReadObjCmd(
iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? channelId");
+ iPtr->flags &= ~INTERP_ALTERNATE_WRONG_ARGS;
return TCL_ERROR;
}
@@ -395,34 +422,44 @@ Tcl_ReadObjCmd(
if (TclGetChannelFromObj(interp, chanObjPtr, &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
- if (!(mode & TCL_READABLE)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "channel \"%s\" wasn't opened for reading",
- TclGetString(chanObjPtr)));
+ if ((mode & TCL_READABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", TclGetString(chanObjPtr),
+ "\" wasn't opened for reading", NULL);
return TCL_ERROR;
}
- i++; /* Consumed channel name. */
+ i++; /* Consumed channel name. */
/*
* Compute how many bytes to read.
*/
- realToRead = -1;
+ toRead = -1;
if (i < objc) {
- if ((Tcl_GetIntFromObj(interp, objv[i], &toRead) != TCL_OK)
- || (toRead < 0)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "expected non-negative integer but got \"%s\"",
- TclGetString(objv[i])));
+ if (TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK) {
+ /*
+ * The code below provides backwards compatibility with an old
+ * form of the command that is no longer recommended or
+ * documented. See also [Bug #3151675]. Will be removed in Tcl 9,
+ * maybe even earlier.
+ */
+
+ if (strcmp(TclGetString(objv[i]), "nonewline") != 0) {
+ return TCL_ERROR;
+ }
+ newline = 1;
+ } else if (toRead < 0) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "expected non-negative integer but got \"",
+ TclGetString(objv[i]), "\"", NULL);
Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL);
return TCL_ERROR;
}
- realToRead = (size_t) toRead;
}
resultPtr = Tcl_NewObj();
Tcl_IncrRefCount(resultPtr);
- charactersRead = Tcl_ReadChars(chan, resultPtr, realToRead, 0);
+ TclChannelPreserve(chan);
+ charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0);
if (charactersRead < 0) {
/*
* TIP #219.
@@ -432,10 +469,12 @@ Tcl_ReadObjCmd(
*/
if (!TclChanCaughtErrorBypass(interp, chan)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "error reading \"%s\": %s",
- TclGetString(chanObjPtr), Tcl_PosixError(interp)));
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "error reading \"",
+ TclGetString(chanObjPtr), "\": ",
+ Tcl_PosixError(interp), NULL);
}
+ TclChannelRelease(chan);
Tcl_DecrRefCount(resultPtr);
return TCL_ERROR;
}
@@ -445,8 +484,8 @@ Tcl_ReadObjCmd(
*/
if ((charactersRead > 0) && (newline != 0)) {
- const char *result;
- size_t length;
+ char *result;
+ int length;
result = TclGetStringFromObj(resultPtr, &length);
if (result[length - 1] == '\n') {
@@ -454,6 +493,7 @@ Tcl_ReadObjCmd(
}
}
Tcl_SetObjResult(interp, resultPtr);
+ TclChannelRelease(chan);
Tcl_DecrRefCount(resultPtr);
return TCL_OK;
}
@@ -481,7 +521,7 @@ int
Tcl_SeekObjCmd(
ClientData clientData, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan; /* The channel to tell on. */
@@ -489,10 +529,10 @@ Tcl_SeekObjCmd(
int mode; /* How to seek? */
Tcl_WideInt result; /* Of calling Tcl_Seek. */
int optionIndex;
- static const char *const originOptions[] = {
+ static const char *originOptions[] = {
"start", "current", "end", NULL
};
- static const int modeArray[] = {SEEK_SET, SEEK_CUR, SEEK_END};
+ static CONST int modeArray[] = {SEEK_SET, SEEK_CUR, SEEK_END};
if ((objc != 3) && (objc != 4)) {
Tcl_WrongNumArgs(interp, 1, objv, "channelId offset ?origin?");
@@ -513,6 +553,7 @@ Tcl_SeekObjCmd(
mode = modeArray[optionIndex];
}
+ TclChannelPreserve(chan);
result = Tcl_Seek(chan, offset, mode);
if (result == Tcl_LongAsWide(-1)) {
/*
@@ -521,14 +562,15 @@ Tcl_SeekObjCmd(
* put them into the regular interpreter result. Fall back to the
* regular message if nothing was found in the bypass.
*/
-
if (!TclChanCaughtErrorBypass(interp, chan)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "error during seek on \"%s\": %s",
- TclGetString(objv[1]), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp, "error during seek on \"",
+ TclGetString(objv[1]), "\": ",
+ Tcl_PosixError(interp), NULL);
}
+ TclChannelRelease(chan);
return TCL_ERROR;
}
+ TclChannelRelease(chan);
return TCL_OK;
}
@@ -554,11 +596,12 @@ int
Tcl_TellObjCmd(
ClientData clientData, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
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, "channelId");
@@ -574,6 +617,7 @@ Tcl_TellObjCmd(
return TCL_ERROR;
}
+ TclChannelPreserve(chan);
newLoc = Tcl_Tell(chan);
/*
@@ -582,7 +626,10 @@ Tcl_TellObjCmd(
* them into the regular interpreter result.
*/
- if (TclChanCaughtErrorBypass(interp, chan)) {
+
+ code = TclChanCaughtErrorBypass(interp, chan);
+ TclChannelRelease(chan);
+ if (code) {
return TCL_ERROR;
}
@@ -612,17 +659,13 @@ int
Tcl_CloseObjCmd(
ClientData clientData, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
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, "channelId ?direction?");
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "channelId");
return TCL_ERROR;
}
@@ -630,45 +673,6 @@ Tcl_CloseObjCmd(
return TCL_ERROR;
}
- if (objc == 3) {
- int index, dir;
-
- /*
- * Get direction requested to close, and check syntax.
- */
-
- if (Tcl_GetIndexFromObj(interp, objv[2], dirOptions, "direction", 0,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- dir = dirArray[index];
-
- /*
- * Check direction against channel mode. It is an error if we try to
- * close a direction not supported by the channel (already closed, or
- * never opened for that direction).
- */
-
- if (!(dir & Tcl_GetChannelMode(chan))) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "Half-close of %s-side not possible, side not opened"
- " or already closed", dirOptions[index]));
- return TCL_ERROR;
- }
-
- /*
- * Special handling is needed if and only if the channel mode supports
- * more than the direction to close. Because if the close the last
- * direction suppported we can and will go through the regular
- * process.
- */
-
- if ((Tcl_GetChannelMode(chan) &
- (TCL_CLOSE_READ|TCL_CLOSE_WRITE)) != dir) {
- return Tcl_CloseEx(interp, chan, dir);
- }
- }
-
if (Tcl_UnregisterChannel(interp, chan) != TCL_OK) {
/*
* If there is an error message and it ends with a newline, remove the
@@ -682,8 +686,8 @@ Tcl_CloseObjCmd(
*/
Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
- const char *string;
- size_t len;
+ char *string;
+ int len;
if (Tcl_IsShared(resultPtr)) {
resultPtr = Tcl_DuplicateObj(resultPtr);
@@ -721,15 +725,16 @@ int
Tcl_FconfigureObjCmd(
ClientData clientData, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- const char *optionName, *valueName;
+ 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, "channelId ?-option value ...?");
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "channelId ?optionName? ?value? ?optionName value?...");
return TCL_ERROR;
}
@@ -797,7 +802,7 @@ int
Tcl_EofObjCmd(
ClientData unused, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
@@ -837,17 +842,22 @@ int
Tcl_ExecObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
+ /*
+ * This function generates an argv array for the string arguments. It
+ * starts out with stack-allocated space but uses dynamically-allocated
+ * storage if needed.
+ */
+
Tcl_Obj *resultPtr;
- const char **argv; /* An array for the string arguments. Stored
- * on the _Tcl_ stack. */
- const char *string;
+ const char **argv;
+ char *string;
Tcl_Channel chan;
- int background, index, keepNewline, result, ignoreStderr;
- size_t argc, i, length, skip;
- static const char *const options[] = {
+ int argc, background, i, index, keepNewline, result, skip, length;
+ int ignoreStderr;
+ static const char *options[] = {
"-ignorestderr", "-keepnewline", "--", NULL
};
enum options {
@@ -879,7 +889,7 @@ Tcl_ExecObjCmd(
}
}
if (objc <= skip) {
- Tcl_WrongNumArgs(interp, 1, objv, "?-switch ...? arg ?arg ...?");
+ Tcl_WrongNumArgs(interp, 1, objv, "?switches? arg ?arg ...?");
return TCL_ERROR;
}
@@ -900,7 +910,8 @@ Tcl_ExecObjCmd(
*/
argc = objc - skip;
- argv = TclStackAlloc(interp, (unsigned)(argc + 1) * sizeof(char *));
+ argv = (const char **)
+ TclStackAlloc(interp, (unsigned)(argc + 1) * sizeof(char *));
/*
* Copy the string conversions of each (post option) object into the
@@ -912,13 +923,13 @@ Tcl_ExecObjCmd(
}
argv[argc] = NULL;
chan = Tcl_OpenCommandChannel(interp, argc, argv, (background ? 0 :
- ignoreStderr ? TCL_STDOUT : TCL_STDOUT|TCL_STDERR));
+ (ignoreStderr ? TCL_STDOUT : TCL_STDOUT|TCL_STDERR)));
/*
* Free the argv array.
*/
- TclStackFree(interp, (void *) argv);
+ TclStackFree(interp, (void *)argv);
if (chan == NULL) {
return TCL_ERROR;
@@ -939,7 +950,7 @@ Tcl_ExecObjCmd(
resultPtr = Tcl_NewObj();
if (Tcl_GetChannelHandle(chan, TCL_READABLE, NULL) == TCL_OK) {
- if (Tcl_ReadChars(chan, resultPtr, TCL_STRLEN, 0) < 0) {
+ if (Tcl_ReadChars(chan, resultPtr, -1, 0) < 0) {
/*
* TIP #219.
* Capture error messages put by the driver into the bypass area
@@ -948,9 +959,9 @@ Tcl_ExecObjCmd(
*/
if (!TclChanCaughtErrorBypass(interp, chan)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "error reading output from command: %s",
- Tcl_PosixError(interp)));
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "error reading output from command: ",
+ Tcl_PosixError(interp), NULL);
Tcl_DecrRefCount(resultPtr);
}
return TCL_ERROR;
@@ -1005,7 +1016,7 @@ int
Tcl_FblockedObjCmd(
ClientData unused, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
@@ -1019,10 +1030,9 @@ Tcl_FblockedObjCmd(
if (TclGetChannelFromObj(interp, objv[1], &chan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
- if (!(mode & TCL_READABLE)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "channel \"%s\" wasn't opened for reading",
- TclGetString(objv[1])));
+ if ((mode & TCL_READABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", TclGetString(objv[1]),
+ "\" wasn't opened for reading", NULL);
return TCL_ERROR;
}
@@ -1052,7 +1062,7 @@ int
Tcl_OpenObjCmd(
ClientData notUsed, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
int pipeline, prot;
@@ -1069,21 +1079,19 @@ Tcl_OpenObjCmd(
} else {
modeString = TclGetString(objv[2]);
if (objc == 4) {
- const char *permString = TclGetString(objv[3]);
+ char *permString = TclGetString(objv[3]);
int code = TCL_ERROR;
int scanned = TclParseAllWhiteSpace(permString, -1);
- /*
- * Support legacy octal numbers.
- */
-
+ /* Support legacy octal numbers */
if ((permString[scanned] == '0')
&& (permString[scanned+1] >= '0')
&& (permString[scanned+1] <= '7')) {
+
Tcl_Obj *permObj;
TclNewLiteralStringObj(permObj, "0o");
- Tcl_AppendToObj(permObj, permString+scanned+1, TCL_STRLEN);
+ Tcl_AppendToObj(permObj, permString+scanned+1, -1);
code = TclGetIntFromObj(NULL, permObj, &prot);
Tcl_DecrRefCount(permObj);
}
@@ -1108,8 +1116,7 @@ Tcl_OpenObjCmd(
if (!pipeline) {
chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot);
} else {
- int mode, seekFlag, binary;
- size_t cmdObjc;
+ int mode, seekFlag, cmdObjc, binary;
const char **cmdArgv;
if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) {
@@ -1141,14 +1148,13 @@ Tcl_OpenObjCmd(
Tcl_SetChannelOption(interp, chan, "-translation", "binary");
}
}
- ckfree(cmdArgv);
+ ckfree((char *) cmdArgv);
}
if (chan == NULL) {
return TCL_ERROR;
}
Tcl_RegisterChannel(interp, chan);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan),
- TCL_STRLEN));
+ Tcl_AppendResult(interp, Tcl_GetChannelName(chan), NULL);
return TCL_OK;
}
@@ -1191,7 +1197,7 @@ TcpAcceptCallbacksDeleteProc(
acceptCallbackPtr->interp = NULL;
}
Tcl_DeleteHashTable(hTblPtr);
- ckfree(hTblPtr);
+ ckfree((char *) hTblPtr);
}
/*
@@ -1228,16 +1234,17 @@ RegisterTcpServerInterpCleanup(
Tcl_HashEntry *hPtr; /* Entry for this record. */
int isNew; /* Is the entry new? */
- hTblPtr = Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
+ hTblPtr = (Tcl_HashTable *)
+ Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
if (hTblPtr == NULL) {
- hTblPtr = ckalloc(sizeof(Tcl_HashTable));
+ hTblPtr = (Tcl_HashTable *) ckalloc((unsigned) sizeof(Tcl_HashTable));
Tcl_InitHashTable(hTblPtr, TCL_ONE_WORD_KEYS);
- Tcl_SetAssocData(interp, "tclTCPAcceptCallbacks",
+ (void) Tcl_SetAssocData(interp, "tclTCPAcceptCallbacks",
TcpAcceptCallbacksDeleteProc, hTblPtr);
}
- hPtr = Tcl_CreateHashEntry(hTblPtr, acceptCallbackPtr, &isNew);
+ hPtr = Tcl_CreateHashEntry(hTblPtr, (char *) acceptCallbackPtr, &isNew);
if (!isNew) {
Tcl_Panic("RegisterTcpServerCleanup: damaged accept record table");
}
@@ -1274,7 +1281,8 @@ UnregisterTcpServerInterpCleanupProc(
Tcl_HashTable *hTblPtr;
Tcl_HashEntry *hPtr;
- hTblPtr = Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
+ hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp,
+ "tclTCPAcceptCallbacks", NULL);
if (hTblPtr == NULL) {
return;
}
@@ -1312,7 +1320,7 @@ AcceptCallbackProc(
char *address, /* Address of client that was accepted. */
int port) /* Port of client that was accepted. */
{
- AcceptCallback *acceptCallbackPtr = callbackData;
+ AcceptCallback *acceptCallbackPtr = (AcceptCallback *) callbackData;
/*
* Check if the callback is still valid; the interpreter may have gone
@@ -1342,7 +1350,7 @@ AcceptCallbackProc(
result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan),
" ", address, " ", portBuf, NULL);
if (result != TCL_OK) {
- Tcl_BackgroundException(interp, result);
+ TclBackgroundException(interp, result);
Tcl_UnregisterChannel(interp, chan);
}
@@ -1357,8 +1365,8 @@ AcceptCallbackProc(
Tcl_Release(script);
} else {
/*
- * The interpreter has been deleted, so there is no useful way to use
- * the client socket - just close it.
+ * The interpreter has been deleted, so there is no useful way to
+ * utilize the client socket - just close it.
*/
Tcl_Close(NULL, chan);
@@ -1391,7 +1399,7 @@ TcpServerCloseProc(
ClientData callbackData) /* The data passed in the call to
* Tcl_CreateCloseHandler. */
{
- AcceptCallback *acceptCallbackPtr = callbackData;
+ AcceptCallback *acceptCallbackPtr = (AcceptCallback *) callbackData;
/* The actual data. */
if (acceptCallbackPtr->interp != NULL) {
@@ -1399,7 +1407,7 @@ TcpServerCloseProc(
acceptCallbackPtr);
}
Tcl_EventuallyFree(acceptCallbackPtr->script, TCL_DYNAMIC);
- ckfree(acceptCallbackPtr);
+ ckfree((char *) acceptCallbackPtr);
}
/*
@@ -1423,17 +1431,17 @@ int
Tcl_SocketObjCmd(
ClientData notUsed, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
- static const char *const socketOptions[] = {
- "-async", "-myaddr", "-myport", "-server", NULL
+ static const char *socketOptions[] = {
+ "-async", "-myaddr", "-myport","-server", NULL
};
enum socketOptions {
SKT_ASYNC, SKT_MYADDR, SKT_MYPORT, SKT_SERVER
};
int optionIndex, a, server = 0, port, myport = 0, async = 0;
- const char *host, *script = NULL, *myaddr = NULL;
+ char *host, *script = NULL, *myaddr = NULL;
Tcl_Channel chan;
if (TclpHasSockets(interp) != TCL_OK) {
@@ -1453,9 +1461,8 @@ Tcl_SocketObjCmd(
switch ((enum socketOptions) optionIndex) {
case SKT_ASYNC:
if (server == 1) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "cannot set -async option for server sockets",
- TCL_STRLEN));
+ Tcl_AppendResult(interp,
+ "cannot set -async option for server sockets", NULL);
return TCL_ERROR;
}
async = 1;
@@ -1463,19 +1470,19 @@ Tcl_SocketObjCmd(
case SKT_MYADDR:
a++;
if (a >= objc) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "no argument given for -myaddr option", TCL_STRLEN));
+ Tcl_AppendResult(interp,
+ "no argument given for -myaddr option", NULL);
return TCL_ERROR;
}
myaddr = TclGetString(objv[a]);
break;
case SKT_MYPORT: {
- const char *myPortName;
+ char *myPortName;
a++;
if (a >= objc) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "no argument given for -myport option", TCL_STRLEN));
+ Tcl_AppendResult(interp,
+ "no argument given for -myport option", NULL);
return TCL_ERROR;
}
myPortName = TclGetString(objv[a]);
@@ -1486,16 +1493,15 @@ Tcl_SocketObjCmd(
}
case SKT_SERVER:
if (async == 1) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "cannot set -async option for server sockets",
- TCL_STRLEN));
+ Tcl_AppendResult(interp,
+ "cannot set -async option for server sockets", NULL);
return TCL_ERROR;
}
server = 1;
a++;
if (a >= objc) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "no argument given for -server option", TCL_STRLEN));
+ Tcl_AppendResult(interp,
+ "no argument given for -server option", NULL);
return TCL_ERROR;
}
script = TclGetString(objv[a]);
@@ -1507,8 +1513,8 @@ Tcl_SocketObjCmd(
if (server) {
host = myaddr; /* NULL implies INADDR_ANY */
if (myport != 0) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "option -myport is not valid for servers", TCL_STRLEN));
+ Tcl_AppendResult(interp, "option -myport is not valid for servers",
+ NULL);
return TCL_ERROR;
}
} else if (a < objc) {
@@ -1524,6 +1530,7 @@ Tcl_SocketObjCmd(
iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
Tcl_WrongNumArgs(interp, 1, objv,
"-server command ?-myaddr addr? port");
+ iPtr->flags &= ~INTERP_ALTERNATE_WRONG_ARGS;
return TCL_ERROR;
}
@@ -1537,7 +1544,8 @@ Tcl_SocketObjCmd(
}
if (server) {
- AcceptCallback *acceptCallbackPtr = ckalloc(sizeof(AcceptCallback));
+ AcceptCallback *acceptCallbackPtr = (AcceptCallback *)
+ ckalloc((unsigned) sizeof(AcceptCallback));
unsigned len = strlen(script) + 1;
char *copyScript = ckalloc(len);
@@ -1548,7 +1556,7 @@ Tcl_SocketObjCmd(
acceptCallbackPtr);
if (chan == NULL) {
ckfree(copyScript);
- ckfree(acceptCallbackPtr);
+ ckfree((char *) acceptCallbackPtr);
return TCL_ERROR;
}
@@ -1574,10 +1582,9 @@ Tcl_SocketObjCmd(
return TCL_ERROR;
}
}
-
Tcl_RegisterChannel(interp, chan);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan),
- TCL_STRLEN));
+ Tcl_AppendResult(interp, Tcl_GetChannelName(chan), NULL);
+
return TCL_OK;
}
@@ -1603,14 +1610,13 @@ int
Tcl_FcopyObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel inChan, outChan;
- int mode, i, index;
- Tcl_WideInt toRead;
+ int mode, i, toRead, index;
Tcl_Obj *cmdPtr;
- static const char *const switches[] = { "-size", "-command", NULL };
+ static const char* switches[] = { "-size", "-command", NULL };
enum { FcopySize, FcopyCommand };
if ((objc < 3) || (objc > 7) || (objc == 4) || (objc == 6)) {
@@ -1627,19 +1633,17 @@ Tcl_FcopyObjCmd(
if (TclGetChannelFromObj(interp, objv[1], &inChan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
- if (!(mode & TCL_READABLE)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "channel \"%s\" wasn't opened for reading",
- TclGetString(objv[1])));
+ if ((mode & TCL_READABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", TclGetString(objv[1]),
+ "\" wasn't opened for reading", NULL);
return TCL_ERROR;
}
if (TclGetChannelFromObj(interp, objv[2], &outChan, &mode, 0) != TCL_OK) {
return TCL_ERROR;
}
- if (!(mode & TCL_WRITABLE)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "channel \"%s\" wasn't opened for writing",
- TclGetString(objv[2])));
+ if ((mode & TCL_WRITABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", TclGetString(objv[2]),
+ "\" wasn't opened for writing", NULL);
return TCL_ERROR;
}
@@ -1652,17 +1656,16 @@ Tcl_FcopyObjCmd(
}
switch (index) {
case FcopySize:
- if (Tcl_GetWideIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) {
+ if (TclGetIntFromObj(interp, objv[i+1], &toRead) != TCL_OK) {
return TCL_ERROR;
}
- if (toRead < 0) {
+ if (toRead<0) {
/*
* Handle all negative sizes like -1, meaning 'copy all'. By
* resetting toRead we avoid changes in the core copying
* functions (which explicitly check for -1 and crash on any
* other negative value).
*/
-
toRead = -1;
}
break;
@@ -1699,12 +1702,12 @@ static int
ChanPendingObjCmd(
ClientData unused, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
int index, mode;
- static const char *const options[] = {"input", "output", NULL};
+ static const char *options[] = {"input", "output", NULL};
enum options {PENDING_INPUT, PENDING_OUTPUT};
if (objc != 3) {
@@ -1723,14 +1726,14 @@ ChanPendingObjCmd(
switch ((enum options) index) {
case PENDING_INPUT:
- if (!(mode & TCL_READABLE)) {
+ if ((mode & TCL_READABLE) == 0) {
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
} else {
Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_InputBuffered(chan)));
}
break;
case PENDING_OUTPUT:
- if (!(mode & TCL_WRITABLE)) {
+ if ((mode & TCL_WRITABLE) == 0) {
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
} else {
Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_OutputBuffered(chan)));
@@ -1761,7 +1764,7 @@ static int
ChanTruncateObjCmd(
ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
+ int objc, /* Number of arguments. */
Tcl_Obj *const objv[]) /* Argument objects. */
{
Tcl_Channel chan;
@@ -1784,9 +1787,8 @@ ChanTruncateObjCmd(
return TCL_ERROR;
}
if (length < 0) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "cannot truncate to negative length of file",
- TCL_STRLEN));
+ Tcl_AppendResult(interp,
+ "cannot truncate to negative length of file", NULL);
return TCL_ERROR;
}
} else {
@@ -1796,110 +1798,27 @@ ChanTruncateObjCmd(
length = Tcl_Tell(chan);
if (length == Tcl_WideAsLong(-1)) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "could not determine current location in \"%s\": %s",
- TclGetString(objv[1]), Tcl_PosixError(interp)));
+ Tcl_AppendResult(interp,
+ "could not determine current location in \"",
+ TclGetString(objv[1]), "\": ",
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
}
if (Tcl_TruncateChannel(chan, length) != TCL_OK) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "error during truncate on \"%s\": %s",
- TclGetString(objv[1]), Tcl_PosixError(interp)));
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ChanPipeObjCmd --
- *
- * This function is invoked to process the "chan pipe" Tcl command.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * Creates a pair of Tcl channels wrapping both ends of a new
- * anonymous pipe.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ChanPipeObjCmd(
- ClientData dummy, /* Not used. */
- Tcl_Interp *interp, /* Current interpreter. */
- size_t objc, /* Number of arguments. */
- Tcl_Obj *const objv[]) /* Argument objects. */
-{
- Tcl_Channel rchan, wchan;
- const char *channelNames[2];
- Tcl_Obj *resultPtr;
-
- if (objc != 1) {
- Tcl_WrongNumArgs(interp, 1, objv, "");
+ Tcl_AppendResult(interp, "error during truncate on \"",
+ TclGetString(objv[1]), "\": ",
+ Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
- if (Tcl_CreatePipe(interp, &rchan, &wchan, 0) != TCL_OK) {
- return TCL_ERROR;
- }
-
- channelNames[0] = Tcl_GetChannelName(rchan);
- channelNames[1] = Tcl_GetChannelName(wchan);
-
- resultPtr = Tcl_NewObj();
- Tcl_ListObjAppendElement(NULL, resultPtr,
- Tcl_NewStringObj(channelNames[0], TCL_STRLEN));
- Tcl_ListObjAppendElement(NULL, resultPtr,
- Tcl_NewStringObj(channelNames[1], TCL_STRLEN));
- Tcl_SetObjResult(interp, resultPtr);
-
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * TclChannelNamesCmd --
- *
- * This function is invoked to process the "chan names" and "file
- * channels" Tcl commands. See the user documentation for details on
- * what they do.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclChannelNamesCmd(
- ClientData clientData,
- Tcl_Interp *interp,
- size_t objc, /* Number of arguments. */
- Tcl_Obj *const objv[]) /* Argument objects. */
-{
- if (objc < 1 || objc > 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
- return TCL_ERROR;
- }
- return Tcl_GetChannelNamesEx(interp,
- ((objc == 1) ? NULL : TclGetString(objv[1])));
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclInitChanCmd --
*
* This function is invoked to create the "chan" Tcl command. See the
@@ -1926,29 +1845,26 @@ TclInitChanCmd(
* function at the moment.
*/
static const EnsembleImplMap initMap[] = {
- {"blocked", Tcl_FblockedObjCmd, NULL, NULL, NULL, 0},
- {"close", Tcl_CloseObjCmd, NULL, NULL, NULL, 0},
- {"copy", Tcl_FcopyObjCmd, NULL, NULL, NULL, 0},
- {"create", TclChanCreateObjCmd, NULL, NULL, NULL, 0}, /* TIP #219 */
- {"eof", Tcl_EofObjCmd, NULL, NULL, NULL, 0},
- {"event", Tcl_FileEventObjCmd, NULL, NULL, NULL, 0},
- {"flush", Tcl_FlushObjCmd, NULL, NULL, NULL, 0},
- {"gets", Tcl_GetsObjCmd, NULL, NULL, NULL, 0},
- {"names", TclChannelNamesCmd, NULL, NULL, NULL, 0},
- {"pending", ChanPendingObjCmd, NULL, NULL, NULL, 0}, /* TIP #287 */
- {"pop", TclChanPopObjCmd, NULL, NULL, NULL, 0}, /* TIP #230 */
- {"postevent", TclChanPostEventObjCmd, NULL, NULL, NULL, 0}, /* TIP #219 */
- {"push", TclChanPushObjCmd, NULL, NULL, NULL, 0}, /* TIP #230 */
- {"puts", Tcl_PutsObjCmd, NULL, NULL, NULL, 0},
- {"read", Tcl_ReadObjCmd, NULL, NULL, NULL, 0},
- {"seek", Tcl_SeekObjCmd, NULL, NULL, NULL, 0},
- {"pipe", ChanPipeObjCmd, NULL, NULL, NULL, 0}, /* TIP #304 */
- {"tell", Tcl_TellObjCmd, NULL, NULL, NULL, 0},
- {"truncate", ChanTruncateObjCmd, NULL, NULL, NULL, 0}, /* TIP #208 */
- {NULL, NULL, NULL, NULL, NULL, 0}
+ {"blocked", Tcl_FblockedObjCmd, NULL},
+ {"close", Tcl_CloseObjCmd, NULL},
+ {"copy", Tcl_FcopyObjCmd, NULL},
+ {"create", TclChanCreateObjCmd, NULL}, /* TIP #219 */
+ {"eof", Tcl_EofObjCmd, NULL},
+ {"event", Tcl_FileEventObjCmd, NULL},
+ {"flush", Tcl_FlushObjCmd, NULL},
+ {"gets", Tcl_GetsObjCmd, NULL},
+ {"pending", ChanPendingObjCmd, NULL}, /* TIP #287 */
+ {"postevent", TclChanPostEventObjCmd, NULL}, /* TIP #219 */
+ {"puts", Tcl_PutsObjCmd, NULL},
+ {"read", Tcl_ReadObjCmd, NULL},
+ {"seek", Tcl_SeekObjCmd, NULL},
+ {"tell", Tcl_TellObjCmd, NULL},
+ {"truncate", ChanTruncateObjCmd, NULL}, /* TIP #208 */
+ {NULL,NULL, NULL}
};
static const char *const extras[] = {
"configure", "::fconfigure",
+ "names", "::file channels",
NULL
};
Tcl_Command ensemble;
@@ -1962,8 +1878,8 @@ TclInitChanCmd(
* Can assume that reference counts are all incremented.
*/
- Tcl_DictObjPut(NULL, mapObj, Tcl_NewStringObj(extras[i], TCL_STRLEN),
- Tcl_NewStringObj(extras[i+1], TCL_STRLEN));
+ Tcl_DictObjPut(NULL, mapObj, Tcl_NewStringObj(extras[i], -1),
+ Tcl_NewStringObj(extras[i+1], -1));
}
Tcl_SetEnsembleMappingDict(interp, ensemble, mapObj);
return ensemble;