]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc.c
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / libc / stdio / fgetwc.c
1 /* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org>
2  *
3  * GNU Library General Public License (LGPL) version 2 or later.
4  *
5  * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
6  */
7
8 #include "_stdio.h"
9
10
11
12 #ifdef __DO_UNLOCKED
13
14 static void munge_stream(register FILE *stream, unsigned char *buf)
15 {
16         stream->__bufend = stream->__bufstart = buf;
17         __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
18         __STDIO_STREAM_DISABLE_GETC(stream);
19         __STDIO_STREAM_DISABLE_PUTC(stream);
20 }
21
22 wint_t fgetwc_unlocked(register FILE *stream)
23 {
24         wint_t wi;
25         wchar_t wc[1];
26         int n;
27         size_t r;
28         unsigned char sbuf[1];
29
30         __STDIO_STREAM_VALIDATE(stream);
31
32         wi = WEOF;                                      /* Prepare for failure. */
33
34         if (__STDIO_STREAM_IS_WIDE_READING(stream)
35                 || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_WIDE)
36                 ) {
37                 if (stream->__modeflags & __FLAG_UNGOT) { /* Any ungetwc()s? */
38                         if (((stream->__modeflags & 1) || stream->__ungot[1])) {
39                                 stream->__ungot_width[0] = 0;   /* Application ungot... */
40                         } else {                        /* scanf ungot */
41                                 stream->__ungot_width[0] = stream->__ungot_width[1];
42                         }
43
44                         wi = stream->__ungot[(stream->__modeflags--) & 1];
45                         stream->__ungot[1] = 0;
46                         goto DONE;
47                 }
48
49                 if (!stream->__bufstart) {      /* Ugh... stream isn't buffered! */
50                         /* Munge the stream temporarily to use a 1-byte buffer. */
51                         munge_stream(stream, sbuf);
52                         ++stream->__bufend;
53                 }
54
55                 if (stream->__state.__mask == 0) { /* If last was a complete char */
56                         stream->__ungot_width[0] = 0; /* then reset the width. */
57                 }
58
59  LOOP:
60                 if ((n = __STDIO_STREAM_BUFFER_RAVAIL(stream)) == 0) {
61                         goto FILL_BUFFER;
62                 }
63
64                 r = mbrtowc(wc, (const char*) stream->__bufpos, n, &stream->__state);
65                 if (((ssize_t) r) >= 0) { /* Success... */
66                         if (r == 0) { /* Nul wide char... means 0 byte for us so */
67                                 ++r;     /* increment r and handle below as single. */
68                         }
69                         stream->__bufpos += r;
70                         stream->__ungot_width[0] += r;
71                         wi = *wc;
72                         goto DONE;
73                 }
74
75                 if (r == ((size_t) -2)) {
76                         /* Potentially valid but incomplete and no more buffered. */
77                         stream->__bufpos += n; /* Update bufpos for stream. */
78                         stream->__ungot_width[0] += n;
79  FILL_BUFFER:
80                         if(__STDIO_FILL_READ_BUFFER(stream)) { /* Refill succeeded? */
81                                 goto LOOP;
82                         }
83                         if (!__FERROR_UNLOCKED(stream)) { /* EOF with no error. */
84                                 if (!stream->__state.__mask) { /* No partial wchar. */
85                                         goto DONE;
86                                 }
87                                 /* EOF but partially complete wchar. */
88                                 /* TODO: should EILSEQ be set? */
89                                 __set_errno(EILSEQ);
90                         }
91                 }
92
93                 /* If we reach here, either r == ((size_t)-1) and mbrtowc set errno
94                  * to EILSEQ, or r == ((size_t)-2) and stream is in an error state
95                  * or at EOF with a partially complete wchar.  Make sure stream's
96                  * error indicator is set. */
97                 stream->__modeflags |= __FLAG_ERROR;
98
99  DONE:
100                 if (stream->__bufstart == sbuf) { /* Need to un-munge the stream. */
101                         munge_stream(stream, NULL);
102                 }
103
104         }
105
106         __STDIO_STREAM_VALIDATE(stream);
107
108         return wi;
109 }
110 libc_hidden_def(fgetwc_unlocked)
111
112 strong_alias(fgetwc_unlocked,getwc_unlocked)
113 #ifndef __UCLIBC_HAS_THREADS__
114 strong_alias(fgetwc_unlocked,fgetwc)
115 libc_hidden_def(fgetwc)
116
117 strong_alias(fgetwc_unlocked,getwc)
118 #endif
119
120 #elif defined __UCLIBC_HAS_THREADS__
121
122 wint_t fgetwc(register FILE *stream)
123 {
124         wint_t retval;
125         __STDIO_AUTO_THREADLOCK_VAR;
126
127         __STDIO_AUTO_THREADLOCK(stream);
128
129         retval = fgetwc_unlocked(stream);
130
131         __STDIO_AUTO_THREADUNLOCK(stream);
132
133         return retval;
134 }
135 libc_hidden_def(fgetwc)
136
137 strong_alias(fgetwc,getwc)
138 #endif