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 <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2023-11-20 20:46:14 +01:00
parent bc986b7ff6
commit 09119463a1
8 changed files with 159 additions and 21 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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++;
}

View File

@ -70,7 +70,28 @@ __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 */
{
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
{
@ -85,6 +106,7 @@ __sfvwrite_r (struct _reent *ptr,
}
}
while (uio->uio_resid > 0);
}
return 0;
}
#endif

View File

@ -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);

View File

@ -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,

66
newlib/libc/stdio/wbufw.c Normal file
View File

@ -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 <stdio.h>
#include <errno.h>
#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;
}