\r
The functions assume that isatty() is TRUE at the time they are called.\r
\r
+ Copyright (c) 2016, Daryl McDaniel. All rights reserved.<BR>\r
Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials are licensed and made available\r
under the terms and conditions of the BSD License which accompanies this\r
#include "IIOutilities.h"\r
#include "IIOechoCtrl.h"\r
\r
+// Instrumentation used for debugging\r
+#define IIO_C_DEBUG 0 ///< Set to 1 to enable instrumentation, 0 to disable\r
+\r
+#if IIO_C_DEBUG\r
+ static volatile size_t IIO_C_WRemainder = 0; ///< Characters in Out buffer after IIO_Write\r
+ static volatile size_t IIO_C_RRemainder = 0; ///< Characters in In buffer after IIO_Read\r
+\r
+ #define W_INSTRUMENT IIO_C_WRemainder =\r
+ #define R_INSTRUMENT IIO_C_RRemainder =\r
+#else // ! IIO_C_DEBUG -- don't instrument code\r
+ #define W_INSTRUMENT (void)\r
+ #define R_INSTRUMENT (void)\r
+#endif // IIO_C_DEBUG\r
+\r
/** Read from an Interactive IO device.\r
\r
NOTE: If _S_IWTTY is set, the internal buffer contains WIDE characters.\r
NumRead = wcstombs((char *)Buffer, (const wchar_t *)gMD->UString2, XlateSz);\r
\r
// Consume the translated characters\r
- (void)This->InBuf->Flush(This->InBuf, Needed);\r
+ (void) This->InBuf->Flush(This->InBuf, Needed);\r
}\r
else {\r
// Data in InBuf is narrow characters. Use verbatim.\r
NumRead = This->InBuf->Read(This->InBuf, Buffer, (INT32)BufferSize);\r
}\r
+#if IIO_C_DEBUG\r
+ IIO_C_RRemainder = This->InBuf->Count(This->InBuf, AsElements);\r
+#endif // IIO_C_DEBUG\r
}\r
return NumRead;\r
}\r
\r
-/** Process characters from buffer buf and write them to the output device\r
+/** Handle write to a Terminal (Interactive) device.\r
+\r
+ Processes characters from buffer buf and writes them to the Terminal device\r
specified by filp.\r
\r
+ The parameter buf points to a MBCS string to be output. This is processed\r
+ and buffered one character at a time by IIO_WriteOne() which handles TAB\r
+ expansion, NEWLINE to CARRIAGE_RETURN + NEWLINE expansion, as well as\r
+ basic line editing functions. The number of characters actually written to\r
+ the output device will seldom equal the number of characters consumed from\r
+ buf.\r
+\r
+ In this implementation, all of the special characters processed by\r
+ IIO_WriteOne() are single-byte characters with values less than 128.\r
+ (7-bit ASCII or the single-byte UTF-8 characters)\r
+\r
+ Every byte that is not one of the recognized special characters is passed,\r
+ unchanged, to the Terminal device.\r
+\r
@param[in] filp Pointer to a file descriptor structure.\r
@param[in] buf Pointer to the MBCS string to be output.\r
@param[in] N Number of bytes in buf.\r
\r
- @retval >=0 Number of bytes sent to the output device.\r
+ @retval >=0 Number of bytes consumed from buf and sent to the\r
+ Terminal device.\r
**/\r
static\r
ssize_t\r
cFIFO *OutBuf;\r
mbstate_t *OutState;\r
char *MbcsPtr;\r
- ssize_t NumWritten;\r
+ ssize_t NumConsumed;\r
ssize_t NumProc;\r
size_t CharLen;\r
UINTN MaxColumn;\r
UINTN MaxRow;\r
- wchar_t OutChar[2]; // Just in case we run into 4-byte MBCS character\r
+ wchar_t OutChar[2]; // Just in case we run into a 4-byte MBCS character\r
int OutMode;\r
\r
- errno = 0; // indicate no error as default\r
- NumWritten = -1;\r
+ NumConsumed = -1;\r
\r
/* Determine what the current screen size is. Also validates the output device. */\r
OutMode = IIO_GetOutputSize(filp->MyFD, &MaxColumn, &MaxRow);\r
This->CurrentXY.Column = This->InitialXY.Column;\r
This->CurrentXY.Row = This->InitialXY.Row;\r
\r
-\r
- NumWritten = 0;\r
- OutChar[0] = (wchar_t)buf[0];\r
- while((OutChar[0] != 0) && (NumWritten < N)) {\r
- CharLen = mbrtowc(OutChar, (const char *)&buf[NumWritten], MB_CUR_MAX, OutState);\r
+ NumConsumed = 0;\r
+ OutChar[0] = (wchar_t)buf[0];\r
+ while((OutChar[0] != 0) && (NumConsumed < N)) {\r
+ CharLen = mbrtowc(OutChar, (const char *)&buf[NumConsumed], MB_CUR_MAX, OutState);\r
+ if (CharLen < 0) { // Encoding Error\r
+ OutChar[0] = BLOCKELEMENT_LIGHT_SHADE;\r
+ CharLen = 1; // Consume a byte\r
+ (void)mbrtowc(NULL, NULL, 1, OutState); // Re-Initialize the conversion state\r
+ }\r
NumProc = IIO_WriteOne(filp, OutBuf, OutChar[0]);\r
- if(NumProc > 0) {\r
+ if(NumProc >= 0) {\r
// Successfully processed and buffered one character\r
- NumWritten += CharLen; // Index of start of next character\r
- }\r
- else if(NumProc == -1) {\r
- // Encoding Error\r
- (void)mbrtowc(NULL, NULL, 1, OutState); // Re-Initialize the conversion state\r
- errno = EILSEQ;\r
- break;\r
+ NumConsumed += CharLen; // Index of start of next character\r
}\r
else {\r
- // Last character was incomplete\r
- break;\r
+ if (errno == ENOSPC) {\r
+ // Not enough room in OutBuf to hold a potentially expanded character\r
+ break;\r
+ }\r
+ return -1; // Something corrupted and filp->devdata is now NULL\r
}\r
}\r
// At this point, the characters to write are in OutBuf\r
// First, linearize the buffer\r
- NumWritten = OutBuf->Copy(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);\r
- gMD->UString[NumWritten] = 0; // Ensure that the buffer is terminated\r
+ NumProc = OutBuf->Copy(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);\r
+ gMD->UString[NumProc] = 0; // Ensure that the buffer is terminated\r
\r
if(filp->f_iflags & _S_IWTTY) {\r
// Output device expects wide characters, Output what we have\r
- NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, gMD->UString);\r
+ NumProc = filp->f_ops->fo_write(filp, NULL, NumProc, gMD->UString);\r
+\r
+ // Consume the output characters\r
+ W_INSTRUMENT OutBuf->Flush(OutBuf, NumProc);\r
}\r
else {\r
// Output device expects narrow characters, convert to MBCS\r
MbcsPtr = (char *)gMD->UString2;\r
- // Determine the needed space\r
+ // Determine the needed space. NumProc is the number of bytes needed.\r
NumProc = (ssize_t)EstimateWtoM((const wchar_t *)gMD->UString, UNICODE_STRING_MAX * sizeof(wchar_t), &CharLen);\r
\r
- // Now translate this into MBCS in Buffer\r
- NumWritten = wcstombs(MbcsPtr, (const wchar_t *)gMD->UString, NumProc);\r
- MbcsPtr[NumWritten] = 0; // Ensure the buffer is terminated\r
+ // Now translate this into MBCS in the buffer pointed to by MbcsPtr.\r
+ // The returned value, NumProc, is the resulting number of bytes.\r
+ NumProc = wcstombs(MbcsPtr, (const wchar_t *)gMD->UString, NumProc);\r
+ MbcsPtr[NumProc] = 0; // Ensure the buffer is terminated\r
\r
// Send the MBCS buffer to Output\r
- NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, MbcsPtr);\r
+ NumProc = filp->f_ops->fo_write(filp, NULL, NumProc, MbcsPtr);\r
+ // Mark the Mbcs buffer after the last byte actually written\r
+ MbcsPtr[NumProc] = 0;\r
+ // Count the CHARACTERS actually sent\r
+ CharLen = CountMbcsChars(MbcsPtr);\r
+\r
+ // Consume the number of output characters actually sent\r
+ W_INSTRUMENT OutBuf->Flush(OutBuf, CharLen);\r
}\r
- // Consume the translated characters\r
- (void)OutBuf->Flush(OutBuf, NumWritten);\r
}\r
else {\r
if(This == NULL) {\r
}\r
// Otherwise, errno is already set.\r
}\r
- return NumWritten;\r
+ return NumConsumed;\r
}\r
\r
/** Echo a character to an output device.\r