tclIO.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:273k
源码类别:

通讯编程

开发平台:

Visual C++

  1.     endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0);
  2.     /*
  3.      * Loop over all UTF-8 characters in src, storing them in staging buffer
  4.      * with proper EOL translation.
  5.      */
  6.     consumedSomething = 1;
  7.     while (consumedSomething && (srcLen + savedLF + endEncoding > 0)) {
  8.         consumedSomething = 0;
  9. stage = statePtr->outputStage;
  10. stageMax = statePtr->bufSize;
  11. stageLen = stageMax;
  12. toWrite = stageLen;
  13. if (toWrite > srcLen) {
  14.     toWrite = srcLen;
  15. }
  16. if (savedLF) {
  17.     /*
  18.      * A 'n' was left over from last call to TranslateOutputEOL()
  19.      * and we need to store it in the staging buffer.  If the
  20.      * channel is line-based, we will need to flush the output
  21.      * buffer (after translating the staging buffer).
  22.      */
  23.     
  24.     *stage++ = 'n';
  25.     stageLen--;
  26.     sawLF++;
  27. }
  28. sawLF += TranslateOutputEOL(statePtr, stage, src, &stageLen, &toWrite);
  29. stage -= savedLF;
  30. stageLen += savedLF;
  31. savedLF = 0;
  32. if (stageLen > stageMax) {
  33.     savedLF = 1;
  34.     stageLen = stageMax;
  35. }
  36. src += toWrite;
  37. srcLen -= toWrite;
  38. /*
  39.  * Loop over all UTF-8 characters in staging buffer, converting them
  40.  * to external encoding, storing them in output buffer.
  41.  */
  42. while (stageLen + saved + endEncoding > 0) {
  43.     bufPtr = statePtr->curOutPtr;
  44.     if (bufPtr == NULL) {
  45. bufPtr = AllocChannelBuffer(statePtr->bufSize);
  46. statePtr->curOutPtr = bufPtr;
  47.     }
  48.     dst = bufPtr->buf + bufPtr->nextAdded;
  49.     dstLen = bufPtr->bufLength - bufPtr->nextAdded;
  50.     if (saved != 0) {
  51. /*
  52.  * Here's some translated bytes left over from the last
  53.  * buffer that we need to stick at the beginning of this
  54.  * buffer.
  55.  */
  56.  
  57. memcpy((VOID *) dst, (VOID *) safe, (size_t) saved);
  58. bufPtr->nextAdded += saved;
  59. dst += saved;
  60. dstLen -= saved;
  61. saved = 0;
  62.     }
  63.     result = Tcl_UtfToExternal(NULL, encoding, stage, stageLen,
  64.     statePtr->outputEncodingFlags,
  65.     &statePtr->outputEncodingState, dst,
  66.     dstLen + BUFFER_PADDING, &stageRead, &dstWrote, NULL);
  67.     /* Fix for SF #506297, reported by Martin Forssen
  68.      * <ruric@users.sourceforge.net>.
  69.      *
  70.      * The encoding chosen in the script exposing the bug writes out
  71.      * three intro characters when TCL_ENCODING_START is set, but does
  72.      * not consume any input as TCL_ENCODING_END is cleared. As some
  73.      * output was generated the enclosing loop calls UtfToExternal
  74.      * again, again with START set. Three more characters in the out
  75.      * and still no use of input ... To break this infinite loop we
  76.      * remove TCL_ENCODING_START from the set of flags after the first
  77.      * call (no condition is required, the later calls remove an unset
  78.      * flag, which is a no-op). This causes the subsequent calls to
  79.      * UtfToExternal to consume and convert the actual input.
  80.      */
  81.     statePtr->outputEncodingFlags &= ~TCL_ENCODING_START;
  82.     /*
  83.      * The following code must be executed only when result is not 0.
  84.      */
  85.     if (result && ((stageRead + dstWrote) == 0)) {
  86. /*
  87.  * We have an incomplete UTF-8 character at the end of the
  88.  * staging buffer.  It will get moved to the beginning of the
  89.  * staging buffer followed by more bytes from src.
  90.  */
  91. src -= stageLen;
  92. srcLen += stageLen;
  93. stageLen = 0;
  94. savedLF = 0;
  95. break;
  96.     }
  97.     bufPtr->nextAdded += dstWrote;
  98.     if (bufPtr->nextAdded > bufPtr->bufLength) {
  99. /*
  100.  * When translating from UTF-8 to external encoding, we
  101.  * allowed the translation to produce a character that
  102.  * crossed the end of the output buffer, so that we would
  103.  * get a completely full buffer before flushing it.  The
  104.  * extra bytes will be moved to the beginning of the next
  105.  * buffer.
  106.  */
  107. saved = bufPtr->nextAdded - bufPtr->bufLength;
  108. memcpy((VOID *) safe, (VOID *) (dst + dstLen), (size_t) saved);
  109. bufPtr->nextAdded = bufPtr->bufLength;
  110.     }
  111.     if (CheckFlush(chanPtr, bufPtr, sawLF) != 0) {
  112. return -1;
  113.     }
  114.     total += dstWrote;
  115.     stage += stageRead;
  116.     stageLen -= stageRead;
  117.     sawLF = 0;
  118.     consumedSomething = 1;
  119.     /*
  120.      * If all translated characters are written to the buffer,
  121.      * endEncoding is set to 0 because the escape sequence may be
  122.      * output.
  123.      */
  124.     if ((stageLen + saved == 0) && (result == 0)) {
  125. endEncoding = 0;
  126.     }
  127. }
  128.     }
  129.     /* If nothing was written and it happened because there was no progress
  130.      * in the UTF conversion, we throw an error.
  131.      */
  132.     if (!consumedSomething && (total == 0)) {
  133.         Tcl_SetErrno (EINVAL);
  134.         return -1;
  135.     }
  136.     return total;
  137. }
  138. /*
  139.  *---------------------------------------------------------------------------
  140.  *
  141.  * TranslateOutputEOL --
  142.  *
  143.  * Helper function for WriteBytes() and WriteChars().  Converts the
  144.  * 'n' characters in the source buffer into the appropriate EOL
  145.  * form specified by the output translation mode.
  146.  *
  147.  * EOL translation stops either when the source buffer is empty
  148.  * or the output buffer is full.
  149.  *
  150.  * When converting to CRLF mode and there is only 1 byte left in
  151.  * the output buffer, this routine stores the 'r' in the last
  152.  * byte and then stores the 'n' in the byte just past the end of the 
  153.  * buffer.  The caller is responsible for passing in a buffer that
  154.  * is large enough to hold the extra byte.
  155.  *
  156.  * Results:
  157.  * The return value is 1 if a 'n' was translated from the source
  158.  * buffer, or 0 otherwise -- this can be used by the caller to
  159.  * decide to flush a line-based channel even though the channel
  160.  * buffer is not full.
  161.  *
  162.  * *dstLenPtr is filled with how many bytes of the output buffer
  163.  * were used.  As mentioned above, this can be one more that
  164.  * the output buffer's specified length if a CRLF was stored.
  165.  *
  166.  * *srcLenPtr is filled with how many bytes of the source buffer
  167.  * were consumed.  
  168.  *
  169.  * Side effects:
  170.  * It may be obvious, but bears mentioning that when converting
  171.  * in CRLF mode (which requires two bytes of storage in the output
  172.  * buffer), the number of bytes consumed from the source buffer
  173.  * will be less than the number of bytes stored in the output buffer.
  174.  *
  175.  *---------------------------------------------------------------------------
  176.  */
  177. static int
  178. TranslateOutputEOL(statePtr, dst, src, dstLenPtr, srcLenPtr)
  179.     ChannelState *statePtr; /* Channel being read, for translation and
  180.  * buffering modes. */
  181.     char *dst; /* Output buffer filled with UTF-8 chars by
  182.  * applying appropriate EOL translation to
  183.  * source characters. */
  184.     CONST char *src; /* Source UTF-8 characters. */
  185.     int *dstLenPtr; /* On entry, the maximum length of output
  186.  * buffer in bytes.  On exit, the number of
  187.  * bytes actually used in output buffer. */
  188.     int *srcLenPtr; /* On entry, the length of source buffer.
  189.  * On exit, the number of bytes read from
  190.  * the source buffer. */
  191. {
  192.     char *dstEnd;
  193.     int srcLen, newlineFound;
  194.     
  195.     newlineFound = 0;
  196.     srcLen = *srcLenPtr;
  197.     switch (statePtr->outputTranslation) {
  198. case TCL_TRANSLATE_LF: {
  199.     for (dstEnd = dst + srcLen; dst < dstEnd; ) {
  200. if (*src == 'n') {
  201.     newlineFound = 1;
  202. }
  203. *dst++ = *src++;
  204.     }
  205.     *dstLenPtr = srcLen;
  206.     break;
  207. }
  208. case TCL_TRANSLATE_CR: {
  209.     for (dstEnd = dst + srcLen; dst < dstEnd;) {
  210. if (*src == 'n') {
  211.     *dst++ = 'r';
  212.     newlineFound = 1;
  213.     src++;
  214. } else {
  215.     *dst++ = *src++;
  216. }
  217.     }
  218.     *dstLenPtr = srcLen;
  219.     break;
  220. }
  221. case TCL_TRANSLATE_CRLF: {
  222.     /*
  223.      * Since this causes the number of bytes to grow, we
  224.      * start off trying to put 'srcLen' bytes into the
  225.      * output buffer, but allow it to store more bytes, as
  226.      * long as there's still source bytes and room in the
  227.      * output buffer.
  228.      */
  229.     char *dstStart, *dstMax;
  230.     CONST char *srcStart;
  231.     
  232.     dstStart = dst;
  233.     dstMax = dst + *dstLenPtr;
  234.     srcStart = src;
  235.     
  236.     if (srcLen < *dstLenPtr) {
  237. dstEnd = dst + srcLen;
  238.     } else {
  239. dstEnd = dst + *dstLenPtr;
  240.     }
  241.     while (dst < dstEnd) {
  242. if (*src == 'n') {
  243.     if (dstEnd < dstMax) {
  244. dstEnd++;
  245.     }
  246.     *dst++ = 'r';
  247.     newlineFound = 1;
  248. }
  249. *dst++ = *src++;
  250.     }
  251.     *srcLenPtr = src - srcStart;
  252.     *dstLenPtr = dst - dstStart;
  253.     break;
  254. }
  255. default: {
  256.     break;
  257. }
  258.     }
  259.     return newlineFound;
  260. }
  261. /*
  262.  *---------------------------------------------------------------------------
  263.  *
  264.  * CheckFlush --
  265.  *
  266.  * Helper function for WriteBytes() and WriteChars().  If the
  267.  * channel buffer is ready to be flushed, flush it.
  268.  *
  269.  * Results:
  270.  * The return value is -1 if there was a problem flushing the
  271.  * channel buffer, or 0 otherwise.
  272.  *
  273.  * Side effects:
  274.  * The buffer will be recycled if it is flushed.
  275.  *
  276.  *---------------------------------------------------------------------------
  277.  */
  278. static int
  279. CheckFlush(chanPtr, bufPtr, newlineFlag)
  280.     Channel *chanPtr; /* Channel being read, for buffering mode. */
  281.     ChannelBuffer *bufPtr; /* Channel buffer to possibly flush. */
  282.     int newlineFlag; /* Non-zero if a the channel buffer
  283.  * contains a newline. */
  284. {
  285.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  286.     /*
  287.      * The current buffer is ready for output:
  288.      * 1. if it is full.
  289.      * 2. if it contains a newline and this channel is line-buffered.
  290.      * 3. if it contains any output and this channel is unbuffered.
  291.      */
  292.     if ((statePtr->flags & BUFFER_READY) == 0) {
  293. if (bufPtr->nextAdded == bufPtr->bufLength) {
  294.     statePtr->flags |= BUFFER_READY;
  295. } else if (statePtr->flags & CHANNEL_LINEBUFFERED) {
  296.     if (newlineFlag != 0) {
  297. statePtr->flags |= BUFFER_READY;
  298.     }
  299. } else if (statePtr->flags & CHANNEL_UNBUFFERED) {
  300.     statePtr->flags |= BUFFER_READY;
  301. }
  302.     }
  303.     if (statePtr->flags & BUFFER_READY) {
  304. if (FlushChannel(NULL, chanPtr, 0) != 0) {
  305.     return -1;
  306. }
  307.     }
  308.     return 0;
  309. }
  310. /*
  311.  *---------------------------------------------------------------------------
  312.  *
  313.  * Tcl_Gets --
  314.  *
  315.  * Reads a complete line of input from the channel into a Tcl_DString.
  316.  *
  317.  * Results:
  318.  * Length of line read (in characters) or -1 if error, EOF, or blocked.
  319.  * If -1, use Tcl_GetErrno() to retrieve the POSIX error code for the
  320.  * error or condition that occurred.
  321.  *
  322.  * Side effects:
  323.  * May flush output on the channel.  May cause input to be consumed
  324.  * from the channel.
  325.  *
  326.  *---------------------------------------------------------------------------
  327.  */
  328. int
  329. Tcl_Gets(chan, lineRead)
  330.     Tcl_Channel chan; /* Channel from which to read. */
  331.     Tcl_DString *lineRead; /* The line read will be appended to this
  332.  * DString as UTF-8 characters.  The caller
  333.  * must have initialized it and is responsible
  334.  * for managing the storage. */
  335. {
  336.     Tcl_Obj *objPtr;
  337.     int charsStored, length;
  338.     char *string;
  339.     objPtr = Tcl_NewObj();
  340.     charsStored = Tcl_GetsObj(chan, objPtr);
  341.     if (charsStored > 0) {
  342. string = Tcl_GetStringFromObj(objPtr, &length);
  343. Tcl_DStringAppend(lineRead, string, length);
  344.     }
  345.     Tcl_DecrRefCount(objPtr);
  346.     return charsStored;
  347. }
  348. /*
  349.  *---------------------------------------------------------------------------
  350.  *
  351.  * Tcl_GetsObj --
  352.  *
  353.  * Accumulate input from the input channel until end-of-line or
  354.  * end-of-file has been seen.  Bytes read from the input channel
  355.  * are converted to UTF-8 using the encoding specified by the
  356.  * channel.
  357.  *
  358.  * Results:
  359.  * Number of characters accumulated in the object or -1 if error,
  360.  * blocked, or EOF.  If -1, use Tcl_GetErrno() to retrieve the
  361.  * POSIX error code for the error or condition that occurred.
  362.  *
  363.  * Side effects:
  364.  * Consumes input from the channel.
  365.  *
  366.  * On reading EOF, leave channel pointing at EOF char.
  367.  * On reading EOL, leave channel pointing after EOL, but don't
  368.  * return EOL in dst buffer.
  369.  *
  370.  *---------------------------------------------------------------------------
  371.  */
  372. int
  373. Tcl_GetsObj(chan, objPtr)
  374.     Tcl_Channel chan; /* Channel from which to read. */
  375.     Tcl_Obj *objPtr; /* The line read will be appended to this
  376.  * object as UTF-8 characters. */
  377. {
  378.     GetsState gs;
  379.     Channel *chanPtr = (Channel *) chan;
  380.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  381.     ChannelBuffer *bufPtr;
  382.     int inEofChar, skip, copiedTotal, oldLength, oldFlags, oldRemoved;
  383.     Tcl_Encoding encoding;
  384.     char *dst, *dstEnd, *eol, *eof;
  385.     Tcl_EncodingState oldState;
  386.     /*
  387.      * This operation should occur at the top of a channel stack.
  388.      */
  389.     chanPtr = statePtr->topChanPtr;
  390.     if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
  391. copiedTotal = -1;
  392. goto done;
  393.     }
  394.     bufPtr = statePtr->inQueueHead;
  395.     encoding = statePtr->encoding;
  396.     /*
  397.      * Preserved so we can restore the channel's state in case we don't
  398.      * find a newline in the available input.
  399.      */
  400.     Tcl_GetStringFromObj(objPtr, &oldLength);
  401.     oldFlags = statePtr->inputEncodingFlags;
  402.     oldState = statePtr->inputEncodingState;
  403.     oldRemoved = BUFFER_PADDING;
  404.     if (bufPtr != NULL) {
  405. oldRemoved = bufPtr->nextRemoved;
  406.     }
  407.     /*
  408.      * If there is no encoding, use "iso8859-1" -- Tcl_GetsObj() doesn't
  409.      * produce ByteArray objects.  To avoid circularity problems,
  410.      * "iso8859-1" is builtin to Tcl.
  411.      */
  412.     if (encoding == NULL) {
  413. encoding = Tcl_GetEncoding(NULL, "iso8859-1");
  414.     }
  415.     /*
  416.      * Object used by FilterInputBytes to keep track of how much data has
  417.      * been consumed from the channel buffers.
  418.      */
  419.     gs.objPtr = objPtr;
  420.     gs.dstPtr = &dst;
  421.     gs.encoding = encoding;
  422.     gs.bufPtr = bufPtr;
  423.     gs.state = oldState;
  424.     gs.rawRead = 0;
  425.     gs.bytesWrote = 0;
  426.     gs.charsWrote = 0;
  427.     gs.totalChars = 0;
  428.     dst = objPtr->bytes + oldLength;
  429.     dstEnd = dst;
  430.     skip = 0;
  431.     eof = NULL;
  432.     inEofChar = statePtr->inEofChar;
  433.     while (1) {
  434. if (dst >= dstEnd) {
  435.     if (FilterInputBytes(chanPtr, &gs) != 0) {
  436. goto restore;
  437.     }
  438.     dstEnd = dst + gs.bytesWrote;
  439. }
  440. /*
  441.  * Remember if EOF char is seen, then look for EOL anyhow, because
  442.  * the EOL might be before the EOF char.
  443.  */
  444. if (inEofChar != '') {
  445.     for (eol = dst; eol < dstEnd; eol++) {
  446. if (*eol == inEofChar) {
  447.     dstEnd = eol;
  448.     eof = eol;
  449.     break;
  450. }
  451.     }
  452. }
  453. /*
  454.  * On EOL, leave current file position pointing after the EOL, but
  455.  * don't store the EOL in the output string.
  456.  */
  457. switch (statePtr->inputTranslation) {
  458.     case TCL_TRANSLATE_LF: {
  459. for (eol = dst; eol < dstEnd; eol++) {
  460.     if (*eol == 'n') {
  461. skip = 1;
  462. goto goteol;
  463.     }
  464. }
  465. break;
  466.     }
  467.     case TCL_TRANSLATE_CR: {
  468. for (eol = dst; eol < dstEnd; eol++) {
  469.     if (*eol == 'r') {
  470. skip = 1;
  471. goto goteol;
  472.     }
  473. }
  474. break;
  475.     }
  476.     case TCL_TRANSLATE_CRLF: {
  477. for (eol = dst; eol < dstEnd; eol++) {
  478.     if (*eol == 'r') {
  479. eol++;
  480. if (eol >= dstEnd) {
  481.     int offset;
  482.     
  483.     offset = eol - objPtr->bytes;
  484.     dst = dstEnd;
  485.     if (FilterInputBytes(chanPtr, &gs) != 0) {
  486. goto restore;
  487.     }
  488.     dstEnd = dst + gs.bytesWrote;
  489.     eol = objPtr->bytes + offset;
  490.     if (eol >= dstEnd) {
  491. skip = 0;
  492. goto goteol;
  493.     }
  494. }
  495. if (*eol == 'n') {
  496.     eol--;
  497.     skip = 2;
  498.     goto goteol;
  499. }
  500.     }
  501. }
  502. break;
  503.     }
  504.     case TCL_TRANSLATE_AUTO: {
  505. eol = dst;
  506. skip = 1;
  507. if (statePtr->flags & INPUT_SAW_CR) {
  508.     statePtr->flags &= ~INPUT_SAW_CR;
  509.     if (*eol == 'n') {
  510. /*
  511.  * Skip the raw bytes that make up the 'n'.
  512.  */
  513. char tmp[1 + TCL_UTF_MAX];
  514. int rawRead;
  515. bufPtr = gs.bufPtr;
  516. Tcl_ExternalToUtf(NULL, gs.encoding,
  517. bufPtr->buf + bufPtr->nextRemoved,
  518. gs.rawRead, statePtr->inputEncodingFlags,
  519. &gs.state, tmp, 1 + TCL_UTF_MAX, &rawRead,
  520. NULL, NULL);
  521. bufPtr->nextRemoved += rawRead;
  522. gs.rawRead -= rawRead;
  523. gs.bytesWrote--;
  524. gs.charsWrote--;
  525. memmove(dst, dst + 1, (size_t) (dstEnd - dst));
  526. dstEnd--;
  527.     }
  528. }
  529. for (eol = dst; eol < dstEnd; eol++) {
  530.     if (*eol == 'r') {
  531. eol++;
  532. if (eol == dstEnd) {
  533.     /*
  534.      * If buffer ended on r, peek ahead to see if a
  535.      * n is available.
  536.      */
  537.     int offset;
  538.     
  539.     offset = eol - objPtr->bytes;
  540.     dst = dstEnd;
  541.     PeekAhead(chanPtr, &dstEnd, &gs);
  542.     eol = objPtr->bytes + offset;
  543.     if (eol >= dstEnd) {
  544. eol--;
  545. statePtr->flags |= INPUT_SAW_CR;
  546. goto goteol;
  547.     }
  548. }
  549. if (*eol == 'n') {
  550.     skip++;
  551. }
  552. eol--;
  553. goto goteol;
  554.     } else if (*eol == 'n') {
  555. goto goteol;
  556.     }
  557. }
  558.     }
  559. }
  560. if (eof != NULL) {
  561.     /*
  562.      * EOF character was seen.  On EOF, leave current file position
  563.      * pointing at the EOF character, but don't store the EOF
  564.      * character in the output string.
  565.      */
  566.     dstEnd = eof;
  567.     statePtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF);
  568.     statePtr->inputEncodingFlags |= TCL_ENCODING_END;
  569. }
  570. if (statePtr->flags & CHANNEL_EOF) {
  571.     skip = 0;
  572.     eol = dstEnd;
  573.     if (eol == objPtr->bytes + oldLength) {
  574. /*
  575.  * If we didn't append any bytes before encountering EOF,
  576.  * caller needs to see -1.
  577.  */
  578. Tcl_SetObjLength(objPtr, oldLength);
  579. CommonGetsCleanup(chanPtr, encoding);
  580. copiedTotal = -1;
  581. goto done;
  582.     }
  583.     goto goteol;
  584. }
  585. dst = dstEnd;
  586.     }
  587.     /*
  588.      * Found EOL or EOF, but the output buffer may now contain too many
  589.      * UTF-8 characters.  We need to know how many raw bytes correspond to
  590.      * the number of UTF-8 characters we want, plus how many raw bytes
  591.      * correspond to the character(s) making up EOL (if any), so we can
  592.      * remove the correct number of bytes from the channel buffer.
  593.      */
  594.      
  595.     goteol:
  596.     bufPtr = gs.bufPtr;
  597.     statePtr->inputEncodingState = gs.state;
  598.     Tcl_ExternalToUtf(NULL, gs.encoding, bufPtr->buf + bufPtr->nextRemoved,
  599.     gs.rawRead, statePtr->inputEncodingFlags,
  600.     &statePtr->inputEncodingState, dst,
  601.     eol - dst + skip + TCL_UTF_MAX, &gs.rawRead, NULL,
  602.     &gs.charsWrote);
  603.     bufPtr->nextRemoved += gs.rawRead;
  604.     /*
  605.      * Recycle all the emptied buffers.
  606.      */
  607.     Tcl_SetObjLength(objPtr, eol - objPtr->bytes);
  608.     CommonGetsCleanup(chanPtr, encoding);
  609.     statePtr->flags &= ~CHANNEL_BLOCKED;
  610.     copiedTotal = gs.totalChars + gs.charsWrote - skip;
  611.     goto done;
  612.     /*
  613.      * Couldn't get a complete line.  This only happens if we get a error
  614.      * reading from the channel or we are non-blocking and there wasn't
  615.      * an EOL or EOF in the data available.
  616.      */
  617.     restore:
  618.     bufPtr = statePtr->inQueueHead;
  619.     bufPtr->nextRemoved = oldRemoved;
  620.     for (bufPtr = bufPtr->nextPtr; bufPtr != NULL; bufPtr = bufPtr->nextPtr) {
  621. bufPtr->nextRemoved = BUFFER_PADDING;
  622.     }
  623.     CommonGetsCleanup(chanPtr, encoding);
  624.     statePtr->inputEncodingState = oldState;
  625.     statePtr->inputEncodingFlags = oldFlags;
  626.     Tcl_SetObjLength(objPtr, oldLength);
  627.     /*
  628.      * We didn't get a complete line so we need to indicate to UpdateInterest
  629.      * that the gets blocked.  It will wait for more data instead of firing
  630.      * a timer, avoiding a busy wait.  This is where we are assuming that the
  631.      * next operation is a gets.  No more file events will be delivered on 
  632.      * this channel until new data arrives or some operation is performed
  633.      * on the channel (e.g. gets, read, fconfigure) that changes the blocking
  634.      * state.  Note that this means a file event will not be delivered even
  635.      * though a read would be able to consume the buffered data.
  636.      */
  637.     statePtr->flags |= CHANNEL_NEED_MORE_DATA;
  638.     copiedTotal = -1;
  639.     done:
  640.     /*
  641.      * Update the notifier state so we don't block while there is still
  642.      * data in the buffers.
  643.      */
  644.     UpdateInterest(chanPtr);
  645.     return copiedTotal;
  646. }
  647. /*
  648.  *---------------------------------------------------------------------------
  649.  *
  650.  * FilterInputBytes --
  651.  *
  652.  * Helper function for Tcl_GetsObj.  Produces UTF-8 characters from
  653.  * raw bytes read from the channel.  
  654.  *
  655.  * Consumes available bytes from channel buffers.  When channel
  656.  * buffers are exhausted, reads more bytes from channel device into
  657.  * a new channel buffer.  It is the caller's responsibility to
  658.  * free the channel buffers that have been exhausted.
  659.  *
  660.  * Results:
  661.  * The return value is -1 if there was an error reading from the
  662.  * channel, 0 otherwise.
  663.  *
  664.  * Side effects:
  665.  * Status object keeps track of how much data from channel buffers
  666.  * has been consumed and where UTF-8 bytes should be stored.
  667.  *
  668.  *---------------------------------------------------------------------------
  669.  */
  670.  
  671. static int
  672. FilterInputBytes(chanPtr, gsPtr)
  673.     Channel *chanPtr; /* Channel to read. */
  674.     GetsState *gsPtr; /* Current state of gets operation. */
  675. {
  676.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  677.     ChannelBuffer *bufPtr;
  678.     char *raw, *rawStart, *rawEnd;
  679.     char *dst;
  680.     int offset, toRead, dstNeeded, spaceLeft, result, rawLen, length;
  681.     Tcl_Obj *objPtr;
  682. #define ENCODING_LINESIZE   20 /* Lower bound on how many bytes to convert
  683.  * at a time.  Since we don't know a priori
  684.  * how many bytes of storage this many source
  685.  * bytes will use, we actually need at least
  686.  * ENCODING_LINESIZE * TCL_MAX_UTF bytes of
  687.  * room. */
  688.     objPtr = gsPtr->objPtr;
  689.     /*
  690.      * Subtract the number of bytes that were removed from channel buffer
  691.      * during last call.
  692.      */
  693.     bufPtr = gsPtr->bufPtr;
  694.     if (bufPtr != NULL) {
  695. bufPtr->nextRemoved += gsPtr->rawRead;
  696. if (bufPtr->nextRemoved >= bufPtr->nextAdded) {
  697.     bufPtr = bufPtr->nextPtr;
  698. }
  699.     }
  700.     gsPtr->totalChars += gsPtr->charsWrote;
  701.     if ((bufPtr == NULL) || (bufPtr->nextAdded == BUFFER_PADDING)) {
  702. /*
  703.  * All channel buffers were exhausted and the caller still hasn't
  704.  * seen EOL.  Need to read more bytes from the channel device.
  705.  * Side effect is to allocate another channel buffer.
  706.  */
  707. read:
  708.         if (statePtr->flags & CHANNEL_BLOCKED) {
  709.             if (statePtr->flags & CHANNEL_NONBLOCKING) {
  710. gsPtr->charsWrote = 0;
  711. gsPtr->rawRead = 0;
  712. return -1;
  713.     }
  714.             statePtr->flags &= ~CHANNEL_BLOCKED;
  715.         }
  716. if (GetInput(chanPtr) != 0) {
  717.     gsPtr->charsWrote = 0;
  718.     gsPtr->rawRead = 0;
  719.     return -1;
  720. }
  721. bufPtr = statePtr->inQueueTail;
  722. gsPtr->bufPtr = bufPtr;
  723.     }
  724.     /*
  725.      * Convert some of the bytes from the channel buffer to UTF-8.  Space in
  726.      * objPtr's string rep is used to hold the UTF-8 characters.  Grow the
  727.      * string rep if we need more space.
  728.      */
  729.     rawStart = bufPtr->buf + bufPtr->nextRemoved;
  730.     raw = rawStart;
  731.     rawEnd = bufPtr->buf + bufPtr->nextAdded;
  732.     rawLen = rawEnd - rawStart;
  733.     dst = *gsPtr->dstPtr;
  734.     offset = dst - objPtr->bytes;
  735.     toRead = ENCODING_LINESIZE;
  736.     if (toRead > rawLen) {
  737. toRead = rawLen;
  738.     }
  739.     dstNeeded = toRead * TCL_UTF_MAX + 1;
  740.     spaceLeft = objPtr->length - offset - TCL_UTF_MAX - 1;
  741.     if (dstNeeded > spaceLeft) {
  742. length = offset * 2;
  743. if (offset < dstNeeded) {
  744.     length = offset + dstNeeded;
  745. }
  746. length += TCL_UTF_MAX + 1;
  747. Tcl_SetObjLength(objPtr, length);
  748. spaceLeft = length - offset;
  749. dst = objPtr->bytes + offset;
  750. *gsPtr->dstPtr = dst;
  751.     }
  752.     gsPtr->state = statePtr->inputEncodingState;
  753.     result = Tcl_ExternalToUtf(NULL, gsPtr->encoding, raw, rawLen,
  754.     statePtr->inputEncodingFlags, &statePtr->inputEncodingState,
  755.     dst, spaceLeft, &gsPtr->rawRead, &gsPtr->bytesWrote,
  756.     &gsPtr->charsWrote);
  757.     /*
  758.      * Make sure that if we go through 'gets', that we reset the
  759.      * TCL_ENCODING_START flag still.  [Bug #523988]
  760.      */
  761.     statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;
  762.     if (result == TCL_CONVERT_MULTIBYTE) {
  763. /*
  764.  * The last few bytes in this channel buffer were the start of a
  765.  * multibyte sequence.  If this buffer was full, then move them to
  766.  * the next buffer so the bytes will be contiguous.  
  767.  */
  768. ChannelBuffer *nextPtr;
  769. int extra;
  770. nextPtr = bufPtr->nextPtr;
  771. if (bufPtr->nextAdded < bufPtr->bufLength) {
  772.     if (gsPtr->rawRead > 0) {
  773. /*
  774.  * Some raw bytes were converted to UTF-8.  Fall through,
  775.  * returning those UTF-8 characters because a EOL might be
  776.  * present in them.
  777.  */
  778.     } else if (statePtr->flags & CHANNEL_EOF) {
  779. /*
  780.  * There was a partial character followed by EOF on the
  781.  * device.  Fall through, returning that nothing was found.
  782.  */
  783. bufPtr->nextRemoved = bufPtr->nextAdded;
  784.     } else {
  785. /*
  786.  * There are no more cached raw bytes left.  See if we can
  787.  * get some more.
  788.  */
  789. goto read;
  790.     }
  791. } else {
  792.     if (nextPtr == NULL) {
  793. nextPtr = AllocChannelBuffer(statePtr->bufSize);
  794. bufPtr->nextPtr = nextPtr;
  795. statePtr->inQueueTail = nextPtr;
  796.     }
  797.     extra = rawLen - gsPtr->rawRead;
  798.     memcpy((VOID *) (nextPtr->buf + BUFFER_PADDING - extra),
  799.     (VOID *) (raw + gsPtr->rawRead), (size_t) extra);
  800.     nextPtr->nextRemoved -= extra;
  801.     bufPtr->nextAdded -= extra;
  802. }
  803.     }
  804.     gsPtr->bufPtr = bufPtr;
  805.     return 0;
  806. }
  807. /*
  808.  *---------------------------------------------------------------------------
  809.  *
  810.  * PeekAhead --
  811.  *
  812.  * Helper function used by Tcl_GetsObj().  Called when we've seen a
  813.  * r at the end of the UTF-8 string and want to look ahead one
  814.  * character to see if it is a n.
  815.  *
  816.  * Results:
  817.  * *gsPtr->dstPtr is filled with a pointer to the start of the range of
  818.  * UTF-8 characters that were found by peeking and *dstEndPtr is filled
  819.  * with a pointer to the bytes just after the end of the range.
  820.  *
  821.  * Side effects:
  822.  * If no more raw bytes were available in one of the channel buffers,
  823.  * tries to perform a non-blocking read to get more bytes from the
  824.  * channel device.
  825.  *
  826.  *---------------------------------------------------------------------------
  827.  */
  828. static void
  829. PeekAhead(chanPtr, dstEndPtr, gsPtr)
  830.     Channel *chanPtr; /* The channel to read. */
  831.     char **dstEndPtr; /* Filled with pointer to end of new range
  832.  * of UTF-8 characters. */
  833.     GetsState *gsPtr; /* Current state of gets operation. */
  834. {
  835.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  836.     ChannelBuffer *bufPtr;
  837.     Tcl_DriverBlockModeProc *blockModeProc;
  838.     int bytesLeft;
  839.     bufPtr = gsPtr->bufPtr;
  840.     /*
  841.      * If there's any more raw input that's still buffered, we'll peek into
  842.      * that.  Otherwise, only get more data from the channel driver if it
  843.      * looks like there might actually be more data.  The assumption is that
  844.      * if the channel buffer is filled right up to the end, then there
  845.      * might be more data to read.
  846.      */
  847.     blockModeProc = NULL;
  848.     if (bufPtr->nextPtr == NULL) {
  849. bytesLeft = bufPtr->nextAdded - (bufPtr->nextRemoved + gsPtr->rawRead);
  850. if (bytesLeft == 0) {
  851.     if (bufPtr->nextAdded < bufPtr->bufLength) {
  852. /*
  853.  * Don't peek ahead if last read was short read.
  854.  */
  855.  
  856. goto cleanup;
  857.     }
  858.     if ((statePtr->flags & CHANNEL_NONBLOCKING) == 0) {
  859. blockModeProc = Tcl_ChannelBlockModeProc(chanPtr->typePtr);
  860. if (blockModeProc == NULL) {
  861.     /*
  862.      * Don't peek ahead if cannot set non-blocking mode.
  863.      */
  864.     goto cleanup;
  865. }
  866. StackSetBlockMode(chanPtr, TCL_MODE_NONBLOCKING);
  867.     }
  868. }
  869.     }
  870.     if (FilterInputBytes(chanPtr, gsPtr) == 0) {
  871. *dstEndPtr = *gsPtr->dstPtr + gsPtr->bytesWrote;
  872.     }
  873.     if (blockModeProc != NULL) {
  874. StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING);
  875.     }
  876.     return;
  877.     cleanup:
  878.     bufPtr->nextRemoved += gsPtr->rawRead;
  879.     gsPtr->rawRead = 0;
  880.     gsPtr->totalChars += gsPtr->charsWrote;
  881.     gsPtr->bytesWrote = 0;
  882.     gsPtr->charsWrote = 0;
  883. }
  884. /*
  885.  *---------------------------------------------------------------------------
  886.  *
  887.  * CommonGetsCleanup --
  888.  *
  889.  * Helper function for Tcl_GetsObj() to restore the channel after
  890.  * a "gets" operation.
  891.  *
  892.  * Results:
  893.  * None.
  894.  *
  895.  * Side effects:
  896.  * Encoding may be freed.
  897.  *
  898.  *---------------------------------------------------------------------------
  899.  */
  900.  
  901. static void
  902. CommonGetsCleanup(chanPtr, encoding)
  903.     Channel *chanPtr;
  904.     Tcl_Encoding encoding;
  905. {
  906.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  907.     ChannelBuffer *bufPtr, *nextPtr;
  908.     
  909.     bufPtr = statePtr->inQueueHead;
  910.     for ( ; bufPtr != NULL; bufPtr = nextPtr) {
  911. nextPtr = bufPtr->nextPtr;
  912. if (bufPtr->nextRemoved < bufPtr->nextAdded) {
  913.     break;
  914. }
  915. RecycleBuffer(statePtr, bufPtr, 0);
  916.     }
  917.     statePtr->inQueueHead = bufPtr;
  918.     if (bufPtr == NULL) {
  919. statePtr->inQueueTail = NULL;
  920.     } else {
  921. /*
  922.  * If any multi-byte characters were split across channel buffer
  923.  * boundaries, the split-up bytes were moved to the next channel
  924.  * buffer by FilterInputBytes().  Move the bytes back to their
  925.  * original buffer because the caller could change the channel's
  926.  * encoding which could change the interpretation of whether those
  927.  * bytes really made up multi-byte characters after all.
  928.  */
  929.  
  930. nextPtr = bufPtr->nextPtr;
  931. for ( ; nextPtr != NULL; nextPtr = bufPtr->nextPtr) {
  932.     int extra;
  933.     extra = bufPtr->bufLength - bufPtr->nextAdded;
  934.     if (extra > 0) {
  935. memcpy((VOID *) (bufPtr->buf + bufPtr->nextAdded),
  936. (VOID *) (nextPtr->buf + BUFFER_PADDING - extra),
  937. (size_t) extra);
  938. bufPtr->nextAdded += extra;
  939. nextPtr->nextRemoved = BUFFER_PADDING;
  940.     }
  941.     bufPtr = nextPtr;
  942. }
  943.     }
  944.     if (statePtr->encoding == NULL) {
  945. Tcl_FreeEncoding(encoding);
  946.     }
  947. }
  948. /*
  949.  *----------------------------------------------------------------------
  950.  *
  951.  * Tcl_Read --
  952.  *
  953.  * Reads a given number of bytes from a channel.  EOL and EOF
  954.  * translation is done on the bytes being read, so the the number
  955.  * of bytes consumed from the channel may not be equal to the
  956.  * number of bytes stored in the destination buffer.
  957.  *
  958.  * No encoding conversions are applied to the bytes being read.
  959.  *
  960.  * Results:
  961.  * The number of bytes read, or -1 on error. Use Tcl_GetErrno()
  962.  * to retrieve the error code for the error that occurred.
  963.  *
  964.  * Side effects:
  965.  * May cause input to be buffered.
  966.  *
  967.  *----------------------------------------------------------------------
  968.  */
  969. int
  970. Tcl_Read(chan, dst, bytesToRead)
  971.     Tcl_Channel chan; /* The channel from which to read. */
  972.     char *dst; /* Where to store input read. */
  973.     int bytesToRead; /* Maximum number of bytes to read. */
  974. {
  975.     Channel *chanPtr = (Channel *) chan;
  976.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  977.     /*
  978.      * This operation should occur at the top of a channel stack.
  979.      */
  980.     chanPtr = statePtr->topChanPtr;
  981.     if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
  982. return -1;
  983.     }
  984.     return DoRead(chanPtr, dst, bytesToRead);
  985. }
  986. /*
  987.  *----------------------------------------------------------------------
  988.  *
  989.  * Tcl_ReadRaw --
  990.  *
  991.  * Reads a given number of bytes from a channel.  EOL and EOF
  992.  * translation is done on the bytes being read, so the the number
  993.  * of bytes consumed from the channel may not be equal to the
  994.  * number of bytes stored in the destination buffer.
  995.  *
  996.  * No encoding conversions are applied to the bytes being read.
  997.  *
  998.  * Results:
  999.  * The number of bytes read, or -1 on error. Use Tcl_GetErrno()
  1000.  * to retrieve the error code for the error that occurred.
  1001.  *
  1002.  * Side effects:
  1003.  * May cause input to be buffered.
  1004.  *
  1005.  *----------------------------------------------------------------------
  1006.  */
  1007. int
  1008. Tcl_ReadRaw(chan, bufPtr, bytesToRead)
  1009.     Tcl_Channel chan; /* The channel from which to read. */
  1010.     char *bufPtr; /* Where to store input read. */
  1011.     int bytesToRead; /* Maximum number of bytes to read. */
  1012. {
  1013.     Channel *chanPtr = (Channel *) chan;
  1014.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  1015.     int nread, result;
  1016.     int copied, copiedNow;
  1017.     /*
  1018.      * The check below does too much because it will reject a call to this
  1019.      * function with a channel which is part of an 'fcopy'. But we have to
  1020.      * allow this here or else the chaining in the transformation drivers
  1021.      * will fail with 'file busy' error instead of retrieving and
  1022.      * transforming the data to copy.
  1023.      *
  1024.      * We let the check procedure now believe that there is no fcopy in
  1025.      * progress. A better solution than this might be an additional flag
  1026.      * argument to switch off specific checks.
  1027.      */
  1028.     if (CheckChannelErrors(statePtr, TCL_READABLE | CHANNEL_RAW_MODE) != 0) {
  1029. return -1;
  1030.     }
  1031.     /*
  1032.      * Check for information in the push-back buffers. If there is
  1033.      * some, use it. Go to the driver only if there is none (anymore)
  1034.      * and the caller requests more bytes.
  1035.      */
  1036.     for (copied = 0; copied < bytesToRead; copied += copiedNow) {
  1037.         copiedNow = CopyBuffer(chanPtr, bufPtr + copied,
  1038.                 bytesToRead - copied);
  1039.         if (copiedNow == 0) {
  1040.             if (statePtr->flags & CHANNEL_EOF) {
  1041. goto done;
  1042.             }
  1043.             if (statePtr->flags & CHANNEL_BLOCKED) {
  1044.                 if (statePtr->flags & CHANNEL_NONBLOCKING) {
  1045.     goto done;
  1046.                 }
  1047.                 statePtr->flags &= (~(CHANNEL_BLOCKED));
  1048.             }
  1049. #ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
  1050.     /* [SF Tcl Bug 943274]. Better emulation of non-blocking
  1051.      * channels for channels without BlockModeProc, by keeping
  1052.      * track of true fileevents generated by the OS == Data
  1053.      * waiting and reading if and only if we are sure to have
  1054.      * data.
  1055.      */
  1056.     if ((statePtr->flags & CHANNEL_NONBLOCKING) &&
  1057. (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) &&
  1058. !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) {
  1059.         /* We bypass the driver, it would block, as no data is available */
  1060.         nread  = -1;
  1061.         result = EWOULDBLOCK;
  1062.     } else {
  1063. #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
  1064.       /*
  1065.        * Now go to the driver to get as much as is possible to
  1066.        * fill the remaining request. Do all the error handling
  1067.        * by ourselves.  The code was stolen from 'GetInput' and
  1068.        * slightly adapted (different return value here).
  1069.        *
  1070.        * The case of 'bytesToRead == 0' at this point cannot happen.
  1071.        */
  1072.       nread = (chanPtr->typePtr->inputProc)(chanPtr->instanceData,
  1073.   bufPtr + copied, bytesToRead - copied, &result);
  1074. #ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
  1075.     }
  1076. #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
  1077.     if (nread > 0) {
  1078.         /*
  1079.  * If we get a short read, signal up that we may be
  1080.  * BLOCKED. We should avoid calling the driver because
  1081.  * on some platforms we will block in the low level
  1082.  * reading code even though the channel is set into
  1083.  * nonblocking mode.
  1084.  */
  1085.             
  1086.         if (nread < (bytesToRead - copied)) {
  1087.     statePtr->flags |= CHANNEL_BLOCKED;
  1088. }
  1089. #ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
  1090.         if (nread <= (bytesToRead - copied)) {
  1091.     /* [SF Tcl Bug 943274] We have read the available
  1092.      * data, clear flag */
  1093.     statePtr->flags &= ~CHANNEL_HAS_MORE_DATA;
  1094. }
  1095. #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
  1096.     } else if (nread == 0) {
  1097.         statePtr->flags |= CHANNEL_EOF;
  1098. statePtr->inputEncodingFlags |= TCL_ENCODING_END;
  1099.     } else if (nread < 0) {
  1100.         if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
  1101.     if (copied > 0) {
  1102.       /*
  1103.        * Information that was copied earlier has precedence
  1104.        * over EAGAIN/WOULDBLOCK handling.
  1105.        */
  1106.       return copied;
  1107.     }
  1108.     statePtr->flags |= CHANNEL_BLOCKED;
  1109.     result = EAGAIN;
  1110. }
  1111. Tcl_SetErrno(result);
  1112. return -1;
  1113.     } 
  1114.     return copied + nread;
  1115.         }
  1116.     }
  1117. done:
  1118.     return copied;
  1119. }
  1120. /*
  1121.  *---------------------------------------------------------------------------
  1122.  *
  1123.  * Tcl_ReadChars --
  1124.  *
  1125.  * Reads from the channel until the requested number of characters
  1126.  * have been seen, EOF is seen, or the channel would block.  EOL
  1127.  * and EOF translation is done.  If reading binary data, the raw
  1128.  * bytes are wrapped in a Tcl byte array object.  Otherwise, the raw
  1129.  * bytes are converted to UTF-8 using the channel's current encoding
  1130.  * and stored in a Tcl string object.
  1131.  *
  1132.  * Results:
  1133.  * The number of characters read, or -1 on error. Use Tcl_GetErrno()
  1134.  * to retrieve the error code for the error that occurred.
  1135.  *
  1136.  * Side effects:
  1137.  * May cause input to be buffered.
  1138.  *
  1139.  *---------------------------------------------------------------------------
  1140.  */
  1141.  
  1142. int
  1143. Tcl_ReadChars(chan, objPtr, toRead, appendFlag)
  1144.     Tcl_Channel chan; /* The channel to read. */
  1145.     Tcl_Obj *objPtr; /* Input data is stored in this object. */
  1146.     int toRead; /* Maximum number of characters to store,
  1147.  * or -1 to read all available data (up to EOF
  1148.  * or when channel blocks). */
  1149.     int appendFlag; /* If non-zero, data read from the channel
  1150.  * will be appended to the object.  Otherwise,
  1151.  * the data will replace the existing contents
  1152.  * of the object. */
  1153. {
  1154.     Channel*      chanPtr  = (Channel *) chan;
  1155.     ChannelState* statePtr = chanPtr->state; /* state info for channel */
  1156.     
  1157.     /*
  1158.      * This operation should occur at the top of a channel stack.
  1159.      */
  1160.     chanPtr = statePtr->topChanPtr;
  1161.     if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
  1162.         /*
  1163.  * Update the notifier state so we don't block while there is still
  1164.  * data in the buffers.
  1165.  */
  1166.         UpdateInterest(chanPtr);
  1167. return -1;
  1168.     }
  1169.     return DoReadChars (chanPtr, objPtr, toRead, appendFlag);
  1170. }
  1171. /*
  1172.  *---------------------------------------------------------------------------
  1173.  *
  1174.  * DoReadChars --
  1175.  *
  1176.  * Reads from the channel until the requested number of characters
  1177.  * have been seen, EOF is seen, or the channel would block.  EOL
  1178.  * and EOF translation is done.  If reading binary data, the raw
  1179.  * bytes are wrapped in a Tcl byte array object.  Otherwise, the raw
  1180.  * bytes are converted to UTF-8 using the channel's current encoding
  1181.  * and stored in a Tcl string object.
  1182.  *
  1183.  * Results:
  1184.  * The number of characters read, or -1 on error. Use Tcl_GetErrno()
  1185.  * to retrieve the error code for the error that occurred.
  1186.  *
  1187.  * Side effects:
  1188.  * May cause input to be buffered.
  1189.  *
  1190.  *---------------------------------------------------------------------------
  1191.  */
  1192.  
  1193. static int
  1194. DoReadChars(chanPtr, objPtr, toRead, appendFlag)
  1195.     Channel* chanPtr; /* The channel to read. */
  1196.     Tcl_Obj *objPtr; /* Input data is stored in this object. */
  1197.     int toRead; /* Maximum number of characters to store,
  1198.  * or -1 to read all available data (up to EOF
  1199.  * or when channel blocks). */
  1200.     int appendFlag; /* If non-zero, data read from the channel
  1201.  * will be appended to the object.  Otherwise,
  1202.  * the data will replace the existing contents
  1203.  * of the object. */
  1204. {
  1205.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  1206.     ChannelBuffer *bufPtr;
  1207.     int offset, factor, copied, copiedNow, result;
  1208.     Tcl_Encoding encoding;
  1209. #define UTF_EXPANSION_FACTOR 1024
  1210.     /*
  1211.      * This operation should occur at the top of a channel stack.
  1212.      */
  1213.     chanPtr  = statePtr->topChanPtr;
  1214.     encoding = statePtr->encoding;
  1215.     factor   = UTF_EXPANSION_FACTOR;
  1216.     if (appendFlag == 0) {
  1217. if (encoding == NULL) {
  1218.     Tcl_SetByteArrayLength(objPtr, 0);
  1219. } else {
  1220.     Tcl_SetObjLength(objPtr, 0);
  1221.     /* 
  1222.      * We're going to access objPtr->bytes directly, so
  1223.      * we must ensure that this is actually a string
  1224.      * object (otherwise it might have been pure Unicode).
  1225.      */
  1226.     Tcl_GetString(objPtr);
  1227. }
  1228. offset = 0;
  1229.     } else {
  1230. if (encoding == NULL) {
  1231.     Tcl_GetByteArrayFromObj(objPtr, &offset);
  1232. } else {
  1233.     Tcl_GetStringFromObj(objPtr, &offset);
  1234. }
  1235.     }
  1236.     for (copied = 0; (unsigned) toRead > 0; ) {
  1237. copiedNow = -1;
  1238. if (statePtr->inQueueHead != NULL) {
  1239.     if (encoding == NULL) {
  1240. copiedNow = ReadBytes(statePtr, objPtr, toRead, &offset);
  1241.     } else {
  1242. copiedNow = ReadChars(statePtr, objPtr, toRead, &offset,
  1243. &factor);
  1244.     }
  1245.     /*
  1246.      * If the current buffer is empty recycle it.
  1247.      */
  1248.     bufPtr = statePtr->inQueueHead;
  1249.     if (bufPtr->nextRemoved == bufPtr->nextAdded) {
  1250. ChannelBuffer *nextPtr;
  1251. nextPtr = bufPtr->nextPtr;
  1252. RecycleBuffer(statePtr, bufPtr, 0);
  1253. statePtr->inQueueHead = nextPtr;
  1254. if (nextPtr == NULL) {
  1255.     statePtr->inQueueTail = NULL;
  1256. }
  1257.     }
  1258. }
  1259. if (copiedNow < 0) {
  1260.     if (statePtr->flags & CHANNEL_EOF) {
  1261. break;
  1262.     }
  1263.     if (statePtr->flags & CHANNEL_BLOCKED) {
  1264. if (statePtr->flags & CHANNEL_NONBLOCKING) {
  1265.     break;
  1266. }
  1267. statePtr->flags &= ~CHANNEL_BLOCKED;
  1268.     }
  1269.     result = GetInput(chanPtr);
  1270.     if (result != 0) {
  1271. if (result == EAGAIN) {
  1272.     break;
  1273. }
  1274. copied = -1;
  1275. goto done;
  1276.     }
  1277. } else {
  1278.     copied += copiedNow;
  1279.     toRead -= copiedNow;
  1280. }
  1281.     }
  1282.     statePtr->flags &= ~CHANNEL_BLOCKED;
  1283.     if (encoding == NULL) {
  1284. Tcl_SetByteArrayLength(objPtr, offset);
  1285.     } else {
  1286. Tcl_SetObjLength(objPtr, offset);
  1287.     }
  1288.     done:
  1289.     /*
  1290.      * Update the notifier state so we don't block while there is still
  1291.      * data in the buffers.
  1292.      */
  1293.     UpdateInterest(chanPtr);
  1294.     return copied;
  1295. }
  1296. /*
  1297.  *---------------------------------------------------------------------------
  1298.  *
  1299.  * ReadBytes --
  1300.  *
  1301.  * Reads from the channel until the requested number of bytes have
  1302.  * been seen, EOF is seen, or the channel would block.  Bytes from
  1303.  * the channel are stored in objPtr as a ByteArray object.  EOL
  1304.  * and EOF translation are done.
  1305.  *
  1306.  * 'bytesToRead' can safely be a very large number because
  1307.  * space is only allocated to hold data read from the channel
  1308.  * as needed.
  1309.  *
  1310.  * Results:
  1311.  * The return value is the number of bytes appended to the object
  1312.  * and *offsetPtr is filled with the total number of bytes in the
  1313.  * object (greater than the return value if there were already bytes
  1314.  * in the object).
  1315.  *
  1316.  * Side effects:
  1317.  * None.
  1318.  *
  1319.  *---------------------------------------------------------------------------
  1320.  */
  1321. static int
  1322. ReadBytes(statePtr, objPtr, bytesToRead, offsetPtr)
  1323.     ChannelState *statePtr; /* State of the channel to read. */
  1324.     Tcl_Obj *objPtr; /* Input data is appended to this ByteArray
  1325.  * object.  Its length is how much space
  1326.  * has been allocated to hold data, not how
  1327.  * many bytes of data have been stored in the
  1328.  * object. */
  1329.     int bytesToRead; /* Maximum number of bytes to store,
  1330.  * or < 0 to get all available bytes.
  1331.  * Bytes are obtained from the first
  1332.  * buffer in the queue -- even if this number
  1333.  * is larger than the number of bytes
  1334.  * available in the first buffer, only the
  1335.  * bytes from the first buffer are
  1336.  * returned. */
  1337.     int *offsetPtr; /* On input, contains how many bytes of
  1338.  * objPtr have been used to hold data.  On
  1339.  * output, filled with how many bytes are now
  1340.  * being used. */
  1341. {
  1342.     int toRead, srcLen, offset, length, srcRead, dstWrote;
  1343.     ChannelBuffer *bufPtr;
  1344.     char *src, *dst;
  1345.     offset = *offsetPtr;
  1346.     bufPtr = statePtr->inQueueHead; 
  1347.     src = bufPtr->buf + bufPtr->nextRemoved;
  1348.     srcLen = bufPtr->nextAdded - bufPtr->nextRemoved;
  1349.     toRead = bytesToRead;
  1350.     if ((unsigned) toRead > (unsigned) srcLen) {
  1351. toRead = srcLen;
  1352.     }
  1353.     dst = (char *) Tcl_GetByteArrayFromObj(objPtr, &length);
  1354.     if (toRead > length - offset - 1) {
  1355. /*
  1356.  * Double the existing size of the object or make enough room to
  1357.  * hold all the characters we may get from the source buffer,
  1358.  * whichever is larger.
  1359.  */
  1360. length = offset * 2;
  1361. if (offset < toRead) {
  1362.     length = offset + toRead + 1;
  1363. }
  1364. dst = (char *) Tcl_SetByteArrayLength(objPtr, length);
  1365.     }
  1366.     dst += offset;
  1367.     if (statePtr->flags & INPUT_NEED_NL) {
  1368. statePtr->flags &= ~INPUT_NEED_NL;
  1369. if ((srcLen == 0) || (*src != 'n')) {
  1370.     *dst = 'r';
  1371.     *offsetPtr += 1;
  1372.     return 1;
  1373. }
  1374. *dst++ = 'n';
  1375. src++;
  1376. srcLen--;
  1377. toRead--;
  1378.     }
  1379.     srcRead = srcLen;
  1380.     dstWrote = toRead;
  1381.     if (TranslateInputEOL(statePtr, dst, src, &dstWrote, &srcRead) != 0) {
  1382. if (dstWrote == 0) {
  1383.     return -1;
  1384. }
  1385.     }
  1386.     bufPtr->nextRemoved += srcRead;
  1387.     *offsetPtr += dstWrote;
  1388.     return dstWrote;
  1389. }
  1390. /*
  1391.  *---------------------------------------------------------------------------
  1392.  *
  1393.  * ReadChars --
  1394.  *
  1395.  * Reads from the channel until the requested number of UTF-8
  1396.  * characters have been seen, EOF is seen, or the channel would
  1397.  * block.  Raw bytes from the channel are converted to UTF-8
  1398.  * and stored in objPtr.  EOL and EOF translation is done.
  1399.  *
  1400.  * 'charsToRead' can safely be a very large number because
  1401.  * space is only allocated to hold data read from the channel
  1402.  * as needed.
  1403.  *
  1404.  * Results:
  1405.  * The return value is the number of characters appended to
  1406.  * the object, *offsetPtr is filled with the number of bytes that
  1407.  * were appended, and *factorPtr is filled with the expansion
  1408.  * factor used to guess how many bytes of UTF-8 to allocate to
  1409.  * hold N source bytes.
  1410.  *
  1411.  * Side effects:
  1412.  * None.
  1413.  *
  1414.  *---------------------------------------------------------------------------
  1415.  */
  1416. static int
  1417. ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr)
  1418.     ChannelState *statePtr; /* State of channel to read. */
  1419.     Tcl_Obj *objPtr; /* Input data is appended to this object.
  1420.  * objPtr->length is how much space has been
  1421.  * allocated to hold data, not how many bytes
  1422.  * of data have been stored in the object. */
  1423.     int charsToRead; /* Maximum number of characters to store,
  1424.  * or -1 to get all available characters.
  1425.  * Characters are obtained from the first
  1426.  * buffer in the queue -- even if this number
  1427.  * is larger than the number of characters
  1428.  * available in the first buffer, only the
  1429.  * characters from the first buffer are
  1430.  * returned. */
  1431.     int *offsetPtr; /* On input, contains how many bytes of
  1432.  * objPtr have been used to hold data.  On
  1433.  * output, filled with how many bytes are now
  1434.  * being used. */
  1435.     int *factorPtr; /* On input, contains a guess of how many
  1436.  * bytes need to be allocated to hold the
  1437.  * result of converting N source bytes to
  1438.  * UTF-8.  On output, contains another guess
  1439.  * based on the data seen so far. */
  1440. {
  1441.     int toRead, factor, offset, spaceLeft, length, srcLen, dstNeeded;
  1442.     int srcRead, dstWrote, numChars, dstRead;
  1443.     ChannelBuffer *bufPtr;
  1444.     char *src, *dst;
  1445.     Tcl_EncodingState oldState;
  1446.     int encEndFlagSuppressed = 0;
  1447.     factor = *factorPtr;
  1448.     offset = *offsetPtr;
  1449.     bufPtr = statePtr->inQueueHead; 
  1450.     src    = bufPtr->buf + bufPtr->nextRemoved;
  1451.     srcLen = bufPtr->nextAdded - bufPtr->nextRemoved;
  1452.     toRead = charsToRead;
  1453.     if ((unsigned)toRead > (unsigned)srcLen) {
  1454. toRead = srcLen;
  1455.     }
  1456.     /*
  1457.      * 'factor' is how much we guess that the bytes in the source buffer
  1458.      * will expand when converted to UTF-8 chars.  This guess comes from
  1459.      * analyzing how many characters were produced by the previous
  1460.      * pass.
  1461.      */
  1462.     dstNeeded = toRead * factor / UTF_EXPANSION_FACTOR;
  1463.     spaceLeft = objPtr->length - offset - TCL_UTF_MAX - 1;
  1464.     if (dstNeeded > spaceLeft) {
  1465. /*
  1466.  * Double the existing size of the object or make enough room to
  1467.  * hold all the characters we want from the source buffer,
  1468.  * whichever is larger.
  1469.  */
  1470. length = offset * 2;
  1471. if (offset < dstNeeded) {
  1472.     length = offset + dstNeeded;
  1473. }
  1474. spaceLeft = length - offset;
  1475. length += TCL_UTF_MAX + 1;
  1476. Tcl_SetObjLength(objPtr, length);
  1477.     }
  1478.     if (toRead == srcLen) {
  1479. /*
  1480.  * Want to convert the whole buffer in one pass.  If we have
  1481.  * enough space, convert it using all available space in object
  1482.  * rather than using the factor.
  1483.  */
  1484. dstNeeded = spaceLeft;
  1485.     }
  1486.     dst = objPtr->bytes + offset;
  1487.     /*
  1488.      * SF Tcl Bug 1462248
  1489.      * The cause of the crash reported in the referenced bug is this:
  1490.      *
  1491.      * - ReadChars, called with a single buffer, with a incomplete
  1492.      *   multi-byte character at the end (only the first byte of it).
  1493.      * - Encoding translation fails, asks for more data
  1494.      * - Data is read, and eof is reached, TCL_ENCODING_END (TEE) is set.
  1495.      * - ReadChar is called again, converts the first buffer, but due
  1496.      *   to TEE it does not check for incomplete multi-byte data, and the
  1497.      *   character just after the end of the first buffer is a valid
  1498.      *   completion of the multi-byte header in the actual buffer. The
  1499.      *   conversion reads more characters from the buffer then present.
  1500.      *   This causes nextRemoved to overshoot nextAdded and the next
  1501.      *   reads compute a negative srcLen, cause further translations to
  1502.      *   fail, causing copying of data into the next buffer using bad
  1503.      *   arguments, causing the mecpy for to eventually fail.
  1504.      *
  1505.      * In the end it is a memory access bug spiraling out of control
  1506.      * if the conditions are _just so_. And ultimate cause is that TEE
  1507.      * is given to a conversion where it should not. TEE signals that
  1508.      * this is the last buffer. Except in our case it is not.
  1509.      *
  1510.      * My solution is to suppress TEE if the first buffer is not the
  1511.      * last. We will eventually need it given that EOF has been
  1512.      * reached, but not right now. This is what the new flag
  1513.      * "endEncSuppressFlag" is for.
  1514.      *
  1515.      * The bug in 'Tcl_Utf2UtfProc' where it read from memory behind
  1516.      * the actual buffer has been fixed as well, and fixes the problem
  1517.      * with the crash too, but this would still allow the generic
  1518.      * layer to accidentially break a multi-byte sequence if the
  1519.      * conditions are just right, because again the ExternalToUtf
  1520.      * would be successful where it should not.
  1521.      */
  1522.     if ((statePtr->inputEncodingFlags & TCL_ENCODING_END) &&
  1523. (bufPtr->nextPtr != NULL)) {
  1524.         /* TEE is set for a buffer which is not the last. Squash it
  1525.  * for now, and restore it later, before yielding control to
  1526.  * our caller.
  1527.  */
  1528.         statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
  1529.         encEndFlagSuppressed = 1;
  1530.     }
  1531.     oldState = statePtr->inputEncodingState;
  1532.     if (statePtr->flags & INPUT_NEED_NL) {
  1533. /*
  1534.  * We want a 'n' because the last character we saw was 'r'.
  1535.  */
  1536. statePtr->flags &= ~INPUT_NEED_NL;
  1537. Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen,
  1538. statePtr->inputEncodingFlags, &statePtr->inputEncodingState,
  1539. dst, TCL_UTF_MAX + 1, &srcRead, &dstWrote, &numChars);
  1540. if ((dstWrote > 0) && (*dst == 'n')) {
  1541.     /*
  1542.      * The next char was a 'n'.  Consume it and produce a 'n'.
  1543.      */
  1544.     bufPtr->nextRemoved += srcRead;
  1545. } else {
  1546.     /*
  1547.      * The next char was not a 'n'.  Produce a 'r'.
  1548.      */
  1549.     *dst = 'r';
  1550. }
  1551. statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;
  1552. *offsetPtr += 1;
  1553. if (encEndFlagSuppressed) {
  1554.     statePtr->inputEncodingFlags |= TCL_ENCODING_END;
  1555. }
  1556.         return 1;
  1557.     }
  1558.     Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen,
  1559.     statePtr->inputEncodingFlags, &statePtr->inputEncodingState, dst,
  1560.     dstNeeded + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars);
  1561.     if (encEndFlagSuppressed) {
  1562.         statePtr->inputEncodingFlags |= TCL_ENCODING_END;
  1563.     }
  1564.     if (srcRead == 0) {
  1565. /*
  1566.  * Not enough bytes in src buffer to make a complete char.  Copy
  1567.  * the bytes to the next buffer to make a new contiguous string,
  1568.  * then tell the caller to fill the buffer with more bytes.
  1569.  */
  1570. ChannelBuffer *nextPtr;
  1571. nextPtr = bufPtr->nextPtr;
  1572. if (nextPtr == NULL) {
  1573.     if (srcLen > 0) {
  1574.         /*
  1575.  * There isn't enough data in the buffers to complete the next
  1576.  * character, so we need to wait for more data before the next
  1577.  * file event can be delivered.
  1578.  *
  1579.  * SF #478856.
  1580.  *
  1581.  * The exception to this is if the input buffer was
  1582.  * completely empty before we tried to convert its
  1583.  * contents. Nothing in, nothing out, and no incomplete
  1584.  * character data. The conversion before the current one
  1585.  * was complete.
  1586.  */
  1587.         statePtr->flags |= CHANNEL_NEED_MORE_DATA;
  1588.     }
  1589.     return -1;
  1590. }
  1591. /* Space is made at the beginning of the buffer to copy the
  1592.  * previous unused bytes there. Check first if the buffer we
  1593.  * are using actually has enough space at its beginning for
  1594.  * the data we are copying. Because if not we will write over the
  1595.  * buffer management information, especially the 'nextPtr'.
  1596.  *
  1597.  * Note that the BUFFER_PADDING (See AllocChannelBuffer) is
  1598.  * used to prevent exactly this situation. I.e. it should
  1599.  * never happen. Therefore it is ok to panic should it happen
  1600.  * despite the precautions.
  1601.  */
  1602. if (nextPtr->nextRemoved - srcLen < 0) {
  1603.     Tcl_Panic ("Buffer Underflow, BUFFER_PADDING not enough");
  1604. }
  1605. nextPtr->nextRemoved -= srcLen;
  1606. memcpy((VOID *) (nextPtr->buf + nextPtr->nextRemoved), (VOID *) src,
  1607. (size_t) srcLen);
  1608. RecycleBuffer(statePtr, bufPtr, 0);
  1609. statePtr->inQueueHead = nextPtr;
  1610. return ReadChars(statePtr, objPtr, charsToRead, offsetPtr, factorPtr);
  1611.     }
  1612.     dstRead = dstWrote;
  1613.     if (TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead) != 0) {
  1614. /*
  1615.  * Hit EOF char.  How many bytes of src correspond to where the
  1616.  * EOF was located in dst? Run the conversion again with an
  1617.  * output buffer just big enough to hold the data so we can
  1618.  * get the correct value for srcRead.
  1619.  */
  1620.  
  1621. if (dstWrote == 0) {
  1622.     return -1;
  1623. }
  1624. statePtr->inputEncodingState = oldState;
  1625. Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen,
  1626. statePtr->inputEncodingFlags, &statePtr->inputEncodingState,
  1627. dst, dstRead + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars);
  1628. TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead);
  1629.     } 
  1630.     /*
  1631.      * The number of characters that we got may be less than the number
  1632.      * that we started with because "rn" sequences may have been
  1633.      * turned into just 'n' in dst.
  1634.      */
  1635.     numChars -= (dstRead - dstWrote);
  1636.     if ((unsigned) numChars > (unsigned) toRead) {
  1637. /*
  1638.  * Got too many chars.
  1639.  */
  1640. CONST char *eof;
  1641. eof = Tcl_UtfAtIndex(dst, toRead);
  1642. statePtr->inputEncodingState = oldState;
  1643. Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen,
  1644. statePtr->inputEncodingFlags, &statePtr->inputEncodingState,
  1645. dst, eof - dst + TCL_UTF_MAX, &srcRead, &dstWrote, &numChars);
  1646. dstRead = dstWrote;
  1647. TranslateInputEOL(statePtr, dst, dst, &dstWrote, &dstRead);
  1648. numChars -= (dstRead - dstWrote);
  1649.     }
  1650.     statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;
  1651.     bufPtr->nextRemoved += srcRead;
  1652.     if (dstWrote > srcRead + 1) {
  1653. *factorPtr = dstWrote * UTF_EXPANSION_FACTOR / srcRead;
  1654.     }
  1655.     *offsetPtr += dstWrote;
  1656.     return numChars;
  1657. }
  1658. /*
  1659.  *---------------------------------------------------------------------------
  1660.  *
  1661.  * TranslateInputEOL --
  1662.  *
  1663.  * Perform input EOL and EOF translation on the source buffer,
  1664.  * leaving the translated result in the destination buffer.  
  1665.  *
  1666.  * Results:
  1667.  * The return value is 1 if the EOF character was found when copying
  1668.  * bytes to the destination buffer, 0 otherwise.  
  1669.  *
  1670.  * Side effects:
  1671.  * None.
  1672.  *
  1673.  *---------------------------------------------------------------------------
  1674.  */
  1675. static int
  1676. TranslateInputEOL(statePtr, dstStart, srcStart, dstLenPtr, srcLenPtr)
  1677.     ChannelState *statePtr; /* Channel being read, for EOL translation
  1678.  * and EOF character. */
  1679.     char *dstStart; /* Output buffer filled with chars by
  1680.  * applying appropriate EOL translation to
  1681.  * source characters. */
  1682.     CONST char *srcStart; /* Source characters. */
  1683.     int *dstLenPtr; /* On entry, the maximum length of output
  1684.  * buffer in bytes; must be <= *srcLenPtr.  On
  1685.  * exit, the number of bytes actually used in
  1686.  * output buffer. */
  1687.     int *srcLenPtr; /* On entry, the length of source buffer.
  1688.  * On exit, the number of bytes read from
  1689.  * the source buffer. */
  1690. {
  1691.     int dstLen, srcLen, inEofChar;
  1692.     CONST char *eof;
  1693.     dstLen = *dstLenPtr;
  1694.     eof = NULL;
  1695.     inEofChar = statePtr->inEofChar;
  1696.     if (inEofChar != '') {
  1697. /*
  1698.  * Find EOF in translated buffer then compress out the EOL.  The
  1699.  * source buffer may be much longer than the destination buffer --
  1700.  * we only want to return EOF if the EOF has been copied to the
  1701.  * destination buffer.
  1702.  */
  1703. CONST char *src, *srcMax;
  1704. srcMax = srcStart + *srcLenPtr;
  1705. for (src = srcStart; src < srcMax; src++) {
  1706.     if (*src == inEofChar) {
  1707. eof = src;
  1708. srcLen = src - srcStart;
  1709. if (srcLen < dstLen) {
  1710.     dstLen = srcLen;
  1711. }
  1712. *srcLenPtr = srcLen;
  1713. break;
  1714.     }
  1715. }
  1716.     }
  1717.     switch (statePtr->inputTranslation) {
  1718. case TCL_TRANSLATE_LF: {
  1719.     if (dstStart != srcStart) {
  1720. memcpy((VOID *) dstStart, (VOID *) srcStart, (size_t) dstLen);
  1721.     }
  1722.     srcLen = dstLen;
  1723.     break;
  1724. }
  1725. case TCL_TRANSLATE_CR: {
  1726.     char *dst, *dstEnd;
  1727.     
  1728.     if (dstStart != srcStart) {
  1729. memcpy((VOID *) dstStart, (VOID *) srcStart, (size_t) dstLen);
  1730.     }
  1731.     dstEnd = dstStart + dstLen;
  1732.     for (dst = dstStart; dst < dstEnd; dst++) {
  1733. if (*dst == 'r') {
  1734.     *dst = 'n';
  1735. }
  1736.     }
  1737.     srcLen = dstLen;
  1738.     break;
  1739. }
  1740. case TCL_TRANSLATE_CRLF: {
  1741.     char *dst;
  1742.     CONST char *src, *srcEnd, *srcMax;
  1743.     
  1744.     dst = dstStart;
  1745.     src = srcStart;
  1746.     srcEnd = srcStart + dstLen;
  1747.     srcMax = srcStart + *srcLenPtr;
  1748.     for ( ; src < srcEnd; ) {
  1749. if (*src == 'r') {
  1750.     src++;
  1751.     if (src >= srcMax) {
  1752. statePtr->flags |= INPUT_NEED_NL;
  1753.     } else if (*src == 'n') {
  1754. *dst++ = *src++;
  1755.     } else {
  1756. *dst++ = 'r';
  1757.     }
  1758. } else {
  1759.     *dst++ = *src++;
  1760. }
  1761.     }
  1762.     srcLen = src - srcStart;
  1763.     dstLen = dst - dstStart;
  1764.     break;
  1765. }
  1766. case TCL_TRANSLATE_AUTO: {
  1767.     char *dst;
  1768.     CONST char *src, *srcEnd, *srcMax;
  1769.     dst = dstStart;
  1770.     src = srcStart;
  1771.     srcEnd = srcStart + dstLen;
  1772.     srcMax = srcStart + *srcLenPtr;
  1773.     if ((statePtr->flags & INPUT_SAW_CR) && (src < srcMax)) {
  1774. if (*src == 'n') {
  1775.     src++;
  1776. }
  1777. statePtr->flags &= ~INPUT_SAW_CR;
  1778.     }
  1779.     for ( ; src < srcEnd; ) {
  1780. if (*src == 'r') {
  1781.     src++;
  1782.     if (src >= srcMax) {
  1783. statePtr->flags |= INPUT_SAW_CR;
  1784.     } else if (*src == 'n') {
  1785. if (srcEnd < srcMax) {
  1786.     srcEnd++;
  1787. }
  1788. src++;
  1789.     }
  1790.     *dst++ = 'n';
  1791. } else {
  1792.     *dst++ = *src++;
  1793. }
  1794.     }
  1795.     srcLen = src - srcStart;
  1796.     dstLen = dst - dstStart;
  1797.     break;
  1798. }
  1799. default: { /* lint. */
  1800.     return 0;
  1801. }
  1802.     }
  1803.     *dstLenPtr = dstLen;
  1804.     if ((eof != NULL) && (srcStart + srcLen >= eof)) {
  1805. /*
  1806.  * EOF character was seen in EOL translated range.  Leave current
  1807.  * file position pointing at the EOF character, but don't store the
  1808.  * EOF character in the output string.
  1809.  */
  1810. statePtr->flags |= (CHANNEL_EOF | CHANNEL_STICKY_EOF);
  1811. statePtr->inputEncodingFlags |= TCL_ENCODING_END;
  1812. statePtr->flags &= ~(INPUT_SAW_CR | INPUT_NEED_NL);
  1813. return 1;
  1814.     }
  1815.     *srcLenPtr = srcLen;
  1816.     return 0;
  1817. }
  1818. /*
  1819.  *----------------------------------------------------------------------
  1820.  *
  1821.  * Tcl_Ungets --
  1822.  *
  1823.  * Causes the supplied string to be added to the input queue of
  1824.  * the channel, at either the head or tail of the queue.
  1825.  *
  1826.  * Results:
  1827.  * The number of bytes stored in the channel, or -1 on error.
  1828.  *
  1829.  * Side effects:
  1830.  * Adds input to the input queue of a channel.
  1831.  *
  1832.  *----------------------------------------------------------------------
  1833.  */
  1834. int
  1835. Tcl_Ungets(chan, str, len, atEnd)
  1836.     Tcl_Channel chan; /* The channel for which to add the input. */
  1837.     CONST char *str; /* The input itself. */
  1838.     int len; /* The length of the input. */
  1839.     int atEnd; /* If non-zero, add at end of queue; otherwise
  1840.                                  * add at head of queue. */    
  1841. {
  1842.     Channel *chanPtr; /* The real IO channel. */
  1843.     ChannelState *statePtr; /* State of actual channel. */
  1844.     ChannelBuffer *bufPtr; /* Buffer to contain the data. */
  1845.     int i, flags;
  1846.     chanPtr = (Channel *) chan;
  1847.     statePtr = chanPtr->state;
  1848.     /*
  1849.      * This operation should occur at the top of a channel stack.
  1850.      */
  1851.     chanPtr = statePtr->topChanPtr;
  1852.     /*
  1853.      * CheckChannelErrors clears too many flag bits in this one case.
  1854.      */
  1855.      
  1856.     flags = statePtr->flags;
  1857.     if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
  1858. len = -1;
  1859. goto done;
  1860.     }
  1861.     statePtr->flags = flags;
  1862.     /*
  1863.      * If we have encountered a sticky EOF, just punt without storing.
  1864.      * (sticky EOF is set if we have seen the input eofChar, to prevent
  1865.      * reading beyond the eofChar). Otherwise, clear the EOF flags, and
  1866.      * clear the BLOCKED bit. We want to discover these conditions anew
  1867.      * in each operation.
  1868.      */
  1869.     if (statePtr->flags & CHANNEL_STICKY_EOF) {
  1870. goto done;
  1871.     }
  1872.     statePtr->flags &= (~(CHANNEL_BLOCKED | CHANNEL_EOF));
  1873.     bufPtr = AllocChannelBuffer(len);
  1874.     for (i = 0; i < len; i++) {
  1875.         bufPtr->buf[bufPtr->nextAdded++] = str[i];
  1876.     }
  1877.     if (statePtr->inQueueHead == (ChannelBuffer *) NULL) {
  1878.         bufPtr->nextPtr = (ChannelBuffer *) NULL;
  1879.         statePtr->inQueueHead = bufPtr;
  1880.         statePtr->inQueueTail = bufPtr;
  1881.     } else if (atEnd) {
  1882.         bufPtr->nextPtr = (ChannelBuffer *) NULL;
  1883.         statePtr->inQueueTail->nextPtr = bufPtr;
  1884.         statePtr->inQueueTail = bufPtr;
  1885.     } else {
  1886.         bufPtr->nextPtr = statePtr->inQueueHead;
  1887.         statePtr->inQueueHead = bufPtr;
  1888.     }
  1889.     done:
  1890.     /*
  1891.      * Update the notifier state so we don't block while there is still
  1892.      * data in the buffers.
  1893.      */
  1894.     UpdateInterest(chanPtr);
  1895.     return len;
  1896. }
  1897. /*
  1898.  *----------------------------------------------------------------------
  1899.  *
  1900.  * Tcl_Flush --
  1901.  *
  1902.  * Flushes output data on a channel.
  1903.  *
  1904.  * Results:
  1905.  * A standard Tcl result.
  1906.  *
  1907.  * Side effects:
  1908.  * May flush output queued on this channel.
  1909.  *
  1910.  *----------------------------------------------------------------------
  1911.  */
  1912. int
  1913. Tcl_Flush(chan)
  1914.     Tcl_Channel chan; /* The Channel to flush. */
  1915. {
  1916.     int result; /* Of calling FlushChannel. */
  1917.     Channel *chanPtr  = (Channel *) chan; /* The actual channel. */
  1918.     ChannelState *statePtr = chanPtr->state; /* State of actual channel. */
  1919.     /*
  1920.      * This operation should occur at the top of a channel stack.
  1921.      */
  1922.     chanPtr = statePtr->topChanPtr;
  1923.     if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
  1924. return -1;
  1925.     }
  1926.     /*
  1927.      * Force current output buffer to be output also.
  1928.      */
  1929.     if ((statePtr->curOutPtr != NULL)
  1930.     && (statePtr->curOutPtr->nextAdded > 0)) {
  1931.         statePtr->flags |= BUFFER_READY;
  1932.     }
  1933.     
  1934.     result = FlushChannel(NULL, chanPtr, 0);
  1935.     if (result != 0) {
  1936.         return TCL_ERROR;
  1937.     }
  1938.     return TCL_OK;
  1939. }
  1940. /*
  1941.  *----------------------------------------------------------------------
  1942.  *
  1943.  * DiscardInputQueued --
  1944.  *
  1945.  * Discards any input read from the channel but not yet consumed
  1946.  * by Tcl reading commands.
  1947.  *
  1948.  * Results:
  1949.  * None.
  1950.  *
  1951.  * Side effects:
  1952.  * May discard input from the channel. If discardLastBuffer is zero,
  1953.  * leaves one buffer in place for back-filling.
  1954.  *
  1955.  *----------------------------------------------------------------------
  1956.  */
  1957. static void
  1958. DiscardInputQueued(statePtr, discardSavedBuffers)
  1959.     ChannelState *statePtr; /* Channel on which to discard
  1960.                                  * the queued input. */
  1961.     int discardSavedBuffers; /* If non-zero, discard all buffers including
  1962.                                  * last one. */
  1963. {
  1964.     ChannelBuffer *bufPtr, *nxtPtr; /* Loop variables. */
  1965.     bufPtr = statePtr->inQueueHead;
  1966.     statePtr->inQueueHead = (ChannelBuffer *) NULL;
  1967.     statePtr->inQueueTail = (ChannelBuffer *) NULL;
  1968.     for (; bufPtr != (ChannelBuffer *) NULL; bufPtr = nxtPtr) {
  1969.         nxtPtr = bufPtr->nextPtr;
  1970.         RecycleBuffer(statePtr, bufPtr, discardSavedBuffers);
  1971.     }
  1972.     /*
  1973.      * If discardSavedBuffers is nonzero, must also discard any previously
  1974.      * saved buffer in the saveInBufPtr field.
  1975.      */
  1976.     
  1977.     if (discardSavedBuffers) {
  1978.         if (statePtr->saveInBufPtr != (ChannelBuffer *) NULL) {
  1979.             ckfree((char *) statePtr->saveInBufPtr);
  1980.             statePtr->saveInBufPtr = (ChannelBuffer *) NULL;
  1981.         }
  1982.     }
  1983. }
  1984. /*
  1985.  *---------------------------------------------------------------------------
  1986.  *
  1987.  * GetInput --
  1988.  *
  1989.  * Reads input data from a device into a channel buffer.  
  1990.  *
  1991.  * Results:
  1992.  * The return value is the Posix error code if an error occurred while
  1993.  * reading from the file, or 0 otherwise.  
  1994.  *
  1995.  * Side effects:
  1996.  * Reads from the underlying device.
  1997.  *
  1998.  *---------------------------------------------------------------------------
  1999.  */
  2000. static int
  2001. GetInput(chanPtr)
  2002.     Channel *chanPtr; /* Channel to read input from. */
  2003. {
  2004.     int toRead; /* How much to read? */
  2005.     int result; /* Of calling driver. */
  2006.     int nread; /* How much was read from channel? */
  2007.     ChannelBuffer *bufPtr; /* New buffer to add to input queue. */
  2008.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  2009.     /*
  2010.      * Prevent reading from a dead channel -- a channel that has been closed
  2011.      * but not yet deallocated, which can happen if the exit handler for
  2012.      * channel cleanup has run but the channel is still registered in some
  2013.      * interpreter.
  2014.      */
  2015.     
  2016.     if (CheckForDeadChannel(NULL, statePtr)) {
  2017. return EINVAL;
  2018.     }
  2019.     /*
  2020.      * First check for more buffers in the pushback area of the
  2021.      * topmost channel in the stack and use them. They can be the
  2022.      * result of a transformation which went away without reading all
  2023.      * the information placed in the area when it was stacked.
  2024.      *
  2025.      * Two possibilities for the state: No buffers in it, or a single
  2026.      * empty buffer. In the latter case we can recycle it now.
  2027.      */
  2028.     if (chanPtr->inQueueHead != (ChannelBuffer*) NULL) {
  2029.         if (statePtr->inQueueHead != (ChannelBuffer*) NULL) {
  2030.     RecycleBuffer(statePtr, statePtr->inQueueHead, 0);
  2031.     statePtr->inQueueHead = (ChannelBuffer*) NULL;
  2032. }
  2033. statePtr->inQueueHead = chanPtr->inQueueHead;
  2034. statePtr->inQueueTail = chanPtr->inQueueTail;
  2035. chanPtr->inQueueHead  = (ChannelBuffer*) NULL;
  2036. chanPtr->inQueueTail  = (ChannelBuffer*) NULL;
  2037. return 0;
  2038.     }
  2039.     /*
  2040.      * Nothing in the pushback area, fall back to the usual handling
  2041.      * (driver, etc.)
  2042.      */
  2043.     /*
  2044.      * See if we can fill an existing buffer. If we can, read only
  2045.      * as much as will fit in it. Otherwise allocate a new buffer,
  2046.      * add it to the input queue and attempt to fill it to the max.
  2047.      */
  2048.     bufPtr = statePtr->inQueueTail;
  2049.     if ((bufPtr != NULL) && (bufPtr->nextAdded < bufPtr->bufLength)) {
  2050.         toRead = bufPtr->bufLength - bufPtr->nextAdded;
  2051.     } else {
  2052. bufPtr = statePtr->saveInBufPtr;
  2053. statePtr->saveInBufPtr = NULL;
  2054. /*
  2055.  * Check the actual buffersize against the requested
  2056.  * buffersize. Buffers which are smaller than requested are
  2057.  * squashed. This is done to honor dynamic changes of the
  2058.  * buffersize made by the user.
  2059.  */
  2060. if ((bufPtr != NULL) && ((bufPtr->bufLength - BUFFER_PADDING) < statePtr->bufSize)) {
  2061.   ckfree((char *) bufPtr);
  2062.   bufPtr = NULL;
  2063. }
  2064. if (bufPtr == NULL) {
  2065.     bufPtr = AllocChannelBuffer(statePtr->bufSize);
  2066. }
  2067.         bufPtr->nextPtr = (ChannelBuffer *) NULL;
  2068. /* SF #427196: Use the actual size of the buffer to determine
  2069.  * the number of bytes to read from the channel and not the
  2070.  * size for new buffers. They can be different if the
  2071.  * buffersize was changed between reads.
  2072.  *
  2073.  * Note: This affects performance negatively if the buffersize
  2074.  * was extended but this small buffer is reused for all
  2075.  * subsequent reads. The system never uses buffers with the
  2076.  * requested bigger size in that case. An adjunct patch could
  2077.  * try and delete all unused buffers it encounters and which
  2078.  * are smaller than the formally requested buffersize.
  2079.  */
  2080. toRead = bufPtr->bufLength - bufPtr->nextAdded;
  2081.         if (statePtr->inQueueTail == NULL) {
  2082.             statePtr->inQueueHead = bufPtr;
  2083.         } else {
  2084.             statePtr->inQueueTail->nextPtr = bufPtr;
  2085.         }
  2086.         statePtr->inQueueTail = bufPtr;
  2087.     }
  2088.     /*
  2089.      * If EOF is set, we should avoid calling the driver because on some
  2090.      * platforms it is impossible to read from a device after EOF.
  2091.      */
  2092.     if (statePtr->flags & CHANNEL_EOF) {
  2093. return 0;
  2094.     }
  2095. #ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
  2096.     /* [SF Tcl Bug 943274]. Better emulation of non-blocking channels
  2097.      * for channels without BlockModeProc, by keeping track of true
  2098.      * fileevents generated by the OS == Data waiting and reading if
  2099.      * and only if we are sure to have data.
  2100.      */
  2101.     if ((statePtr->flags & CHANNEL_NONBLOCKING) &&
  2102. (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) &&
  2103. !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) {
  2104.         /* Bypass the driver, it would block, as no data is available */
  2105.         nread = -1;
  2106.         result = EWOULDBLOCK;
  2107.     } else {
  2108. #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
  2109.         nread = (chanPtr->typePtr->inputProc)(chanPtr->instanceData,
  2110.     bufPtr->buf + bufPtr->nextAdded, toRead, &result);
  2111. #ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
  2112.     }
  2113. #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
  2114.     if (nread > 0) {
  2115. bufPtr->nextAdded += nread;
  2116. /*
  2117.  * If we get a short read, signal up that we may be BLOCKED. We
  2118.  * should avoid calling the driver because on some platforms we
  2119.  * will block in the low level reading code even though the
  2120.  * channel is set into nonblocking mode.
  2121.  */
  2122.             
  2123. if (nread < toRead) {
  2124.     statePtr->flags |= CHANNEL_BLOCKED;
  2125. }
  2126. #ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
  2127. if (nread <= toRead) {
  2128.   /* [SF Tcl Bug 943274] We have read the available data,
  2129.    * clear flag */
  2130.   statePtr->flags &= ~CHANNEL_HAS_MORE_DATA;
  2131. }
  2132. #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
  2133.     } else if (nread == 0) {
  2134. statePtr->flags |= CHANNEL_EOF;
  2135. statePtr->inputEncodingFlags |= TCL_ENCODING_END;
  2136.     } else if (nread < 0) {
  2137. if ((result == EWOULDBLOCK) || (result == EAGAIN)) {
  2138.     statePtr->flags |= CHANNEL_BLOCKED;
  2139.     result = EAGAIN;
  2140. }
  2141. Tcl_SetErrno(result);
  2142. return result;
  2143.     }
  2144.     return 0;
  2145. }
  2146. /*
  2147.  *----------------------------------------------------------------------
  2148.  *
  2149.  * Tcl_Seek --
  2150.  *
  2151.  * Implements seeking on Tcl Channels. This is a public function
  2152.  * so that other C facilities may be implemented on top of it.
  2153.  *
  2154.  * Results:
  2155.  * The new access point or -1 on error. If error, use Tcl_GetErrno()
  2156.  * to retrieve the POSIX error code for the error that occurred.
  2157.  *
  2158.  * Side effects:
  2159.  * May flush output on the channel. May discard queued input.
  2160.  *
  2161.  *----------------------------------------------------------------------
  2162.  */
  2163. Tcl_WideInt
  2164. Tcl_Seek(chan, offset, mode)
  2165.     Tcl_Channel chan; /* The channel on which to seek. */
  2166.     Tcl_WideInt offset; /* Offset to seek to. */
  2167.     int mode; /* Relative to which location to seek? */
  2168. {
  2169.     Channel *chanPtr = (Channel *) chan; /* The real IO channel. */
  2170.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  2171.     int inputBuffered, outputBuffered;
  2172. /* # bytes held in buffers. */
  2173.     int result; /* Of device driver operations. */
  2174.     Tcl_WideInt curPos; /* Position on the device. */
  2175.     int wasAsync; /* Was the channel nonblocking before the
  2176.                                  * seek operation? If so, must restore to
  2177.                                  * nonblocking mode after the seek. */
  2178.     if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) {
  2179. return Tcl_LongAsWide(-1);
  2180.     }
  2181.     /*
  2182.      * Disallow seek on dead channels -- channels that have been closed but
  2183.      * not yet been deallocated. Such channels can be found if the exit
  2184.      * handler for channel cleanup has run but the channel is still
  2185.      * registered in an interpreter.
  2186.      */
  2187.     if (CheckForDeadChannel(NULL, statePtr)) {
  2188. return Tcl_LongAsWide(-1);
  2189.     }
  2190.     /*
  2191.      * This operation should occur at the top of a channel stack.
  2192.      */
  2193.     chanPtr = statePtr->topChanPtr;
  2194.     /*
  2195.      * Disallow seek on channels whose type does not have a seek procedure
  2196.      * defined. This means that the channel does not support seeking.
  2197.      */
  2198.     if (chanPtr->typePtr->seekProc == (Tcl_DriverSeekProc *) NULL) {
  2199.         Tcl_SetErrno(EINVAL);
  2200.         return Tcl_LongAsWide(-1);
  2201.     }
  2202.     /*
  2203.      * Compute how much input and output is buffered. If both input and
  2204.      * output is buffered, cannot compute the current position.
  2205.      */
  2206.     inputBuffered = Tcl_InputBuffered(chan);
  2207.     outputBuffered = Tcl_OutputBuffered(chan);
  2208.     if ((inputBuffered != 0) && (outputBuffered != 0)) {
  2209.         Tcl_SetErrno(EFAULT);
  2210.         return Tcl_LongAsWide(-1);
  2211.     }
  2212.     /*
  2213.      * If we are seeking relative to the current position, compute the
  2214.      * corrected offset taking into account the amount of unread input.
  2215.      */
  2216.     if (mode == SEEK_CUR) {
  2217.         offset -= inputBuffered;
  2218.     }
  2219.     /*
  2220.      * Discard any queued input - this input should not be read after
  2221.      * the seek.
  2222.      */
  2223.     DiscardInputQueued(statePtr, 0);
  2224.     /*
  2225.      * Reset EOF and BLOCKED flags. We invalidate them by moving the
  2226.      * access point. Also clear CR related flags.
  2227.      */
  2228.     statePtr->flags &=
  2229.         (~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED | INPUT_SAW_CR));
  2230.     
  2231.     /*
  2232.      * If the channel is in asynchronous output mode, switch it back
  2233.      * to synchronous mode and cancel any async flush that may be
  2234.      * scheduled. After the flush, the channel will be put back into
  2235.      * asynchronous output mode.
  2236.      */
  2237.     wasAsync = 0;
  2238.     if (statePtr->flags & CHANNEL_NONBLOCKING) {
  2239.         wasAsync = 1;
  2240.         result = StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING);
  2241. if (result != 0) {
  2242.     return Tcl_LongAsWide(-1);
  2243. }
  2244.         statePtr->flags &= (~(CHANNEL_NONBLOCKING));
  2245.         if (statePtr->flags & BG_FLUSH_SCHEDULED) {
  2246.             statePtr->flags &= (~(BG_FLUSH_SCHEDULED));
  2247.         }
  2248.     }
  2249.     
  2250.     /*
  2251.      * If the flush fails we cannot recover the original position. In
  2252.      * that case the seek is not attempted because we do not know where
  2253.      * the access position is - instead we return the error. FlushChannel
  2254.      * has already called Tcl_SetErrno() to report the error upwards.
  2255.      * If the flush succeeds we do the seek also.
  2256.      */
  2257.     
  2258.     if (FlushChannel(NULL, chanPtr, 0) != 0) {
  2259.         curPos = -1;
  2260.     } else {
  2261.         /*
  2262.          * Now seek to the new position in the channel as requested by the
  2263.          * caller.  Note that we prefer the wideSeekProc if that is
  2264.  * available and non-NULL...
  2265.          */
  2266. if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) &&
  2267. chanPtr->typePtr->wideSeekProc != NULL) {
  2268.     curPos = (chanPtr->typePtr->wideSeekProc) (chanPtr->instanceData,
  2269.     offset, mode, &result);
  2270. } else if (offset < Tcl_LongAsWide(LONG_MIN) ||
  2271. offset > Tcl_LongAsWide(LONG_MAX)) {
  2272.     result = EOVERFLOW;
  2273.     curPos = Tcl_LongAsWide(-1);
  2274. } else {
  2275.     curPos = Tcl_LongAsWide((chanPtr->typePtr->seekProc) (
  2276.     chanPtr->instanceData, Tcl_WideAsLong(offset), mode,
  2277.     &result));
  2278. }
  2279. if (curPos == Tcl_LongAsWide(-1)) {
  2280.     Tcl_SetErrno(result);
  2281. }
  2282.     }
  2283.     
  2284.     /*
  2285.      * Restore to nonblocking mode if that was the previous behavior.
  2286.      *
  2287.      * NOTE: Even if there was an async flush active we do not restore
  2288.      * it now because we already flushed all the queued output, above.
  2289.      */
  2290.     
  2291.     if (wasAsync) {
  2292.         statePtr->flags |= CHANNEL_NONBLOCKING;
  2293.         result = StackSetBlockMode(chanPtr, TCL_MODE_NONBLOCKING);
  2294. if (result != 0) {
  2295.     return Tcl_LongAsWide(-1);
  2296. }
  2297.     }
  2298.     return curPos;
  2299. }
  2300. /*
  2301.  *----------------------------------------------------------------------
  2302.  *
  2303.  * Tcl_Tell --
  2304.  *
  2305.  * Returns the position of the next character to be read/written on
  2306.  * this channel.
  2307.  *
  2308.  * Results:
  2309.  * A nonnegative integer on success, -1 on failure. If failed,
  2310.  * use Tcl_GetErrno() to retrieve the POSIX error code for the
  2311.  * error that occurred.
  2312.  *
  2313.  * Side effects:
  2314.  * None.
  2315.  *
  2316.  *----------------------------------------------------------------------
  2317.  */
  2318. Tcl_WideInt
  2319. Tcl_Tell(chan)
  2320.     Tcl_Channel chan; /* The channel to return pos for. */
  2321. {
  2322.     Channel *chanPtr = (Channel *) chan; /* The real IO channel. */
  2323.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  2324.     int inputBuffered, outputBuffered; /* # bytes held in buffers. */
  2325.     int result; /* Of calling device driver. */
  2326.     Tcl_WideInt curPos; /* Position on device. */
  2327.     if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) {
  2328. return Tcl_LongAsWide(-1);
  2329.     }
  2330.     /*
  2331.      * Disallow tell on dead channels -- channels that have been closed but
  2332.      * not yet been deallocated. Such channels can be found if the exit
  2333.      * handler for channel cleanup has run but the channel is still
  2334.      * registered in an interpreter.
  2335.      */
  2336.     if (CheckForDeadChannel(NULL, statePtr)) {
  2337. return Tcl_LongAsWide(-1);
  2338.     }
  2339.     /*
  2340.      * This operation should occur at the top of a channel stack.
  2341.      */
  2342.     chanPtr = statePtr->topChanPtr;
  2343.     /*
  2344.      * Disallow tell on channels whose type does not have a seek procedure
  2345.      * defined. This means that the channel does not support seeking.
  2346.      */
  2347.     if (chanPtr->typePtr->seekProc == (Tcl_DriverSeekProc *) NULL) {
  2348.         Tcl_SetErrno(EINVAL);
  2349.         return Tcl_LongAsWide(-1);
  2350.     }
  2351.     /*
  2352.      * Compute how much input and output is buffered. If both input and
  2353.      * output is buffered, cannot compute the current position.
  2354.      */
  2355.     inputBuffered = Tcl_InputBuffered(chan);
  2356.     outputBuffered = Tcl_OutputBuffered(chan);
  2357.     if ((inputBuffered != 0) && (outputBuffered != 0)) {
  2358.         Tcl_SetErrno(EFAULT);
  2359.         return Tcl_LongAsWide(-1);
  2360.     }
  2361.     /*
  2362.      * Get the current position in the device and compute the position
  2363.      * where the next character will be read or written.  Note that we
  2364.      * prefer the wideSeekProc if that is available and non-NULL...
  2365.      */
  2366.     if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) &&
  2367.     chanPtr->typePtr->wideSeekProc != NULL) {
  2368. curPos = (chanPtr->typePtr->wideSeekProc) (chanPtr->instanceData,
  2369. Tcl_LongAsWide(0), SEEK_CUR, &result);
  2370.     } else {
  2371. curPos = Tcl_LongAsWide((chanPtr->typePtr->seekProc) (
  2372. chanPtr->instanceData, 0, SEEK_CUR, &result));
  2373.     }
  2374.     if (curPos == Tcl_LongAsWide(-1)) {
  2375.         Tcl_SetErrno(result);
  2376.         return Tcl_LongAsWide(-1);
  2377.     }
  2378.     if (inputBuffered != 0) {
  2379.         return curPos - inputBuffered;
  2380.     }
  2381.     return curPos + outputBuffered;
  2382. }
  2383. /*
  2384.  *---------------------------------------------------------------------------
  2385.  *
  2386.  * Tcl_SeekOld, Tcl_TellOld --
  2387.  *
  2388.  * Backward-compatability versions of the seek/tell interface that
  2389.  * do not support 64-bit offsets.  This interface is not documented
  2390.  * or expected to be supported indefinitely.
  2391.  *
  2392.  * Results:
  2393.  * As for Tcl_Seek and Tcl_Tell respectively, except truncated to
  2394.  * whatever value will fit in an 'int'.
  2395.  *
  2396.  * Side effects:
  2397.  * As for Tcl_Seek and Tcl_Tell respectively.
  2398.  *
  2399.  *---------------------------------------------------------------------------
  2400.  */
  2401. int
  2402. Tcl_SeekOld(chan, offset, mode)
  2403.     Tcl_Channel chan; /* The channel on which to seek. */
  2404.     int offset; /* Offset to seek to. */
  2405.     int mode; /* Relative to which location to seek? */
  2406. {
  2407.     Tcl_WideInt wOffset, wResult;
  2408.     wOffset = Tcl_LongAsWide((long)offset);
  2409.     wResult = Tcl_Seek(chan, wOffset, mode);
  2410.     return (int)Tcl_WideAsLong(wResult);
  2411. }
  2412. int
  2413. Tcl_TellOld(chan)
  2414.     Tcl_Channel chan; /* The channel to return pos for. */
  2415. {
  2416.     Tcl_WideInt wResult;
  2417.     wResult = Tcl_Tell(chan);
  2418.     return (int)Tcl_WideAsLong(wResult);
  2419. }
  2420. /*
  2421.  *---------------------------------------------------------------------------
  2422.  *
  2423.  * CheckChannelErrors --
  2424.  *
  2425.  * See if the channel is in an ready state and can perform the
  2426.  * desired operation.
  2427.  *
  2428.  * Results:
  2429.  * The return value is 0 if the channel is OK, otherwise the
  2430.  * return value is -1 and errno is set to indicate the error.
  2431.  *
  2432.  * Side effects:
  2433.  * May clear the EOF and/or BLOCKED bits if reading from channel.
  2434.  *
  2435.  *---------------------------------------------------------------------------
  2436.  */
  2437.  
  2438. static int
  2439. CheckChannelErrors(statePtr, flags)
  2440.     ChannelState *statePtr; /* Channel to check. */
  2441.     int flags; /* Test if channel supports desired operation:
  2442.  * TCL_READABLE, TCL_WRITABLE.  Also indicates
  2443.  * Raw read or write for special close
  2444.  * processing*/
  2445. {
  2446.     int direction = flags & (TCL_READABLE|TCL_WRITABLE);
  2447.     /*
  2448.      * Check for unreported error.
  2449.      */
  2450.     if (statePtr->unreportedError != 0) {
  2451.         Tcl_SetErrno(statePtr->unreportedError);
  2452.         statePtr->unreportedError = 0;
  2453.         return -1;
  2454.     }
  2455.     /*
  2456.      * Only the raw read and write operations are allowed during close
  2457.      * in order to drain data from stacked channels.
  2458.      */
  2459.     if ((statePtr->flags & CHANNEL_CLOSED) &&
  2460.     ((flags & CHANNEL_RAW_MODE) == 0)) {
  2461.         Tcl_SetErrno(EACCES);
  2462.         return -1;
  2463.     }
  2464.     /*
  2465.      * Fail if the channel is not opened for desired operation.
  2466.      */
  2467.     if ((statePtr->flags & direction) == 0) {
  2468.         Tcl_SetErrno(EACCES);
  2469.         return -1;
  2470.     }
  2471.     /*
  2472.      * Fail if the channel is in the middle of a background copy.
  2473.      *
  2474.      * Don't do this tests for raw channels here or else the chaining in the
  2475.      * transformation drivers will fail with 'file busy' error instead of
  2476.      * retrieving and transforming the data to copy.
  2477.      */
  2478.     if ((statePtr->csPtr != NULL) && ((flags & CHANNEL_RAW_MODE) == 0)) {
  2479. Tcl_SetErrno(EBUSY);
  2480. return -1;
  2481.     }
  2482.     if (direction == TCL_READABLE) {
  2483. /*
  2484.  * If we have not encountered a sticky EOF, clear the EOF bit
  2485.  * (sticky EOF is set if we have seen the input eofChar, to prevent
  2486.  * reading beyond the eofChar). Also, always clear the BLOCKED bit.
  2487.  * We want to discover these conditions anew in each operation.
  2488.  */
  2489. if ((statePtr->flags & CHANNEL_STICKY_EOF) == 0) {
  2490.     statePtr->flags &= ~CHANNEL_EOF;
  2491. }
  2492. statePtr->flags &= ~(CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA);
  2493.     }
  2494.     return 0;
  2495. }
  2496. /*
  2497.  *----------------------------------------------------------------------
  2498.  *
  2499.  * Tcl_Eof --
  2500.  *
  2501.  * Returns 1 if the channel is at EOF, 0 otherwise.
  2502.  *
  2503.  * Results:
  2504.  * 1 or 0, always.
  2505.  *
  2506.  * Side effects:
  2507.  * None.
  2508.  *
  2509.  *----------------------------------------------------------------------
  2510.  */
  2511. int
  2512. Tcl_Eof(chan)
  2513.     Tcl_Channel chan; /* Does this channel have EOF? */
  2514. {
  2515.     ChannelState *statePtr = ((Channel *) chan)->state;
  2516. /* State of real channel structure. */
  2517.     return ((statePtr->flags & CHANNEL_STICKY_EOF) ||
  2518.             ((statePtr->flags & CHANNEL_EOF) &&
  2519.     (Tcl_InputBuffered(chan) == 0))) ? 1 : 0;
  2520. }
  2521. /*
  2522.  *----------------------------------------------------------------------
  2523.  *
  2524.  * Tcl_InputBlocked --
  2525.  *
  2526.  * Returns 1 if input is blocked on this channel, 0 otherwise.
  2527.  *
  2528.  * Results:
  2529.  * 0 or 1, always.
  2530.  *
  2531.  * Side effects:
  2532.  * None.
  2533.  *
  2534.  *----------------------------------------------------------------------
  2535.  */
  2536. int
  2537. Tcl_InputBlocked(chan)
  2538.     Tcl_Channel chan; /* Is this channel blocked? */
  2539. {
  2540.     ChannelState *statePtr = ((Channel *) chan)->state;
  2541. /* State of real channel structure. */
  2542.     return (statePtr->flags & CHANNEL_BLOCKED) ? 1 : 0;
  2543. }
  2544. /*
  2545.  *----------------------------------------------------------------------
  2546.  *
  2547.  * Tcl_InputBuffered --
  2548.  *
  2549.  * Returns the number of bytes of input currently buffered in the
  2550.  * common internal buffer of a channel.
  2551.  *
  2552.  * Results:
  2553.  * The number of input bytes buffered, or zero if the channel is not
  2554.  * open for reading.
  2555.  *
  2556.  * Side effects:
  2557.  * None.
  2558.  *
  2559.  *----------------------------------------------------------------------
  2560.  */
  2561. int
  2562. Tcl_InputBuffered(chan)
  2563.     Tcl_Channel chan; /* The channel to query. */
  2564. {
  2565.     ChannelState *statePtr = ((Channel *) chan)->state;
  2566. /* State of real channel structure. */
  2567.     ChannelBuffer *bufPtr;
  2568.     int bytesBuffered;
  2569.     for (bytesBuffered = 0, bufPtr = statePtr->inQueueHead;
  2570.  bufPtr != (ChannelBuffer *) NULL;
  2571.  bufPtr = bufPtr->nextPtr) {
  2572.         bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved);
  2573.     }
  2574.     /*
  2575.      * Don't forget the bytes in the topmost pushback area.
  2576.      */
  2577.     for (bufPtr = statePtr->topChanPtr->inQueueHead;
  2578.  bufPtr != (ChannelBuffer *) NULL;
  2579.  bufPtr = bufPtr->nextPtr) {
  2580.         bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved);
  2581.     }
  2582.     return bytesBuffered;
  2583. }
  2584. /*
  2585.  *----------------------------------------------------------------------
  2586.  *
  2587.  * Tcl_OutputBuffered --
  2588.  *
  2589.  *    Returns the number of bytes of output currently buffered in the
  2590.  *    common internal buffer of a channel.
  2591.  *
  2592.  * Results:
  2593.  *    The number of output bytes buffered, or zero if the channel is not
  2594.  *    open for writing.
  2595.  *
  2596.  * Side effects:
  2597.  *    None.
  2598.  *
  2599.  *----------------------------------------------------------------------
  2600.  */
  2601. int
  2602. Tcl_OutputBuffered(chan)
  2603.     Tcl_Channel chan;                 /* The channel to query. */
  2604. {
  2605.     ChannelState *statePtr = ((Channel *) chan)->state;
  2606.                                       /* State of real channel structure. */
  2607.     ChannelBuffer *bufPtr;
  2608.     int bytesBuffered;
  2609.     for (bytesBuffered = 0, bufPtr = statePtr->outQueueHead;
  2610. bufPtr != (ChannelBuffer *) NULL;
  2611. bufPtr = bufPtr->nextPtr) {
  2612. bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved);
  2613.     }
  2614.     if ((statePtr->curOutPtr != (ChannelBuffer *) NULL) &&
  2615. (statePtr->curOutPtr->nextAdded > statePtr->curOutPtr->nextRemoved)) {
  2616. statePtr->flags |= BUFFER_READY;
  2617. bytesBuffered +=
  2618.     (statePtr->curOutPtr->nextAdded - statePtr->curOutPtr->nextRemoved);
  2619.     }
  2620.     return bytesBuffered;
  2621. }
  2622. /*
  2623.  *----------------------------------------------------------------------
  2624.  *
  2625.  * Tcl_ChannelBuffered --
  2626.  *
  2627.  * Returns the number of bytes of input currently buffered in the
  2628.  * internal buffer (push back area) of a channel.
  2629.  *
  2630.  * Results:
  2631.  * The number of input bytes buffered, or zero if the channel is not
  2632.  * open for reading.
  2633.  *
  2634.  * Side effects:
  2635.  * None.
  2636.  *
  2637.  *----------------------------------------------------------------------
  2638.  */
  2639. int
  2640. Tcl_ChannelBuffered(chan)
  2641.     Tcl_Channel chan; /* The channel to query. */
  2642. {
  2643.     Channel *chanPtr = (Channel *) chan;
  2644. /* real channel structure. */
  2645.     ChannelBuffer *bufPtr;
  2646.     int bytesBuffered;
  2647.     for (bytesBuffered = 0, bufPtr = chanPtr->inQueueHead;
  2648.  bufPtr != (ChannelBuffer *) NULL;
  2649.  bufPtr = bufPtr->nextPtr) {
  2650.         bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved);
  2651.     }
  2652.     return bytesBuffered;
  2653. }
  2654. /*
  2655.  *----------------------------------------------------------------------
  2656.  *
  2657.  * Tcl_SetChannelBufferSize --
  2658.  *
  2659.  * Sets the size of buffers to allocate to store input or output
  2660.  * in the channel. The size must be between 1 byte and 1 MByte.
  2661.  *
  2662.  * Results:
  2663.  * None.
  2664.  *
  2665.  * Side effects:
  2666.  * Sets the size of buffers subsequently allocated for this channel.
  2667.  *
  2668.  *----------------------------------------------------------------------
  2669.  */
  2670. void
  2671. Tcl_SetChannelBufferSize(chan, sz)
  2672.     Tcl_Channel chan; /* The channel whose buffer size
  2673.                                          * to set. */
  2674.     int sz; /* The size to set. */
  2675. {
  2676.     ChannelState *statePtr; /* State of real channel structure. */
  2677.     
  2678.     /*
  2679.      * If the buffer size is smaller than 1 byte or larger than one MByte,
  2680.      * do not accept the requested size and leave the current buffer size.
  2681.      */
  2682.     
  2683.     if (sz < 1) {
  2684.         return;
  2685.     }
  2686.     if (sz > (1024 * 1024)) {
  2687.         return;
  2688.     }
  2689.     statePtr = ((Channel *) chan)->state;
  2690.     statePtr->bufSize = sz;
  2691.     if (statePtr->outputStage != NULL) {
  2692. ckfree((char *) statePtr->outputStage);
  2693. statePtr->outputStage = NULL;
  2694.     }
  2695.     if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) {
  2696. statePtr->outputStage = (char *)
  2697.     ckalloc((unsigned) (statePtr->bufSize + 2));
  2698.     }
  2699. }
  2700. /*
  2701.  *----------------------------------------------------------------------
  2702.  *
  2703.  * Tcl_GetChannelBufferSize --
  2704.  *
  2705.  * Retrieves the size of buffers to allocate for this channel.
  2706.  *
  2707.  * Results:
  2708.  * The size.
  2709.  *
  2710.  * Side effects:
  2711.  * None.
  2712.  *
  2713.  *----------------------------------------------------------------------
  2714.  */
  2715. int
  2716. Tcl_GetChannelBufferSize(chan)
  2717.     Tcl_Channel chan; /* The channel for which to find the
  2718.                                  * buffer size. */
  2719. {
  2720.     ChannelState *statePtr = ((Channel *) chan)->state;
  2721. /* State of real channel structure. */
  2722.     return statePtr->bufSize;
  2723. }
  2724. /*
  2725.  *----------------------------------------------------------------------
  2726.  *
  2727.  * Tcl_BadChannelOption --
  2728.  *
  2729.  * This procedure generates a "bad option" error message in an
  2730.  * (optional) interpreter.  It is used by channel drivers when 
  2731.  *      a invalid Set/Get option is requested. Its purpose is to concatenate
  2732.  *      the generic options list to the specific ones and factorize
  2733.  *      the generic options error message string.
  2734.  *
  2735.  * Results:
  2736.  * TCL_ERROR.
  2737.  *
  2738.  * Side effects:
  2739.  * An error message is generated in interp's result object to
  2740.  * indicate that a command was invoked with the a bad option
  2741.  * The message has the form
  2742.  * bad option "blah": should be one of 
  2743.  *              <...generic options...>+<...specific options...>
  2744.  * "blah" is the optionName argument and "<specific options>"
  2745.  * is a space separated list of specific option words.
  2746.  *      The function takes good care of inserting minus signs before
  2747.  *      each option, commas after, and an "or" before the last option.
  2748.  *
  2749.  *----------------------------------------------------------------------
  2750.  */
  2751. int
  2752. Tcl_BadChannelOption(interp, optionName, optionList)
  2753.     Tcl_Interp *interp; /* Current interpreter. (can be NULL)*/
  2754.     CONST char *optionName; /* 'bad option' name */
  2755.     CONST char *optionList; /* Specific options list to append 
  2756.  * to the standard generic options.
  2757.  * can be NULL for generic options 
  2758.  * only.
  2759.  */
  2760. {
  2761.     if (interp) {
  2762. CONST char *genericopt = 
  2763.     "blocking buffering buffersize encoding eofchar translation";
  2764. CONST char **argv;
  2765. int  argc, i;
  2766. Tcl_DString ds;
  2767. Tcl_DStringInit(&ds);
  2768. Tcl_DStringAppend(&ds, genericopt, -1);
  2769. if (optionList && (*optionList)) {
  2770.     Tcl_DStringAppend(&ds, " ", 1);
  2771.     Tcl_DStringAppend(&ds, optionList, -1);
  2772. }
  2773. if (Tcl_SplitList(interp, Tcl_DStringValue(&ds), 
  2774. &argc, &argv) != TCL_OK) {
  2775.     panic("malformed option list in channel driver");
  2776. }
  2777. Tcl_ResetResult(interp);
  2778. Tcl_AppendResult(interp, "bad option "", optionName, 
  2779. "": should be one of ", (char *) NULL);
  2780. argc--;
  2781. for (i = 0; i < argc; i++) {
  2782.     Tcl_AppendResult(interp, "-", argv[i], ", ", (char *) NULL);
  2783. }
  2784. Tcl_AppendResult(interp, "or -", argv[i], (char *) NULL);
  2785. Tcl_DStringFree(&ds);
  2786. ckfree((char *) argv);
  2787.     }
  2788.     Tcl_SetErrno(EINVAL);
  2789.     return TCL_ERROR;
  2790. }
  2791. /*
  2792.  *----------------------------------------------------------------------
  2793.  *
  2794.  * Tcl_GetChannelOption --
  2795.  *
  2796.  * Gets a mode associated with an IO channel. If the optionName arg
  2797.  * is non NULL, retrieves the value of that option. If the optionName
  2798.  * arg is NULL, retrieves a list of alternating option names and
  2799.  * values for the given channel.
  2800.  *
  2801.  * Results:
  2802.  * A standard Tcl result. Also sets the supplied DString to the
  2803.  * string value of the option(s) returned.
  2804.  *
  2805.  * Side effects:
  2806.  *      None.
  2807.  *
  2808.  *----------------------------------------------------------------------
  2809.  */
  2810. int
  2811. Tcl_GetChannelOption(interp, chan, optionName, dsPtr)
  2812.     Tcl_Interp *interp; /* For error reporting - can be NULL. */
  2813.     Tcl_Channel chan; /* Channel on which to get option. */
  2814.     CONST char *optionName; /* Option to get. */
  2815.     Tcl_DString *dsPtr; /* Where to store value(s). */
  2816. {
  2817.     size_t len; /* Length of optionName string. */
  2818.     char optionVal[128]; /* Buffer for sprintf. */
  2819.     Channel *chanPtr = (Channel *) chan;
  2820.     ChannelState *statePtr = chanPtr->state; /* state info for channel */
  2821.     int flags;
  2822.     /*
  2823.      * Disallow options on dead channels -- channels that have been closed but
  2824.      * not yet been deallocated. Such channels can be found if the exit
  2825.      * handler for channel cleanup has run but the channel is still
  2826.      * registered in an interpreter.
  2827.      */
  2828.     if (CheckForDeadChannel(interp, statePtr)) {
  2829. return TCL_ERROR;
  2830.     }
  2831.     /*
  2832.      * This operation should occur at the top of a channel stack.
  2833.      */
  2834.     chanPtr = statePtr->topChanPtr;