diff options
Diffstat (limited to 'lib/libc/stdio')
42 files changed, 805 insertions, 182 deletions
diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map index df66ab3..cafb0c6 100644 --- a/lib/libc/stdio/Symbol.map +++ b/lib/libc/stdio/Symbol.map @@ -117,6 +117,46 @@ FBSD_1.1 { vdprintf; }; +FBSD_1.3 { + asprintf_l; + fprintf_l; + fwprintf_l; + printf_l; + snprintf_l; + sprintf_l; + swprintf_l; + vasprintf_l; + vfprintf_l; + vfwprintf_l; + vprintf_l; + vsnprintf_l; + vsprintf_l; + vswprintf_l; + vwprintf_l; + wprintf_l; + fgetwc_l; + fputwc_l; + ungetwc_l; + vfwscanf_l; + vswscanf_l; + fscanf_l; + fwscanf_l; + scanf_l; + sscanf_l; + swscanf_l; + vfscanf_l; + vscanf_l; + vsscanf_l; + vwscanf_l; + wscanf_l; + fgetws_l; + fputws_l; + getwc_l; + getwchar_l; + putwc_l; + putwchar_l; +}; + FBSDprivate_1.0 { _flockfile; _flockfile_debug_stub; diff --git a/lib/libc/stdio/asprintf.c b/lib/libc/stdio/asprintf.c index 90c62bc..cd475cd 100644 --- a/lib/libc/stdio/asprintf.c +++ b/lib/libc/stdio/asprintf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <stdarg.h> +#include <xlocale.h> int asprintf(char ** __restrict s, char const * __restrict fmt, ...) @@ -47,3 +53,15 @@ asprintf(char ** __restrict s, char const * __restrict fmt, ...) va_end(ap); return (ret); } +int +asprintf_l(char ** __restrict s, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vasprintf_l(s, locale, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/lib/libc/stdio/fgetwc.c b/lib/libc/stdio/fgetwc.c index 3a5b09b..0e87753 100644 --- a/lib/libc/stdio/fgetwc.c +++ b/lib/libc/stdio/fgetwc.c @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -36,31 +41,39 @@ __FBSDID("$FreeBSD$"); #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * MT-safe version. */ wint_t -fgetwc(FILE *fp) +fgetwc_l(FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fgetwc(fp); + r = __fgetwc(fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fgetwc(FILE *fp) +{ + return fgetwc_l(fp, __get_locale()); +} /* * Non-MT-safe version. */ wint_t -__fgetwc(FILE *fp) +__fgetwc(FILE *fp, locale_t locale) { wchar_t wc; size_t nconv; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (fp->_r <= 0 && __srefill(fp)) return (WEOF); @@ -71,7 +84,7 @@ __fgetwc(FILE *fp) return (wc); } do { - nconv = __mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); + nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate); if (nconv == (size_t)-1) break; else if (nconv == (size_t)-2) diff --git a/lib/libc/stdio/fgetwln.c b/lib/libc/stdio/fgetwln.c index 1a1ad2d..6d9087b 100644 --- a/lib/libc/stdio/fgetwln.c +++ b/lib/libc/stdio/fgetwln.c @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,18 +38,20 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" wchar_t * -fgetwln(FILE * __restrict fp, size_t *lenp) +fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale) { wint_t wc; size_t len; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); len = 0; - while ((wc = __fgetwc(fp)) != WEOF) { + while ((wc = __fgetwc(fp, locale)) != WEOF) { #define GROW 512 if (len * sizeof(wchar_t) >= fp->_lb._size && __slbexpand(fp, (len + GROW) * sizeof(wchar_t))) @@ -65,3 +72,8 @@ error: *lenp = 0; return (NULL); } +wchar_t * +fgetwln(FILE * __restrict fp, size_t *lenp) +{ + return fgetwln_l(fp, lenp, __get_locale()); +} diff --git a/lib/libc/stdio/fgetws.c b/lib/libc/stdio/fgetws.c index 550843d..f7a63fe 100644 --- a/lib/libc/stdio/fgetws.c +++ b/lib/libc/stdio/fgetws.c @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,12 +43,14 @@ __FBSDID("$FreeBSD$"); #include "mblocal.h" wchar_t * -fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale) { 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); @@ -60,7 +67,7 @@ fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) do { src = fp->_p; nl = memchr(fp->_p, '\n', fp->_r); - nconv = __mbsnrtowcs(wsp, &src, + nconv = l->__mbsnrtowcs(wsp, &src, nl != NULL ? (nl - fp->_p + 1) : fp->_r, n - 1, &fp->_mbstate); if (nconv == (size_t)-1) @@ -86,7 +93,7 @@ fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) if (wsp == ws) /* EOF */ goto error; - if (!__mbsinit(&fp->_mbstate)) + if (!l->__mbsinit(&fp->_mbstate)) /* Incomplete character */ goto error; *wsp = L'\0'; @@ -98,3 +105,8 @@ error: FUNLOCKFILE(fp); return (NULL); } +wchar_t * +fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp) +{ + return fgetws_l(ws, n, fp, __get_locale()); +} diff --git a/lib/libc/stdio/fprintf.c b/lib/libc/stdio/fprintf.c index bebc182..169532d 100644 --- a/lib/libc/stdio/fprintf.c +++ b/lib/libc/stdio/fprintf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <stdarg.h> +#include "xlocale_private.h" int fprintf(FILE * __restrict fp, const char * __restrict fmt, ...) @@ -46,7 +52,19 @@ fprintf(FILE * __restrict fp, const char * __restrict fmt, ...) va_list ap; va_start(ap, fmt); - ret = vfprintf(fp, fmt, ap); + ret = vfprintf_l(fp, __get_locale(), fmt, ap); + va_end(ap); + return (ret); +} +int +fprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vfprintf_l(fp, locale, fmt, ap); va_end(ap); return (ret); } diff --git a/lib/libc/stdio/fputwc.c b/lib/libc/stdio/fputwc.c index ae92f66..7b05d4a 100644 --- a/lib/libc/stdio/fputwc.c +++ b/lib/libc/stdio/fputwc.c @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,10 +47,11 @@ __FBSDID("$FreeBSD$"); * Non-MT-safe version. */ wint_t -__fputwc(wchar_t wc, FILE *fp) +__fputwc(wchar_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t i, len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) { /* @@ -56,7 +62,7 @@ __fputwc(wchar_t wc, FILE *fp) *buf = (unsigned char)wc; len = 1; } else { - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -73,14 +79,20 @@ __fputwc(wchar_t wc, FILE *fp) * MT-safe version. */ wint_t -fputwc(wchar_t wc, FILE *fp) +fputwc_l(wchar_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __fputwc(wc, fp); + r = __fputwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +fputwc(wchar_t wc, FILE *fp) +{ + return fputwc_l(wc, fp, __get_locale()); +} diff --git a/lib/libc/stdio/fputws.c b/lib/libc/stdio/fputws.c index b4462b7..a318e2d 100644 --- a/lib/libc/stdio/fputws.c +++ b/lib/libc/stdio/fputws.c @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,13 +44,15 @@ __FBSDID("$FreeBSD$"); #include "mblocal.h" int -fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale) { size_t nbytes; char buf[BUFSIZ]; struct __suio uio; struct __siov iov; const wchar_t *wsp; + FIX_LOCALE(locale); + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); FLOCKFILE(fp); ORIENT(fp, 1); @@ -56,7 +63,7 @@ fputws(const wchar_t * __restrict ws, FILE * __restrict fp) iov.iov_base = buf; do { wsp = ws; - nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), + nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), &fp->_mbstate); if (nbytes == (size_t)-1) goto error; @@ -71,3 +78,9 @@ error: FUNLOCKFILE(fp); return (-1); } + +int +fputws(const wchar_t * __restrict ws, FILE * __restrict fp) +{ + return fputws_l(ws, fp, __get_locale()); +} diff --git a/lib/libc/stdio/fscanf.c b/lib/libc/stdio/fscanf.c index ce3001a..c5fa85f 100644 --- a/lib/libc/stdio/fscanf.c +++ b/lib/libc/stdio/fscanf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int fscanf(FILE * __restrict fp, char const * __restrict fmt, ...) @@ -51,7 +57,21 @@ fscanf(FILE * __restrict fp, char const * __restrict fmt, ...) va_start(ap, fmt); FLOCKFILE(fp); - ret = __svfscanf(fp, fmt, ap); + ret = __svfscanf(fp, __get_locale(), fmt, ap); + va_end(ap); + FUNLOCKFILE(fp); + return (ret); +} +int +fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt, ap); va_end(ap); FUNLOCKFILE(fp); return (ret); diff --git a/lib/libc/stdio/fwprintf.c b/lib/libc/stdio/fwprintf.c index a22edae..f4342ab 100644 --- a/lib/libc/stdio/fwprintf.c +++ b/lib/libc/stdio/fwprintf.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) return (ret); } +int +fwprintf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(fp, locale, fmt, ap); + va_end(ap); + + return (ret); +} diff --git a/lib/libc/stdio/fwscanf.c b/lib/libc/stdio/fwscanf.c index f779c53..1756077 100644 --- a/lib/libc/stdio/fwscanf.c +++ b/lib/libc/stdio/fwscanf.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...) return (r); } +int +fwscanf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(fp, locale, fmt, ap); + va_end(ap); + + return (r); +} diff --git a/lib/libc/stdio/getwc.c b/lib/libc/stdio/getwc.c index ba5ab60..666350b 100644 --- a/lib/libc/stdio/getwc.c +++ b/lib/libc/stdio/getwc.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include <stdio.h> #include <wchar.h> +#include <xlocale.h> #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -46,3 +52,9 @@ getwc(FILE *fp) return (fgetwc(fp)); } +wint_t +getwc_l(FILE *fp, locale_t locale) +{ + + return (fgetwc_l(fp, locale)); +} diff --git a/lib/libc/stdio/getwchar.c b/lib/libc/stdio/getwchar.c index 79dd7bc..bc3b8a6 100644 --- a/lib/libc/stdio/getwchar.c +++ b/lib/libc/stdio/getwchar.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include <stdio.h> #include <wchar.h> +#include <xlocale.h> #include "un-namespace.h" #include "libc_private.h" #include "local.h" @@ -42,6 +48,10 @@ __FBSDID("$FreeBSD$"); wint_t getwchar(void) { - return (fgetwc(stdin)); } +wint_t +getwchar_l(locale_t locale) +{ + return (fgetwc_l(stdin, locale)); +} diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h index 6380b83..8b37f0d 100644 --- a/lib/libc/stdio/local.h +++ b/lib/libc/stdio/local.h @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,6 +42,7 @@ #include <pthread.h> #include <string.h> #include <wchar.h> +#include <locale.h> /* * Information local to this implementation of stdio, @@ -50,8 +56,8 @@ extern int _ftello(FILE *, fpos_t *); extern int _fseeko(FILE *, off_t, int, int); extern int __fflush(FILE *fp); extern void __fcloseall(void); -extern wint_t __fgetwc(FILE *); -extern wint_t __fputwc(wchar_t, FILE *); +extern wint_t __fgetwc(FILE *, locale_t); +extern wint_t __fputwc(wchar_t, FILE *, locale_t); extern int __sflush(FILE *); extern FILE *__sfp(void); extern int __slbexpand(FILE *, size_t); @@ -65,15 +71,15 @@ extern void _cleanup(void); extern void __smakebuf(FILE *); extern int __swhatbuf(FILE *, size_t *, int *); extern int _fwalk(int (*)(FILE *)); -extern int __svfscanf(FILE *, const char *, __va_list); +extern int __svfscanf(FILE *, locale_t, const char *, __va_list); extern int __swsetup(FILE *); extern int __sflags(const char *, int *); extern int __ungetc(int, FILE *); -extern wint_t __ungetwc(wint_t, FILE *); -extern int __vfprintf(FILE *, const char *, __va_list); +extern wint_t __ungetwc(wint_t, FILE *, locale_t); +extern int __vfprintf(FILE *, locale_t, const char *, __va_list); extern int __vfscanf(FILE *, const char *, __va_list); -extern int __vfwprintf(FILE *, const wchar_t *, __va_list); -extern int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, +extern int __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list); +extern int __vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict, __va_list); extern size_t __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp); diff --git a/lib/libc/stdio/printf.c b/lib/libc/stdio/printf.c index df290fa..f623f2f 100644 --- a/lib/libc/stdio/printf.c +++ b/lib/libc/stdio/printf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <stdarg.h> +#include <xlocale.h> int printf(char const * __restrict fmt, ...) @@ -50,3 +56,14 @@ printf(char const * __restrict fmt, ...) va_end(ap); return (ret); } +int +printf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf_l(stdout, locale, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/lib/libc/stdio/printfcommon.h b/lib/libc/stdio/printfcommon.h index 39b0003..97acc53 100644 --- a/lib/libc/stdio/printfcommon.h +++ b/lib/libc/stdio/printfcommon.h @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -79,14 +84,14 @@ io_init(struct io_state *iop, FILE *fp) * remain valid until io_flush() is called. */ static inline int -io_print(struct io_state *iop, const CHAR * __restrict ptr, int len) +io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale) { iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; iop->iov[iop->uio.uio_iovcnt].iov_len = len; iop->uio.uio_resid += len; if (++iop->uio.uio_iovcnt >= NIOV) - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); else return (0); } @@ -107,13 +112,14 @@ static const CHAR zeroes[PADSIZE] = * or the zeroes array. */ static inline int -io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with) +io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, + locale_t locale) { int n; while (howmany > 0) { n = (howmany >= PADSIZE) ? PADSIZE : howmany; - if (io_print(iop, with, n)) + if (io_print(iop, with, n, locale)) return (-1); howmany -= n; } @@ -126,7 +132,7 @@ io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with) */ static inline int io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, - int len, const CHAR * __restrict with) + int len, const CHAR * __restrict with, locale_t locale) { int p_len; @@ -134,19 +140,19 @@ io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, if (p_len > len) p_len = len; if (p_len > 0) { - if (io_print(iop, p, p_len)) + if (io_print(iop, p, p_len, locale)) return (-1); } else { p_len = 0; } - return (io_pad(iop, len - p_len, with)); + return (io_pad(iop, len - p_len, with, locale)); } static inline int -io_flush(struct io_state *iop) +io_flush(struct io_state *iop, locale_t locale) { - return (__sprint(iop->fp, &iop->uio)); + return (__sprint(iop->fp, &iop->uio, locale)); } /* diff --git a/lib/libc/stdio/putwc.c b/lib/libc/stdio/putwc.c index 8fe065b..56acf50 100644 --- a/lib/libc/stdio/putwc.c +++ b/lib/libc/stdio/putwc.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwc @@ -41,8 +47,13 @@ __FBSDID("$FreeBSD$"); * macro, may evaluate `fp' more than once. */ wint_t +putwc_l(wchar_t wc, FILE *fp, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, fp, locale)); +} +wint_t putwc(wchar_t wc, FILE *fp) { - - return (fputwc(wc, fp)); + return putwc_l(wc, fp, __get_locale()); } diff --git a/lib/libc/stdio/putwchar.c b/lib/libc/stdio/putwchar.c index 5503071..8673bd5 100644 --- a/lib/libc/stdio/putwchar.c +++ b/lib/libc/stdio/putwchar.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #undef putwchar @@ -40,8 +46,13 @@ __FBSDID("$FreeBSD$"); * Synonym for fputwc(wc, stdout). */ wint_t +putwchar_l(wchar_t wc, locale_t locale) +{ + FIX_LOCALE(locale); + return (fputwc_l(wc, stdout, locale)); +} +wint_t putwchar(wchar_t wc) { - - return (fputwc(wc, stdout)); + return putwchar_l(wc, __get_locale()); } diff --git a/lib/libc/stdio/scanf.c b/lib/libc/stdio/scanf.c index 4ae88da..ba33caa 100644 --- a/lib/libc/stdio/scanf.c +++ b/lib/libc/stdio/scanf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -42,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int scanf(char const * __restrict fmt, ...) @@ -51,7 +57,21 @@ scanf(char const * __restrict fmt, ...) va_start(ap, fmt); FLOCKFILE(stdin); - ret = __svfscanf(stdin, fmt, ap); + ret = __svfscanf(stdin, __get_locale(), fmt, ap); + FUNLOCKFILE(stdin); + va_end(ap); + return (ret); +} +int +scanf_l(locale_t locale, char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + FLOCKFILE(stdin); + ret = __svfscanf(stdin, locale, fmt, ap); FUNLOCKFILE(stdin); va_end(ap); return (ret); diff --git a/lib/libc/stdio/snprintf.c b/lib/libc/stdio/snprintf.c index e6d7115..74af42d 100644 --- a/lib/libc/stdio/snprintf.c +++ b/lib/libc/stdio/snprintf.c @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -39,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <limits.h> #include <stdio.h> #include <stdarg.h> +#include "xlocale_private.h" #include "local.h" @@ -59,7 +65,32 @@ snprintf(char * __restrict str, size_t n, char const * __restrict fmt, ...) f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, __get_locale(), fmt, ap); + if (on > 0) + *f._p = '\0'; + va_end(ap); + return (ret); +} +int +snprintf_l(char * __restrict str, size_t n, locale_t locale, + char const * __restrict fmt, ...) +{ + size_t on; + int ret; + va_list ap; + FILE f = FAKE_FILE; + FIX_LOCALE(locale); + + on = n; + if (n != 0) + n--; + if (n > INT_MAX) + n = INT_MAX; + va_start(ap, fmt); + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *)str; + f._bf._size = f._w = n; + ret = __vfprintf(&f, locale, fmt, ap); if (on > 0) *f._p = '\0'; va_end(ap); diff --git a/lib/libc/stdio/sprintf.c b/lib/libc/stdio/sprintf.c index b55bd6c..6e20e04 100644 --- a/lib/libc/stdio/sprintf.c +++ b/lib/libc/stdio/sprintf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -40,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <limits.h> #include "local.h" +#include "xlocale_private.h" int sprintf(char * __restrict str, char const * __restrict fmt, ...) @@ -52,3 +58,16 @@ sprintf(char * __restrict str, char const * __restrict fmt, ...) va_end(ap); return (ret); } +int +sprintf_l(char * __restrict str, locale_t locale, char const * __restrict fmt, + ...) +{ + int ret; + va_list ap; + FIX_LOCALE(locale); + + va_start(ap, fmt); + ret = vsprintf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/lib/libc/stdio/sscanf.c b/lib/libc/stdio/sscanf.c index c793b86..1c339eb 100644 --- a/lib/libc/stdio/sscanf.c +++ b/lib/libc/stdio/sscanf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <string.h> #include <stdarg.h> +#include <xlocale.h> #include "local.h" int @@ -52,3 +58,15 @@ sscanf(const char * __restrict str, char const * __restrict fmt, ...) va_end(ap); return (ret); } +int +sscanf_l(const char * __restrict str, locale_t locale, + char const * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vsscanf_l(str, locale, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/lib/libc/stdio/swprintf.c b/lib/libc/stdio/swprintf.c index d665318..1f6ecc6 100644 --- a/lib/libc/stdio/swprintf.c +++ b/lib/libc/stdio/swprintf.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int swprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ swprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, ...) return (ret); } +int +swprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vswprintf_l(s, n, locale, fmt, ap); + va_end(ap); + + return (ret); +} diff --git a/lib/libc/stdio/swscanf.c b/lib/libc/stdio/swscanf.c index 728a3d6..c305ac1 100644 --- a/lib/libc/stdio/swscanf.c +++ b/lib/libc/stdio/swscanf.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...) @@ -43,3 +49,16 @@ swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...) return (r); } +int +swscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vswscanf_l(str, locale, fmt, ap); + va_end(ap); + + return (r); +} diff --git a/lib/libc/stdio/ungetwc.c b/lib/libc/stdio/ungetwc.c index 10dbbbf..78bc38d 100644 --- a/lib/libc/stdio/ungetwc.c +++ b/lib/libc/stdio/ungetwc.c @@ -2,6 +2,11 @@ * Copyright (c) 2002-2004 Tim J. Robbins. * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,19 +42,21 @@ __FBSDID("$FreeBSD$"); #include "libc_private.h" #include "local.h" #include "mblocal.h" +#include "xlocale_private.h" /* * Non-MT-safe version. */ wint_t -__ungetwc(wint_t wc, FILE *fp) +__ungetwc(wint_t wc, FILE *fp, locale_t locale) { char buf[MB_LEN_MAX]; size_t len; + struct xlocale_ctype *l = XLOCALE_CTYPE(locale); if (wc == WEOF) return (WEOF); - if ((len = __wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { + if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) { fp->_flags |= __SERR; return (WEOF); } @@ -64,14 +71,20 @@ __ungetwc(wint_t wc, FILE *fp) * MT-safe version. */ wint_t -ungetwc(wint_t wc, FILE *fp) +ungetwc_l(wint_t wc, FILE *fp, locale_t locale) { wint_t r; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - r = __ungetwc(wc, fp); + r = __ungetwc(wc, fp, locale); FUNLOCKFILE(fp); return (r); } +wint_t +ungetwc(wint_t wc, FILE *fp) +{ + return ungetwc_l(wc, fp, __get_locale()); +} diff --git a/lib/libc/stdio/vasprintf.c b/lib/libc/stdio/vasprintf.c index a1b600a..8feb23d 100644 --- a/lib/libc/stdio/vasprintf.c +++ b/lib/libc/stdio/vasprintf.c @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,13 +38,15 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include "xlocale_private.h" #include "local.h" int -vasprintf(char **str, const char *fmt, __va_list ap) +vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap) { FILE f = FAKE_FILE; int ret; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR | __SALC; f._bf._base = f._p = malloc(128); @@ -49,7 +56,7 @@ vasprintf(char **str, const char *fmt, __va_list ap) return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (ret < 0) { free(f._bf._base); *str = NULL; @@ -60,3 +67,8 @@ vasprintf(char **str, const char *fmt, __va_list ap) *str = (char *)f._bf._base; return (ret); } +int +vasprintf(char **str, const char *fmt, __va_list ap) +{ + return vasprintf_l(str, __get_locale(), fmt, ap); +} diff --git a/lib/libc/stdio/vdprintf.c b/lib/libc/stdio/vdprintf.c index 3ad273e..454b0f9 100644 --- a/lib/libc/stdio/vdprintf.c +++ b/lib/libc/stdio/vdprintf.c @@ -2,6 +2,11 @@ * Copyright (c) 2009 David Schultz <das@FreeBSD.org> * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "local.h" +#include "xlocale_private.h" int vdprintf(int fd, const char * __restrict fmt, va_list ap) @@ -57,7 +63,7 @@ vdprintf(int fd, const char * __restrict fmt, va_list ap) f._bf._base = buf; f._bf._size = sizeof(buf); - if ((ret = __vfprintf(&f, fmt, ap)) < 0) + if ((ret = __vfprintf(&f, __get_locale(), fmt, ap)) < 0) return (ret); return (__fflush(&f) ? EOF : ret); diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c index 17ad824..bfbdc13 100644 --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -57,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include <printf.h> #include <stdarg.h> +#include "xlocale_private.h" #include "un-namespace.h" #include "libc_private.h" @@ -64,8 +70,8 @@ __FBSDID("$FreeBSD$"); #include "fvwrite.h" #include "printflocal.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0) +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0) __noinline; static char *__wcsconv(wchar_t *, int); @@ -87,11 +93,11 @@ struct grouping_state { * of bytes that will be needed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t loc) { struct lconv *locale; - locale = localeconv(); + locale = localeconv_l(loc); gs->grouping = locale->grouping; gs->thousands_sep = locale->thousands_sep; gs->thousep_len = strlen(gs->thousands_sep); @@ -116,11 +122,11 @@ grouping_init(struct grouping_state *gs, int ndigits) */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -130,9 +136,9 @@ grouping_print(struct grouping_state *gs, struct io_state *iop, gs->grouping--; gs->nseps--; } - if (io_print(iop, gs->thousands_sep, gs->thousep_len)) + if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -146,7 +152,7 @@ grouping_print(struct grouping_state *gs, struct io_state *iop, * then reset it so that it can be reused. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { int err; @@ -166,7 +172,7 @@ __sprint(FILE *fp, struct __suio *uio) * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const char *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap) { int ret; FILE fake = FAKE_FILE; @@ -190,7 +196,7 @@ __sbprintf(FILE *fp, const char *fmt, va_list ap) fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfprintf(&fake, fmt, ap); + ret = __vfprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = EOF; if (fake._flags & __SERR) @@ -261,21 +267,27 @@ __wcsconv(wchar_t *wcsarg, int prec) * MT-safe version */ int -vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) - +vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0, + va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfprintf(fp, fmt0, ap); + ret = __vfprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) +{ + return vfprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -292,7 +304,7 @@ vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) * Non-MT-safe version */ int -__vfprintf(FILE *fp, const char *fmt0, va_list ap) +__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -357,19 +369,19 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -454,7 +466,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) ret = 0; #ifndef NO_FLOATING_POINT dtoaresult = NULL; - decimal_point = localeconv()->decimal_point; + decimal_point = localeconv_l(locale)->decimal_point; /* The overwhelmingly common case is decpt_len == 1. */ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); #endif @@ -750,7 +762,7 @@ fp_common: if (prec || flags & ALT) size += prec + decpt_len; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -887,7 +899,7 @@ number: if ((dprec = prec) >= 0) if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -950,7 +962,7 @@ number: if ((dprec = prec) >= 0) /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -968,7 +980,7 @@ number: if ((dprec = prec) >= 0) } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, dtoaend); + cp, dtoaend, locale); if (n < 0) goto error; cp += n; diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c index bce4481..0e78949 100644 --- a/lib/libc/stdio/vfscanf.c +++ b/lib/libc/stdio/vfscanf.c @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Chris Torek. * @@ -51,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include "collate.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" #ifndef NO_FLOATING_POINT #include <locale.h> @@ -95,7 +101,7 @@ __FBSDID("$FreeBSD$"); static const u_char *__sccl(char *, const u_char *); #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, char *, char *); +static int parsefloat(FILE *, char *, char *, locale_t); #endif __weak_reference(__vfscanf, vfscanf); @@ -109,7 +115,18 @@ __vfscanf(FILE *fp, char const *fmt0, va_list ap) int ret; FLOCKFILE(fp); - ret = __svfscanf(fp, fmt0, ap); + ret = __svfscanf(fp, __get_locale(), fmt0, ap); + FUNLOCKFILE(fp); + return (ret); +} +int +vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap) +{ + int ret; + FIX_LOCALE(locale); + + FLOCKFILE(fp); + ret = __svfscanf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } @@ -118,7 +135,7 @@ __vfscanf(FILE *fp, char const *fmt0, va_list ap) * __svfscanf - non-MT-safe version of __vfscanf */ int -__svfscanf(FILE *fp, const char *fmt0, va_list ap) +__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) { const u_char *fmt = (const u_char *)fmt0; int c; /* character from format, or conversion */ @@ -733,9 +750,9 @@ literal: *p = 0; if ((flags & UNSIGNED) == 0) - res = strtoimax(buf, (char **)NULL, base); + res = strtoimax_l(buf, (char **)NULL, base, locale); else - res = strtoumax(buf, (char **)NULL, base); + res = strtoumax_l(buf, (char **)NULL, base, locale); if (flags & POINTER) *va_arg(ap, void **) = (void *)(uintptr_t)res; @@ -766,17 +783,17 @@ literal: /* scan a floating point number as if by strtod */ if (width == 0 || width > sizeof(buf) - 1) width = sizeof(buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { - long double res = strtold(buf, &p); + long double res = strtold_l(buf, &p, locale); *va_arg(ap, long double *) = res; } else if (flags & LONG) { - double res = strtod(buf, &p); + double res = strtod_l(buf, &p, locale); *va_arg(ap, double *) = res; } else { - float res = strtof(buf, &p); + float res = strtof_l(buf, &p, locale); *va_arg(ap, float *) = res; } nassigned++; @@ -805,6 +822,8 @@ __sccl(tab, fmt) const u_char *fmt; { int c, n, v, i; + struct xlocale_collate *table = + (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ @@ -858,8 +877,8 @@ doswitch: */ n = *fmt; if (n == ']' - || (__collate_load_error ? n < c : - __collate_range_cmp (n, c) < 0 + || (table->__collate_load_error ? n < c : + __collate_range_cmp (table, n, c) < 0 ) ) { c = '-'; @@ -867,14 +886,14 @@ doswitch: } fmt++; /* fill in the range */ - if (__collate_load_error) { + if (table->__collate_load_error) { do { tab[++c] = v; } while (c < n); } else { for (i = 0; i < 256; i ++) - if ( __collate_range_cmp (c, i) < 0 - && __collate_range_cmp (i, n) <= 0 + if ( __collate_range_cmp (table, c, i) < 0 + && __collate_range_cmp (table, i, n) <= 0 ) tab[i] = v; } @@ -908,7 +927,7 @@ doswitch: #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, char *buf, char *end) +parsefloat(FILE *fp, char *buf, char *end, locale_t locale) { char *commit, *p; int infnanpos = 0, decptpos = 0; @@ -917,7 +936,7 @@ parsefloat(FILE *fp, char *buf, char *end) S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS } state = S_START; unsigned char c; - const char *decpt = localeconv()->decimal_point; + const char *decpt = localeconv_l(locale)->decimal_point; _Bool gotmantdig = 0, ishex = 0; /* diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c index d34f559..73e37c9 100644 --- a/lib/libc/stdio/vfwprintf.c +++ b/lib/libc/stdio/vfwprintf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -65,10 +70,11 @@ __FBSDID("$FreeBSD$"); #include "local.h" #include "fvwrite.h" #include "printflocal.h" +#include "xlocale_private.h" -static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline; -static wint_t __xfputwc(wchar_t, FILE *); +static int __sprint(FILE *, struct __suio *, locale_t); +static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list) __noinline; +static wint_t __xfputwc(wchar_t, FILE *, locale_t); static wchar_t *__mbsconv(char *, int); #define CHAR wchar_t @@ -85,28 +91,28 @@ struct grouping_state { static const mbstate_t initial_mbs; static inline wchar_t -get_decpt(void) +get_decpt(locale_t locale) { mbstate_t mbs; wchar_t decpt; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs); + nconv = mbrtowc(&decpt, localeconv_l(locale)->decimal_point, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) decpt = '.'; /* failsafe */ return (decpt); } static inline wchar_t -get_thousep(void) +get_thousep(locale_t locale) { mbstate_t mbs; wchar_t thousep; int nconv; mbs = initial_mbs; - nconv = mbrtowc(&thousep, localeconv()->thousands_sep, + nconv = mbrtowc(&thousep, localeconv_l(locale)->thousands_sep, MB_CUR_MAX, &mbs); if (nconv == (size_t)-1 || nconv == (size_t)-2) thousep = '\0'; /* failsafe */ @@ -119,11 +125,11 @@ get_thousep(void) * of wide characters that will be printed. */ static int -grouping_init(struct grouping_state *gs, int ndigits) +grouping_init(struct grouping_state *gs, int ndigits, locale_t locale) { - gs->grouping = localeconv()->grouping; - gs->thousands_sep = get_thousep(); + gs->grouping = localeconv_l(locale)->grouping; + gs->thousands_sep = get_thousep(locale); gs->nseps = gs->nrepeats = 0; gs->lead = ndigits; @@ -145,11 +151,11 @@ grouping_init(struct grouping_state *gs, int ndigits) */ static int grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep) + const CHAR *cp, const CHAR *ep, locale_t locale) { const CHAR *cp0 = cp; - if (io_printandpad(iop, cp, ep, gs->lead, zeroes)) + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) return (-1); cp += gs->lead; while (gs->nseps > 0 || gs->nrepeats > 0) { @@ -159,9 +165,9 @@ grouping_print(struct grouping_state *gs, struct io_state *iop, gs->grouping--; gs->nseps--; } - if (io_print(iop, &gs->thousands_sep, 1)) + if (io_print(iop, &gs->thousands_sep, 1, locale)) return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes)) + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) return (-1); cp += *gs->grouping; } @@ -180,7 +186,7 @@ grouping_print(struct grouping_state *gs, struct io_state *iop, * string eclipses the benefits of buffering. */ static int -__sprint(FILE *fp, struct __suio *uio) +__sprint(FILE *fp, struct __suio *uio, locale_t locale) { struct __siov *iov; wchar_t *p; @@ -191,7 +197,7 @@ __sprint(FILE *fp, struct __suio *uio) p = (wchar_t *)iov->iov_base; len = iov->iov_len; for (i = 0; i < len; i++) { - if (__xfputwc(p[i], fp) == WEOF) + if (__xfputwc(p[i], fp, locale) == WEOF) return (-1); } } @@ -205,7 +211,7 @@ __sprint(FILE *fp, struct __suio *uio) * worries about ungetc buffers and so forth. */ static int -__sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) +__sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap) { int ret; FILE fake; @@ -229,7 +235,7 @@ __sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ - ret = __vfwprintf(&fake, fmt, ap); + ret = __vfwprintf(&fake, locale, fmt, ap); if (ret >= 0 && __fflush(&fake)) ret = WEOF; if (fake._flags & __SERR) @@ -242,7 +248,7 @@ __sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) * File must already be locked. */ static wint_t -__xfputwc(wchar_t wc, FILE *fp) +__xfputwc(wchar_t wc, FILE *fp, locale_t locale) { mbstate_t mbs; char buf[MB_LEN_MAX]; @@ -251,7 +257,7 @@ __xfputwc(wchar_t wc, FILE *fp) size_t len; if ((fp->_flags & __SSTR) == 0) - return (__fputwc(wc, fp)); + return (__fputwc(wc, fp, locale)); mbs = initial_mbs; if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) { @@ -343,21 +349,27 @@ __mbsconv(char *mbsarg, int prec) * MT-safe version */ int -vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +vfwprintf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt0, va_list ap) { int ret; - + FIX_LOCALE(locale); FLOCKFILE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) - ret = __sbprintf(fp, fmt0, ap); + ret = __sbprintf(fp, locale, fmt0, ap); else - ret = __vfwprintf(fp, fmt0, ap); + ret = __vfwprintf(fp, locale, fmt0, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) +{ + return vfwprintf_l(fp, __get_locale(), fmt0, ap); +} /* * The size of the buffer we use as scratch space for integer @@ -374,7 +386,7 @@ vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) * Non-MT-safe version */ int -__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) +__vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap) { wchar_t *fmt; /* format string */ wchar_t ch; /* character from fmt */ @@ -437,19 +449,19 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) do { \ - if (io_print(&io, (ptr), (len))) \ + if (io_print(&io, (ptr), (len), locale)) \ goto error; \ } while (0) #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with))) \ + if (io_pad(&io, (howmany), (with), locale)) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with))) \ + if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ goto error; \ } #define FLUSH() { \ - if (io_flush(&io)) \ + if (io_flush(&io, locale)) \ goto error; \ } @@ -529,7 +541,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) io_init(&io, fp); ret = 0; #ifndef NO_FLOATING_POINT - decimal_point = get_decpt(); + decimal_point = get_decpt(locale); #endif /* @@ -816,7 +828,7 @@ fp_common: if (prec || flags & ALT) size += prec + 1; if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt); + size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -955,7 +967,7 @@ number: if ((dprec = prec) >= 0) if (size > BUF) /* should never happen */ abort(); if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size); + size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -1018,7 +1030,7 @@ number: if ((dprec = prec) >= 0) /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF) < 0) + if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) goto error; } else { PRINT(cp, size); @@ -1036,7 +1048,7 @@ number: if ((dprec = prec) >= 0) } else { if (gs.grouping) { n = grouping_print(&gs, &io, - cp, convbuf + ndig); + cp, convbuf + ndig, locale); if (n < 0) goto error; cp += n; diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c index 60c7c71..22b0827 100644 --- a/lib/libc/stdio/vfwscanf.c +++ b/lib/libc/stdio/vfwscanf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -53,10 +58,7 @@ __FBSDID("$FreeBSD$"); #include "libc_private.h" #include "local.h" - -#ifndef NO_FLOATING_POINT -#include <locale.h> -#endif +#include "xlocale_private.h" #define BUF 513 /* Maximum length of numeric string. */ @@ -96,7 +98,7 @@ __FBSDID("$FreeBSD$"); #define CT_FLOAT 4 /* %[efgEFG] conversion */ #ifndef NO_FLOATING_POINT -static int parsefloat(FILE *, wchar_t *, wchar_t *); +static int parsefloat(FILE *, wchar_t *, wchar_t *, locale_t); #endif #define INCCL(_c) \ @@ -109,22 +111,30 @@ static const mbstate_t initial_mbs; * MT-safe version. */ int -vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +vfwscanf_l(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { int ret; + FIX_LOCALE(locale); FLOCKFILE(fp); ORIENT(fp, 1); - ret = __vfwscanf(fp, fmt, ap); + ret = __vfwscanf(fp, locale, fmt, ap); FUNLOCKFILE(fp); return (ret); } +int +vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +{ + return vfwscanf_l(fp, __get_locale(), fmt, ap); +} /* * Non-MT-safe version. */ int -__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) +__vfwscanf(FILE * __restrict fp, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { wint_t c; /* character from format, or conversion */ size_t width; /* field width, or 0 */ @@ -159,11 +169,11 @@ __vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) if (c == 0) return (nassigned); if (iswspace(c)) { - while ((c = __fgetwc(fp)) != WEOF && - iswspace(c)) + while ((c = __fgetwc(fp, locale)) != WEOF && + iswspace_l(c, locale)) ; if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); continue; } if (c != '%') @@ -178,10 +188,10 @@ again: c = *fmt++; switch (c) { case '%': literal: - if ((wi = __fgetwc(fp)) == WEOF) + if ((wi = __fgetwc(fp, locale)) == WEOF) goto input_failure; if (wi != c) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); goto input_failure; } nread++; @@ -341,11 +351,11 @@ literal: * that suppress this. */ if ((flags & NOSKIP) == 0) { - while ((wi = __fgetwc(fp)) != WEOF && iswspace(wi)) + while ((wi = __fgetwc(fp, locale)) != WEOF && iswspace(wi)) nread++; if (wi == WEOF) goto input_failure; - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } /* @@ -362,7 +372,7 @@ literal: p = va_arg(ap, wchar_t *); n = 0; while (width-- != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (!(flags & SUPPRESS)) *p++ = (wchar_t)wi; n++; @@ -378,7 +388,7 @@ literal: n = 0; mbs = initial_mbs; while (width != 0 && - (wi = __fgetwc(fp)) != WEOF) { + (wi = __fgetwc(fp, locale)) != WEOF) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { nconv = wcrtomb(mbp, wi, &mbs); @@ -390,7 +400,7 @@ literal: if (nconv == (size_t)-1) goto input_failure; if (nconv > width) { - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); break; } if (!(flags & SUPPRESS)) @@ -418,20 +428,20 @@ literal: /* take only those things in the class */ if ((flags & SUPPRESS) && (flags & LONG)) { n = 0; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) n++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (n == 0) goto match_failure; } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && INCCL(wi)) *p++ = (wchar_t)wi; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); n = p - p0; if (n == 0) goto match_failure; @@ -442,7 +452,7 @@ literal: mbp = va_arg(ap, char *); n = 0; mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && INCCL(wi)) { if (width >= MB_CUR_MAX && !(flags & SUPPRESS)) { @@ -466,7 +476,7 @@ literal: n++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -481,29 +491,29 @@ literal: if (width == 0) width = (size_t)~0; if ((flags & SUPPRESS) && (flags & LONG)) { - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) nread++; if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); } else if (flags & LONG) { p0 = p = va_arg(ap, wchar_t *); - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 && !iswspace(wi)) { *p++ = (wchar_t)wi; nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); *p = '\0'; nassigned++; } else { if (!(flags & SUPPRESS)) mbp = va_arg(ap, char *); mbs = initial_mbs; - while ((wi = __fgetwc(fp)) != WEOF && + while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 && !iswspace(wi)) { if (width >= MB_CUR_MAX && @@ -528,7 +538,7 @@ literal: nread++; } if (wi != WEOF) - __ungetwc(wi, fp); + __ungetwc(wi, fp, locale); if (!(flags & SUPPRESS)) { *mbp = 0; nassigned++; @@ -544,7 +554,7 @@ literal: width = sizeof(buf) / sizeof(*buf) - 1; flags |= SIGNOK | NDIGITS | NZDIGITS; for (p = buf; width; width--) { - c = __fgetwc(fp); + c = __fgetwc(fp, locale); /* * Switch on the character; `goto ok' * if we accept it as a part of number. @@ -628,7 +638,7 @@ literal: * for a number. Stop accumulating digits. */ if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); break; ok: /* @@ -644,13 +654,13 @@ literal: */ if (flags & NDIGITS) { if (p > buf) - __ungetwc(*--p, fp); + __ungetwc(*--p, fp, locale); goto match_failure; } c = p[-1]; if (c == 'x' || c == 'X') { --p; - __ungetwc(c, fp); + __ungetwc(c, fp, locale); } if ((flags & SUPPRESS) == 0) { uintmax_t res; @@ -691,7 +701,7 @@ literal: if (width == 0 || width > sizeof(buf) / sizeof(*buf) - 1) width = sizeof(buf) / sizeof(*buf) - 1; - if ((width = parsefloat(fp, buf, buf + width)) == 0) + if ((width = parsefloat(fp, buf, buf + width, locale)) == 0) goto match_failure; if ((flags & SUPPRESS) == 0) { if (flags & LONGDBL) { @@ -720,7 +730,7 @@ match_failure: #ifndef NO_FLOATING_POINT static int -parsefloat(FILE *fp, wchar_t *buf, wchar_t *end) +parsefloat(FILE *fp, wchar_t *buf, wchar_t *end, locale_t locale) { mbstate_t mbs; size_t nconv; @@ -751,7 +761,7 @@ parsefloat(FILE *fp, wchar_t *buf, wchar_t *end) commit = buf - 1; c = WEOF; for (p = buf; p < end; ) { - if ((c = __fgetwc(fp)) == WEOF) + if ((c = __fgetwc(fp, locale)) == WEOF) break; reswitch: switch (state) { @@ -871,9 +881,9 @@ reswitch: parsedone: if (c != WEOF) - __ungetwc(c, fp); + __ungetwc(c, fp, locale); while (commit < --p) - __ungetwc(*p, fp); + __ungetwc(*p, fp, locale); *++commit = '\0'; return (commit - buf); } diff --git a/lib/libc/stdio/vprintf.c b/lib/libc/stdio/vprintf.c index a610b7d..c15ef4d 100644 --- a/lib/libc/stdio/vprintf.c +++ b/lib/libc/stdio/vprintf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -37,10 +42,15 @@ static char sccsid[] = "@(#)vprintf.c 8.1 (Berkeley) 6/4/93"; __FBSDID("$FreeBSD$"); #include <stdio.h> +#include <xlocale.h> int vprintf(const char * __restrict fmt, __va_list ap) { - return (vfprintf(stdout, fmt, ap)); } +int +vprintf_l(locale_t locale, const char * __restrict fmt, __va_list ap) +{ + return (vfprintf_l(stdout, locale, fmt, ap)); +} diff --git a/lib/libc/stdio/vscanf.c b/lib/libc/stdio/vscanf.c index 25bce72..d56bb3b 100644 --- a/lib/libc/stdio/vscanf.c +++ b/lib/libc/stdio/vscanf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,16 +46,26 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "libc_private.h" #include "local.h" +#include "xlocale_private.h" int -vscanf(fmt, ap) +vscanf_l(locale, fmt, ap) + locale_t locale; const char * __restrict fmt; __va_list ap; { int retval; + FIX_LOCALE(locale); FLOCKFILE(stdin); - retval = __svfscanf(stdin, fmt, ap); + retval = __svfscanf(stdin, locale, fmt, ap); FUNLOCKFILE(stdin); return (retval); } +int +vscanf(fmt, ap) + const char * __restrict fmt; + __va_list ap; +{ + return vscanf_l(__get_locale(), fmt, ap); +} diff --git a/lib/libc/stdio/vsnprintf.c b/lib/libc/stdio/vsnprintf.c index 70e4c53..d2bad0f 100644 --- a/lib/libc/stdio/vsnprintf.c +++ b/lib/libc/stdio/vsnprintf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,15 +44,17 @@ __FBSDID("$FreeBSD$"); #include <limits.h> #include <stdio.h> #include "local.h" +#include "xlocale_private.h" int -vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, - __va_list ap) +vsnprintf_l(char * __restrict str, size_t n, locale_t locale, + const char * __restrict fmt, __va_list ap) { size_t on; int ret; char dummy[2]; FILE f = FAKE_FILE; + FIX_LOCALE(locale); on = n; if (n != 0) @@ -64,8 +71,14 @@ vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = n; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); if (on > 0) *f._p = '\0'; return (ret); } +int +vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt, + __va_list ap) +{ + return vsnprintf_l(str, n, __get_locale(), fmt, ap); +} diff --git a/lib/libc/stdio/vsprintf.c b/lib/libc/stdio/vsprintf.c index 3890af7..04f2df3 100644 --- a/lib/libc/stdio/vsprintf.c +++ b/lib/libc/stdio/vsprintf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Chris Torek. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -39,17 +44,25 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <limits.h> #include "local.h" +#include "xlocale_private.h" int -vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +vsprintf_l(char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { int ret; FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SWR | __SSTR; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._w = INT_MAX; - ret = __vfprintf(&f, fmt, ap); + ret = __vfprintf(&f, locale, fmt, ap); *f._p = 0; return (ret); } +int +vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap) +{ + return vsprintf_l(str, __get_locale(), fmt, ap); +} diff --git a/lib/libc/stdio/vsscanf.c b/lib/libc/stdio/vsscanf.c index 82429c6..5668ab5 100644 --- a/lib/libc/stdio/vsscanf.c +++ b/lib/libc/stdio/vsscanf.c @@ -2,6 +2,11 @@ * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * @@ -39,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <string.h> #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -52,14 +58,21 @@ eofread(void *cookie, char *buf, int len) } int -vsscanf(const char * __restrict str, const char * __restrict fmt, - __va_list ap) +vsscanf_l(const char * __restrict str, locale_t locale, + const char * __restrict fmt, __va_list ap) { FILE f = FAKE_FILE; + FIX_LOCALE(locale); f._flags = __SRD; f._bf._base = f._p = (unsigned char *)str; f._bf._size = f._r = strlen(str); f._read = eofread; - return (__svfscanf(&f, fmt, ap)); + return (__svfscanf(&f, locale, fmt, ap)); +} +int +vsscanf(const char * __restrict str, const char * __restrict fmt, + __va_list ap) +{ + return vsscanf_l(str, __get_locale(), fmt, ap); } diff --git a/lib/libc/stdio/vswprintf.c b/lib/libc/stdio/vswprintf.c index 2cfe724..023c537 100644 --- a/lib/libc/stdio/vswprintf.c +++ b/lib/libc/stdio/vswprintf.c @@ -4,6 +4,11 @@ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -38,10 +43,11 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <wchar.h> #include "local.h" +#include "xlocale_private.h" int -vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, - __va_list ap) +vswprintf_l(wchar_t * __restrict s, size_t n, locale_t locale, + const wchar_t * __restrict fmt, __va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -49,6 +55,7 @@ vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, char *mbp; int ret, sverrno; size_t nwc; + FIX_LOCALE(locale); if (n == 0) { errno = EINVAL; @@ -62,7 +69,7 @@ vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, return (-1); } f._bf._size = f._w = 127; /* Leave room for the NUL */ - ret = __vfwprintf(&f, fmt, ap); + ret = __vfwprintf(&f, locale, fmt, ap); if (ret < 0) { sverrno = errno; free(f._bf._base); @@ -76,7 +83,7 @@ vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, * fputwc() did in __vfwprintf(). */ mbs = initial; - nwc = mbsrtowcs(s, (const char **)&mbp, n, &mbs); + nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, locale); free(f._bf._base); if (nwc == (size_t)-1) { errno = EILSEQ; @@ -90,3 +97,9 @@ vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, return (ret); } +int +vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, + __va_list ap) +{ + return vswprintf_l(s, n, __get_locale(), fmt, ap); +} diff --git a/lib/libc/stdio/vswscanf.c b/lib/libc/stdio/vswscanf.c index f06fc02..f646e85 100644 --- a/lib/libc/stdio/vswscanf.c +++ b/lib/libc/stdio/vswscanf.c @@ -5,6 +5,11 @@ * This code is derived from software contributed to Berkeley by * Donn Seeley at UUNET Technologies, Inc. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -46,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <wchar.h> #include "local.h" +#include "xlocale_private.h" static int eofread(void *, char *, int); @@ -57,8 +63,8 @@ eofread(void *cookie, char *buf, int len) } int -vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, - va_list ap) +vswscanf_l(const wchar_t * __restrict str, locale_t locale, + const wchar_t * __restrict fmt, va_list ap) { static const mbstate_t initial; mbstate_t mbs; @@ -67,6 +73,7 @@ vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, size_t mlen; int r; const wchar_t *strp; + FIX_LOCALE(locale); /* * XXX Convert the wide character string to multibyte, which @@ -76,7 +83,7 @@ vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, return (EOF); mbs = initial; strp = str; - if ((mlen = wcsrtombs(mbstr, &strp, SIZE_T_MAX, &mbs)) == (size_t)-1) { + if ((mlen = wcsrtombs_l(mbstr, &strp, SIZE_T_MAX, &mbs, locale)) == (size_t)-1) { free(mbstr); return (EOF); } @@ -84,8 +91,14 @@ vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, f._bf._base = f._p = (unsigned char *)mbstr; f._bf._size = f._r = mlen; f._read = eofread; - r = __vfwscanf(&f, fmt, ap); + r = __vfwscanf(&f, locale, fmt, ap); free(mbstr); return (r); } +int +vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, + va_list ap) +{ + return vswscanf_l(str, __get_locale(), fmt, ap); +} diff --git a/lib/libc/stdio/vwprintf.c b/lib/libc/stdio/vwprintf.c index 91212a8..e09a30e 100644 --- a/lib/libc/stdio/vwprintf.c +++ b/lib/libc/stdio/vwprintf.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,10 +35,15 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int vwprintf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwprintf(stdout, fmt, ap)); } +int +vwprintf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwprintf_l(stdout, locale, fmt, ap)); +} diff --git a/lib/libc/stdio/vwscanf.c b/lib/libc/stdio/vwscanf.c index 4a21af2..730beee 100644 --- a/lib/libc/stdio/vwscanf.c +++ b/lib/libc/stdio/vwscanf.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,10 +35,15 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int vwscanf(const wchar_t * __restrict fmt, va_list ap) { - return (vfwscanf(stdin, fmt, ap)); } +int +vwscanf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap) +{ + return (vfwscanf_l(stdin, locale, fmt, ap)); +} diff --git a/lib/libc/stdio/wprintf.c b/lib/libc/stdio/wprintf.c index 92426f6..fdffa86 100644 --- a/lib/libc/stdio/wprintf.c +++ b/lib/libc/stdio/wprintf.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int wprintf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ wprintf(const wchar_t * __restrict fmt, ...) return (ret); } +int +wprintf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfwprintf_l(stdout, locale, fmt, ap); + va_end(ap); + + return (ret); +} diff --git a/lib/libc/stdio/wscanf.c b/lib/libc/stdio/wscanf.c index 5e27b40..22ce9bd 100644 --- a/lib/libc/stdio/wscanf.c +++ b/lib/libc/stdio/wscanf.c @@ -2,6 +2,11 @@ * Copyright (c) 2002 Tim J. Robbins * All rights reserved. * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -30,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdio.h> #include <wchar.h> +#include <xlocale.h> int wscanf(const wchar_t * __restrict fmt, ...) @@ -43,3 +49,15 @@ wscanf(const wchar_t * __restrict fmt, ...) return (r); } +int +wscanf_l(locale_t locale, const wchar_t * __restrict fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vfwscanf_l(stdin, locale, fmt, ap); + va_end(ap); + + return (r); +} |