configUSE_NEWLIB_REENTRANT
configUSE_NEWLIB_REENTRANT
STM32CubeIde HardFault その17
cantwriteの中で、__swsetup_rを呼んでいる。
/* Return true and set errno and stream error flag iff the given FILE cannot be written now. */ #define cantwrite(ptr, fp) \ ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \ __swsetup_r(ptr, fp))
/* * Write the given string to stdout, appending a newline. */ int _puts_r (struct _reent *ptr, const char * s) { #ifdef _FVWRITE_IN_STREAMIO (略) #else int result = EOF; const char *p = s; FILE *fp; _REENT_SMALL_CHECK_INIT (ptr); fp = _stdout_r (ptr); CHECK_INIT (ptr, fp); _newlib_flockfile_start (fp); ORIENT (fp, -1); /* Make sure we can write. */ if (cantwrite (ptr, fp)) <==cantwite goto err; while (*p) { if (__sputc_r (ptr, *p++, fp) == EOF) goto err; } if (__sputc_r (ptr, '\n', fp) == EOF) goto err; result = '\n'; err: _newlib_flockfile_end (fp); return result; #endif } #ifndef _REENT_ONLY int puts (char const * s) { return _puts_r (_REENT, s); } #endif
#ifdef __GNUC__ _ELIDABLE_INLINE int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) { #ifdef __SCLE if ((_p->_flags & __SCLE) && _c == '\n') __sputc_r (_ptr, '\r', _p); #endif if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) return (*_p->_p++ = _c); else return (__swbuf_r(_ptr, _c, _p)); } #else /* * This has been tuned to generate reasonable code on the vax using pcc */ #define __sputc_raw_r(__ptr, __c, __p) \ (--(__p)->_w < 0 ? \ (__p)->_w >= (__p)->_lbfsize ? \ (*(__p)->_p = (__c)), *(__p)->_p != '\n' ? \ (int)*(__p)->_p++ : \ __swbuf_r(__ptr, '\n', __p) : \ __swbuf_r(__ptr, (int)(__c), __p) : \ (*(__p)->_p = (__c), (int)*(__p)->_p++)) #ifdef __SCLE #define __sputc_r(__ptr, __c, __p) \ ((((__p)->_flags & __SCLE) && ((__c) == '\n')) \ ? __sputc_raw_r(__ptr, '\r', (__p)) : 0 , \ __sputc_raw_r((__ptr), (__c), (__p))) #else #define __sputc_r(__ptr, __c, __p) __sputc_raw_r(__ptr, __c, __p) #endif #endif
STM32CubeIde HardFault その16 周辺のnewlibのソース
newlib/newlib/libc/stdio/findfp.c __sinit()
/* * __sinit() is called whenever stdio's internal variables must be set up. */ void __sinit (struct _reent *s) { __sinit_lock_acquire (); if (s->__sdidinit) { __sinit_lock_release (); return; } /* make sure we clean up on exit */ s->__cleanup = _cleanup_r; /* conservative */ s->__sglue._next = NULL; #ifndef _REENT_SMALL # ifndef _REENT_GLOBAL_STDIO_STREAMS s->__sglue._niobs = 3; s->__sglue._iobs = &s->__sf[0]; # endif /* _REENT_GLOBAL_STDIO_STREAMS */ #else s->__sglue._niobs = 0; s->__sglue._iobs = NULL; /* Avoid infinite recursion when calling __sfp for _GLOBAL_REENT. The problem is that __sfp checks for _GLOBAL_REENT->__sdidinit and calls __sinit if it's 0. */ if (s == _GLOBAL_REENT) s->__sdidinit = 1; # ifndef _REENT_GLOBAL_STDIO_STREAMS s->_stdin = __sfp(s); s->_stdout = __sfp(s); s->_stderr = __sfp(s); # else /* _REENT_GLOBAL_STDIO_STREAMS */ s->_stdin = &__sf[0]; s->_stdout = &__sf[1]; s->_stderr = &__sf[2]; # endif /* _REENT_GLOBAL_STDIO_STREAMS */ #endif #ifdef _REENT_GLOBAL_STDIO_STREAMS if (__sf[0]._cookie == NULL) { _GLOBAL_REENT->__sglue._niobs = 3; _GLOBAL_REENT->__sglue._iobs = &__sf[0]; stdin_init (&__sf[0]); stdout_init (&__sf[1]); stderr_init (&__sf[2]); } #else /* _REENT_GLOBAL_STDIO_STREAMS */ stdin_init (s->_stdin); stdout_init (s->_stdout); stderr_init (s->_stderr); #endif /* _REENT_GLOBAL_STDIO_STREAMS */ s->__sdidinit = 1; __sinit_lock_release (); }
__sfp
/* * Find a free FILE for fopen et al. */ FILE * __sfp (struct _reent *d) { FILE *fp; int n; struct _glue *g; _newlib_sfp_lock_start (); if (!_GLOBAL_REENT->__sdidinit) __sinit (_GLOBAL_REENT); for (g = &_GLOBAL_REENT->__sglue;; g = g->_next) { for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) if (fp->_flags == 0) goto found; if (g->_next == NULL && (g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL) break; } _newlib_sfp_lock_exit (); d->_errno = ENOMEM; return NULL; found: fp->_file = -1; /* no file */ fp->_flags = 1; /* reserve this slot; caller sets real flags */ fp->_flags2 = 0; #ifndef __SINGLE_THREAD__ __lock_init_recursive (fp->_lock); #endif _newlib_sfp_lock_end (); 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 */ memset (&fp->_mbstate, 0, sizeof (_mbstate_t)); /* 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; return fp; }
__sfmoreglue
struct glue_with_file { struct _glue glue; FILE file; }; struct _glue * __sfmoreglue (struct _reent *d, register int n) { struct glue_with_file *g; g = (struct glue_with_file *) _malloc_r (d, sizeof (*g) + (n - 1) * sizeof (FILE)); if (g == NULL) return NULL; g->glue._next = NULL; g->glue._niobs = n; g->glue._iobs = &g->file; memset (&g->file, 0, n * sizeof (FILE)); return &g->glue; }
#if (defined (__OPTIMIZE_SIZE__) || defined (PREFER_SIZE_OVER_SPEED)) _NOINLINE_STATIC void #else static void #endif std (FILE *ptr, int flags, int file) { ptr->_p = 0; ptr->_r = 0; ptr->_w = 0; ptr->_flags = flags; ptr->_flags2 = 0; ptr->_file = file; ptr->_bf._base = 0; ptr->_bf._size = 0; ptr->_lbfsize = 0; memset (&ptr->_mbstate, 0, sizeof (_mbstate_t)); ptr->_cookie = ptr; ptr->_read = __sread; #ifndef __LARGE64_FILES ptr->_write = __swrite; #else /* __LARGE64_FILES */ ptr->_write = __swrite64; ptr->_seek64 = __sseek64; ptr->_flags |= __SL64; #endif /* __LARGE64_FILES */ ptr->_seek = __sseek; #ifdef _STDIO_CLOSE_PER_REENT_STD_STREAMS ptr->_close = __sclose; #else /* _STDIO_CLOSE_STD_STREAMS */ ptr->_close = NULL; #endif /* _STDIO_CLOSE_STD_STREAMS */ #if !defined(__SINGLE_THREAD__) && !(defined(_REENT_SMALL) && !defined(_REENT_GLOBAL_STDIO_STREAMS)) __lock_init_recursive (ptr->_lock); /* * #else * lock is already initialized in __sfp */ #endif #ifdef __SCLE if (__stextmode (ptr->_file)) ptr->_flags |= __SCLE; #endif }