/* * __sinit() is called whenever stdio's internal variables must be set up. */ void __sinit(void) { _THREAD_PRIVATE_MUTEX(__sinit_mutex); _THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex); if (__sdidinit) { /* bail out if caller lost the race */ _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex); return; } /* Initialize stdin/stdout/stderr (for the recursive mutex). http://b/18208568. */ for (size_t i = 0; i < 3; ++i) { _FILEEXT_SETUP(__sF+i, __sFext+i); } /* Initialize the pre-allocated (but initially unused) streams. */ for (size_t i = 0; i < FOPEN_MAX - 3; ++i) { _FILEEXT_SETUP(usual+i, usualext+i); } /* make sure we clean up on exit */ __atexit_register_cleanup(_cleanup); /* conservative */ __sdidinit = 1; _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex); }
/* * Helper function for `fprintf to unbuffered unix file': creates a * temporary buffer. We only work on write-only files; this avoids * worries about ungetc buffers and so forth. */ static int __sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap) { int ret; FILE fake; struct __sfileext fakeext; unsigned char buf[BUFSIZ]; _FILEEXT_SETUP(&fake, &fakeext); /* copy the important variables */ fake._flags = fp->_flags & ~__SNBF; fake._file = fp->_file; fake._cookie = fp->_cookie; fake._write = fp->_write; #ifdef notyet fake._orientation = fp->_orientation; fake._mbstate = fp->_mbstate; #endif /* set up the buffer */ fake._bf._base = fake._p = buf; fake._bf._size = fake._w = sizeof(buf); fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ ret = __vfwprintf(&fake, locale, fmt, ap); if (ret >= 0 && __sflush(&fake)) ret = WEOF; if (fake._flags & __SERR) fp->_flags |= __SERR; return (ret); }
int vsnprintf(char *str, size_t n, const char *fmt, __va_list ap) { int ret; char dummy; FILE f; struct __sfileext fext; _FILEEXT_SETUP(&f, &fext); /* While snprintf(3) specifies size_t stdio uses an int internally */ if (n > INT_MAX) n = INT_MAX; /* Stdio internals do not deal correctly with zero length buffer */ if (n == 0) { str = &dummy; n = 1; } f._file = -1; f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n - 1; ret = vfprintf(&f, fmt, ap); *f._p = '\0'; return (ret); }
static struct glue * moreglue(int n) { struct glue *g; FILE *p; struct __sfileext *pext; static FILE empty; char *data; data = malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE) + n * sizeof(struct __sfileext)); if (data == NULL) return (NULL); g = (struct glue *)data; p = (FILE *)ALIGN(data + sizeof(*g)); pext = (struct __sfileext *) (ALIGN(data + sizeof(*g)) + n * sizeof(FILE)); g->next = NULL; g->niobs = n; g->iobs = p; while (--n >= 0) { *p = empty; _FILEEXT_SETUP(p, pext); p++; pext++; } return (g); }
int vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap) { int ret; FILE f; struct __sfileext fext; unsigned char *_base; FIX_LOCALE(locale); _FILEEXT_SETUP(&f, &fext); f._file = -1; f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = (unsigned char *)malloc(128); if (f._bf._base == NULL) goto err; f._bf._size = f._w = 127; /* Leave room for the NUL */ ret = __vfprintf(&f, locale, fmt, ap); if (ret == -1) goto err; *f._p = '\0'; _base = realloc(f._bf._base, ret + 1); if (_base == NULL) goto err; *str = (char *)_base; return (ret); err: if (f._bf._base) { free(f._bf._base); f._bf._base = NULL; } *str = NULL; errno = ENOMEM; return (-1); }
static struct glue * moreglue(int n) { struct glue *g; FILE *p; struct __sfileext *pext; static FILE empty; g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE) + n * sizeof(struct __sfileext)); if (g == NULL) return (NULL); p = (FILE *)ALIGN((g + 1)); g->next = NULL; g->niobs = n; g->iobs = p; pext = (void *)(p + n); while (--n >= 0) { *p = empty; _FILEEXT_SETUP(p, pext); p++; pext++; } return (g); }
int snprintf(char *str, size_t n, char const *fmt, ...) { int ret; va_list ap; FILE f; struct __sfileext fext; unsigned char dummy[1]; _DIAGASSERT(n == 0 || str != NULL); _DIAGASSERT(fmt != NULL); if ((int)n < 0) { errno = EINVAL; return (-1); } va_start(ap, fmt); _FILEEXT_SETUP(&f, &fext); f._file = -1; f._flags = __SWR | __SSTR; if (n == 0) { f._bf._base = f._p = dummy; f._bf._size = f._w = 0; } else { f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n - 1; } ret = __vfprintf_unlocked(&f, fmt, ap); *f._p = 0; va_end(ap); return (ret); }
float_type wcstod(const wchar_t* str, wchar_t** end, float_type strtod_fn(const char*, char**)) { const wchar_t* original_str = str; while (iswspace(*str)) { str++; } // What's the longest span of the input that might be part of the float? size_t max_len = wcsspn(str, L"-+0123456789.xXeEpP()nNaAiIfFtTyY"); // We know the only valid characters are ASCII, so convert them by brute force. char* ascii_str = new char[max_len + 1]; if (!ascii_str) return float_type(); for (size_t i = 0; i < max_len; ++i) { ascii_str[i] = str[i] & 0xff; } ascii_str[max_len] = 0; // Set up a fake FILE that points to those ASCII characters, for `parsefloat`. FILE f; __sfileext fext; _FILEEXT_SETUP(&f, &fext); f._flags = __SRD; f._bf._base = f._p = reinterpret_cast<unsigned char*>(ascii_str); f._bf._size = f._r = max_len; f._read = [](void*, char*, int) { return 0; }; // aka `eofread`, aka "no more data". f._lb._base = NULL; // Ask `parsefloat` to look at the same data more carefully. // We can't just do this straight away because we can't construct a suitable FILE* // in the absence of any `fwmemopen` analogous to `fmemopen`. And we don't want to // duplicate the `parsefloat` logic. We also don't want to actually have to have wchar_t // implementations of the ASCII `strtod` logic (though if you were designing a libc // from scratch, you'd probably want to just make that more generic and lose all the // cruft on top). size_t actual_len = parsefloat(&f, ascii_str, ascii_str + max_len); // Finally let the ASCII conversion function do the work. char* ascii_end; float_type result = strtod_fn(ascii_str, &ascii_end); if (ascii_end != ascii_str + actual_len) abort(); if (end) { if (actual_len == 0) { // There was an error. We need to set the end pointer back to the original string, not the // one we advanced past the leading whitespace. *end = const_cast<wchar_t*>(original_str); } else { *end = const_cast<wchar_t*>(str) + actual_len; } } delete[] ascii_str; return result; }
/* * __sinit() is called whenever stdio's internal variables must be set up. */ void __sinit( void ) { int i; for (i = 0; i < FOPEN_MAX - 3; i++) _FILEEXT_SETUP(&usual[i], &usualext[i]); /* make sure we clean up on exit */ gMD->cleanup = _cleanup; /* conservative */ __sdidinit = 1; }
int vsscanf(const char *str, const char *fmt, __va_list ap) { FILE f; struct __sfileext fext; _FILEEXT_SETUP((&f), &fext); f._flags = __SRD; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._r = strlen(str); f._read = eofread; f._lb._base = NULL; return (vfscanf(&f, fmt, ap)); }
int vsprintf(char *str, const char *fmt, __va_list ap) { int ret; FILE f; struct __sfileext fext; _FILEEXT_SETUP(&f, &fext); f._file = -1; f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = INT_MAX; ret = vfprintf(&f, fmt, ap); *f._p = '\0'; return (ret); }
/* * __sinit() is called whenever stdio's internal variables must be set up. */ void __sinit(void) { _THREAD_PRIVATE_MUTEX(__sinit_mutex); int i; _THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex); if (__sdidinit) goto out; /* bail out if caller lost the race */ for (i = 0; i < FOPEN_MAX - 3; i++) { _FILEEXT_SETUP(usual+i, usualext+i); } /* make sure we clean up on exit */ __atexit_register_cleanup(_cleanup); /* conservative */ __sdidinit = 1; out: _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex); }
int sscanf(const char *str, const char *fmt, ...) { int ret; va_list ap; FILE f; struct __sfileext fext; _FILEEXT_SETUP(&f, &fext); f._flags = __SRD; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._r = strlen(str); f._read = eofread; f._lb._base = NULL; va_start(ap, fmt); ret = vfscanf(&f, fmt, ap); va_end(ap); return (ret); }
int sprintf(char *str, char const *fmt, ...) { int ret; va_list ap; FILE f; struct __sfileext fext; _DIAGASSERT(str != NULL); _DIAGASSERT(fmt != NULL); _FILEEXT_SETUP(&f, &fext); f._file = -1; f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = INT_MAX; va_start(ap, fmt); ret = __vfprintf_unlocked(&f, fmt, ap); va_end(ap); *f._p = 0; return (ret); }
int asprintf(char **str, const char *fmt, ...) { int ret; va_list ap; FILE f; struct __sfileext fext; unsigned char *_base; _FILEEXT_SETUP(&f, &fext); f._file = -1; f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = (unsigned char *)malloc(128); if (f._bf._base == NULL) goto err; f._bf._size = f._w = 127; /* Leave room for the NUL */ va_start(ap, fmt); ret = vfprintf(&f, fmt, ap); va_end(ap); if (ret == -1) goto err; *f._p = '\0'; _base = realloc(f._bf._base, ret + 1); if (_base == NULL) goto err; *str = (char *)_base; return (ret); err: if (f._bf._base) { free(f._bf._base); f._bf._base = NULL; } *str = NULL; errno = ENOMEM; return (-1); }
int asprintf(char **str, char const *fmt, ...) { int ret; va_list ap; FILE f; struct __sfileext fext; unsigned char *_base; _DIAGASSERT(str != NULL); _FILEEXT_SETUP(&f, &fext); f._file = -1; f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = malloc((size_t)128); if (f._bf._base == NULL) goto err; f._bf._size = f._w = 127; /* Leave room for the NUL */ va_start(ap, fmt); ret = __vfprintf_unlocked(&f, fmt, ap); va_end(ap); if (ret < 0) goto err; *f._p = '\0'; _base = realloc(f._bf._base, (size_t)ret + 1); if (_base == NULL) goto err; *str = (char *)_base; return (ret); err: if (f._bf._base) free(f._bf._base); *str = NULL; errno = ENOMEM; return (-1); }