diff options
| -rw-r--r-- | src/internal/stdio_impl.h | 1 | ||||
| -rw-r--r-- | src/locale/iconv.c | 6 | ||||
| -rw-r--r-- | src/stdio/fgetwc.c | 15 | ||||
| -rw-r--r-- | src/stdio/fputwc.c | 5 | ||||
| -rw-r--r-- | src/stdio/fputws.c | 5 | ||||
| -rw-r--r-- | src/stdio/fwide.c | 11 | ||||
| -rw-r--r-- | src/stdio/ungetwc.c | 5 | 
7 files changed, 40 insertions, 8 deletions
| diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h index e1325fe1..72c55192 100644 --- a/src/internal/stdio_impl.h +++ b/src/internal/stdio_impl.h @@ -47,6 +47,7 @@ struct _IO_FILE {  	unsigned char *shend;  	off_t shlim, shcnt;  	FILE *prev_locked, *next_locked; +	struct __locale_struct *locale;  };  size_t __stdio_read(FILE *, unsigned char *, size_t); diff --git a/src/locale/iconv.c b/src/locale/iconv.c index e6121aea..1eeea94e 100644 --- a/src/locale/iconv.c +++ b/src/locale/iconv.c @@ -5,6 +5,7 @@  #include <stdlib.h>  #include <limits.h>  #include <stdint.h> +#include "locale_impl.h"  #define UTF_32BE    0300  #define UTF_16LE    0301 @@ -165,9 +166,12 @@ size_t iconv(iconv_t cd0, char **restrict in, size_t *restrict inb, char **restr  	int err;  	unsigned char type = map[-1];  	unsigned char totype = tomap[-1]; +	locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;  	if (!in || !*in || !*inb) return 0; +	*ploc = UTF8_LOCALE; +  	for (; *inb; *in+=l, *inb-=l) {  		c = *(unsigned char *)*in;  		l = 1; @@ -431,6 +435,7 @@ size_t iconv(iconv_t cd0, char **restrict in, size_t *restrict inb, char **restr  			break;  		}  	} +	*ploc = loc;  	return x;  ilseq:  	err = EILSEQ; @@ -445,5 +450,6 @@ starved:  	x = -1;  end:  	errno = err; +	*ploc = loc;  	return x;  } diff --git a/src/stdio/fgetwc.c b/src/stdio/fgetwc.c index b261b44f..e455cfec 100644 --- a/src/stdio/fgetwc.c +++ b/src/stdio/fgetwc.c @@ -1,8 +1,9 @@  #include "stdio_impl.h" +#include "locale_impl.h"  #include <wchar.h>  #include <errno.h> -wint_t __fgetwc_unlocked(FILE *f) +static wint_t __fgetwc_unlocked_internal(FILE *f)  {  	mbstate_t st = { 0 };  	wchar_t wc; @@ -10,8 +11,6 @@ wint_t __fgetwc_unlocked(FILE *f)  	unsigned char b;  	size_t l; -	if (f->mode <= 0) fwide(f, 1); -  	/* Convert character from buffer if possible */  	if (f->rpos < f->rend) {  		l = mbrtowc(&wc, (void *)f->rpos, f->rend - f->rpos, &st); @@ -39,6 +38,16 @@ wint_t __fgetwc_unlocked(FILE *f)  	return wc;  } +wint_t __fgetwc_unlocked(FILE *f) +{ +	locale_t *ploc = &CURRENT_LOCALE, loc = *ploc; +	if (f->mode <= 0) fwide(f, 1); +	*ploc = f->locale; +	wchar_t wc = __fgetwc_unlocked_internal(f); +	*ploc = loc; +	return wc; +} +  wint_t fgetwc(FILE *f)  {  	wint_t c; diff --git a/src/stdio/fputwc.c b/src/stdio/fputwc.c index 1bf165bf..789fe9c9 100644 --- a/src/stdio/fputwc.c +++ b/src/stdio/fputwc.c @@ -1,4 +1,5 @@  #include "stdio_impl.h" +#include "locale_impl.h"  #include <wchar.h>  #include <limits.h>  #include <ctype.h> @@ -7,8 +8,10 @@ wint_t __fputwc_unlocked(wchar_t c, FILE *f)  {  	char mbc[MB_LEN_MAX];  	int l; +	locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;  	if (f->mode <= 0) fwide(f, 1); +	*ploc = f->locale;  	if (isascii(c)) {  		c = putc_unlocked(c, f); @@ -20,6 +23,8 @@ wint_t __fputwc_unlocked(wchar_t c, FILE *f)  		l = wctomb(mbc, c);  		if (l < 0 || __fwritex((void *)mbc, l, f) < l) c = WEOF;  	} +	if (c==WEOF) f->flags |= F_ERR; +	*ploc = loc;  	return c;  } diff --git a/src/stdio/fputws.c b/src/stdio/fputws.c index 317d65f1..0ed02f1c 100644 --- a/src/stdio/fputws.c +++ b/src/stdio/fputws.c @@ -1,23 +1,28 @@  #include "stdio_impl.h" +#include "locale_impl.h"  #include <wchar.h>  int fputws(const wchar_t *restrict ws, FILE *restrict f)  {  	unsigned char buf[BUFSIZ];  	size_t l=0; +	locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;  	FLOCK(f);  	fwide(f, 1); +	*ploc = f->locale;  	while (ws && (l = wcsrtombs((void *)buf, (void*)&ws, sizeof buf, 0))+1 > 1)  		if (__fwritex(buf, l, f) < l) {  			FUNLOCK(f); +			*ploc = loc;  			return -1;  		}  	FUNLOCK(f); +	*ploc = loc;  	return l; /* 0 or -1 */  } diff --git a/src/stdio/fwide.c b/src/stdio/fwide.c index 8088e7ad..8410b153 100644 --- a/src/stdio/fwide.c +++ b/src/stdio/fwide.c @@ -1,13 +1,14 @@ -#include <wchar.h>  #include "stdio_impl.h" - -#define SH (8*sizeof(int)-1) -#define NORMALIZE(x) ((x)>>SH | -((-(x))>>SH)) +#include "locale_impl.h"  int fwide(FILE *f, int mode)  {  	FLOCK(f); -	if (!f->mode) f->mode = NORMALIZE(mode); +	if (mode) { +		if (!f->locale) f->locale = MB_CUR_MAX==1 +			? C_LOCALE : UTF8_LOCALE; +		if (!f->mode) f->mode = mode>0 ? 1 : -1; +	}  	mode = f->mode;  	FUNLOCK(f);  	return mode; diff --git a/src/stdio/ungetwc.c b/src/stdio/ungetwc.c index d4c7de39..80d6e203 100644 --- a/src/stdio/ungetwc.c +++ b/src/stdio/ungetwc.c @@ -1,4 +1,5 @@  #include "stdio_impl.h" +#include "locale_impl.h"  #include <wchar.h>  #include <limits.h>  #include <ctype.h> @@ -8,15 +9,18 @@ wint_t ungetwc(wint_t c, FILE *f)  {  	unsigned char mbc[MB_LEN_MAX];  	int l=1; +	locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;  	FLOCK(f);  	if (f->mode <= 0) fwide(f, 1); +	*ploc = f->locale;  	if (!f->rpos) __toread(f);  	if (!f->rpos || f->rpos < f->buf - UNGET + l || c == WEOF ||  	    (!isascii(c) && (l = wctomb((void *)mbc, c)) < 0)) {  		FUNLOCK(f); +		*ploc = loc;  		return WEOF;  	} @@ -26,5 +30,6 @@ wint_t ungetwc(wint_t c, FILE *f)  	f->flags &= ~F_EOF;  	FUNLOCK(f); +	*ploc = loc;  	return c;  } | 
