summaryrefslogtreecommitdiff
path: root/libc/misc/wchar/wstdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/misc/wchar/wstdio.c')
-rw-r--r--libc/misc/wchar/wstdio.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/libc/misc/wchar/wstdio.c b/libc/misc/wchar/wstdio.c
index dfeb35c30..1069ee938 100644
--- a/libc/misc/wchar/wstdio.c
+++ b/libc/misc/wchar/wstdio.c
@@ -171,7 +171,6 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
size_t r;
unsigned char c[1];
unsigned char sbuf[1];
- unsigned char ungot_width; /* Support ftell after wscanf ungetwc. */
wi = WEOF; /* Prepare for failure. */
@@ -183,8 +182,18 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
stream->modeflags |= __FLAG_WIDE;
if (stream->modeflags & __MASK_UNGOT) {/* Any ungetwc()s? */
- assert( (stream->modeflags & (__FLAG_READING|__FLAG_ERROR))
- == __FLAG_READING);
+
+ assert(stream->modeflags & __FLAG_READING);
+
+/* assert( (stream->modeflags & (__FLAG_READING|__FLAG_ERROR)) */
+/* == __FLAG_READING); */
+
+ if ((((stream->modeflags & __MASK_UNGOT) > 1) || stream->ungot[1])) {
+ stream->ungot_width[0] = 0; /* Application ungot... */
+ } else {
+ stream->ungot_width[0] = stream->ungot_width[1]; /* scanf ungot */
+ }
+
wi = stream->ungot[(--stream->modeflags) & __MASK_UNGOT];
stream->ungot[1] = 0;
goto DONE;
@@ -196,7 +205,9 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
++stream->bufend;
}
- ungot_width = 0;
+ if (stream->state.mask == 0) { /* If last was a complete char */
+ stream->ungot_width[0] = 0; /* then reset the width. */
+ }
LOOP:
if ((n = stream->bufread - stream->bufpos) == 0) {
@@ -204,12 +215,12 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
}
r = mbrtowc(wc, stream->bufpos, n, &stream->state);
- if (((ssize_t) r) >= 0) { /* Single byte... */
+ if (((ssize_t) r) >= 0) { /* Success... */
if (r == 0) { /* Nul wide char... means 0 byte for us so */
++r; /* increment r and handle below as single. */
}
stream->bufpos += r;
- stream->ungot_width[0] = ungot_width + r;
+ stream->ungot_width[0] += r;
wi = *wc;
goto DONE;
}
@@ -217,7 +228,7 @@ UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
if (r == ((size_t) -2)) {
/* Potentially valid but incomplete and no more buffered. */
stream->bufpos += n; /* Update bufpos for stream. */
- ungot_width += n;
+ stream->ungot_width[0] += n;
FILL_BUFFER:
if (_stdio_fread(c, (size_t) 1, stream) > 0) {
assert(stream->bufpos == stream->bufstart + 1);
@@ -371,7 +382,8 @@ UNLOCKED(int,fputws,(const wchar_t *__restrict ws,
#ifdef L_ungetwc
/*
* Note: This is the application-callable ungetwc. If wscanf calls this, it
- * should also set stream->ungot[1] to 0 if this is the only ungot.
+ * should also set stream->ungot[1] to 0 if this is the only ungot, as well
+ * as reset stream->ungot_width[1] for use by _stdio_adjpos().
*/
/* Reentrant. */
@@ -389,8 +401,7 @@ wint_t ungetwc(wint_t c, register FILE *stream)
}
stream->modeflags |= __FLAG_WIDE;
- /* If can't read or there's been an error, or c == EOF, or ungot slots
- * already filled, then return EOF */
+ /* If can't read or c == WEOF or ungot slots already filled, then fail. */
if ((stream->modeflags
& (__MASK_UNGOT2|__FLAG_WRITEONLY
#ifndef __STDIO_AUTO_RW_TRANSITION
@@ -406,14 +417,18 @@ wint_t ungetwc(wint_t c, register FILE *stream)
/* ungot_width */
#ifdef __STDIO_BUFFERS
- /* TODO: shouldn't allow writing??? */
+#ifdef __STDIO_AUTO_RW_TRANSITION
if (stream->modeflags & __FLAG_WRITING) {
fflush_unlocked(stream); /* Commit any write-buffered chars. */
}
+#endif /* __STDIO_AUTO_RW_TRANSITION */
#endif /* __STDIO_BUFFERS */
/* Clear EOF and WRITING flags, and set READING FLAG */
stream->modeflags &= ~(__FLAG_EOF|__FLAG_WRITING);
+#ifdef __UCLIBC_MJN3_ONLY__
+#warning CONSIDER: Is setting the reading flag after an ungetwc necessary?
+#endif /* __UCLIBC_MJN3_ONLY__ */
stream->modeflags |= __FLAG_READING;
stream->ungot[1] = 1; /* Flag as app ungetc call; wscanf fixes up. */
stream->ungot[(stream->modeflags++) & __MASK_UNGOT] = c;