2000-02-18 03:39:52 +08:00
|
|
|
/*
|
|
|
|
* 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,
|
2020-01-29 02:54:53 +08:00
|
|
|
* and/or other materials related to such
|
2000-02-18 03:39:52 +08:00
|
|
|
* 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.
|
|
|
|
*/
|
2004-04-23 Artem B. Bityuckiy <abitytsky@softminecorp.com>
* libc/stdio/asprintf.c libc/stdio/clearerr.c,
libc/stdio/fclose.c libc/stdio/fcloseall.c libc/stdio/fdopen.c,
libc/stdio/feof.c libc/stdio/ferror.c libc/stdio/fflush.c,
libc/stdio/fgetc.c libc/stdio/fgetpos.c libc/stdio/fgets.c,
libc/stdio/fileno.c libc/stdio/findfp.c libc/stdio/fiprintf.c,
libc/stdio/flags.c libc/stdio/fopen.c libc/stdio/fprintf.c,
libc/stdio/fputc.c libc/stdio/fputs.c libc/stdio/fread.c,
libc/stdio/freopen.c libc/stdio/fscanf.c libc/stdio/fseek.c,
libc/stdio/fseeko.c libc/stdio/fsetpos.c libc/stdio/ftell.c,
libc/stdio/ftello.c libc/stdio/fvwrite.c libc/stdio/fwalk.c,
libc/stdio/fwrite.c libc/stdio/getc.c libc/stdio/getc_u.c,
libc/stdio/getchar.c libc/stdio/getchar_u.c,
libc/stdio/getdelim.c libc/stdio/getline.c libc/stdio/gets.c,
libc/stdio/getw.c libc/stdio/iprintf.c libc/stdio/local.h,
libc/stdio/makebuf.c libc/stdio/mktemp.c libc/stdio/perror.c,
libc/stdio/printf.c libc/stdio/putc.c libc/stdio/putc_u.c,
libc/stdio/putchar.c libc/stdio/putchar_u.c libc/stdio/puts.c,
libc/stdio/putw.c libc/stdio/refill.c libc/stdio/remove.c,
libc/stdio/rename.c libc/stdio/rewind.c libc/stdio/rget.c,
libc/stdio/scanf.c libc/stdio/setbuf.c libc/stdio/setbuffer.c,
libc/stdio/setlinebuf.c libc/stdio/setvbuf.c,
libc/stdio/siprintf.c libc/stdio/snprintf.c,
libc/stdio/sprintf.c libc/stdio/sscanf.c libc/stdio/stdio.c,
libc/stdio/tmpfile.c libc/stdio/tmpnam.c libc/stdio/ungetc.c,
libc/stdio/vasprintf.c libc/stdio/vfieeefp.h,
libc/stdio/vfprintf.c libc/stdio/vfscanf.c,
libc/stdio/vprintf.c libc/stdio/vscanf.c,
libc/stdio/vsnprintf.c libc/stdio/vsprintf.c,
libc/stdio/vsscanf.c libc/stdio/wbuf.c,
libc/stdio/wsetup.c: Perform minor formatting changes. Move
copyright notices to top of file, ensure that <_ansi.h> is
included, be consistent with open parentheses, use _DEFUN macro,
include "local.h" where needed, and remove various compiler
warnings.
2004-04-24 04:01:55 +08:00
|
|
|
/* No user fns here. Pesch 15apr92. */
|
2000-02-18 03:39:52 +08:00
|
|
|
|
2004-04-23 Artem B. Bityuckiy <abitytsky@softminecorp.com>
* libc/stdio/asprintf.c libc/stdio/clearerr.c,
libc/stdio/fclose.c libc/stdio/fcloseall.c libc/stdio/fdopen.c,
libc/stdio/feof.c libc/stdio/ferror.c libc/stdio/fflush.c,
libc/stdio/fgetc.c libc/stdio/fgetpos.c libc/stdio/fgets.c,
libc/stdio/fileno.c libc/stdio/findfp.c libc/stdio/fiprintf.c,
libc/stdio/flags.c libc/stdio/fopen.c libc/stdio/fprintf.c,
libc/stdio/fputc.c libc/stdio/fputs.c libc/stdio/fread.c,
libc/stdio/freopen.c libc/stdio/fscanf.c libc/stdio/fseek.c,
libc/stdio/fseeko.c libc/stdio/fsetpos.c libc/stdio/ftell.c,
libc/stdio/ftello.c libc/stdio/fvwrite.c libc/stdio/fwalk.c,
libc/stdio/fwrite.c libc/stdio/getc.c libc/stdio/getc_u.c,
libc/stdio/getchar.c libc/stdio/getchar_u.c,
libc/stdio/getdelim.c libc/stdio/getline.c libc/stdio/gets.c,
libc/stdio/getw.c libc/stdio/iprintf.c libc/stdio/local.h,
libc/stdio/makebuf.c libc/stdio/mktemp.c libc/stdio/perror.c,
libc/stdio/printf.c libc/stdio/putc.c libc/stdio/putc_u.c,
libc/stdio/putchar.c libc/stdio/putchar_u.c libc/stdio/puts.c,
libc/stdio/putw.c libc/stdio/refill.c libc/stdio/remove.c,
libc/stdio/rename.c libc/stdio/rewind.c libc/stdio/rget.c,
libc/stdio/scanf.c libc/stdio/setbuf.c libc/stdio/setbuffer.c,
libc/stdio/setlinebuf.c libc/stdio/setvbuf.c,
libc/stdio/siprintf.c libc/stdio/snprintf.c,
libc/stdio/sprintf.c libc/stdio/sscanf.c libc/stdio/stdio.c,
libc/stdio/tmpfile.c libc/stdio/tmpnam.c libc/stdio/ungetc.c,
libc/stdio/vasprintf.c libc/stdio/vfieeefp.h,
libc/stdio/vfprintf.c libc/stdio/vfscanf.c,
libc/stdio/vprintf.c libc/stdio/vscanf.c,
libc/stdio/vsnprintf.c libc/stdio/vsprintf.c,
libc/stdio/vsscanf.c libc/stdio/wbuf.c,
libc/stdio/wsetup.c: Perform minor formatting changes. Move
copyright notices to top of file, ensure that <_ansi.h> is
included, be consistent with open parentheses, use _DEFUN macro,
include "local.h" where needed, and remove various compiler
warnings.
2004-04-24 04:01:55 +08:00
|
|
|
#include <_ansi.h>
|
|
|
|
#include <reent.h>
|
2000-02-18 03:39:52 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
2000-05-24 07:51:54 +08:00
|
|
|
#include <fcntl.h>
|
2002-09-04 03:40:36 +08:00
|
|
|
#include <sys/lock.h>
|
2000-02-18 03:39:52 +08:00
|
|
|
#include "local.h"
|
|
|
|
|
2022-05-03 12:51:22 +08:00
|
|
|
void (*__stdio_exit_handler) (void);
|
|
|
|
|
2017-06-22 15:22:47 +08:00
|
|
|
__FILE __sf[3];
|
Use global stdio streams for all configurations
The _REENT_GLOBAL_STDIO_STREAMS was introduced by commit
668a4c8722090fffd10869dbb15b879651c1370d in 2017. Since then it was enabled by
default for RTEMS. Recently, the option was enabled for Cygwin which
previously used an alternative implementation to use global stdio streams.
In Newlib, the stdio streams are defined to thread-specific pointers
_reent::_stdin, _reent::_stdout and _reent::_stderr. If the option is disabled
(the default for most systems), then these pointers are initialized to
thread-specific FILE objects which use file descriptors 0, 1, and 2,
respectively. There are at least three problems with this:
(1) The thread-specific FILE objects are closed by _reclaim_reent(). This
leads to problems with language run-time libraries that provide wrappers to
the C/POSIX stdio streams (for example C++ and Ada), since they use the
thread-specific FILE objects of the initialization thread. In case the
initialization thread is deleted, then they use freed memory.
(2) Since thread-specific FILE objects are used with a common output device via
file descriptors 0, 1 and 2, the locking at FILE object level cannot ensure
atomicity of the output, e.g. a call to printf().
(3) There are resource managment issues, see:
https://sourceware.org/pipermail/newlib/2022/019558.html
https://bugs.linaro.org/show_bug.cgi?id=5841
This patch enables the _REENT_GLOBAL_STDIO_STREAMS behaviour for all Newlib
configurations and removes the option. This removes a couple of #ifdef blocks.
2022-05-18 00:28:52 +08:00
|
|
|
|
2022-05-02 14:58:25 +08:00
|
|
|
struct _glue __sglue = {NULL, 3, &__sf[0]};
|
2017-06-22 15:22:47 +08:00
|
|
|
|
Add --enable-newlib-reent-thread-local option
By default, Newlib uses a huge object of type struct _reent to store
thread-specific data. This object is returned by __getreent() if the
__DYNAMIC_REENT__ Newlib configuration option is defined.
The reentrancy structure contains for example errno and the standard input,
output, and error file streams. This means that if an application only uses
errno it has a dependency on the file stream support even if it does not use
it. This is an issue for lower end targets and applications which need to
qualify the software according to safety standards (for example ECSS-E-ST-40C,
ECSS-Q-ST-80C, IEC 61508, ISO 26262, DO-178, DO-330, DO-333).
If the new _REENT_THREAD_LOCAL configuration option is enabled, then struct
_reent is replaced by dedicated thread-local objects for each struct _reent
member. The thread-local objects are defined in translation units which use
the corresponding object.
2022-05-16 17:51:54 +08:00
|
|
|
#ifdef _REENT_THREAD_LOCAL
|
|
|
|
_Thread_local __FILE *_tls_stdin = &__sf[0];
|
|
|
|
_Thread_local __FILE *_tls_stdout = &__sf[1];
|
|
|
|
_Thread_local __FILE *_tls_stderr = &__sf[2];
|
|
|
|
_Thread_local void (*_tls_cleanup)(struct _reent *);
|
|
|
|
#endif
|
|
|
|
|
2022-05-03 12:29:36 +08:00
|
|
|
#ifdef _STDIO_BSD_SEMANTICS
|
|
|
|
/* BSD and Glibc systems only flush streams which have been written to
|
|
|
|
at exit time. Calling flush rather than close for speed, as on
|
|
|
|
the aforementioned systems. */
|
|
|
|
#define CLEANUP_FILE __sflushw_r
|
|
|
|
#else
|
|
|
|
/* Otherwise close files and flush read streams, too.
|
|
|
|
Note we call flush directly if "--enable-lite-exit" is in effect. */
|
|
|
|
#ifdef _LITE_EXIT
|
|
|
|
#define CLEANUP_FILE _fflush_r
|
|
|
|
#else
|
|
|
|
#define CLEANUP_FILE _fclose_r
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2014-08-14 16:33:00 +08:00
|
|
|
#if (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED))
|
2017-12-04 11:12:33 +08:00
|
|
|
_NOINLINE_STATIC void
|
2014-08-14 16:33:00 +08:00
|
|
|
#else
|
2017-12-04 11:12:33 +08:00
|
|
|
static void
|
2014-08-14 16:33:00 +08:00
|
|
|
#endif
|
2017-12-04 11:43:30 +08:00
|
|
|
std (FILE *ptr,
|
2017-12-04 09:31:41 +08:00
|
|
|
int flags,
|
2017-06-23 15:22:37 +08:00
|
|
|
int file)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
ptr->_p = 0;
|
|
|
|
ptr->_r = 0;
|
|
|
|
ptr->_w = 0;
|
|
|
|
ptr->_flags = flags;
|
2008-11-25 01:15:43 +08:00
|
|
|
ptr->_flags2 = 0;
|
2000-02-18 03:39:52 +08:00
|
|
|
ptr->_file = file;
|
|
|
|
ptr->_bf._base = 0;
|
|
|
|
ptr->_bf._size = 0;
|
|
|
|
ptr->_lbfsize = 0;
|
2008-12-10 Corinna Vinschen <corinna@vinschen.de>
Implement basic wide char stdio functionality, based on FreeBSD.
* libc/include/stdio.h (__SORD): Define.
(__SWID): Define.
* libc/include/wchar.h: Add declarations for new wide char functions.
(getwc): Define as macro.
(getwchar): Ditto.
(putwc): Ditto.
(putwchar): Ditto.
* libc/include/sys/reent.h (struct __sFILE): Add _mbstate member.
(struct __sFILE64): Ditto.
* libc/stdio/Makefile.am (ELIX_4_SOURCES): Add fgetwc.c, fgetws.c,
fputwc.c, fputws.c, fwide.c, getwc.c, getwchar.c, putwc.c, putwchar.c
and ungetwc.c.
(CHEWOUT_FILES): Add fgetwc.def, fgetws.def, fputwc.def, fputws.def,
fwide.def, getwc.def, getwchar.def, putwc.def, putwchar.def and
ungetwc.def.
Add header dependency rules for the new files.
* libc/stdio/Makefile.in: Regenerate.
* libc/stdio/fgetwc.c: New file, implementing fgetwc and _fgetwc_r.
* libc/stdio/fgetws.c: New file, implementing fgetws and _fgetws_r.
* libc/stdio/findfp.c (std): Initialize FILE's _mbstate member.
(__sfmoreglue): Ditto.
* libc/stdio/fputs.c (_fputs_r): Set stream orientation.
* libc/stdio/fputwc.c: New file, implementing fputwc and _fputwc_r.
* libc/stdio/fputws.c: New file, implementing fputws and _fputws_r.
* libc/stdio/fread.c (_fread_r): Set stream orientation.
* libc/stdio/freopen.c (_freopen_r): Reset stream orientation. Reset
_mbstate.
* libc/stdio/fseek.c (_fseek_r): Reset _mbstate.
* libc/stdio/fwide.c: New file, implementing fwide and _fwide_r.
* libc/stdio/fwrite.c (_fwrite_r): Set stream orientation.
* libc/stdio/getwc.c: New file, implementing getwc and _getwc_r.
* libc/stdio/getwchar.c: New file, implementing getwchar and
_getwchar_r.
* libc/stdio/local.h (ORIENT): New macro.
* libc/stdio/puts.c (_puts_r): Set stream orientation.
* libc/stdio/putwc.c: New file, implementing putwc and _putwc_r.
* libc/stdio/putwchar.c: New file, implementing putwchar and
_putwchar_r.
* libc/stdio/refill.c (__srefill_r): Set stream orientation.
* libc/stdio/stdio.tex: Add documentation for new functions.
* libc/stdio/ungetc.c (_ungetc_r): Set stream orientation.
* libc/stdio/ungetwc.c: New file, implementing ungetwc and _ungetwc_r.
* libc/stdio/vfscanf.c (__SVFSCANF_R): Set stream orientation.
* libc/stdio/wbuf.c (__swbuf_r): Ditto.
2008-12-11 07:43:12 +08:00
|
|
|
memset (&ptr->_mbstate, 0, sizeof (_mbstate_t));
|
2000-02-18 03:39:52 +08:00
|
|
|
ptr->_cookie = ptr;
|
|
|
|
ptr->_read = __sread;
|
2007-05-02 07:03:36 +08:00
|
|
|
#ifndef __LARGE64_FILES
|
2000-02-18 03:39:52 +08:00
|
|
|
ptr->_write = __swrite;
|
2007-05-02 07:03:36 +08:00
|
|
|
#else /* __LARGE64_FILES */
|
|
|
|
ptr->_write = __swrite64;
|
|
|
|
ptr->_seek64 = __sseek64;
|
|
|
|
ptr->_flags |= __SL64;
|
|
|
|
#endif /* __LARGE64_FILES */
|
2000-02-18 03:39:52 +08:00
|
|
|
ptr->_seek = __sseek;
|
2013-04-25 23:29:19 +08:00
|
|
|
#ifdef _STDIO_CLOSE_PER_REENT_STD_STREAMS
|
2000-02-18 03:39:52 +08:00
|
|
|
ptr->_close = __sclose;
|
2013-04-25 23:29:19 +08:00
|
|
|
#else /* _STDIO_CLOSE_STD_STREAMS */
|
|
|
|
ptr->_close = NULL;
|
|
|
|
#endif /* _STDIO_CLOSE_STD_STREAMS */
|
2022-08-30 21:54:53 +08:00
|
|
|
#ifndef __SINGLE_THREAD__
|
|
|
|
if (ptr == &__sf[0] || ptr == &__sf[1] || ptr == &__sf[2])
|
|
|
|
__lock_init_recursive (ptr->_lock);
|
|
|
|
#endif
|
2000-05-24 07:51:54 +08:00
|
|
|
#ifdef __SCLE
|
2004-04-23 Artem B. Bityuckiy <abitytsky@softminecorp.com>
* libc/stdio/asprintf.c libc/stdio/clearerr.c,
libc/stdio/fclose.c libc/stdio/fcloseall.c libc/stdio/fdopen.c,
libc/stdio/feof.c libc/stdio/ferror.c libc/stdio/fflush.c,
libc/stdio/fgetc.c libc/stdio/fgetpos.c libc/stdio/fgets.c,
libc/stdio/fileno.c libc/stdio/findfp.c libc/stdio/fiprintf.c,
libc/stdio/flags.c libc/stdio/fopen.c libc/stdio/fprintf.c,
libc/stdio/fputc.c libc/stdio/fputs.c libc/stdio/fread.c,
libc/stdio/freopen.c libc/stdio/fscanf.c libc/stdio/fseek.c,
libc/stdio/fseeko.c libc/stdio/fsetpos.c libc/stdio/ftell.c,
libc/stdio/ftello.c libc/stdio/fvwrite.c libc/stdio/fwalk.c,
libc/stdio/fwrite.c libc/stdio/getc.c libc/stdio/getc_u.c,
libc/stdio/getchar.c libc/stdio/getchar_u.c,
libc/stdio/getdelim.c libc/stdio/getline.c libc/stdio/gets.c,
libc/stdio/getw.c libc/stdio/iprintf.c libc/stdio/local.h,
libc/stdio/makebuf.c libc/stdio/mktemp.c libc/stdio/perror.c,
libc/stdio/printf.c libc/stdio/putc.c libc/stdio/putc_u.c,
libc/stdio/putchar.c libc/stdio/putchar_u.c libc/stdio/puts.c,
libc/stdio/putw.c libc/stdio/refill.c libc/stdio/remove.c,
libc/stdio/rename.c libc/stdio/rewind.c libc/stdio/rget.c,
libc/stdio/scanf.c libc/stdio/setbuf.c libc/stdio/setbuffer.c,
libc/stdio/setlinebuf.c libc/stdio/setvbuf.c,
libc/stdio/siprintf.c libc/stdio/snprintf.c,
libc/stdio/sprintf.c libc/stdio/sscanf.c libc/stdio/stdio.c,
libc/stdio/tmpfile.c libc/stdio/tmpnam.c libc/stdio/ungetc.c,
libc/stdio/vasprintf.c libc/stdio/vfieeefp.h,
libc/stdio/vfprintf.c libc/stdio/vfscanf.c,
libc/stdio/vprintf.c libc/stdio/vscanf.c,
libc/stdio/vsnprintf.c libc/stdio/vsprintf.c,
libc/stdio/vsscanf.c libc/stdio/wbuf.c,
libc/stdio/wsetup.c: Perform minor formatting changes. Move
copyright notices to top of file, ensure that <_ansi.h> is
included, be consistent with open parentheses, use _DEFUN macro,
include "local.h" where needed, and remove various compiler
warnings.
2004-04-24 04:01:55 +08:00
|
|
|
if (__stextmode (ptr->_file))
|
2000-05-24 07:51:54 +08:00
|
|
|
ptr->_flags |= __SCLE;
|
|
|
|
#endif
|
2000-02-18 03:39:52 +08:00
|
|
|
}
|
|
|
|
|
2017-06-23 15:48:58 +08:00
|
|
|
static inline void
|
|
|
|
stdin_init(FILE *ptr)
|
|
|
|
{
|
|
|
|
std (ptr, __SRD, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
stdout_init(FILE *ptr)
|
|
|
|
{
|
|
|
|
/* On platforms that have true file system I/O, we can verify
|
|
|
|
whether stdout is an interactive terminal or not, as part of
|
|
|
|
__smakebuf on first use of the stream. For all other platforms,
|
|
|
|
we will default to line buffered mode here. Technically, POSIX
|
|
|
|
requires both stdin and stdout to be line-buffered, but tradition
|
|
|
|
leaves stdin alone on systems without fcntl. */
|
|
|
|
#ifdef HAVE_FCNTL
|
|
|
|
std (ptr, __SWR, 1);
|
|
|
|
#else
|
|
|
|
std (ptr, __SWR | __SLBF, 1);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
stderr_init(FILE *ptr)
|
|
|
|
{
|
|
|
|
/* POSIX requires stderr to be opened for reading and writing, even
|
|
|
|
when the underlying fd 2 is write-only. */
|
|
|
|
std (ptr, __SRW | __SNBF, 2);
|
|
|
|
}
|
|
|
|
|
2013-03-15 21:19:29 +08:00
|
|
|
struct glue_with_file {
|
|
|
|
struct _glue glue;
|
|
|
|
FILE file;
|
|
|
|
};
|
|
|
|
|
2022-03-30 17:19:59 +08:00
|
|
|
static struct _glue *
|
|
|
|
sfmoreglue (struct _reent *d, int n)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
2013-03-15 21:19:29 +08:00
|
|
|
struct glue_with_file *g;
|
2000-02-18 03:39:52 +08:00
|
|
|
|
2013-03-15 21:19:29 +08:00
|
|
|
g = (struct glue_with_file *)
|
|
|
|
_malloc_r (d, sizeof (*g) + (n - 1) * sizeof (FILE));
|
2000-02-18 03:39:52 +08:00
|
|
|
if (g == NULL)
|
|
|
|
return NULL;
|
2013-03-15 21:19:29 +08:00
|
|
|
g->glue._next = NULL;
|
|
|
|
g->glue._niobs = n;
|
|
|
|
g->glue._iobs = &g->file;
|
|
|
|
memset (&g->file, 0, n * sizeof (FILE));
|
|
|
|
return &g->glue;
|
2000-02-18 03:39:52 +08:00
|
|
|
}
|
|
|
|
|
2022-05-03 12:51:22 +08:00
|
|
|
static void
|
|
|
|
stdio_exit_handler (void)
|
|
|
|
{
|
2022-05-02 14:58:25 +08:00
|
|
|
(void) _fwalk_sglue (_GLOBAL_REENT, CLEANUP_FILE, &__sglue);
|
2022-05-03 12:51:22 +08:00
|
|
|
}
|
|
|
|
|
2022-05-17 17:52:24 +08:00
|
|
|
static void
|
|
|
|
global_stdio_init (void)
|
|
|
|
{
|
|
|
|
if (__stdio_exit_handler == NULL) {
|
|
|
|
__stdio_exit_handler = stdio_exit_handler;
|
|
|
|
stdin_init (&__sf[0]);
|
|
|
|
stdout_init (&__sf[1]);
|
|
|
|
stderr_init (&__sf[2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-02-18 03:39:52 +08:00
|
|
|
/*
|
|
|
|
* Find a free FILE for fopen et al.
|
|
|
|
*/
|
|
|
|
|
|
|
|
FILE *
|
2017-12-04 11:43:30 +08:00
|
|
|
__sfp (struct _reent *d)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
int n;
|
|
|
|
struct _glue *g;
|
|
|
|
|
2012-05-30 16:58:42 +08:00
|
|
|
_newlib_sfp_lock_start ();
|
2022-05-17 17:52:24 +08:00
|
|
|
global_stdio_init ();
|
2022-05-03 12:17:15 +08:00
|
|
|
|
2022-05-02 14:58:25 +08:00
|
|
|
for (g = &__sglue;; g = g->_next)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++)
|
|
|
|
if (fp->_flags == 0)
|
|
|
|
goto found;
|
|
|
|
if (g->_next == NULL &&
|
2022-03-30 17:19:59 +08:00
|
|
|
(g->_next = sfmoreglue (d, NDYNAMIC)) == NULL)
|
2000-02-18 03:39:52 +08:00
|
|
|
break;
|
|
|
|
}
|
2012-05-30 16:58:42 +08:00
|
|
|
_newlib_sfp_lock_exit ();
|
2022-01-18 17:13:04 +08:00
|
|
|
_REENT_ERRNO(d) = ENOMEM;
|
2000-02-18 03:39:52 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
found:
|
2004-03-26 06:29:18 +08:00
|
|
|
fp->_file = -1; /* no file */
|
2000-02-18 03:39:52 +08:00
|
|
|
fp->_flags = 1; /* reserve this slot; caller sets real flags */
|
2008-11-25 01:15:43 +08:00
|
|
|
fp->_flags2 = 0;
|
2004-01-23 06:06:57 +08:00
|
|
|
#ifndef __SINGLE_THREAD__
|
2004-06-12 04:37:10 +08:00
|
|
|
__lock_init_recursive (fp->_lock);
|
2004-01-23 06:06:57 +08:00
|
|
|
#endif
|
2012-05-30 16:58:42 +08:00
|
|
|
_newlib_sfp_lock_end ();
|
2004-03-26 06:29:18 +08:00
|
|
|
|
2000-02-18 03:39:52 +08:00
|
|
|
fp->_p = NULL; /* no current pointer */
|
|
|
|
fp->_w = 0; /* nothing to read or write */
|
|
|
|
fp->_r = 0;
|
|
|
|
fp->_bf._base = NULL; /* no buffer */
|
|
|
|
fp->_bf._size = 0;
|
|
|
|
fp->_lbfsize = 0; /* not line buffered */
|
2008-12-10 Corinna Vinschen <corinna@vinschen.de>
Implement basic wide char stdio functionality, based on FreeBSD.
* libc/include/stdio.h (__SORD): Define.
(__SWID): Define.
* libc/include/wchar.h: Add declarations for new wide char functions.
(getwc): Define as macro.
(getwchar): Ditto.
(putwc): Ditto.
(putwchar): Ditto.
* libc/include/sys/reent.h (struct __sFILE): Add _mbstate member.
(struct __sFILE64): Ditto.
* libc/stdio/Makefile.am (ELIX_4_SOURCES): Add fgetwc.c, fgetws.c,
fputwc.c, fputws.c, fwide.c, getwc.c, getwchar.c, putwc.c, putwchar.c
and ungetwc.c.
(CHEWOUT_FILES): Add fgetwc.def, fgetws.def, fputwc.def, fputws.def,
fwide.def, getwc.def, getwchar.def, putwc.def, putwchar.def and
ungetwc.def.
Add header dependency rules for the new files.
* libc/stdio/Makefile.in: Regenerate.
* libc/stdio/fgetwc.c: New file, implementing fgetwc and _fgetwc_r.
* libc/stdio/fgetws.c: New file, implementing fgetws and _fgetws_r.
* libc/stdio/findfp.c (std): Initialize FILE's _mbstate member.
(__sfmoreglue): Ditto.
* libc/stdio/fputs.c (_fputs_r): Set stream orientation.
* libc/stdio/fputwc.c: New file, implementing fputwc and _fputwc_r.
* libc/stdio/fputws.c: New file, implementing fputws and _fputws_r.
* libc/stdio/fread.c (_fread_r): Set stream orientation.
* libc/stdio/freopen.c (_freopen_r): Reset stream orientation. Reset
_mbstate.
* libc/stdio/fseek.c (_fseek_r): Reset _mbstate.
* libc/stdio/fwide.c: New file, implementing fwide and _fwide_r.
* libc/stdio/fwrite.c (_fwrite_r): Set stream orientation.
* libc/stdio/getwc.c: New file, implementing getwc and _getwc_r.
* libc/stdio/getwchar.c: New file, implementing getwchar and
_getwchar_r.
* libc/stdio/local.h (ORIENT): New macro.
* libc/stdio/puts.c (_puts_r): Set stream orientation.
* libc/stdio/putwc.c: New file, implementing putwc and _putwc_r.
* libc/stdio/putwchar.c: New file, implementing putwchar and
_putwchar_r.
* libc/stdio/refill.c (__srefill_r): Set stream orientation.
* libc/stdio/stdio.tex: Add documentation for new functions.
* libc/stdio/ungetc.c (_ungetc_r): Set stream orientation.
* libc/stdio/ungetwc.c: New file, implementing ungetwc and _ungetwc_r.
* libc/stdio/vfscanf.c (__SVFSCANF_R): Set stream orientation.
* libc/stdio/wbuf.c (__swbuf_r): Ditto.
2008-12-11 07:43:12 +08:00
|
|
|
memset (&fp->_mbstate, 0, sizeof (_mbstate_t));
|
2000-02-18 03:39:52 +08:00
|
|
|
/* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */
|
|
|
|
fp->_ub._base = NULL; /* no ungetc buffer */
|
|
|
|
fp->_ub._size = 0;
|
|
|
|
fp->_lb._base = NULL; /* no line buffer */
|
|
|
|
fp->_lb._size = 0;
|
2004-01-16 03:12:17 +08:00
|
|
|
|
2000-02-18 03:39:52 +08:00
|
|
|
return fp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* exit() calls _cleanup() through *__cleanup, set whenever we
|
|
|
|
* open or buffer a file. This chicanery is done so that programs
|
|
|
|
* that do not use stdio need not link it all in.
|
|
|
|
*
|
|
|
|
* The name `_cleanup' is, alas, fairly well known outside stdio.
|
|
|
|
*/
|
|
|
|
|
2022-03-31 22:34:54 +08:00
|
|
|
static void
|
|
|
|
cleanup_stdio (struct _reent *ptr)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
2022-01-28 17:58:36 +08:00
|
|
|
if (_REENT_STDIN(ptr) != &__sf[0])
|
|
|
|
CLEANUP_FILE (ptr, _REENT_STDIN(ptr));
|
2022-02-01 19:37:46 +08:00
|
|
|
if (_REENT_STDOUT(ptr) != &__sf[1])
|
|
|
|
CLEANUP_FILE (ptr, _REENT_STDOUT(ptr));
|
2022-02-01 20:05:53 +08:00
|
|
|
if (_REENT_STDERR(ptr) != &__sf[2])
|
|
|
|
CLEANUP_FILE (ptr, _REENT_STDERR(ptr));
|
2000-02-18 03:39:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* __sinit() is called whenever stdio's internal variables must be set up.
|
|
|
|
*/
|
|
|
|
|
2017-12-04 11:12:33 +08:00
|
|
|
void
|
2017-12-04 11:43:30 +08:00
|
|
|
__sinit (struct _reent *s)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
2022-04-08 17:24:38 +08:00
|
|
|
__sfp_lock_acquire ();
|
2005-02-08 09:05:50 +08:00
|
|
|
|
2022-02-03 17:18:53 +08:00
|
|
|
if (_REENT_CLEANUP(s))
|
2005-02-08 09:05:50 +08:00
|
|
|
{
|
2022-04-08 17:24:38 +08:00
|
|
|
__sfp_lock_release ();
|
2005-02-08 09:05:50 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-02-18 03:39:52 +08:00
|
|
|
/* make sure we clean up on exit */
|
2022-02-03 17:18:53 +08:00
|
|
|
_REENT_CLEANUP(s) = cleanup_stdio; /* conservative */
|
2000-02-18 03:39:52 +08:00
|
|
|
|
2022-05-17 17:52:24 +08:00
|
|
|
global_stdio_init ();
|
2022-04-08 17:24:38 +08:00
|
|
|
__sfp_lock_release ();
|
2000-02-18 03:39:52 +08:00
|
|
|
}
|
2004-03-10 05:27:37 +08:00
|
|
|
|
|
|
|
#ifndef __SINGLE_THREAD__
|
|
|
|
|
2017-01-29 17:27:17 +08:00
|
|
|
__LOCK_INIT_RECURSIVE(static, __sfp_recursive_mutex);
|
2004-03-26 06:29:18 +08:00
|
|
|
|
2017-12-04 11:12:33 +08:00
|
|
|
void
|
2017-12-04 11:00:43 +08:00
|
|
|
__sfp_lock_acquire (void)
|
2004-03-26 06:29:18 +08:00
|
|
|
{
|
2017-01-29 17:27:17 +08:00
|
|
|
__lock_acquire_recursive (__sfp_recursive_mutex);
|
2004-03-26 06:29:18 +08:00
|
|
|
}
|
|
|
|
|
2017-12-04 11:12:33 +08:00
|
|
|
void
|
2017-12-04 11:00:43 +08:00
|
|
|
__sfp_lock_release (void)
|
2004-03-26 06:29:18 +08:00
|
|
|
{
|
2017-01-29 17:27:17 +08:00
|
|
|
__lock_release_recursive (__sfp_recursive_mutex);
|
2004-03-26 06:29:18 +08:00
|
|
|
}
|
|
|
|
|
2004-03-10 05:27:37 +08:00
|
|
|
/* Walkable file locking routine. */
|
|
|
|
static int
|
2022-03-30 17:15:07 +08:00
|
|
|
__fp_lock (struct _reent * ptr __unused, FILE * fp)
|
2004-03-10 05:27:37 +08:00
|
|
|
{
|
2022-03-30 17:15:07 +08:00
|
|
|
if (!(fp->_flags2 & __SNLK))
|
|
|
|
_flockfile (fp);
|
2004-03-10 05:27:37 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Walkable file unlocking routine. */
|
|
|
|
static int
|
2022-03-30 17:15:07 +08:00
|
|
|
__fp_unlock (struct _reent * ptr __unused, FILE * fp)
|
2004-03-10 05:27:37 +08:00
|
|
|
{
|
2022-03-30 17:15:07 +08:00
|
|
|
if (!(fp->_flags2 & __SNLK))
|
|
|
|
_funlockfile (fp);
|
2004-03-10 05:27:37 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-12-04 11:12:33 +08:00
|
|
|
void
|
2017-12-04 11:00:43 +08:00
|
|
|
__fp_lock_all (void)
|
2004-03-10 05:27:37 +08:00
|
|
|
{
|
2007-05-02 07:03:36 +08:00
|
|
|
__sfp_lock_acquire ();
|
2022-05-18 19:26:13 +08:00
|
|
|
(void) _fwalk_sglue (NULL, __fp_lock, &__sglue);
|
2004-03-10 05:27:37 +08:00
|
|
|
}
|
|
|
|
|
2017-12-04 11:12:33 +08:00
|
|
|
void
|
2017-12-04 11:00:43 +08:00
|
|
|
__fp_unlock_all (void)
|
2004-03-10 05:27:37 +08:00
|
|
|
{
|
2022-05-18 19:26:13 +08:00
|
|
|
(void) _fwalk_sglue (NULL, __fp_unlock, &__sglue);
|
2004-03-31 05:11:53 +08:00
|
|
|
__sfp_lock_release ();
|
2004-03-10 05:27:37 +08:00
|
|
|
}
|
|
|
|
#endif
|