sl@0
|
1 |
/*
|
sl@0
|
2 |
* tclIO.h --
|
sl@0
|
3 |
*
|
sl@0
|
4 |
* This file provides the generic portions (those that are the same on
|
sl@0
|
5 |
* all platforms and for all channel types) of Tcl's IO facilities.
|
sl@0
|
6 |
*
|
sl@0
|
7 |
* Copyright (c) 1998-2000 Ajuba Solutions
|
sl@0
|
8 |
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
sl@0
|
9 |
*
|
sl@0
|
10 |
* See the file "license.terms" for information on usage and redistribution
|
sl@0
|
11 |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
sl@0
|
12 |
*
|
sl@0
|
13 |
* RCS: @(#) $Id: tclIO.h,v 1.5.4.2 2004/07/15 20:46:19 andreas_kupries Exp $
|
sl@0
|
14 |
*/
|
sl@0
|
15 |
|
sl@0
|
16 |
/*
|
sl@0
|
17 |
* Make sure that both EAGAIN and EWOULDBLOCK are defined. This does not
|
sl@0
|
18 |
* compile on systems where neither is defined. We want both defined so
|
sl@0
|
19 |
* that we can test safely for both. In the code we still have to test for
|
sl@0
|
20 |
* both because there may be systems on which both are defined and have
|
sl@0
|
21 |
* different values.
|
sl@0
|
22 |
*/
|
sl@0
|
23 |
|
sl@0
|
24 |
#if ((!defined(EWOULDBLOCK)) && (defined(EAGAIN)))
|
sl@0
|
25 |
# define EWOULDBLOCK EAGAIN
|
sl@0
|
26 |
#endif
|
sl@0
|
27 |
#if ((!defined(EAGAIN)) && (defined(EWOULDBLOCK)))
|
sl@0
|
28 |
# define EAGAIN EWOULDBLOCK
|
sl@0
|
29 |
#endif
|
sl@0
|
30 |
#if ((!defined(EAGAIN)) && (!defined(EWOULDBLOCK)))
|
sl@0
|
31 |
error one of EWOULDBLOCK or EAGAIN must be defined
|
sl@0
|
32 |
#endif
|
sl@0
|
33 |
|
sl@0
|
34 |
/*
|
sl@0
|
35 |
* The following structure encapsulates the state for a background channel
|
sl@0
|
36 |
* copy. Note that the data buffer for the copy will be appended to this
|
sl@0
|
37 |
* structure.
|
sl@0
|
38 |
*/
|
sl@0
|
39 |
|
sl@0
|
40 |
typedef struct CopyState {
|
sl@0
|
41 |
struct Channel *readPtr; /* Pointer to input channel. */
|
sl@0
|
42 |
struct Channel *writePtr; /* Pointer to output channel. */
|
sl@0
|
43 |
int readFlags; /* Original read channel flags. */
|
sl@0
|
44 |
int writeFlags; /* Original write channel flags. */
|
sl@0
|
45 |
int toRead; /* Number of bytes to copy, or -1. */
|
sl@0
|
46 |
int total; /* Total bytes transferred (written). */
|
sl@0
|
47 |
Tcl_Interp *interp; /* Interp that started the copy. */
|
sl@0
|
48 |
Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */
|
sl@0
|
49 |
int bufSize; /* Size of appended buffer. */
|
sl@0
|
50 |
char buffer[1]; /* Copy buffer, this must be the last
|
sl@0
|
51 |
* field. */
|
sl@0
|
52 |
} CopyState;
|
sl@0
|
53 |
|
sl@0
|
54 |
/*
|
sl@0
|
55 |
* struct ChannelBuffer:
|
sl@0
|
56 |
*
|
sl@0
|
57 |
* Buffers data being sent to or from a channel.
|
sl@0
|
58 |
*/
|
sl@0
|
59 |
|
sl@0
|
60 |
typedef struct ChannelBuffer {
|
sl@0
|
61 |
int nextAdded; /* The next position into which a character
|
sl@0
|
62 |
* will be put in the buffer. */
|
sl@0
|
63 |
int nextRemoved; /* Position of next byte to be removed
|
sl@0
|
64 |
* from the buffer. */
|
sl@0
|
65 |
int bufLength; /* How big is the buffer? */
|
sl@0
|
66 |
struct ChannelBuffer *nextPtr;
|
sl@0
|
67 |
/* Next buffer in chain. */
|
sl@0
|
68 |
char buf[4]; /* Placeholder for real buffer. The real
|
sl@0
|
69 |
* buffer occuppies this space + bufSize-4
|
sl@0
|
70 |
* bytes. This must be the last field in
|
sl@0
|
71 |
* the structure. */
|
sl@0
|
72 |
} ChannelBuffer;
|
sl@0
|
73 |
|
sl@0
|
74 |
#define CHANNELBUFFER_HEADER_SIZE (sizeof(ChannelBuffer) - 4)
|
sl@0
|
75 |
|
sl@0
|
76 |
/*
|
sl@0
|
77 |
* How much extra space to allocate in buffer to hold bytes from previous
|
sl@0
|
78 |
* buffer (when converting to UTF-8) or to hold bytes that will go to
|
sl@0
|
79 |
* next buffer (when converting from UTF-8).
|
sl@0
|
80 |
*/
|
sl@0
|
81 |
|
sl@0
|
82 |
#define BUFFER_PADDING 16
|
sl@0
|
83 |
|
sl@0
|
84 |
/*
|
sl@0
|
85 |
* The following defines the *default* buffer size for channels.
|
sl@0
|
86 |
*/
|
sl@0
|
87 |
|
sl@0
|
88 |
#define CHANNELBUFFER_DEFAULT_SIZE (1024 * 4)
|
sl@0
|
89 |
|
sl@0
|
90 |
/*
|
sl@0
|
91 |
* Structure to record a close callback. One such record exists for
|
sl@0
|
92 |
* each close callback registered for a channel.
|
sl@0
|
93 |
*/
|
sl@0
|
94 |
|
sl@0
|
95 |
typedef struct CloseCallback {
|
sl@0
|
96 |
Tcl_CloseProc *proc; /* The procedure to call. */
|
sl@0
|
97 |
ClientData clientData; /* Arbitrary one-word data to pass
|
sl@0
|
98 |
* to the callback. */
|
sl@0
|
99 |
struct CloseCallback *nextPtr; /* For chaining close callbacks. */
|
sl@0
|
100 |
} CloseCallback;
|
sl@0
|
101 |
|
sl@0
|
102 |
/*
|
sl@0
|
103 |
* The following structure describes the information saved from a call to
|
sl@0
|
104 |
* "fileevent". This is used later when the event being waited for to
|
sl@0
|
105 |
* invoke the saved script in the interpreter designed in this record.
|
sl@0
|
106 |
*/
|
sl@0
|
107 |
|
sl@0
|
108 |
typedef struct EventScriptRecord {
|
sl@0
|
109 |
struct Channel *chanPtr; /* The channel for which this script is
|
sl@0
|
110 |
* registered. This is used only when an
|
sl@0
|
111 |
* error occurs during evaluation of the
|
sl@0
|
112 |
* script, to delete the handler. */
|
sl@0
|
113 |
Tcl_Obj *scriptPtr; /* Script to invoke. */
|
sl@0
|
114 |
Tcl_Interp *interp; /* In what interpreter to invoke script? */
|
sl@0
|
115 |
int mask; /* Events must overlap current mask for the
|
sl@0
|
116 |
* stored script to be invoked. */
|
sl@0
|
117 |
struct EventScriptRecord *nextPtr;
|
sl@0
|
118 |
/* Next in chain of records. */
|
sl@0
|
119 |
} EventScriptRecord;
|
sl@0
|
120 |
|
sl@0
|
121 |
/*
|
sl@0
|
122 |
* struct Channel:
|
sl@0
|
123 |
*
|
sl@0
|
124 |
* One of these structures is allocated for each open channel. It contains data
|
sl@0
|
125 |
* specific to the channel but which belongs to the generic part of the Tcl
|
sl@0
|
126 |
* channel mechanism, and it points at an instance specific (and type
|
sl@0
|
127 |
* specific) * instance data, and at a channel type structure.
|
sl@0
|
128 |
*/
|
sl@0
|
129 |
|
sl@0
|
130 |
typedef struct Channel {
|
sl@0
|
131 |
struct ChannelState *state; /* Split out state information */
|
sl@0
|
132 |
|
sl@0
|
133 |
ClientData instanceData; /* Instance-specific data provided by
|
sl@0
|
134 |
* creator of channel. */
|
sl@0
|
135 |
Tcl_ChannelType *typePtr; /* Pointer to channel type structure. */
|
sl@0
|
136 |
|
sl@0
|
137 |
struct Channel *downChanPtr;/* Refers to channel this one was stacked
|
sl@0
|
138 |
* upon. This reference is NULL for normal
|
sl@0
|
139 |
* channels. See Tcl_StackChannel. */
|
sl@0
|
140 |
struct Channel *upChanPtr; /* Refers to the channel above stacked this
|
sl@0
|
141 |
* one. NULL for the top most channel. */
|
sl@0
|
142 |
|
sl@0
|
143 |
/*
|
sl@0
|
144 |
* Intermediate buffers to hold pre-read data for consumption by a
|
sl@0
|
145 |
* newly stacked transformation. See 'Tcl_StackChannel'.
|
sl@0
|
146 |
*/
|
sl@0
|
147 |
ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */
|
sl@0
|
148 |
ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */
|
sl@0
|
149 |
} Channel;
|
sl@0
|
150 |
|
sl@0
|
151 |
/*
|
sl@0
|
152 |
* struct ChannelState:
|
sl@0
|
153 |
*
|
sl@0
|
154 |
* One of these structures is allocated for each open channel. It contains data
|
sl@0
|
155 |
* specific to the channel but which belongs to the generic part of the Tcl
|
sl@0
|
156 |
* channel mechanism, and it points at an instance specific (and type
|
sl@0
|
157 |
* specific) * instance data, and at a channel type structure.
|
sl@0
|
158 |
*/
|
sl@0
|
159 |
|
sl@0
|
160 |
typedef struct ChannelState {
|
sl@0
|
161 |
CONST char *channelName; /* The name of the channel instance in Tcl
|
sl@0
|
162 |
* commands. Storage is owned by the generic IO
|
sl@0
|
163 |
* code, is dynamically allocated. */
|
sl@0
|
164 |
int flags; /* ORed combination of the flags defined
|
sl@0
|
165 |
* below. */
|
sl@0
|
166 |
Tcl_Encoding encoding; /* Encoding to apply when reading or writing
|
sl@0
|
167 |
* data on this channel. NULL means no
|
sl@0
|
168 |
* encoding is applied to data. */
|
sl@0
|
169 |
Tcl_EncodingState inputEncodingState;
|
sl@0
|
170 |
/* Current encoding state, used when converting
|
sl@0
|
171 |
* input data bytes to UTF-8. */
|
sl@0
|
172 |
int inputEncodingFlags; /* Encoding flags to pass to conversion
|
sl@0
|
173 |
* routine when converting input data bytes to
|
sl@0
|
174 |
* UTF-8. May be TCL_ENCODING_START before
|
sl@0
|
175 |
* converting first byte and TCL_ENCODING_END
|
sl@0
|
176 |
* when EOF is seen. */
|
sl@0
|
177 |
Tcl_EncodingState outputEncodingState;
|
sl@0
|
178 |
/* Current encoding state, used when converting
|
sl@0
|
179 |
* UTF-8 to output data bytes. */
|
sl@0
|
180 |
int outputEncodingFlags; /* Encoding flags to pass to conversion
|
sl@0
|
181 |
* routine when converting UTF-8 to output
|
sl@0
|
182 |
* data bytes. May be TCL_ENCODING_START
|
sl@0
|
183 |
* before converting first byte and
|
sl@0
|
184 |
* TCL_ENCODING_END when EOF is seen. */
|
sl@0
|
185 |
TclEolTranslation inputTranslation;
|
sl@0
|
186 |
/* What translation to apply for end of line
|
sl@0
|
187 |
* sequences on input? */
|
sl@0
|
188 |
TclEolTranslation outputTranslation;
|
sl@0
|
189 |
/* What translation to use for generating
|
sl@0
|
190 |
* end of line sequences in output? */
|
sl@0
|
191 |
int inEofChar; /* If nonzero, use this as a signal of EOF
|
sl@0
|
192 |
* on input. */
|
sl@0
|
193 |
int outEofChar; /* If nonzero, append this to the channel
|
sl@0
|
194 |
* when it is closed if it is open for
|
sl@0
|
195 |
* writing. */
|
sl@0
|
196 |
int unreportedError; /* Non-zero if an error report was deferred
|
sl@0
|
197 |
* because it happened in the background. The
|
sl@0
|
198 |
* value is the POSIX error code. */
|
sl@0
|
199 |
int refCount; /* How many interpreters hold references to
|
sl@0
|
200 |
* this IO channel? */
|
sl@0
|
201 |
|
sl@0
|
202 |
CloseCallback *closeCbPtr; /* Callbacks registered to be called when the
|
sl@0
|
203 |
* channel is closed. */
|
sl@0
|
204 |
char *outputStage; /* Temporary staging buffer used when
|
sl@0
|
205 |
* translating EOL before converting from
|
sl@0
|
206 |
* UTF-8 to external form. */
|
sl@0
|
207 |
ChannelBuffer *curOutPtr; /* Current output buffer being filled. */
|
sl@0
|
208 |
ChannelBuffer *outQueueHead;/* Points at first buffer in output queue. */
|
sl@0
|
209 |
ChannelBuffer *outQueueTail;/* Points at last buffer in output queue. */
|
sl@0
|
210 |
|
sl@0
|
211 |
ChannelBuffer *saveInBufPtr;/* Buffer saved for input queue - eliminates
|
sl@0
|
212 |
* need to allocate a new buffer for "gets"
|
sl@0
|
213 |
* that crosses buffer boundaries. */
|
sl@0
|
214 |
ChannelBuffer *inQueueHead; /* Points at first buffer in input queue. */
|
sl@0
|
215 |
ChannelBuffer *inQueueTail; /* Points at last buffer in input queue. */
|
sl@0
|
216 |
|
sl@0
|
217 |
struct ChannelHandler *chPtr;/* List of channel handlers registered
|
sl@0
|
218 |
* for this channel. */
|
sl@0
|
219 |
int interestMask; /* Mask of all events this channel has
|
sl@0
|
220 |
* handlers for. */
|
sl@0
|
221 |
EventScriptRecord *scriptRecordPtr;
|
sl@0
|
222 |
/* Chain of all scripts registered for
|
sl@0
|
223 |
* event handlers ("fileevent") on this
|
sl@0
|
224 |
* channel. */
|
sl@0
|
225 |
|
sl@0
|
226 |
int bufSize; /* What size buffers to allocate? */
|
sl@0
|
227 |
Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */
|
sl@0
|
228 |
CopyState *csPtr; /* State of background copy, or NULL. */
|
sl@0
|
229 |
Channel *topChanPtr; /* Refers to topmost channel in a stack.
|
sl@0
|
230 |
* Never NULL. */
|
sl@0
|
231 |
Channel *bottomChanPtr; /* Refers to bottommost channel in a stack.
|
sl@0
|
232 |
* This channel can be relied on to live as
|
sl@0
|
233 |
* long as the channel state. Never NULL. */
|
sl@0
|
234 |
struct ChannelState *nextCSPtr;
|
sl@0
|
235 |
/* Next in list of channels currently open. */
|
sl@0
|
236 |
Tcl_ThreadId managingThread; /* TIP #10: Id of the thread managing
|
sl@0
|
237 |
* this stack of channels. */
|
sl@0
|
238 |
} ChannelState;
|
sl@0
|
239 |
|
sl@0
|
240 |
/*
|
sl@0
|
241 |
* Values for the flags field in Channel. Any ORed combination of the
|
sl@0
|
242 |
* following flags can be stored in the field. These flags record various
|
sl@0
|
243 |
* options and state bits about the channel. In addition to the flags below,
|
sl@0
|
244 |
* the channel can also have TCL_READABLE (1<<1) and TCL_WRITABLE (1<<2) set.
|
sl@0
|
245 |
*/
|
sl@0
|
246 |
|
sl@0
|
247 |
#define CHANNEL_NONBLOCKING (1<<3) /* Channel is currently in
|
sl@0
|
248 |
* nonblocking mode. */
|
sl@0
|
249 |
#define CHANNEL_LINEBUFFERED (1<<4) /* Output to the channel must be
|
sl@0
|
250 |
* flushed after every newline. */
|
sl@0
|
251 |
#define CHANNEL_UNBUFFERED (1<<5) /* Output to the channel must always
|
sl@0
|
252 |
* be flushed immediately. */
|
sl@0
|
253 |
#define BUFFER_READY (1<<6) /* Current output buffer (the
|
sl@0
|
254 |
* curOutPtr field in the
|
sl@0
|
255 |
* channel structure) should be
|
sl@0
|
256 |
* output as soon as possible even
|
sl@0
|
257 |
* though it may not be full. */
|
sl@0
|
258 |
#define BG_FLUSH_SCHEDULED (1<<7) /* A background flush of the
|
sl@0
|
259 |
* queued output buffers has been
|
sl@0
|
260 |
* scheduled. */
|
sl@0
|
261 |
#define CHANNEL_CLOSED (1<<8) /* Channel has been closed. No
|
sl@0
|
262 |
* further Tcl-level IO on the
|
sl@0
|
263 |
* channel is allowed. */
|
sl@0
|
264 |
#define CHANNEL_EOF (1<<9) /* EOF occurred on this channel.
|
sl@0
|
265 |
* This bit is cleared before every
|
sl@0
|
266 |
* input operation. */
|
sl@0
|
267 |
#define CHANNEL_STICKY_EOF (1<<10) /* EOF occurred on this channel because
|
sl@0
|
268 |
* we saw the input eofChar. This bit
|
sl@0
|
269 |
* prevents clearing of the EOF bit
|
sl@0
|
270 |
* before every input operation. */
|
sl@0
|
271 |
#define CHANNEL_BLOCKED (1<<11) /* EWOULDBLOCK or EAGAIN occurred
|
sl@0
|
272 |
* on this channel. This bit is
|
sl@0
|
273 |
* cleared before every input or
|
sl@0
|
274 |
* output operation. */
|
sl@0
|
275 |
#define INPUT_SAW_CR (1<<12) /* Channel is in CRLF eol input
|
sl@0
|
276 |
* translation mode and the last
|
sl@0
|
277 |
* byte seen was a "\r". */
|
sl@0
|
278 |
#define INPUT_NEED_NL (1<<15) /* Saw a '\r' at end of last buffer,
|
sl@0
|
279 |
* and there should be a '\n' at
|
sl@0
|
280 |
* beginning of next buffer. */
|
sl@0
|
281 |
#define CHANNEL_DEAD (1<<13) /* The channel has been closed by
|
sl@0
|
282 |
* the exit handler (on exit) but
|
sl@0
|
283 |
* not deallocated. When any IO
|
sl@0
|
284 |
* operation sees this flag on a
|
sl@0
|
285 |
* channel, it does not call driver
|
sl@0
|
286 |
* level functions to avoid referring
|
sl@0
|
287 |
* to deallocated data. */
|
sl@0
|
288 |
#define CHANNEL_NEED_MORE_DATA (1<<14) /* The last input operation failed
|
sl@0
|
289 |
* because there was not enough data
|
sl@0
|
290 |
* to complete the operation. This
|
sl@0
|
291 |
* flag is set when gets fails to
|
sl@0
|
292 |
* get a complete line or when read
|
sl@0
|
293 |
* fails to get a complete character.
|
sl@0
|
294 |
* When set, file events will not be
|
sl@0
|
295 |
* delivered for buffered data until
|
sl@0
|
296 |
* the state of the channel changes. */
|
sl@0
|
297 |
#define CHANNEL_RAW_MODE (1<<16) /* When set, notes that the Raw API is
|
sl@0
|
298 |
* being used. */
|
sl@0
|
299 |
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
|
sl@0
|
300 |
#define CHANNEL_TIMER_FEV (1<<17) /* When set the event we are
|
sl@0
|
301 |
* notified by is a fileevent
|
sl@0
|
302 |
* generated by a timer. We
|
sl@0
|
303 |
* don't know if the driver
|
sl@0
|
304 |
* has more data and should
|
sl@0
|
305 |
* not try to read from it. If
|
sl@0
|
306 |
* the system needs more than
|
sl@0
|
307 |
* is in the buffers out read
|
sl@0
|
308 |
* routines will simulate a
|
sl@0
|
309 |
* short read (0 characters
|
sl@0
|
310 |
* read) */
|
sl@0
|
311 |
#define CHANNEL_HAS_MORE_DATA (1<<18) /* Set by NotifyChannel for a
|
sl@0
|
312 |
* channel if and only if the
|
sl@0
|
313 |
* channel is configured
|
sl@0
|
314 |
* non-blocking, the driver
|
sl@0
|
315 |
* for said channel has no
|
sl@0
|
316 |
* blockmodeproc, and data has
|
sl@0
|
317 |
* arrived for reading at the
|
sl@0
|
318 |
* OS level). A GetInput will
|
sl@0
|
319 |
* pass reading from the
|
sl@0
|
320 |
* driver if the channel is
|
sl@0
|
321 |
* non-blocking, without
|
sl@0
|
322 |
* blockmode proc and the flag
|
sl@0
|
323 |
* has not been set. A read
|
sl@0
|
324 |
* will be performed if the
|
sl@0
|
325 |
* flag is set. This will
|
sl@0
|
326 |
* reset the flag as well. */
|
sl@0
|
327 |
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
|
sl@0
|
328 |
|
sl@0
|
329 |
#define CHANNEL_INCLOSE (1<<19) /* Channel is currently being
|
sl@0
|
330 |
* closed. Its structures are
|
sl@0
|
331 |
* still live and usable, but
|
sl@0
|
332 |
* it may not be closed again
|
sl@0
|
333 |
* from within the close handler.
|
sl@0
|
334 |
*/
|
sl@0
|
335 |
|
sl@0
|
336 |
/*
|
sl@0
|
337 |
* For each channel handler registered in a call to Tcl_CreateChannelHandler,
|
sl@0
|
338 |
* there is one record of the following type. All of records for a specific
|
sl@0
|
339 |
* channel are chained together in a singly linked list which is stored in
|
sl@0
|
340 |
* the channel structure.
|
sl@0
|
341 |
*/
|
sl@0
|
342 |
|
sl@0
|
343 |
typedef struct ChannelHandler {
|
sl@0
|
344 |
Channel *chanPtr; /* The channel structure for this channel. */
|
sl@0
|
345 |
int mask; /* Mask of desired events. */
|
sl@0
|
346 |
Tcl_ChannelProc *proc; /* Procedure to call in the type of
|
sl@0
|
347 |
* Tcl_CreateChannelHandler. */
|
sl@0
|
348 |
ClientData clientData; /* Argument to pass to procedure. */
|
sl@0
|
349 |
struct ChannelHandler *nextPtr;
|
sl@0
|
350 |
/* Next one in list of registered handlers. */
|
sl@0
|
351 |
} ChannelHandler;
|
sl@0
|
352 |
|
sl@0
|
353 |
/*
|
sl@0
|
354 |
* This structure keeps track of the current ChannelHandler being invoked in
|
sl@0
|
355 |
* the current invocation of ChannelHandlerEventProc. There is a potential
|
sl@0
|
356 |
* problem if a ChannelHandler is deleted while it is the current one, since
|
sl@0
|
357 |
* ChannelHandlerEventProc needs to look at the nextPtr field. To handle this
|
sl@0
|
358 |
* problem, structures of the type below indicate the next handler to be
|
sl@0
|
359 |
* processed for any (recursively nested) dispatches in progress. The
|
sl@0
|
360 |
* nextHandlerPtr field is updated if the handler being pointed to is deleted.
|
sl@0
|
361 |
* The nextPtr field is used to chain together all recursive invocations, so
|
sl@0
|
362 |
* that Tcl_DeleteChannelHandler can find all the recursively nested
|
sl@0
|
363 |
* invocations of ChannelHandlerEventProc and compare the handler being
|
sl@0
|
364 |
* deleted against the NEXT handler to be invoked in that invocation; when it
|
sl@0
|
365 |
* finds such a situation, Tcl_DeleteChannelHandler updates the nextHandlerPtr
|
sl@0
|
366 |
* field of the structure to the next handler.
|
sl@0
|
367 |
*/
|
sl@0
|
368 |
|
sl@0
|
369 |
typedef struct NextChannelHandler {
|
sl@0
|
370 |
ChannelHandler *nextHandlerPtr; /* The next handler to be invoked in
|
sl@0
|
371 |
* this invocation. */
|
sl@0
|
372 |
struct NextChannelHandler *nestedHandlerPtr;
|
sl@0
|
373 |
/* Next nested invocation of
|
sl@0
|
374 |
* ChannelHandlerEventProc. */
|
sl@0
|
375 |
} NextChannelHandler;
|
sl@0
|
376 |
|
sl@0
|
377 |
|
sl@0
|
378 |
/*
|
sl@0
|
379 |
* The following structure describes the event that is added to the Tcl
|
sl@0
|
380 |
* event queue by the channel handler check procedure.
|
sl@0
|
381 |
*/
|
sl@0
|
382 |
|
sl@0
|
383 |
typedef struct ChannelHandlerEvent {
|
sl@0
|
384 |
Tcl_Event header; /* Standard header for all events. */
|
sl@0
|
385 |
Channel *chanPtr; /* The channel that is ready. */
|
sl@0
|
386 |
int readyMask; /* Events that have occurred. */
|
sl@0
|
387 |
} ChannelHandlerEvent;
|
sl@0
|
388 |
|
sl@0
|
389 |
/*
|
sl@0
|
390 |
* The following structure is used by Tcl_GetsObj() to encapsulates the
|
sl@0
|
391 |
* state for a "gets" operation.
|
sl@0
|
392 |
*/
|
sl@0
|
393 |
|
sl@0
|
394 |
typedef struct GetsState {
|
sl@0
|
395 |
Tcl_Obj *objPtr; /* The object to which UTF-8 characters
|
sl@0
|
396 |
* will be appended. */
|
sl@0
|
397 |
char **dstPtr; /* Pointer into objPtr's string rep where
|
sl@0
|
398 |
* next character should be stored. */
|
sl@0
|
399 |
Tcl_Encoding encoding; /* The encoding to use to convert raw bytes
|
sl@0
|
400 |
* to UTF-8. */
|
sl@0
|
401 |
ChannelBuffer *bufPtr; /* The current buffer of raw bytes being
|
sl@0
|
402 |
* emptied. */
|
sl@0
|
403 |
Tcl_EncodingState state; /* The encoding state just before the last
|
sl@0
|
404 |
* external to UTF-8 conversion in
|
sl@0
|
405 |
* FilterInputBytes(). */
|
sl@0
|
406 |
int rawRead; /* The number of bytes removed from bufPtr
|
sl@0
|
407 |
* in the last call to FilterInputBytes(). */
|
sl@0
|
408 |
int bytesWrote; /* The number of bytes of UTF-8 data
|
sl@0
|
409 |
* appended to objPtr during the last call to
|
sl@0
|
410 |
* FilterInputBytes(). */
|
sl@0
|
411 |
int charsWrote; /* The corresponding number of UTF-8
|
sl@0
|
412 |
* characters appended to objPtr during the
|
sl@0
|
413 |
* last call to FilterInputBytes(). */
|
sl@0
|
414 |
int totalChars; /* The total number of UTF-8 characters
|
sl@0
|
415 |
* appended to objPtr so far, just before the
|
sl@0
|
416 |
* last call to FilterInputBytes(). */
|
sl@0
|
417 |
} GetsState;
|