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