wint_t __ungetwc(wint_t wc, FILE *fp, locale_t locale) { struct wchar_io_data *wcio; char buf[MB_LEN_MAX]; size_t len; struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (wc == WEOF) return (WEOF); _SET_ORIENTATION(fp, 1); wcio = WCIO_GET(fp); if (wcio == 0) { errno = ENOMEM; /* XXX */ return (WEOF); } len = l->__wcrtomb(buf, wc, &wcio->wcio_mbstate_in); if (len == (size_t)-1) return (WEOF); while (len--) { if (__ungetc(buf[len], fp) == EOF) return (WEOF); } __sclearerr(fp); return wc; }
int fwide(FILE *fp, int mode) { struct wchar_io_data *wcio; /* * this implementation use only -1, 0, 1 * for mode value. * (we don't need to do this, but * this can make things simpler.) */ if (mode > 0) mode = 1; else if (mode < 0) mode = -1; FLOCKFILE(fp); wcio = WCIO_GET(fp); if (!wcio) return 0; /* XXX */ if (wcio->wcio_mode == 0 && mode != 0) wcio->wcio_mode = mode; else mode = wcio->wcio_mode; FUNLOCKFILE(fp); return mode; }
int vasprintf(char **str, const char *fmt, __va_list ap) { int ret; FILE f; f.pub._fileno = -1; f.pub._flags = __SWR | __SSTR | __SALC; f._bf._base = f.pub._p = (unsigned char *)malloc(128); if (f._bf._base == NULL) { *str = NULL; errno = ENOMEM; return (-1); } f._bf._size = f.pub._w = 127; /* Leave room for the NUL */ memset(WCIO_GET(&f), 0, sizeof(struct wchar_io_data)); ret = __vfprintf(&f, fmt, ap); if (ret < 0) { free(f._bf._base); *str = NULL; errno = ENOMEM; return (-1); } *f.pub._p = '\0'; *str = (char *)f._bf._base; return (ret); }
wint_t __fgetwc_unlock(FILE *fp) { struct wchar_io_data *wcio; mbstate_t *st; wchar_t wc; size_t size; _DIAGASSERT(fp != NULL); if(fp == NULL) { errno = ENOSTR; return WEOF; } _SET_ORIENTATION(fp, 1); wcio = WCIO_GET(fp); if (wcio == 0) { errno = ENOMEM; return WEOF; } /* if there're ungetwc'ed wchars, use them */ if (wcio->wcio_ungetwc_inbuf) { wc = wcio->wcio_ungetwc_buf[--wcio->wcio_ungetwc_inbuf]; return wc; } st = &wcio->wcio_mbstate_in; do { char c; int ch = __sgetc(fp); if (ch == EOF) { return WEOF; } c = (char)ch; size = mbrtowc(&wc, &c, 1, st); if (size == (size_t)-1) { errno = EILSEQ; fp->_flags |= __SERR; return WEOF; } } while (size == (size_t)-2); _DIAGASSERT(size == 1); return wc; }
wint_t __fputwc_unlock(wchar_t wc, FILE *fp) { struct wchar_io_data *wcio; mbstate_t *st; size_t size; char buf[MB_LEN_MAX]; struct __suio uio; struct __siov iov; _DIAGASSERT(fp != NULL); if(fp == NULL) { errno = EINVAL; return (WEOF); } /* LINTED we don't play with buf */ iov.iov_base = (void *)buf; uio.uio_iov = &iov; uio.uio_iovcnt = 1; _SET_ORIENTATION(fp, 1); wcio = WCIO_GET(fp); if (wcio == 0) { errno = ENOMEM; return WEOF; } wcio->wcio_ungetwc_inbuf = 0; st = &wcio->wcio_mbstate_out; size = wcrtomb(buf, wc, st); if (size == (size_t)-1) { errno = EILSEQ; return WEOF; } _DIAGASSERT(size != 0); uio.uio_resid = (int)(iov.iov_len = size); if (__sfvwrite(fp, &uio)) { return WEOF; } return (wint_t)wc; }
/* * Find a free FILE for fopen et al. */ FILE * __sfp(void) { FILE *fp; int n; struct glue *g; if (!__sdidinit) __sinit(); /* * The list must be locked because a FILE may be updated. */ THREAD_LOCK(); for (g = &__sglue; g != NULL; g = g->next) { for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) if (fp->pub._flags == 0) goto found; } THREAD_UNLOCK(); /* don't hold lock while malloc()ing. */ if ((g = moreglue(NDYNAMIC)) == NULL) return (NULL); THREAD_LOCK(); /* reacquire the lock */ SET_GLUE_PTR(lastglue->next, g); /* atomically append glue to list */ lastglue = g; /* not atomic; only accessed when locked */ fp = g->iobs; found: fp->pub._flags = 1; /* reserve this slot; caller sets real flags */ THREAD_UNLOCK(); fp->pub._p = NULL; /* no current pointer */ fp->pub._w = 0; /* nothing to read or write */ fp->pub._r = 0; fp->_bf._base = NULL; /* no buffer */ fp->_bf._size = 0; fp->pub._lbfsize = 0; /* not line buffered */ fp->pub._fileno = -1; /* no file */ /* 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; /* fp->_lock = NULL; */ /* once set always set (reused) */ memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); return (fp); }
/* * Non-MT-safe version. */ wint_t __fputwc(wchar_t wc, FILE *fp, locale_t locale) { struct wchar_io_data *wcio; mbstate_t *st; char buf[MB_LEN_MAX]; size_t i, len; struct xlocale_ctype *l = XLOCALE_CTYPE(locale); ORIENT(fp, 1); wcio = WCIO_GET(fp); if (wcio == NULL) { errno = ENOMEM; return WEOF; } wcio->wcio_ungetwc_inbuf = 0; st = &wcio->wcio_mbstate_out; if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { /* * Assume single-byte locale with no special encoding. * A more careful test would be to check * _CurrentRuneLocale->encoding. */ *buf = (unsigned char)wc; len = 1; } else { if ((len = l->__wcrtomb(buf, wc, st)) == (size_t)-1) { fp->pub._flags |= __SERR; return (WEOF); } } for (i = 0; i < len; i++) if (__sputc((unsigned char)buf[i], fp) == EOF) return (WEOF); return ((wint_t)wc); }
/* * Find a free FILE for fopen et al. */ FILE * __sfp() { FILE *fp; int n; struct glue *g; if (!__sdidinit) __sinit(); rwlock_wrlock(&__sfp_lock); for (g = &__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 = moreglue(NDYNAMIC)) == NULL) break; } rwlock_unlock(&__sfp_lock); return (NULL); found: fp->_flags = 1; /* reserve this slot; caller sets real flags */ 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 */ fp->_file = -1; /* no file */ /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ _UB(fp)._base = NULL; /* no ungetc buffer */ _UB(fp)._size = 0; fp->_lb._base = NULL; /* no line buffer */ fp->_lb._size = 0; memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); rwlock_unlock(&__sfp_lock); return (fp); }
wint_t ungetwc(wint_t wc, FILE *fp) { struct wchar_io_data *wcio; _DIAGASSERT(fp); if (wc == WEOF) return WEOF; FLOCKFILE(fp); _SET_ORIENTATION(fp, 1); /* * XXX since we have no way to transform a wchar string to * a char string in reverse order, we can't use ungetc. */ /* XXX should we flush ungetc buffer? */ wcio = WCIO_GET(fp); if (wcio == 0) { FUNLOCKFILE(fp); errno = ENOMEM; /* XXX */ return WEOF; } if (wcio->wcio_ungetwc_inbuf >= WCIO_UNGETWC_BUFSIZE) { FUNLOCKFILE(fp); return WEOF; } wcio->wcio_ungetwc_buf[wcio->wcio_ungetwc_inbuf++] = (wchar_t)wc; __sclearerr(fp); FUNLOCKFILE(fp); return wc; }
wchar_t * fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale) { struct wchar_io_data *wcio; mbstate_t *st; wchar_t *wsp; size_t nconv; const char *src; unsigned char *nl; FIX_LOCALE(locale); struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); wcio = WCIO_GET(fp); if (wcio == NULL) { errno = ENOMEM; goto error; } if (n <= 0) { errno = EINVAL; goto error; } wcio->wcio_ungetwc_inbuf = 0; st = &wcio->wcio_mbstate_out; if (fp->pub._r <= 0 && __srefill(fp)) /* EOF */
/* * Seek the given file to the given offset. * `Whence' must be one of the three SEEK_* macros. */ int _fseeko(FILE *fp, off_t offset, int whence, int ltest) { fpos_t (*seekfn)(void *, fpos_t, int); fpos_t target, curoff, ret; size_t n; struct stat st; int havepos; /* * Have to be able to seek. */ if ((seekfn = fp->_seek) == NULL) { errno = ESPIPE; /* historic practice */ return (-1); } /* * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. * After this, whence is either SEEK_SET or SEEK_END. */ switch (whence) { case SEEK_CUR: /* * In order to seek relative to the current stream offset, * we have to first find the current stream offset via * ftell (see ftell for details). */ if (_ftello(fp, &curoff)) return (-1); if (curoff < 0) { /* Unspecified position because of ungetc() at 0 */ errno = ESPIPE; return (-1); } if (offset > 0 && curoff > OFF_MAX - offset) { errno = EOVERFLOW; return (-1); } offset += curoff; if (offset < 0) { errno = EINVAL; return (-1); } if (ltest && offset > LONG_MAX) { errno = EOVERFLOW; return (-1); } whence = SEEK_SET; havepos = 1; break; case SEEK_SET: if (offset < 0) { errno = EINVAL; return (-1); } case SEEK_END: curoff = 0; /* XXX just to keep gcc quiet */ havepos = 0; break; default: errno = EINVAL; return (-1); } /* * Can only optimise if: * reading (and not reading-and-writing); * not unbuffered; and * this is a `regular' Unix file (and hence seekfn==__sseek). * We must check __NBF first, because it is possible to have __NBF * and __SOPT both set. */ if (fp->_bf._base == NULL) __smakebuf(fp); if (fp->pub._flags & (__SWR | __SRW | __SNBF | __SNPT)) goto dumb; if ((fp->pub._flags & __SOPT) == 0) { if (seekfn != __sseek || fp->pub._fileno < 0 || _fstat(fp->pub._fileno, &st) || (st.st_mode & S_IFMT) != S_IFREG) { fp->pub._flags |= __SNPT; goto dumb; } fp->_blksize = st.st_blksize; fp->pub._flags |= __SOPT; } /* * We are reading; we can try to optimise. * Figure out where we are going and where we are now. */ if (whence == SEEK_SET) target = offset; else { if (_fstat(fp->pub._fileno, &st)) goto dumb; if (offset > 0 && st.st_size > OFF_MAX - offset) { errno = EOVERFLOW; return (-1); } target = st.st_size + offset; if ((off_t)target < 0) { errno = EINVAL; return (-1); } if (ltest && (off_t)target > LONG_MAX) { errno = EOVERFLOW; return (-1); } } if (!havepos && _ftello(fp, &curoff)) goto dumb; /* * (If the buffer was modified, we have to * skip this; see fgetln.c.) */ if (fp->pub._flags & __SMOD) goto abspos; /* * Compute the number of bytes in the input buffer (pretending * that any ungetc() input has been discarded). Adjust current * offset backwards by this count so that it represents the * file offset for the first byte in the current input buffer. */ if (HASUB(fp)) { curoff += fp->pub._r; /* kill off ungetc */ n = fp->_up - fp->_bf._base; curoff -= n; n += fp->_ur; } else { n = fp->pub._p - fp->_bf._base; curoff -= n; n += fp->pub._r; } /* * If the target offset is within the current buffer, * simply adjust the pointers, clear EOF, undo ungetc(), * and return. */ if (target >= curoff && target < curoff + n) { size_t o = target - curoff; fp->pub._p = fp->_bf._base + o; fp->pub._r = n - o; if (HASUB(fp)) FREEUB(fp); fp->pub._flags &= ~__SEOF; memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); return (0); } abspos: /* * The place we want to get to is not within the current buffer, * but we can still be kind to the kernel copyout mechanism. * By aligning the file offset to a block boundary, we can let * the kernel use the VM hardware to map pages instead of * copying bytes laboriously. Using a block boundary also * ensures that we only read one block, rather than two. */ curoff = target & ~(fp->_blksize - 1); if (_sseek(fp, curoff, SEEK_SET) == POS_ERR) goto dumb; fp->pub._r = 0; fp->pub._p = fp->_bf._base; if (HASUB(fp)) FREEUB(fp); n = target - curoff; if (n) { if (__srefill(fp) || fp->pub._r < n) goto dumb; fp->pub._p += n; fp->pub._r -= n; } fp->pub._flags &= ~__SEOF; memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); return (0); /* * We get here if we cannot optimise the seek ... just * do it. Allow the seek function to change fp->_bf._base. */ dumb: if (__sflush(fp) || (ret = _sseek(fp, (fpos_t)offset, whence)) == POS_ERR) return (-1); if (ltest && ret > LONG_MAX) { fp->pub._flags |= __SERR; errno = EOVERFLOW; return (-1); } /* success: clear EOF indicator and discard ungetc() data */ if (HASUB(fp)) FREEUB(fp); fp->pub._p = fp->_bf._base; fp->pub._r = 0; /* fp->pub._w = 0; */ /* unnecessary (I think...) */ fp->pub._flags &= ~__SEOF; memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); return (0); }
* * @(#)sprintf.c 8.1 (Berkeley) 6/4/93 * $FreeBSD: src/lib/libc/stdio/sprintf.c,v 1.16 2008/04/17 22:17:54 jhb Exp $ * $DragonFly: src/lib/libc/stdio/sprintf.c,v 1.7 2006/03/02 18:05:30 joerg Exp $ */ #include <stdio.h> #include <stdarg.h> #include <limits.h> #include "local.h" #include "priv_stdio.h" int sprintf(char * __restrict str, const char * __restrict fmt, ...) { int ret; va_list ap; FILE f; f.pub._fileno = -1; f.pub._flags = __SWR | __SSTR; f._bf._base = f.pub._p = (unsigned char *)str; f._bf._size = f.pub._w = INT_MAX; memset(WCIO_GET(&f), 0, sizeof(struct wchar_io_data)); va_start(ap, fmt); ret = __vfprintf(&f, fmt, ap); va_end(ap); *f.pub._p = 0; return (ret); }