fgetwc.c raw

   1  #include "stdio_impl.h"
   2  #include "locale_impl.h"
   3  #include <wchar.h>
   4  #include <errno.h>
   5  
   6  static wint_t __fgetwc_unlocked_internal(FILE *f)
   7  {
   8  	wchar_t wc;
   9  	int c;
  10  	size_t l;
  11  
  12  	/* Convert character from buffer if possible */
  13  	if (f->rpos != f->rend) {
  14  		l = mbtowc(&wc, (void *)f->rpos, f->rend - f->rpos);
  15  		if (l+1 >= 1) {
  16  			f->rpos += l + !l; /* l==0 means 1 byte, null */
  17  			return wc;
  18  		}
  19  	}
  20  
  21  	/* Convert character byte-by-byte */
  22  	mbstate_t st = { 0 };
  23  	unsigned char b;
  24  	int first = 1;
  25  	do {
  26  		b = c = getc_unlocked(f);
  27  		if (c < 0) {
  28  			if (!first) {
  29  				f->flags |= F_ERR;
  30  				errno = EILSEQ;
  31  			}
  32  			return WEOF;
  33  		}
  34  		l = mbrtowc(&wc, (void *)&b, 1, &st);
  35  		if (l == -1) {
  36  			if (!first) {
  37  				f->flags |= F_ERR;
  38  				ungetc(b, f);
  39  			}
  40  			return WEOF;
  41  		}
  42  		first = 0;
  43  	} while (l == -2);
  44  
  45  	return wc;
  46  }
  47  
  48  wint_t __fgetwc_unlocked(FILE *f)
  49  {
  50  	locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
  51  	if (f->mode <= 0) fwide(f, 1);
  52  	*ploc = f->locale;
  53  	wchar_t wc = __fgetwc_unlocked_internal(f);
  54  	*ploc = loc;
  55  	return wc;
  56  }
  57  
  58  wint_t fgetwc(FILE *f)
  59  {
  60  	wint_t c;
  61  	FLOCK(f);
  62  	c = __fgetwc_unlocked(f);
  63  	FUNLOCK(f);
  64  	return c;
  65  }
  66  
  67  weak_alias(__fgetwc_unlocked, fgetwc_unlocked);
  68  weak_alias(__fgetwc_unlocked, getwc_unlocked);
  69