diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2023-11-20 20:46:14 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2023-11-20 20:59:13 +0100 |
commit | 09119463a1445be498f8a6ce3834d462361c7dd3 (patch) | |
tree | ad5e3e893c9ec6b07b032ee9c3768ba509e402c9 /newlib/libc | |
parent | bc986b7ff668aa98372fc4e885307339e7ab3f51 (diff) | |
download | newlib-09119463a1445be498f8a6ce3834d462361c7dd3.zip newlib-09119463a1445be498f8a6ce3834d462361c7dd3.tar.gz newlib-09119463a1445be498f8a6ce3834d462361c7dd3.tar.bz2 |
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>
Diffstat (limited to 'newlib/libc')
-rw-r--r-- | newlib/libc/stdio/Makefile.inc | 1 | ||||
-rw-r--r-- | newlib/libc/stdio/fputwc.c | 7 | ||||
-rw-r--r-- | newlib/libc/stdio/fputws.c | 2 | ||||
-rw-r--r-- | newlib/libc/stdio/fvwrite.c | 48 | ||||
-rw-r--r-- | newlib/libc/stdio/local.h | 33 | ||||
-rw-r--r-- | newlib/libc/stdio/wbuf.c | 3 | ||||
-rw-r--r-- | newlib/libc/stdio/wbufw.c | 66 |
7 files changed, 140 insertions, 20 deletions
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 <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; +} |