|
@@ -1,457 +0,0 @@
|
|
|
-
|
|
|
- *
|
|
|
- * This library is free software; you can redistribute it and/or
|
|
|
- * modify it under the terms of the GNU Library General Public
|
|
|
- * License as published by the Free Software Foundation; either
|
|
|
- * version 2 of the License, or (at your option) any later version.
|
|
|
- *
|
|
|
- * This library is distributed in the hope that it will be useful,
|
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
- * Library General Public License for more details.
|
|
|
- *
|
|
|
- * You should have received a copy of the GNU Library General Public
|
|
|
- * License along with this library; if not, write to the Free
|
|
|
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
- */
|
|
|
-
|
|
|
-
|
|
|
- *
|
|
|
- * Besides uClibc, I'm using this code in my libc for elks, which is
|
|
|
- * a 16-bit environment with a fairly limited compiler. It would make
|
|
|
- * things much easier for me if this file isn't modified unnecessarily.
|
|
|
- * In particular, please put any new or replacement functions somewhere
|
|
|
- * else, and modify the makefile to use your version instead.
|
|
|
- * Thanks. Manuel
|
|
|
- *
|
|
|
- * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
|
|
|
-
|
|
|
-
|
|
|
- *
|
|
|
- * Reimplement fputwc and fputws in terms of internal function _wstdio_fwrite.
|
|
|
- */
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- * ANSI/ISO C99 says
|
|
|
-
|
|
|
- 9 Although both text and binary wideoriented streams are conceptually sequences of wide
|
|
|
- characters, the external file associated with a wideoriented stream is a sequence of
|
|
|
- multibyte characters, generalized as follows:
|
|
|
- --- Multibyte encodings within files may contain embedded null bytes (unlike multibyte
|
|
|
- encodings valid for use internal to the program).
|
|
|
- --- A file need not begin nor end in the initial shift state. 225)
|
|
|
-
|
|
|
- * How do we deal with this?
|
|
|
-
|
|
|
- * Should auto_wr_transition init the mbstate object?
|
|
|
-*/
|
|
|
-
|
|
|
-#include <stdio.h>
|
|
|
-#include <wchar.h>
|
|
|
-#include <limits.h>
|
|
|
-#include <errno.h>
|
|
|
-#include <assert.h>
|
|
|
-
|
|
|
-libc_hidden_proto(fgetwc_unlocked)
|
|
|
-libc_hidden_proto(fputwc_unlocked)
|
|
|
-
|
|
|
-#ifndef __UCLIBC_HAS_THREADS__
|
|
|
-
|
|
|
-#ifdef __BCC__
|
|
|
-#define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
|
|
|
-asm(".text\nexport _" "NAME" "_unlocked\n_" "NAME" "_unlocked = _" "NAME"); \
|
|
|
-RETURNTYPE NAME PARAMS
|
|
|
-#else
|
|
|
-#define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
|
|
|
-strong_alias(NAME,NAME##_unlocked) \
|
|
|
-RETURNTYPE NAME PARAMS
|
|
|
-#endif
|
|
|
-
|
|
|
-#define UNLOCKED(RETURNTYPE,NAME,PARAMS,ARGS) \
|
|
|
- UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,stream)
|
|
|
-
|
|
|
-#ifdef __BCC__
|
|
|
-#define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
|
|
|
-asm(".text\nexport _" "NAME" "_unlocked\n_" "NAME" "_unlocked = _" "NAME"); \
|
|
|
-void NAME PARAMS
|
|
|
-#else
|
|
|
-#define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
|
|
|
-strong_alias(NAME,NAME##_unlocked) \
|
|
|
-void NAME PARAMS
|
|
|
-#endif
|
|
|
-
|
|
|
-#define __STDIO_THREADLOCK_OPENLIST
|
|
|
-#define __STDIO_THREADUNLOCK_OPENLIST
|
|
|
-
|
|
|
-#else
|
|
|
-
|
|
|
-#include <pthread.h>
|
|
|
-
|
|
|
-#define UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,STREAM) \
|
|
|
-RETURNTYPE NAME PARAMS \
|
|
|
-{ \
|
|
|
- RETURNTYPE retval; \
|
|
|
- __STDIO_THREADLOCK(STREAM); \
|
|
|
- retval = NAME##_unlocked ARGS ; \
|
|
|
- __STDIO_THREADUNLOCK(STREAM); \
|
|
|
- return retval; \
|
|
|
-} \
|
|
|
-RETURNTYPE NAME##_unlocked PARAMS
|
|
|
-
|
|
|
-#define UNLOCKED(RETURNTYPE,NAME,PARAMS,ARGS) \
|
|
|
- UNLOCKED_STREAM(RETURNTYPE,NAME,PARAMS,ARGS,stream)
|
|
|
-
|
|
|
-#define UNLOCKED_VOID_RETURN(NAME,PARAMS,ARGS) \
|
|
|
-void NAME PARAMS \
|
|
|
-{ \
|
|
|
- __STDIO_THREADLOCK(stream); \
|
|
|
- NAME##_unlocked ARGS ; \
|
|
|
- __STDIO_THREADUNLOCK(stream); \
|
|
|
-} \
|
|
|
-void NAME##_unlocked PARAMS
|
|
|
-
|
|
|
-#define __STDIO_THREADLOCK_OPENLIST \
|
|
|
- __pthread_mutex_lock(&_stdio_openlist_lock)
|
|
|
-
|
|
|
-#define __STDIO_THREADUNLOCK_OPENLIST \
|
|
|
- __pthread_mutex_unlock(&_stdio_openlist_lock)
|
|
|
-
|
|
|
-#define __STDIO_THREADTRYLOCK_OPENLIST \
|
|
|
- __pthread_mutex_trylock(&_stdio_openlist_lock)
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifndef __STDIO_BUFFERS
|
|
|
-#error stdio buffers are currently required for wide i/o
|
|
|
-#endif
|
|
|
-
|
|
|
-
|
|
|
-#ifdef L_fwide
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-int fwide(register FILE *stream, int mode)
|
|
|
-{
|
|
|
- __STDIO_THREADLOCK(stream);
|
|
|
-
|
|
|
- if (mode && !(stream->modeflags & (__FLAG_WIDE|__FLAG_NARROW))) {
|
|
|
- stream->modeflags |= ((mode > 0) ? __FLAG_WIDE : __FLAG_NARROW);
|
|
|
- }
|
|
|
-
|
|
|
- mode = (stream->modeflags & __FLAG_WIDE)
|
|
|
- - (stream->modeflags & __FLAG_NARROW);
|
|
|
-
|
|
|
- __STDIO_THREADUNLOCK(stream);
|
|
|
-
|
|
|
- return mode;
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef L_fgetwc
|
|
|
-
|
|
|
-static void munge_stream(register FILE *stream, unsigned char *buf)
|
|
|
-{
|
|
|
-#ifdef __STDIO_GETC_MACRO
|
|
|
- stream->bufgetc =
|
|
|
-#endif
|
|
|
-#ifdef __STDIO_PUTC_MACRO
|
|
|
- stream->bufputc =
|
|
|
-#endif
|
|
|
- stream->bufpos = stream->bufread = stream->bufend = stream->bufstart = buf;
|
|
|
-}
|
|
|
-
|
|
|
-libc_hidden_proto(mbrtowc)
|
|
|
-
|
|
|
-UNLOCKED(wint_t,fgetwc,(register FILE *stream),(stream))
|
|
|
-{
|
|
|
- wint_t wi;
|
|
|
- wchar_t wc[1];
|
|
|
- int n;
|
|
|
- size_t r;
|
|
|
- unsigned char c[1];
|
|
|
- unsigned char sbuf[1];
|
|
|
-
|
|
|
- wi = WEOF;
|
|
|
-
|
|
|
- if (stream->modeflags & __FLAG_NARROW) {
|
|
|
- stream->modeflags |= __FLAG_ERROR;
|
|
|
- __set_errno(EBADF);
|
|
|
- goto DONE;
|
|
|
- }
|
|
|
- stream->modeflags |= __FLAG_WIDE;
|
|
|
-
|
|
|
- if (stream->modeflags & __MASK_UNGOT) {
|
|
|
-
|
|
|
- assert(stream->modeflags & __FLAG_READING);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if ((((stream->modeflags & __MASK_UNGOT) > 1) || stream->ungot[1])) {
|
|
|
- stream->ungot_width[0] = 0;
|
|
|
- } else {
|
|
|
- stream->ungot_width[0] = stream->ungot_width[1];
|
|
|
- }
|
|
|
-
|
|
|
- wi = stream->ungot[(--stream->modeflags) & __MASK_UNGOT];
|
|
|
- stream->ungot[1] = 0;
|
|
|
- goto DONE;
|
|
|
- }
|
|
|
-
|
|
|
- if (!stream->bufstart) {
|
|
|
-
|
|
|
- munge_stream(stream, sbuf);
|
|
|
- ++stream->bufend;
|
|
|
- }
|
|
|
-
|
|
|
- if (stream->state.mask == 0) {
|
|
|
- stream->ungot_width[0] = 0;
|
|
|
- }
|
|
|
-
|
|
|
- LOOP:
|
|
|
- if ((n = stream->bufread - stream->bufpos) == 0) {
|
|
|
- goto FILL_BUFFER;
|
|
|
- }
|
|
|
-
|
|
|
- r = mbrtowc(wc, stream->bufpos, n, &stream->state);
|
|
|
- if (((ssize_t) r) >= 0) {
|
|
|
- if (r == 0) {
|
|
|
- ++r;
|
|
|
- }
|
|
|
- stream->bufpos += r;
|
|
|
- stream->ungot_width[0] += r;
|
|
|
- wi = *wc;
|
|
|
- goto DONE;
|
|
|
- }
|
|
|
-
|
|
|
- if (r == ((size_t) -2)) {
|
|
|
-
|
|
|
- stream->bufpos += n;
|
|
|
- stream->ungot_width[0] += n;
|
|
|
- FILL_BUFFER:
|
|
|
- if (_stdio_fread(c, (size_t) 1, stream) > 0) {
|
|
|
- assert(stream->bufpos == stream->bufstart + 1);
|
|
|
- *--stream->bufpos = *c;
|
|
|
- goto LOOP;
|
|
|
- }
|
|
|
- if (!__FERROR(stream)) {
|
|
|
- if (!stream->state.mask) {
|
|
|
- goto DONE;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- __set_errno(EILSEQ);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * to EILSEQ, or r == ((size_t)-2) and stream is in an error state
|
|
|
- * or at EOF with a partially complete wchar. Make sure stream's
|
|
|
- * error indicator is set. */
|
|
|
- stream->modeflags |= __FLAG_ERROR;
|
|
|
-
|
|
|
- DONE:
|
|
|
- if (stream->bufstart == sbuf) {
|
|
|
- munge_stream(stream, NULL);
|
|
|
- }
|
|
|
-
|
|
|
- return wi;
|
|
|
-}
|
|
|
-libc_hidden_def(fgetwc_unlocked)
|
|
|
-
|
|
|
-strong_alias(fgetwc_unlocked,getwc_unlocked)
|
|
|
-strong_alias(fgetwc,getwc)
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef L_getwchar
|
|
|
-
|
|
|
-UNLOCKED_STREAM(wint_t,getwchar,(void),(),stdin)
|
|
|
-{
|
|
|
- register FILE *stream = stdin;
|
|
|
-
|
|
|
- return fgetwc_unlocked(stream);
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef L_fgetws
|
|
|
-
|
|
|
-UNLOCKED(wchar_t *,fgetws,(wchar_t *__restrict ws, int n,
|
|
|
- FILE *__restrict stream),(ws, n, stream))
|
|
|
-{
|
|
|
- register wchar_t *p = ws;
|
|
|
- wint_t wi;
|
|
|
-
|
|
|
- while ((n > 1)
|
|
|
- && ((wi = fgetwc_unlocked(stream)) != WEOF)
|
|
|
- && ((*p++ = wi) != '\n')
|
|
|
- ) {
|
|
|
- --n;
|
|
|
- }
|
|
|
- if (p == ws) {
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- *p = 0;
|
|
|
- return ws;
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef L_fputwc
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-UNLOCKED(wint_t,fputwc,(wchar_t wc, FILE *stream),(wc, stream))
|
|
|
-{
|
|
|
-#if 1
|
|
|
- return _wstdio_fwrite(&wc, 1, stream) ? wc : WEOF;
|
|
|
-#else
|
|
|
- size_t n;
|
|
|
- char buf[MB_LEN_MAX];
|
|
|
-
|
|
|
- if (stream->modeflags & __FLAG_NARROW) {
|
|
|
- stream->modeflags |= __FLAG_ERROR;
|
|
|
- __set_errno(EBADF);
|
|
|
- return WEOF;
|
|
|
- }
|
|
|
- stream->modeflags |= __FLAG_WIDE;
|
|
|
-
|
|
|
- return (((n = wcrtomb(buf, wc, &stream->state)) != ((size_t)-1))
|
|
|
- && (_stdio_fwrite(buf, n, stream) == n))
|
|
|
- ? wc : WEOF;
|
|
|
-#endif
|
|
|
-}
|
|
|
-libc_hidden_def(fputwc_unlocked)
|
|
|
-
|
|
|
-strong_alias(fputwc_unlocked,putwc_unlocked)
|
|
|
-strong_alias(fputwc,putwc)
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef L_putwchar
|
|
|
-
|
|
|
-UNLOCKED_STREAM(wint_t,putwchar,(wchar_t wc),(wc),stdout)
|
|
|
-{
|
|
|
- register FILE *stream = stdout;
|
|
|
-
|
|
|
- return fputwc_unlocked(wc, stream);
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#ifdef L_fputws
|
|
|
-
|
|
|
-libc_hidden_proto(wcslen)
|
|
|
-
|
|
|
-
|
|
|
-UNLOCKED(int,fputws,(const wchar_t *__restrict ws,
|
|
|
- register FILE *__restrict stream),(ws, stream))
|
|
|
-{
|
|
|
-#if 1
|
|
|
- size_t n = wcslen(ws);
|
|
|
-
|
|
|
- return (_wstdio_fwrite(ws, n, stream) == n) ? 0 : -1;
|
|
|
-#else
|
|
|
- size_t n;
|
|
|
- char buf[64];
|
|
|
-
|
|
|
- if (stream->modeflags & __FLAG_NARROW) {
|
|
|
- stream->modeflags |= __FLAG_ERROR;
|
|
|
- __set_errno(EBADF);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- stream->modeflags |= __FLAG_WIDE;
|
|
|
-
|
|
|
- while ((n = wcsrtombs(buf, &ws, sizeof(buf), &stream->state)) != 0) {
|
|
|
-
|
|
|
- if ((n == ((size_t) -1))
|
|
|
- || (_stdio_fwrite(buf, n, stream) != n)
|
|
|
- ) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (!ws) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return 1;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-#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, as well
|
|
|
- * as reset stream->ungot_width[1] for use by _stdio_adjpos().
|
|
|
- */
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-libc_hidden_proto(fflush_unlocked)
|
|
|
-
|
|
|
-wint_t ungetwc(wint_t c, register FILE *stream)
|
|
|
-{
|
|
|
- __STDIO_THREADLOCK(stream);
|
|
|
-
|
|
|
- __stdio_validate_FILE(stream);
|
|
|
-
|
|
|
- if (stream->modeflags & __FLAG_NARROW) {
|
|
|
- stream->modeflags |= __FLAG_ERROR;
|
|
|
- c = WEOF;
|
|
|
- goto DONE;
|
|
|
- }
|
|
|
- stream->modeflags |= __FLAG_WIDE;
|
|
|
-
|
|
|
-
|
|
|
- if ((stream->modeflags
|
|
|
- & (__MASK_UNGOT2|__FLAG_WRITEONLY
|
|
|
-#ifndef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__
|
|
|
- |__FLAG_WRITING
|
|
|
-#endif
|
|
|
- ))
|
|
|
- || ((stream->modeflags & __MASK_UNGOT1) && (stream->ungot[1]))
|
|
|
- || (c == WEOF) ) {
|
|
|
- c = WEOF;
|
|
|
- goto DONE;;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-#ifdef __STDIO_BUFFERS
|
|
|
-#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__
|
|
|
- if (stream->modeflags & __FLAG_WRITING) {
|
|
|
- fflush_unlocked(stream);
|
|
|
- }
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-
|
|
|
-
|
|
|
- stream->modeflags &= ~(__FLAG_EOF|__FLAG_WRITING);
|
|
|
-#ifdef __UCLIBC_MJN3_ONLY__
|
|
|
-#warning CONSIDER: Is setting the reading flag after an ungetwc necessary?
|
|
|
-#endif
|
|
|
- stream->modeflags |= __FLAG_READING;
|
|
|
- stream->ungot[1] = 1;
|
|
|
- stream->ungot[(stream->modeflags++) & __MASK_UNGOT] = c;
|
|
|
-
|
|
|
- __stdio_validate_FILE(stream);
|
|
|
-
|
|
|
- DONE:
|
|
|
- __STDIO_THREADUNLOCK(stream);
|
|
|
-
|
|
|
- return c;
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|