298 lines
11 KiB
C
298 lines
11 KiB
C
/*
|
||
* tclIO.h --
|
||
*
|
||
* This file provides the generic portions (those that are the same on
|
||
* all platforms and for all channel types) of Tcl's IO facilities.
|
||
*
|
||
* Copyright (c) 1998-2000 Ajuba Solutions
|
||
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
||
*
|
||
* See the file "license.terms" for information on usage and redistribution of
|
||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||
*/
|
||
|
||
/*
|
||
* Make sure that both EAGAIN and EWOULDBLOCK are defined. This does not
|
||
* compile on systems where neither is defined. We want both defined so that
|
||
* we can test safely for both. In the code we still have to test for both
|
||
* because there may be systems on which both are defined and have different
|
||
* values.
|
||
*/
|
||
|
||
#if ((!defined(EWOULDBLOCK)) && (defined(EAGAIN)))
|
||
# define EWOULDBLOCK EAGAIN
|
||
#endif
|
||
#if ((!defined(EAGAIN)) && (defined(EWOULDBLOCK)))
|
||
# define EAGAIN EWOULDBLOCK
|
||
#endif
|
||
#if ((!defined(EAGAIN)) && (!defined(EWOULDBLOCK)))
|
||
#error one of EWOULDBLOCK or EAGAIN must be defined
|
||
#endif
|
||
|
||
/*
|
||
* struct ChannelBuffer:
|
||
*
|
||
* Buffers data being sent to or from a channel.
|
||
*/
|
||
|
||
typedef struct ChannelBuffer {
|
||
int refCount; /* Current uses count */
|
||
int nextAdded; /* The next position into which a character
|
||
* will be put in the buffer. */
|
||
int nextRemoved; /* Position of next byte to be removed from
|
||
* the buffer. */
|
||
int bufLength; /* How big is the buffer? */
|
||
struct ChannelBuffer *nextPtr;
|
||
/* Next buffer in chain. */
|
||
char buf[TCLFLEXARRAY]; /* Placeholder for real buffer. The real
|
||
* buffer occuppies this space + bufSize-1
|
||
* bytes. This must be the last field in the
|
||
* structure. */
|
||
} ChannelBuffer;
|
||
|
||
#define CHANNELBUFFER_HEADER_SIZE TclOffset(ChannelBuffer, buf)
|
||
|
||
/*
|
||
* How much extra space to allocate in buffer to hold bytes from previous
|
||
* buffer (when converting to UTF-8) or to hold bytes that will go to next
|
||
* buffer (when converting from UTF-8).
|
||
*/
|
||
|
||
#define BUFFER_PADDING 16
|
||
|
||
/*
|
||
* The following defines the *default* buffer size for channels.
|
||
*/
|
||
|
||
#define CHANNELBUFFER_DEFAULT_SIZE (1024 * 4)
|
||
|
||
/*
|
||
* The following structure describes the information saved from a call to
|
||
* "fileevent". This is used later when the event being waited for to invoke
|
||
* the saved script in the interpreter designed in this record.
|
||
*/
|
||
|
||
typedef struct EventScriptRecord {
|
||
struct Channel *chanPtr; /* The channel for which this script is
|
||
* registered. This is used only when an error
|
||
* occurs during evaluation of the script, to
|
||
* delete the handler. */
|
||
Tcl_Obj *scriptPtr; /* Script to invoke. */
|
||
Tcl_Interp *interp; /* In what interpreter to invoke script? */
|
||
int mask; /* Events must overlap current mask for the
|
||
* stored script to be invoked. */
|
||
struct EventScriptRecord *nextPtr;
|
||
/* Next in chain of records. */
|
||
} EventScriptRecord;
|
||
|
||
/*
|
||
* struct Channel:
|
||
*
|
||
* One of these structures is allocated for each open channel. It contains
|
||
* data specific to the channel but which belongs to the generic part of the
|
||
* Tcl channel mechanism, and it points at an instance specific (and type
|
||
* specific) instance data, and at a channel type structure.
|
||
*/
|
||
|
||
typedef struct Channel {
|
||
struct ChannelState *state; /* Split out state information */
|
||
ClientData instanceData; /* Instance-specific data provided by creator
|
||
* of channel. */
|
||
const Tcl_ChannelType *typePtr; /* Pointer to channel type structure. */
|
||
struct Channel *downChanPtr;/* Refers to channel this one was stacked
|
||
* upon. This reference is NULL for normal
|
||
* channels. See Tcl_StackChannel. */
|
||
struct Channel *upChanPtr; /* Refers to the channel above stacked this
|
||
* one. NULL for the top most channel. */
|
||
|
||
/*
|
||
* Intermediate buffers to hold pre-read data for consumption by a newly
|
||
* stacked transformation. See 'Tcl_StackChannel'.
|
||
*/
|
||
|
||
ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */
|
||
ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */
|
||
|
||
int refCount;
|
||
} Channel;
|
||
|
||
/*
|
||
* struct ChannelState:
|
||
*
|
||
* One of these structures is allocated for each open channel. It contains
|
||
* data specific to the channel but which belongs to the generic part of the
|
||
* Tcl channel mechanism, and it points at an instance specific (and type
|
||
* specific) instance data, and at a channel type structure.
|
||
*/
|
||
|
||
typedef struct ChannelState {
|
||
char *channelName; /* The name of the channel instance in Tcl
|
||
* commands. Storage is owned by the generic
|
||
* IO code, is dynamically allocated. */
|
||
int flags; /* ORed combination of the flags defined
|
||
* below. */
|
||
Tcl_Encoding encoding; /* Encoding to apply when reading or writing
|
||
* data on this channel. NULL means no
|
||
* encoding is applied to data. */
|
||
Tcl_EncodingState inputEncodingState;
|
||
/* Current encoding state, used when
|
||
* converting input data bytes to UTF-8. */
|
||
int inputEncodingFlags; /* Encoding flags to pass to conversion
|
||
* routine when converting input data bytes to
|
||
* UTF-8. May be TCL_ENCODING_START before
|
||
* converting first byte and TCL_ENCODING_END
|
||
* when EOF is seen. */
|
||
Tcl_EncodingState outputEncodingState;
|
||
/* Current encoding state, used when
|
||
* converting UTF-8 to output data bytes. */
|
||
int outputEncodingFlags; /* Encoding flags to pass to conversion
|
||
* routine when converting UTF-8 to output
|
||
* data bytes. May be TCL_ENCODING_START
|
||
* before converting first byte and
|
||
* TCL_ENCODING_END when EOF is seen. */
|
||
TclEolTranslation inputTranslation;
|
||
/* What translation to apply for end of line
|
||
* sequences on input? */
|
||
TclEolTranslation outputTranslation;
|
||
/* What translation to use for generating end
|
||
* of line sequences in output? */
|
||
int inEofChar; /* If nonzero, use this as a signal of EOF on
|
||
* input. */
|
||
int outEofChar; /* If nonzero, append this to the channel when
|
||
* it is closed if it is open for writing. */
|
||
int unreportedError; /* Non-zero if an error report was deferred
|
||
* because it happened in the background. The
|
||
* value is the POSIX error code. */
|
||
int refCount; /* How many interpreters hold references to
|
||
* this IO channel? */
|
||
struct CloseCallback *closeCbPtr;
|
||
/* Callbacks registered to be called when the
|
||
* channel is closed. */
|
||
char *outputStage; /* Temporary staging buffer used when
|
||
* translating EOL before converting from
|
||
* UTF-8 to external form. */
|
||
ChannelBuffer *curOutPtr; /* Current output buffer being filled. */
|
||
ChannelBuffer *outQueueHead;/* Points at first buffer in output queue. */
|
||
ChannelBuffer *outQueueTail;/* Points at last buffer in output queue. */
|
||
ChannelBuffer *saveInBufPtr;/* Buffer saved for input queue - eliminates
|
||
* need to allocate a new buffer for "gets"
|
||
* that crosses buffer boundaries. */
|
||
ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */
|
||
ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */
|
||
struct ChannelHandler *chPtr;/* List of channel handlers registered for
|
||
* this channel. */
|
||
int interestMask; /* Mask of all events this channel has
|
||
* handlers for. */
|
||
EventScriptRecord *scriptRecordPtr;
|
||
/* Chain of all scripts registered for event
|
||
* handlers ("fileevent") on this channel. */
|
||
int bufSize; /* What size buffers to allocate? */
|
||
Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */
|
||
struct CopyState *csPtrR; /* State of background copy for which channel
|
||
* is input, or NULL. */
|
||
struct CopyState *csPtrW; /* State of background copy for which channel
|
||
* is output, or NULL. */
|
||
Channel *topChanPtr; /* Refers to topmost channel in a stack. Never
|
||
* NULL. */
|
||
Channel *bottomChanPtr; /* Refers to bottommost channel in a stack.
|
||
* This channel can be relied on to live as
|
||
* long as the channel state. Never NULL. */
|
||
struct ChannelState *nextCSPtr;
|
||
/* Next in list of channels currently open. */
|
||
Tcl_ThreadId managingThread;/* TIP #10: Id of the thread managing this
|
||
* stack of channels. */
|
||
|
||
/*
|
||
* TIP #219 ... Info for the I/O system ...
|
||
* Error message set by channel drivers, for the propagation of arbitrary
|
||
* Tcl errors. This information, if present (chanMsg not NULL), takes
|
||
* precedence over a posix error code returned by a channel operation.
|
||
*/
|
||
|
||
Tcl_Obj* chanMsg;
|
||
Tcl_Obj* unreportedMsg; /* Non-NULL if an error report was deferred
|
||
* because it happened in the background. The
|
||
* value is the chanMg, if any. #219's
|
||
* companion to 'unreportedError'. */
|
||
int epoch; /* Used to test validity of stored channelname
|
||
* lookup results. */
|
||
} ChannelState;
|
||
|
||
/*
|
||
* Values for the flags field in Channel. Any ORed combination of the
|
||
* following flags can be stored in the field. These flags record various
|
||
* options and state bits about the channel. In addition to the flags below,
|
||
* the channel can also have TCL_READABLE (1<<1) and TCL_WRITABLE (1<<2) set.
|
||
*/
|
||
|
||
#define CHANNEL_NONBLOCKING (1<<3) /* Channel is currently in nonblocking
|
||
* mode. */
|
||
#define CHANNEL_LINEBUFFERED (1<<4) /* Output to the channel must be
|
||
* flushed after every newline. */
|
||
#define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always
|
||
* be flushed immediately. */
|
||
#define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the queued
|
||
* output buffers has been
|
||
* scheduled. */
|
||
#define CHANNEL_CLOSED (1<<8) /* Channel has been closed. No further
|
||
* Tcl-level IO on the channel is
|
||
* allowed. */
|
||
#define CHANNEL_EOF (1<<9) /* EOF occurred on this channel. This
|
||
* bit is cleared before every input
|
||
* operation. */
|
||
#define CHANNEL_STICKY_EOF (1<<10) /* EOF occurred on this channel
|
||
* because we saw the input
|
||
* eofChar. This bit prevents clearing
|
||
* of the EOF bit before every input
|
||
* operation. */
|
||
#define CHANNEL_BLOCKED (1<<11) /* EWOULDBLOCK or EAGAIN occurred on
|
||
* this channel. This bit is cleared
|
||
* before every input or output
|
||
* operation. */
|
||
#define INPUT_SAW_CR (1<<12) /* Channel is in CRLF eol input
|
||
* translation mode and the last byte
|
||
* seen was a "\r". */
|
||
#define CHANNEL_DEAD (1<<13) /* The channel has been closed by the
|
||
* exit handler (on exit) but not
|
||
* deallocated. When any IO operation
|
||
* sees this flag on a channel, it
|
||
* does not call driver level
|
||
* functions to avoid referring to
|
||
* deallocated data. */
|
||
#define CHANNEL_NEED_MORE_DATA (1<<14) /* The last input operation failed
|
||
* because there was not enough data
|
||
* to complete the operation. This
|
||
* flag is set when gets fails to get
|
||
* a complete line or when read fails
|
||
* to get a complete character. When
|
||
* set, file events will not be
|
||
* delivered for buffered data until
|
||
* the state of the channel
|
||
* changes. */
|
||
#define CHANNEL_RAW_MODE (1<<16) /* When set, notes that the Raw API is
|
||
* being used. */
|
||
|
||
#define CHANNEL_INCLOSE (1<<19) /* Channel is currently being closed.
|
||
* Its structures are still live and
|
||
* usable, but it may not be closed
|
||
* again from within the close
|
||
* handler. */
|
||
#define CHANNEL_CLOSEDWRITE (1<<21) /* Channel write side has been closed.
|
||
* No further Tcl-level write IO on
|
||
* the channel is allowed. */
|
||
|
||
/*
|
||
* The length of time to wait between synthetic timer events. Must be zero or
|
||
* bad things tend to happen.
|
||
*/
|
||
|
||
#define SYNTHETIC_EVENT_TIME 0
|
||
|
||
/*
|
||
* Local Variables:
|
||
* mode: c
|
||
* c-basic-offset: 4
|
||
* fill-column: 78
|
||
* End:
|
||
*/
|