summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
authorkjnash <k.j.nash@usa.net>2022-10-19 13:31:18 (GMT)
committerkjnash <k.j.nash@usa.net>2022-10-19 13:31:18 (GMT)
commitd2d5e829ae476810925276ba33be6e7656291f97 (patch)
treedc57e1bed1794f29aefcbfdf90283834f81f3553 /generic/tclIO.c
parentbf9bd6f5fe6cf2220c77b85a5881596b5eebf27e (diff)
parentb3790dd8a34b665a9759136118a0ead98ef22a21 (diff)
downloadtcl-d2d5e829ae476810925276ba33be6e7656291f97.zip
tcl-d2d5e829ae476810925276ba33be6e7656291f97.tar.gz
tcl-d2d5e829ae476810925276ba33be6e7656291f97.tar.bz2
Merge 8.7
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r--generic/tclIO.c349
1 files changed, 264 insertions, 85 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index e00b99b..6a9c306 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -28,7 +28,7 @@ typedef struct ChannelHandler {
int mask; /* Mask of desired events. */
Tcl_ChannelProc *proc; /* Procedure to call in the type of
* Tcl_CreateChannelHandler. */
- ClientData clientData; /* Argument to pass to procedure. */
+ void *clientData; /* Argument to pass to procedure. */
struct ChannelHandler *nextPtr;
/* Next one in list of registered handlers. */
} ChannelHandler;
@@ -142,7 +142,7 @@ static Tcl_ThreadDataKey dataKey;
typedef struct CloseCallback {
Tcl_CloseProc *proc; /* The procedure to call. */
- ClientData clientData; /* Arbitrary one-word data to pass
+ void *clientData; /* Arbitrary one-word data to pass
* to the callback. */
struct CloseCallback *nextPtr; /* For chaining close callbacks. */
} CloseCallback;
@@ -156,7 +156,7 @@ static void PreserveChannelBuffer(ChannelBuffer *bufPtr);
static void ReleaseChannelBuffer(ChannelBuffer *bufPtr);
static int IsShared(ChannelBuffer *bufPtr);
static void ChannelFree(Channel *chanPtr);
-static void ChannelTimerProc(ClientData clientData);
+static void ChannelTimerProc(void *clientData);
static int ChanRead(Channel *chanPtr, char *dst, int dstSize);
static int CheckChannelErrors(ChannelState *statePtr,
int direction);
@@ -178,12 +178,12 @@ static void MBCallback(CopyState *csPtr, Tcl_Obj *errObj);
static void MBError(CopyState *csPtr, int mask, int errorCode);
static int MBRead(CopyState *csPtr);
static int MBWrite(CopyState *csPtr);
-static void MBEvent(ClientData clientData, int mask);
+static void MBEvent(void *clientData, int mask);
-static void CopyEventProc(ClientData clientData, int mask);
+static void CopyEventProc(void *clientData, int mask);
static void CreateScriptRecord(Tcl_Interp *interp,
Channel *chanPtr, int mask, Tcl_Obj *scriptPtr);
-static void DeleteChannelTable(ClientData clientData,
+static void DeleteChannelTable(void *clientData,
Tcl_Interp *interp);
static void DeleteScriptRecord(Tcl_Interp *interp,
Channel *chanPtr, int mask);
@@ -446,7 +446,16 @@ ChanRead(
}
ResetFlag(chanPtr->state, CHANNEL_BLOCKED | CHANNEL_EOF);
chanPtr->state->inputEncodingFlags &= ~TCL_ENCODING_END;
- if (bytesRead > 0) {
+ if (bytesRead < 0) {
+ if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
+ SetFlag(chanPtr->state, CHANNEL_BLOCKED);
+ result = EAGAIN;
+ }
+ Tcl_SetErrno(result);
+ } else if (bytesRead == 0) {
+ SetFlag(chanPtr->state, CHANNEL_EOF);
+ chanPtr->state->inputEncodingFlags |= TCL_ENCODING_END;
+ } else {
/*
* If we get a short read, signal up that we may be BLOCKED. We should
* avoid calling the driver because on some platforms we will block in
@@ -457,15 +466,6 @@ ChanRead(
if (bytesRead < dstSize) {
SetFlag(chanPtr->state, CHANNEL_BLOCKED);
}
- } else if (bytesRead == 0) {
- SetFlag(chanPtr->state, CHANNEL_EOF);
- chanPtr->state->inputEncodingFlags |= TCL_ENCODING_END;
- } else if (bytesRead < 0) {
- if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
- SetFlag(chanPtr->state, CHANNEL_BLOCKED);
- result = EAGAIN;
- }
- Tcl_SetErrno(result);
}
return bytesRead;
}
@@ -847,7 +847,7 @@ Tcl_CreateCloseHandler(
* callback. */
Tcl_CloseProc *proc, /* The callback routine to call when the
* channel will be closed. */
- ClientData clientData) /* Arbitrary data to pass to the close
+ void *clientData) /* Arbitrary data to pass to the close
* callback. */
{
ChannelState *statePtr = ((Channel *) chan)->state;
@@ -885,7 +885,7 @@ Tcl_DeleteCloseHandler(
* callback. */
Tcl_CloseProc *proc, /* The procedure for the callback to
* remove. */
- ClientData clientData) /* The callback data for the callback to
+ void *clientData) /* The callback data for the callback to
* remove. */
{
ChannelState *statePtr = ((Channel *) chan)->state;
@@ -984,7 +984,7 @@ GetChannelTable(
static void
DeleteChannelTable(
- ClientData clientData, /* The per-interpreter data structure. */
+ void *clientData, /* The per-interpreter data structure. */
Tcl_Interp *interp) /* The interpreter being deleted. */
{
Tcl_HashTable *hTblPtr; /* The hash table. */
@@ -1478,7 +1478,7 @@ Tcl_GetChannel(
chanPtr = (Channel *)Tcl_GetHashValue(hPtr);
chanPtr = chanPtr->state->bottomChanPtr;
if (modePtr != NULL) {
- *modePtr = chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE);
+ *modePtr = GotFlag(chanPtr->state, TCL_READABLE|TCL_WRITABLE);
}
return (Tcl_Channel) chanPtr;
@@ -1556,7 +1556,7 @@ TclGetChannelFromObj(
* Re-use the ResolvedCmdName struct.
*/
- Tcl_Release((ClientData) resPtr->statePtr);
+ Tcl_Release((void *) resPtr->statePtr);
} else {
resPtr = (ResolvedChanName *) ckalloc(sizeof(ResolvedChanName));
resPtr->refCount = 0;
@@ -1564,7 +1564,7 @@ TclGetChannelFromObj(
}
statePtr = ((Channel *)chan)->state;
resPtr->statePtr = statePtr;
- Tcl_Preserve((ClientData) statePtr);
+ Tcl_Preserve((void *) statePtr);
resPtr->interp = interp;
resPtr->epoch = statePtr->epoch;
@@ -1572,7 +1572,7 @@ TclGetChannelFromObj(
*channelPtr = (Tcl_Channel) statePtr->bottomChanPtr;
if (modePtr != NULL) {
- *modePtr = statePtr->flags & (TCL_READABLE|TCL_WRITABLE);
+ *modePtr = GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE);
}
return TCL_OK;
@@ -1598,7 +1598,7 @@ Tcl_Channel
Tcl_CreateChannel(
const Tcl_ChannelType *typePtr, /* The channel type record. */
const char *chanName, /* Name of channel to record. */
- ClientData instanceData, /* Instance specific data. */
+ void *instanceData, /* Instance specific data. */
int mask) /* TCL_READABLE & TCL_WRITABLE to indicate if
* the channel is readable, writable. */
{
@@ -1681,6 +1681,7 @@ Tcl_CreateChannel(
}
statePtr->channelName = tmp;
statePtr->flags = mask;
+ statePtr->maxPerms = mask; /* Save max privileges for close callback */
/*
* Set the channel to system default encoding.
@@ -1830,7 +1831,7 @@ Tcl_StackChannel(
const Tcl_ChannelType *typePtr,
/* The channel type record for the new
* channel. */
- ClientData instanceData, /* Instance specific data for the new
+ void *instanceData, /* Instance specific data for the new
* channel. */
int mask, /* TCL_READABLE & TCL_WRITABLE to indicate if
* the channel is readable, writable. */
@@ -1876,7 +1877,7 @@ Tcl_StackChannel(
* --+---+---+---+----+
*/
- if ((mask & (statePtr->flags & (TCL_READABLE | TCL_WRITABLE))) == 0) {
+ if ((mask & GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE)) == 0) {
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"reading and writing both disallowed for channel \"%s\"",
@@ -2166,8 +2167,11 @@ Tcl_UnstackChannel(
/*
* Close and free the channel driver state.
+ * TIP #220: This is done with maximum privileges (as created).
*/
+ ResetFlag(statePtr, TCL_READABLE|TCL_WRITABLE);
+ SetFlag(statePtr, statePtr->maxPerms);
result = ChanClose(chanPtr, interp);
ChannelFree(chanPtr);
@@ -2286,7 +2290,7 @@ Tcl_GetTopChannel(
*----------------------------------------------------------------------
*/
-ClientData
+void *
Tcl_GetChannelInstanceData(
Tcl_Channel chan) /* Channel for which to return client data. */
{
@@ -2374,7 +2378,7 @@ Tcl_GetChannelMode(
ChannelState *statePtr = ((Channel *) chan)->state;
/* State of actual channel. */
- return (statePtr->flags & (TCL_READABLE | TCL_WRITABLE));
+ return GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE);
}
/*
@@ -2425,10 +2429,10 @@ int
Tcl_GetChannelHandle(
Tcl_Channel chan, /* The channel to get file from. */
int direction, /* TCL_WRITABLE or TCL_READABLE. */
- ClientData *handlePtr) /* Where to store handle */
+ void **handlePtr) /* Where to store handle */
{
Channel *chanPtr; /* The actual channel. */
- ClientData handle;
+ void *handle;
int result;
chanPtr = ((Channel *) chan)->state->bottomChanPtr;
@@ -2447,6 +2451,54 @@ Tcl_GetChannelHandle(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_RemoveChannelMode --
+ *
+ * Remove either read or write privileges from the channel.
+ *
+ * Results:
+ * A standard Tcl result code.
+ *
+ * Side effects:
+ * May change the access mode of the channel.
+ * May leave an error message in the interp.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_RemoveChannelMode(
+ Tcl_Interp* interp, /* The interp for an error message. Allowed to be NULL. */
+ Tcl_Channel chan, /* The channel which is modified. */
+ int mode) /* The access mode to drop from the channel */
+{
+ const char* emsg;
+ ChannelState *statePtr = ((Channel *) chan)->state;
+ /* State of actual channel. */
+
+ if ((mode != TCL_READABLE) && (mode != TCL_WRITABLE)) {
+ emsg = "Illegal mode value.";
+ goto error;
+ }
+ if (0 == (GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE) & ~mode)) {
+ emsg = "Bad mode, would make channel inacessible";
+ goto error;
+ }
+
+ ResetFlag(statePtr, mode);
+ return TCL_OK;
+
+ error:
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "Tcl_RemoveChannelMode error: %s. Channel: \"%s\"",
+ emsg, Tcl_GetChannelName((Tcl_Channel) chan)));
+ }
+ return TCL_ERROR;
+}
+
+/*
*---------------------------------------------------------------------------
*
* AllocChannelBuffer --
@@ -2491,7 +2543,7 @@ static void
PreserveChannelBuffer(
ChannelBuffer *bufPtr)
{
- if (bufPtr->refCount == 0) {
+ if (!bufPtr->refCount) {
Tcl_Panic("Reuse of ChannelBuffer! %p", bufPtr);
}
bufPtr->refCount++;
@@ -2558,7 +2610,7 @@ RecycleBuffer(
* This is to honor dynamic changes of the buffersize made by the user.
*/
- if ((bufPtr->bufLength - BUFFER_PADDING) != statePtr->bufSize) {
+ if ((bufPtr->bufLength) != statePtr->bufSize + BUFFER_PADDING) {
ReleaseChannelBuffer(bufPtr);
return;
}
@@ -3654,7 +3706,7 @@ Tcl_CloseEx(
* opened for that direction).
*/
- if (!(statePtr->flags & (TCL_READABLE | TCL_WRITABLE) & flags)) {
+ if (!(GotFlag(statePtr, TCL_READABLE|TCL_WRITABLE) & flags)) {
const char *msg;
if (flags & TCL_CLOSE_READ) {
@@ -4031,8 +4083,8 @@ Tcl_ClearChannelHandlers(
* No encoding conversions are applied to the bytes being read.
*
* Results:
- * The number of bytes written or -1 in case of error. If -1,
- * Tcl_GetErrno will return the error code.
+ * The number of bytes written or TCL_INDEX_NONE in case of error. If
+ * TCL_INDEX_NONE, Tcl_GetErrno will return the error code.
*
* Side effects:
* May buffer up output and may cause output to be produced on the
@@ -4066,7 +4118,7 @@ Tcl_Write(
srcLen = strlen(src);
}
if (WriteBytes(chanPtr, src, srcLen) < 0) {
- return -1;
+ return TCL_INDEX_NONE;
}
return srcLen;
}
@@ -4085,8 +4137,8 @@ Tcl_Write(
* No encoding conversions are applied to the bytes being read.
*
* Results:
- * The number of bytes written or -1 in case of error. If -1,
- * Tcl_GetErrno will return the error code.
+ * The number of bytes written or TCL_INDEX_NONE in case of error. If
+ * TCL_INDEX_NONE, Tcl_GetErrno will return the error code.
*
* Side effects:
* May buffer up output and may cause output to be produced on the
@@ -4108,7 +4160,7 @@ Tcl_WriteRaw(
int errorCode, written;
if (CheckChannelErrors(statePtr, TCL_WRITABLE | CHANNEL_RAW_MODE) != 0) {
- return -1;
+ return TCL_INDEX_NONE;
}
if (srcLen < 0) {
@@ -4141,8 +4193,8 @@ Tcl_WriteRaw(
* specified channel to the topmost channel in a stack.
*
* Results:
- * The number of bytes written or -1 in case of error. If -1,
- * Tcl_GetErrno will return the error code.
+ * The number of bytes written or TCL_INDEX_NONE in case of error. If
+ * TCL_INDEX_NONE, Tcl_GetErrno will return the error code.
*
* Side effects:
* May buffer up output and may cause output to be produced on the
@@ -4165,7 +4217,7 @@ Tcl_WriteChars(
Tcl_Obj *objPtr;
if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
- return -1;
+ return TCL_INDEX_NONE;
}
chanPtr = statePtr->topChanPtr;
@@ -4210,8 +4262,8 @@ Tcl_WriteChars(
* line buffering mode.
*
* Results:
- * The number of bytes written or -1 in case of error. If -1,
- * Tcl_GetErrno() will return the error code.
+ * The number of bytes written or TCL_INDEX_NONE in case of error. If
+ * TCL_INDEX_NONE, Tcl_GetErrno() will return the error code.
*
* Side effects:
* May buffer up output and may cause output to be produced on the
@@ -4238,7 +4290,7 @@ Tcl_WriteObj(
chanPtr = statePtr->topChanPtr;
if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
- return -1;
+ return TCL_INDEX_NONE;
}
if (statePtr->encoding == NULL) {
src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen);
@@ -4342,6 +4394,21 @@ Write(
}
/*
+ * Transfer encoding strict/nocomplain option to the encoding flags
+ */
+
+ if (GotFlag(statePtr, CHANNEL_ENCODING_STRICT)) {
+ statePtr->outputEncodingFlags |= TCL_ENCODING_STRICT;
+#ifdef TCL_NO_DEPRECATED
+ } else if (GotFlag(statePtr, CHANNEL_ENCODING_NOCOMPLAIN)) {
+ statePtr->outputEncodingFlags &= ~TCL_ENCODING_STRICT;
+ statePtr->outputEncodingFlags |= TCL_ENCODING_NOCOMPLAIN;
+#endif
+ } else {
+ statePtr->outputEncodingFlags &= ~TCL_ENCODING_STRICT;
+ }
+
+ /*
* Write the terminated escape sequence even if srcLen is 0.
*/
@@ -4594,7 +4661,7 @@ Tcl_GetsObj(
Tcl_EncodingState oldState;
if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
- return -1;
+ return TCL_INDEX_NONE;
}
/*
@@ -4609,7 +4676,7 @@ Tcl_GetsObj(
/* TODO: Do we need this? */
UpdateInterest(chanPtr);
- return -1;
+ return TCL_INDEX_NONE;
}
/*
@@ -4657,6 +4724,21 @@ Tcl_GetsObj(
}
/*
+ * Transfer encoding nocomplain/strict option to the encoding flags
+ */
+
+ if (GotFlag(statePtr, CHANNEL_ENCODING_STRICT)) {
+ statePtr->inputEncodingFlags |= TCL_ENCODING_STRICT;
+#ifdef TCL_NO_DEPRECATED
+ } else if (GotFlag(statePtr, CHANNEL_ENCODING_NOCOMPLAIN)) {
+ statePtr->inputEncodingFlags &= ~TCL_ENCODING_STRICT;
+ statePtr->inputEncodingFlags |= TCL_ENCODING_NOCOMPLAIN;
+#endif
+ } else {
+ statePtr->inputEncodingFlags &= ~TCL_ENCODING_STRICT;
+ }
+
+ /*
* Object used by FilterInputBytes to keep track of how much data has been
* consumed from the channel buffers.
*/
@@ -5004,8 +5086,9 @@ TclGetsObjBinary(
ChannelState *statePtr = chanPtr->state;
/* State info for channel */
ChannelBuffer *bufPtr;
- int inEofChar, skip, copiedTotal, oldLength, oldFlags, oldRemoved;
- int rawLen, byteLen, eolChar;
+ int inEofChar, skip, copiedTotal, oldFlags, oldRemoved;
+ int rawLen, byteLen, oldLength;
+ int eolChar;
unsigned char *dst, *dstEnd, *eol, *eof, *byteArray;
/*
@@ -5257,7 +5340,7 @@ TclGetsObjBinary(
static void
FreeBinaryEncoding(
- TCL_UNUSED(ClientData))
+ TCL_UNUSED(void *))
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -5412,6 +5495,22 @@ FilterInputBytes(
*gsPtr->dstPtr = dst;
}
gsPtr->state = statePtr->inputEncodingState;
+
+ /*
+ * Transfer encoding nocomplain/strict option to the encoding flags
+ */
+
+ if (GotFlag(statePtr, CHANNEL_ENCODING_STRICT)) {
+ statePtr->inputEncodingFlags |= TCL_ENCODING_STRICT;
+#ifdef TCL_NO_DEPRECATED
+ } else if (GotFlag(statePtr, CHANNEL_ENCODING_NOCOMPLAIN)) {
+ statePtr->inputEncodingFlags &= ~TCL_ENCODING_STRICT;
+ statePtr->inputEncodingFlags |= TCL_ENCODING_NOCOMPLAIN;
+#endif
+ } else {
+ statePtr->inputEncodingFlags &= ~TCL_ENCODING_STRICT;
+ }
+
result = Tcl_ExternalToUtf(NULL, gsPtr->encoding, raw, rawLen,
statePtr->inputEncodingFlags | TCL_ENCODING_NO_TERMINATE,
&statePtr->inputEncodingState, dst, spaceLeft, &gsPtr->rawRead,
@@ -5662,7 +5761,7 @@ Tcl_Read(
chanPtr = statePtr->topChanPtr;
if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
- return -1;
+ return TCL_INDEX_NONE;
}
return DoRead(chanPtr, dst, bytesToRead, 0);
@@ -5703,7 +5802,7 @@ Tcl_ReadRaw(
assert(bytesToRead > 0);
if (CheckChannelErrors(statePtr, TCL_READABLE | CHANNEL_RAW_MODE) != 0) {
- return -1;
+ return TCL_INDEX_NONE;
}
/*
@@ -5757,13 +5856,7 @@ Tcl_ReadRaw(
if (bytesToRead > 0) {
int nread = ChanRead(chanPtr, readBuf, bytesToRead);
- if (nread > 0) {
- /*
- * Successful read (short is OK) - add to bytes copied.
- */
-
- copied += nread;
- } else if (nread < 0) {
+ if (nread < 0) {
/*
* An error signaled. If CHANNEL_BLOCKED, then the error is not
* real, but an indication of blocked state. In that case, retain
@@ -5777,6 +5870,12 @@ Tcl_ReadRaw(
if (!GotFlag(statePtr, CHANNEL_BLOCKED) || copied == 0) {
copied = -1;
}
+ } else if (nread > 0) {
+ /*
+ * Successful read (short is OK) - add to bytes copied.
+ */
+
+ copied += nread;
} else {
/*
* nread == 0. Driver is at EOF. Let that state filter up.
@@ -6153,7 +6252,8 @@ ReadChars(
int savedIEFlags = statePtr->inputEncodingFlags;
int savedFlags = statePtr->flags;
char *dst, *src = RemovePoint(bufPtr);
- int numBytes, srcLen = BytesLeft(bufPtr);
+ int numBytes;
+ int srcLen = BytesLeft(bufPtr);
/*
* One src byte can yield at most one character. So when the number of
@@ -6185,6 +6285,21 @@ ReadChars(
}
/*
+ * Transfer encoding nocomplain/strict option to the encoding flags
+ */
+
+ if (GotFlag(statePtr, CHANNEL_ENCODING_STRICT)) {
+ statePtr->inputEncodingFlags |= TCL_ENCODING_STRICT;
+#ifdef TCL_NO_DEPRECATED
+ } else if (GotFlag(statePtr, CHANNEL_ENCODING_NOCOMPLAIN)) {
+ statePtr->inputEncodingFlags &= ~TCL_ENCODING_STRICT;
+ statePtr->inputEncodingFlags |= TCL_ENCODING_NOCOMPLAIN;
+#endif
+ } else {
+ statePtr->inputEncodingFlags &= ~TCL_ENCODING_STRICT;
+ }
+
+ /*
* This routine is burdened with satisfying several constraints. It cannot
* append more than 'charsToRead` chars onto objPtr. This is measured
* after encoding and translation transformations are completed. There is
@@ -6364,7 +6479,7 @@ ReadChars(
return 1;
}
- } else if (statePtr->flags & CHANNEL_EOF) {
+ } else if (GotFlag(statePtr, CHANNEL_EOF)) {
/*
* The bare \r is the only char and we will never read a
* subsequent char to make the determination.
@@ -6630,7 +6745,7 @@ TranslateInputEOL(
char *dst = dstStart;
int lesser;
- if ((statePtr->flags & INPUT_SAW_CR) && srcLen) {
+ if (GotFlag(statePtr, INPUT_SAW_CR) && srcLen) {
if (*src == '\n') { src++; srcLen--; }
ResetFlag(statePtr, INPUT_SAW_CR);
}
@@ -6682,7 +6797,7 @@ TranslateInputEOL(
* channel, at either the head or tail of the queue.
*
* Results:
- * The number of bytes stored in the channel, or -1 on error.
+ * The number of bytes stored in the channel, or TCL_INDEX_NONE on error.
*
* Side effects:
* Adds input to the input queue of a channel.
@@ -6718,7 +6833,7 @@ Tcl_Ungets(
flags = statePtr->flags;
if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
- len = -1;
+ len = TCL_INDEX_NONE;
goto done;
}
statePtr->flags = flags;
@@ -6961,7 +7076,7 @@ GetInput(
*/
if ((bufPtr != NULL)
- && (bufPtr->bufLength - BUFFER_PADDING != statePtr->bufSize)) {
+ && (bufPtr->bufLength != statePtr->bufSize + BUFFER_PADDING)) {
ReleaseChannelBuffer(bufPtr);
bufPtr = NULL;
}
@@ -7400,7 +7515,7 @@ CheckChannelErrors(
* Fail if the channel is not opened for desired operation.
*/
- if ((statePtr->flags & direction) == 0) {
+ if (GotFlag(statePtr, direction) == 0) {
Tcl_SetErrno(EACCES);
return -1;
}
@@ -7920,6 +8035,31 @@ Tcl_GetChannelOption(
return TCL_OK;
}
}
+ if (len == 0 || HaveOpt(1, "-nocomplainencoding")) {
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-nocomplainencoding");
+ }
+#ifdef TCL_NO_DEPRECATED
+ Tcl_DStringAppendElement(dsPtr,
+ (flags & CHANNEL_ENCODING_NOCOMPLAIN) ? "1" : "0");
+#else
+ Tcl_DStringAppendElement(dsPtr,
+ (flags & CHANNEL_ENCODING_STRICT) ? "0" : "1");
+#endif
+ if (len > 0) {
+ return TCL_OK;
+ }
+ }
+ if (len == 0 || HaveOpt(1, "-strictencoding")) {
+ if (len == 0) {
+ Tcl_DStringAppendElement(dsPtr, "-strictencoding");
+ }
+ Tcl_DStringAppendElement(dsPtr,
+ (flags & CHANNEL_ENCODING_STRICT) ? "1" : "0");
+ if (len > 0) {
+ return TCL_OK;
+ }
+ }
if (len == 0 || HaveOpt(1, "-translation")) {
if (len == 0) {
Tcl_DStringAppendElement(dsPtr, "-translation");
@@ -8173,6 +8313,43 @@ Tcl_SetChannelOption(
ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_STICKY_EOF|CHANNEL_BLOCKED);
statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
return TCL_OK;
+ } else if (HaveOpt(1, "-nocomplainencoding")) {
+ int newMode;
+
+ if (Tcl_GetBoolean(interp, newValue, &newMode) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (newMode) {
+ ResetFlag(statePtr, CHANNEL_ENCODING_STRICT);
+ SetFlag(statePtr, CHANNEL_ENCODING_NOCOMPLAIN);
+ } else {
+#ifdef TCL_NO_DEPRECATED
+ ResetFlag(statePtr, CHANNEL_ENCODING_NOCOMPLAIN);
+#else
+ if (SetFlag(statePtr, CHANNEL_ENCODING_STRICT)) {
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "bad value for -nocomplainencoding: only true allowed",
+ TCL_INDEX_NONE));
+ }
+ return TCL_ERROR;
+ }
+#endif
+ }
+ return TCL_OK;
+ } else if (HaveOpt(1, "-strictencoding")) {
+ int newMode;
+
+ if (Tcl_GetBoolean(interp, newValue, &newMode) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (newMode) {
+ ResetFlag(statePtr, CHANNEL_ENCODING_NOCOMPLAIN);
+ SetFlag(statePtr, CHANNEL_ENCODING_STRICT);
+ } else {
+ ResetFlag(statePtr, CHANNEL_ENCODING_STRICT);
+ }
+ return TCL_OK;
} else if (HaveOpt(1, "-translation")) {
const char *readMode, *writeMode;
@@ -8630,7 +8807,7 @@ UpdateInterest(
static void
ChannelTimerProc(
- ClientData clientData)
+ void *clientData)
{
Channel *chanPtr = (Channel *)clientData;
@@ -8708,7 +8885,7 @@ Tcl_CreateChannelHandler(
* handler. */
Tcl_ChannelProc *proc, /* Procedure to call for each selected
* event. */
- ClientData clientData) /* Arbitrary data to pass to proc. */
+ void *clientData) /* Arbitrary data to pass to proc. */
{
ChannelHandler *chPtr;
Channel *chanPtr = (Channel *) chan;
@@ -8780,7 +8957,7 @@ Tcl_DeleteChannelHandler(
Tcl_Channel chan, /* The channel for which to remove the
* callback. */
Tcl_ChannelProc *proc, /* The procedure in the callback to delete. */
- ClientData clientData) /* The client data in the callback to
+ void *clientData) /* The client data in the callback to
* delete. */
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -8986,7 +9163,7 @@ CreateScriptRecord(
void
TclChannelEventScriptInvoker(
- ClientData clientData, /* The script+interp record. */
+ void *clientData, /* The script+interp record. */
TCL_UNUSED(int) /*mask*/)
{
EventScriptRecord *esPtr = (EventScriptRecord *)clientData;
@@ -9054,7 +9231,7 @@ TclChannelEventScriptInvoker(
int
Tcl_FileEventObjCmd(
- TCL_UNUSED(ClientData),
+ TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter in which the channel for which
* to create the handler is found. */
int objc, /* Number of arguments. */
@@ -9086,7 +9263,7 @@ Tcl_FileEventObjCmd(
}
chanPtr = (Channel *) chan;
statePtr = chanPtr->state;
- if ((statePtr->flags & mask) == 0) {
+ if (GotFlag(statePtr, mask) == 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf("channel is not %s",
(mask == TCL_READABLE) ? "readable" : "writable"));
return TCL_ERROR;
@@ -9148,7 +9325,7 @@ Tcl_FileEventObjCmd(
static void
ZeroTransferTimerProc(
- ClientData clientData)
+ void *clientData)
{
/* calling CopyData with mask==0 still implies immediate invocation of the
* -command callback, and completion of the fcopy.
@@ -9253,8 +9430,8 @@ TclCopyChannel(
* Make sure the output side is unbuffered.
*/
- outStatePtr->flags = (outStatePtr->flags & ~CHANNEL_LINEBUFFERED)
- | CHANNEL_UNBUFFERED;
+ ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED);
+ SetFlag(outStatePtr, CHANNEL_UNBUFFERED);
/*
* Test for conditions where we know we can just move bytes from input
@@ -9384,7 +9561,7 @@ MBError(
static void
MBEvent(
- ClientData clientData,
+ void *clientData,
int mask)
{
CopyState *csPtr = (CopyState *) clientData;
@@ -9567,7 +9744,8 @@ CopyData(
Tcl_Obj *cmdPtr, *errObj = NULL, *bufObj = NULL, *msg = NULL;
Tcl_Channel inChan, outChan;
ChannelState *inStatePtr, *outStatePtr;
- int result = TCL_OK, size, sizeb;
+ int result = TCL_OK, size;
+ int sizeb;
Tcl_WideInt total;
const char *buffer;
int inBinary, outBinary, sameEncoding;
@@ -10033,7 +10211,7 @@ DoRead(
* There's no more buffered data...
*/
- if (statePtr->flags & CHANNEL_EOF) {
+ if (GotFlag(statePtr, CHANNEL_EOF)) {
/*
* ...and there never will be.
*/
@@ -10041,7 +10219,7 @@ DoRead(
*p++ = '\r';
bytesToRead--;
bufPtr->nextRemoved++;
- } else if (statePtr->flags & CHANNEL_BLOCKED) {
+ } else if (GotFlag(statePtr, CHANNEL_BLOCKED)) {
/*
* ...and we cannot get more now.
*/
@@ -10128,7 +10306,7 @@ DoRead(
static void
CopyEventProc(
- ClientData clientData,
+ void *clientData,
int mask)
{
(void) CopyData((CopyState *)clientData, mask);
@@ -10174,20 +10352,20 @@ StopCopy(
*/
nonBlocking = csPtr->readFlags & CHANNEL_NONBLOCKING;
- if (nonBlocking != (inStatePtr->flags & CHANNEL_NONBLOCKING)) {
+ if (nonBlocking != GotFlag(inStatePtr, CHANNEL_NONBLOCKING)) {
SetBlockMode(NULL, csPtr->readPtr,
nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING);
}
if (csPtr->readPtr != csPtr->writePtr) {
nonBlocking = csPtr->writeFlags & CHANNEL_NONBLOCKING;
- if (nonBlocking != (outStatePtr->flags & CHANNEL_NONBLOCKING)) {
+ if (nonBlocking != GotFlag(outStatePtr, CHANNEL_NONBLOCKING)) {
SetBlockMode(NULL, csPtr->writePtr,
nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING);
}
}
ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED);
- outStatePtr->flags |=
- csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED);
+ SetFlag(outStatePtr,
+ csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED));
if (csPtr->cmdPtr) {
Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr);
@@ -11078,7 +11256,8 @@ static Tcl_Obj *
FixLevelCode(
Tcl_Obj *msg)
{
- int explicitResult, numOptions, lc, lcn;
+ int explicitResult, numOptions, lcn;
+ int lc;
Tcl_Obj **lv, **lvn;
int res, i, j, val, lignore, cignore;
int newlevel = -1, newcode = -1;