From 09119463a1445be498f8a6ce3834d462361c7dd3 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 20 Nov 2023 20:46:14 +0100 Subject: stdio: split byte- and wide-char-oriented low-level output functions Introduce function __swbufw_r and macros/inline-functions called __swputc_r. Call these functions/macros exclusively from wide-char functions. This allows to set and test the stream orientation correctly even if output is only performed using byte-oriented macros from stdio.h. Signed-off-by: Corinna Vinschen --- newlib/Makefile.in | 20 ++++++++++++- newlib/libc/stdio/Makefile.inc | 1 + newlib/libc/stdio/fputwc.c | 7 ++--- newlib/libc/stdio/fputws.c | 2 +- newlib/libc/stdio/fvwrite.c | 48 +++++++++++++++++++++--------- newlib/libc/stdio/local.h | 33 +++++++++++++++++++++ newlib/libc/stdio/wbuf.c | 3 +- newlib/libc/stdio/wbufw.c | 66 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 newlib/libc/stdio/wbufw.c (limited to 'newlib') diff --git a/newlib/Makefile.in b/newlib/Makefile.in index ff2f88f..644e595 100644 --- a/newlib/Makefile.in +++ b/newlib/Makefile.in @@ -292,7 +292,7 @@ check_PROGRAMS = @HAVE_STDIO_DIR_TRUE@ libc/stdio/vsnprintf.c \ @HAVE_STDIO_DIR_TRUE@ libc/stdio/vsprintf.c \ @HAVE_STDIO_DIR_TRUE@ libc/stdio/vsscanf.c libc/stdio/wbuf.c \ -@HAVE_STDIO_DIR_TRUE@ libc/stdio/wsetup.c \ +@HAVE_STDIO_DIR_TRUE@ libc/stdio/wbufw.c libc/stdio/wsetup.c \ @HAVE_STDIO_DIR_TRUE@ $(libc_stdio_ELIX_2_SOURCES) \ @HAVE_STDIO_DIR_TRUE@ $(libc_stdio_ELIX_4_SOURCES) @ELIX_LEVEL_1_FALSE@@HAVE_STDIO_DIR_TRUE@@NEWLIB_NANO_FORMATTED_IO_FALSE@am__append_13 = \ @@ -1330,6 +1330,7 @@ am__objects_5 = libc/stdlib/libc_a-rpmatch.$(OBJEXT) \ @HAVE_STDIO_DIR_TRUE@ libc/stdio/libc_a-vsprintf.$(OBJEXT) \ @HAVE_STDIO_DIR_TRUE@ libc/stdio/libc_a-vsscanf.$(OBJEXT) \ @HAVE_STDIO_DIR_TRUE@ libc/stdio/libc_a-wbuf.$(OBJEXT) \ +@HAVE_STDIO_DIR_TRUE@ libc/stdio/libc_a-wbufw.$(OBJEXT) \ @HAVE_STDIO_DIR_TRUE@ libc/stdio/libc_a-wsetup.$(OBJEXT) \ @HAVE_STDIO_DIR_TRUE@ $(am__objects_13) $(am__objects_15) @ELIX_LEVEL_1_FALSE@@HAVE_STDIO64_DIR_TRUE@am__objects_17 = libc/stdio64/libc_a-fdopen64.$(OBJEXT) \ @@ -6126,6 +6127,8 @@ libc/stdio/libc_a-vsscanf.$(OBJEXT): libc/stdio/$(am__dirstamp) \ libc/stdio/$(DEPDIR)/$(am__dirstamp) libc/stdio/libc_a-wbuf.$(OBJEXT): libc/stdio/$(am__dirstamp) \ libc/stdio/$(DEPDIR)/$(am__dirstamp) +libc/stdio/libc_a-wbufw.$(OBJEXT): libc/stdio/$(am__dirstamp) \ + libc/stdio/$(DEPDIR)/$(am__dirstamp) libc/stdio/libc_a-wsetup.$(OBJEXT): libc/stdio/$(am__dirstamp) \ libc/stdio/$(DEPDIR)/$(am__dirstamp) libc/stdio/libc_a-asprintf.$(OBJEXT): libc/stdio/$(am__dirstamp) \ @@ -13509,6 +13512,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@libc/stdio/$(DEPDIR)/libc_a-vwprintf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/stdio/$(DEPDIR)/libc_a-vwscanf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/stdio/$(DEPDIR)/libc_a-wbuf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@libc/stdio/$(DEPDIR)/libc_a-wbufw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/stdio/$(DEPDIR)/libc_a-wprintf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/stdio/$(DEPDIR)/libc_a-wscanf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@libc/stdio/$(DEPDIR)/libc_a-wsetup.Po@am__quote@ @@ -25124,6 +25128,20 @@ libc/stdio/libc_a-wbuf.obj: libc/stdio/wbuf.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/stdio/libc_a-wbuf.obj `if test -f 'libc/stdio/wbuf.c'; then $(CYGPATH_W) 'libc/stdio/wbuf.c'; else $(CYGPATH_W) '$(srcdir)/libc/stdio/wbuf.c'; fi` +libc/stdio/libc_a-wbufw.o: libc/stdio/wbufw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/stdio/libc_a-wbufw.o -MD -MP -MF libc/stdio/$(DEPDIR)/libc_a-wbufw.Tpo -c -o libc/stdio/libc_a-wbufw.o `test -f 'libc/stdio/wbufw.c' || echo '$(srcdir)/'`libc/stdio/wbufw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/stdio/$(DEPDIR)/libc_a-wbufw.Tpo libc/stdio/$(DEPDIR)/libc_a-wbufw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libc/stdio/wbufw.c' object='libc/stdio/libc_a-wbufw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/stdio/libc_a-wbufw.o `test -f 'libc/stdio/wbufw.c' || echo '$(srcdir)/'`libc/stdio/wbufw.c + +libc/stdio/libc_a-wbufw.obj: libc/stdio/wbufw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/stdio/libc_a-wbufw.obj -MD -MP -MF libc/stdio/$(DEPDIR)/libc_a-wbufw.Tpo -c -o libc/stdio/libc_a-wbufw.obj `if test -f 'libc/stdio/wbufw.c'; then $(CYGPATH_W) 'libc/stdio/wbufw.c'; else $(CYGPATH_W) '$(srcdir)/libc/stdio/wbufw.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/stdio/$(DEPDIR)/libc_a-wbufw.Tpo libc/stdio/$(DEPDIR)/libc_a-wbufw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libc/stdio/wbufw.c' object='libc/stdio/libc_a-wbufw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -c -o libc/stdio/libc_a-wbufw.obj `if test -f 'libc/stdio/wbufw.c'; then $(CYGPATH_W) 'libc/stdio/wbufw.c'; else $(CYGPATH_W) '$(srcdir)/libc/stdio/wbufw.c'; fi` + libc/stdio/libc_a-wsetup.o: libc/stdio/wsetup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libc_a_CPPFLAGS) $(CPPFLAGS) $(libc_a_CFLAGS) $(CFLAGS) -MT libc/stdio/libc_a-wsetup.o -MD -MP -MF libc/stdio/$(DEPDIR)/libc_a-wsetup.Tpo -c -o libc/stdio/libc_a-wsetup.o `test -f 'libc/stdio/wsetup.c' || echo '$(srcdir)/'`libc/stdio/wsetup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libc/stdio/$(DEPDIR)/libc_a-wsetup.Tpo libc/stdio/$(DEPDIR)/libc_a-wsetup.Po diff --git a/newlib/libc/stdio/Makefile.inc b/newlib/libc/stdio/Makefile.inc index 0780e5c..e256802 100644 --- a/newlib/libc/stdio/Makefile.inc +++ b/newlib/libc/stdio/Makefile.inc @@ -117,6 +117,7 @@ libc_a_SOURCES += \ %D%/vsprintf.c \ %D%/vsscanf.c \ %D%/wbuf.c \ + %D%/wbufw.c \ %D%/wsetup.c ## The following are EL/IX level 2 interfaces diff --git a/newlib/libc/stdio/fputwc.c b/newlib/libc/stdio/fputwc.c index ef2be10..8430446 100644 --- a/newlib/libc/stdio/fputwc.c +++ b/newlib/libc/stdio/fputwc.c @@ -155,7 +155,7 @@ __fputwc (struct _reent *ptr, } for (i = 0; i < len; i++) - if (__sputc_r (ptr, (unsigned char) buf[i], fp) == EOF) + if (__swputc_r (ptr, (unsigned char) buf[i], fp) == EOF) return WEOF; return (wint_t) wc; @@ -169,10 +169,7 @@ _fputwc_r (struct _reent *ptr, wint_t r; _newlib_flockfile_start (fp); - if (ORIENT(fp, 1) != 1) - r = WEOF; - else - r = __fputwc(ptr, wc, fp); + __fputwc(ptr, wc, fp); _newlib_flockfile_end (fp); return r; } diff --git a/newlib/libc/stdio/fputws.c b/newlib/libc/stdio/fputws.c index a9ac9d6..d696383 100644 --- a/newlib/libc/stdio/fputws.c +++ b/newlib/libc/stdio/fputws.c @@ -143,7 +143,7 @@ error: goto error; while (i < nbytes) { - if (__sputc_r (ptr, buf[i], fp) == EOF) + if (__swputc_r (ptr, buf[i], fp) == EOF) goto error; i++; } diff --git a/newlib/libc/stdio/fvwrite.c b/newlib/libc/stdio/fvwrite.c index fc79951..add48ba 100644 --- a/newlib/libc/stdio/fvwrite.c +++ b/newlib/libc/stdio/fvwrite.c @@ -70,21 +70,43 @@ __sfvwrite_r (struct _reent *ptr, len = 0; #ifdef __SCLE + /* This only affects Cygwin, so calling __sputc_r *and* __swputc_r + * from here doesn't matter. + */ if (fp->_flags & __SCLE) /* text mode */ { - do - { - GETIOV (;); - while (len > 0) - { - if (__sputc_r (ptr, *p, fp) == EOF) - return EOF; - p++; - len--; - uio->uio_resid--; - } - } - while (uio->uio_resid > 0); + if (fp->_flags2 & __SWID) + { + do + { + GETIOV (;); + while (len > 0) + { + if (__swputc_r (ptr, *p, fp) == EOF) + return EOF; + p++; + len--; + uio->uio_resid--; + } + } + while (uio->uio_resid > 0); + } + else + { + do + { + GETIOV (;); + while (len > 0) + { + if (__sputc_r (ptr, *p, fp) == EOF) + return EOF; + p++; + len--; + uio->uio_resid--; + } + } + while (uio->uio_resid > 0); + } return 0; } #endif diff --git a/newlib/libc/stdio/local.h b/newlib/libc/stdio/local.h index 3b86cf1..63c0618 100644 --- a/newlib/libc/stdio/local.h +++ b/newlib/libc/stdio/local.h @@ -251,6 +251,39 @@ extern _READ_WRITE_RETURN_TYPE __swrite64 (struct _reent *, void *, #define ORIENT(fp,ori) (-1) #endif +/* Same thing as the functions in stdio.h, but these are to be called + from inside the wide-char functions. */ +int __swbufw_r (struct _reent *, int, FILE *); +#ifdef __GNUC__ +_ELIDABLE_INLINE int __swputc_r(struct _reent *_ptr, int _c, FILE *_p) { +#ifdef __SCLE + if ((_p->_flags & __SCLE) && _c == '\n') + __swputc_r (_ptr, '\r', _p); +#endif + if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) + return (*_p->_p++ = _c); + else + return (__swbufw_r(_ptr, _c, _p)); +} +#else +#define __swputc_raw_r(__ptr, __c, __p) \ + (--(__p)->_w < 0 ? \ + (__p)->_w >= (__p)->_lbfsize ? \ + (*(__p)->_p = (__c)), *(__p)->_p != '\n' ? \ + (int)*(__p)->_p++ : \ + __swbufw_r(__ptr, '\n', __p) : \ + __swbufw_r(__ptr, (int)(__c), __p) : \ + (*(__p)->_p = (__c), (int)*(__p)->_p++)) +#ifdef __SCLE +#define __swputc_r(__ptr, __c, __p) \ + ((((__p)->_flags & __SCLE) && ((__c) == '\n')) \ + ? __swputc_raw_r(__ptr, '\r', (__p)) : 0 , \ + __swputc_raw_r((__ptr), (__c), (__p))) +#else +#define __swputc_r(__ptr, __c, __p) __swputc_raw_r(__ptr, __c, __p) +#endif +#endif + /* WARNING: _dcvt is defined in the stdlib directory, not here! */ char *_dcvt (struct _reent *, char *, double, int, int, char, int); diff --git a/newlib/libc/stdio/wbuf.c b/newlib/libc/stdio/wbuf.c index 2474903..2e742e2 100644 --- a/newlib/libc/stdio/wbuf.c +++ b/newlib/libc/stdio/wbuf.c @@ -56,7 +56,8 @@ __swbuf_r (struct _reent *ptr, return EOF; c = (unsigned char) c; - ORIENT (fp, -1); + if (ORIENT (fp, -1) != -1) + return EOF; /* * If it is completely full, flush it out. Then, in any case, diff --git a/newlib/libc/stdio/wbufw.c b/newlib/libc/stdio/wbufw.c new file mode 100644 index 0000000..01639df --- /dev/null +++ b/newlib/libc/stdio/wbufw.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * and/or other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* No user fns here. Pesch 15apr92. */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <_ansi.h> +#include +#include +#include "local.h" +#include "fvwrite.h" + +/* + * Note that this is the same function as __swbuf_r, just to be called + * from wide-char functions! + * + * The only difference is that we set and test the orientation differently. + */ + +int +__swbufw_r (struct _reent *ptr, + register int c, + register FILE *fp) +{ + register int n; + + CHECK_INIT (ptr, fp); + + fp->_w = fp->_lbfsize; + if (cantwrite (ptr, fp)) + return EOF; + c = (unsigned char) c; + + if (ORIENT (fp, 1) != 1) + return EOF; + + n = fp->_p - fp->_bf._base; + if (n >= fp->_bf._size) + { + if (_fflush_r (ptr, fp)) + return EOF; + n = 0; + } + fp->_w--; + *fp->_p++ = c; + if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n')) + if (_fflush_r (ptr, fp)) + return EOF; + return c; +} -- cgit v1.1