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