aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2023-11-20 20:46:14 +0100
committerCorinna Vinschen <corinna@vinschen.de>2023-11-20 20:59:13 +0100
commit09119463a1445be498f8a6ce3834d462361c7dd3 (patch)
treead5e3e893c9ec6b07b032ee9c3768ba509e402c9 /newlib/libc
parentbc986b7ff668aa98372fc4e885307339e7ab3f51 (diff)
downloadnewlib-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.inc1
-rw-r--r--newlib/libc/stdio/fputwc.c7
-rw-r--r--newlib/libc/stdio/fputws.c2
-rw-r--r--newlib/libc/stdio/fvwrite.c48
-rw-r--r--newlib/libc/stdio/local.h33
-rw-r--r--newlib/libc/stdio/wbuf.c3
-rw-r--r--newlib/libc/stdio/wbufw.c66
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;
+}