[25] | 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 | */ |
---|