Home | History | Annotate | Line # | Download | only in stdio
fgetwc.c revision 1.12
      1  1.12  christos /* $NetBSD: fgetwc.c,v 1.12 2012/03/13 21:13:46 christos Exp $ */
      2   1.1      yamt 
      3   1.1      yamt /*-
      4   1.1      yamt  * Copyright (c)2001 Citrus Project,
      5   1.1      yamt  * All rights reserved.
      6   1.1      yamt  *
      7   1.1      yamt  * Redistribution and use in source and binary forms, with or without
      8   1.1      yamt  * modification, are permitted provided that the following conditions
      9   1.1      yamt  * are met:
     10   1.1      yamt  * 1. Redistributions of source code must retain the above copyright
     11   1.1      yamt  *    notice, this list of conditions and the following disclaimer.
     12   1.1      yamt  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1      yamt  *    notice, this list of conditions and the following disclaimer in the
     14   1.1      yamt  *    documentation and/or other materials provided with the distribution.
     15   1.1      yamt  *
     16   1.1      yamt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17   1.1      yamt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18   1.1      yamt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19   1.1      yamt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20   1.1      yamt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21   1.1      yamt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22   1.1      yamt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23   1.1      yamt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24   1.1      yamt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25   1.1      yamt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26   1.1      yamt  * SUCH DAMAGE.
     27   1.1      yamt  *
     28   1.1      yamt  * $Citrus$
     29   1.1      yamt  */
     30   1.1      yamt 
     31   1.4     lukem #include <sys/cdefs.h>
     32   1.4     lukem #if defined(LIBC_SCCS) && !defined(lint)
     33  1.12  christos __RCSID("$NetBSD: fgetwc.c,v 1.12 2012/03/13 21:13:46 christos Exp $");
     34   1.4     lukem #endif /* LIBC_SCCS and not lint */
     35   1.4     lukem 
     36   1.1      yamt #include <assert.h>
     37   1.1      yamt #include <errno.h>
     38   1.1      yamt #include <stdio.h>
     39   1.1      yamt #include <wchar.h>
     40   1.2   thorpej #include "reentrant.h"
     41   1.1      yamt #include "local.h"
     42   1.1      yamt 
     43   1.1      yamt wint_t
     44   1.3  tshiozak __fgetwc_unlock(FILE *fp)
     45   1.1      yamt {
     46   1.1      yamt 	struct wchar_io_data *wcio;
     47   1.1      yamt 	wchar_t wc;
     48   1.6   tnozaki 	size_t nr;
     49   1.1      yamt 
     50   1.1      yamt 	_DIAGASSERT(fp != NULL);
     51   1.1      yamt 
     52   1.1      yamt 	_SET_ORIENTATION(fp, 1);
     53   1.1      yamt 	wcio = WCIO_GET(fp);
     54   1.6   tnozaki 	_DIAGASSERT(wcio != NULL);
     55   1.1      yamt 
     56   1.1      yamt 	/* if there're ungetwc'ed wchars, use them */
     57   1.6   tnozaki 	if (wcio->wcio_ungetwc_inbuf)
     58   1.6   tnozaki 		return wcio->wcio_ungetwc_buf[--wcio->wcio_ungetwc_inbuf];
     59   1.1      yamt 
     60   1.6   tnozaki 	if (fp->_r <= 0) {
     61   1.6   tnozaki restart:
     62   1.6   tnozaki 		if (__srefill(fp) != 0)
     63   1.6   tnozaki 			return WEOF;
     64   1.1      yamt 	}
     65   1.6   tnozaki 	nr = mbrtowc(&wc, (const char *)fp->_p,
     66  1.11  christos 	    (size_t)fp->_r, &wcio->wcio_mbstate_in);
     67   1.6   tnozaki 	if (nr == (size_t)-1) {
     68   1.6   tnozaki 		fp->_flags |= __SERR;
     69   1.6   tnozaki 		return WEOF;
     70   1.6   tnozaki 	} else if (nr == (size_t)-2) {
     71   1.6   tnozaki 		fp->_p += fp->_r;
     72   1.6   tnozaki 		fp->_r = 0;
     73   1.6   tnozaki 		goto restart;
     74   1.6   tnozaki 	}
     75   1.7   tnozaki 	if (wc == L'\0') {
     76   1.8   tnozaki 		while (*fp->_p != '\0') {
     77   1.8   tnozaki 			++fp->_p;
     78   1.8   tnozaki 			--fp->_r;
     79   1.8   tnozaki 		}
     80   1.8   tnozaki 		nr = 1;
     81   1.7   tnozaki 	}
     82   1.8   tnozaki 	fp->_p += nr;
     83  1.12  christos 	_DIAGASSERT(__type_fit(int, fp->_r - nr));
     84  1.12  christos 	fp->_r -= (int)nr;
     85   1.1      yamt 
     86   1.1      yamt 	return wc;
     87   1.1      yamt }
     88   1.3  tshiozak 
     89   1.3  tshiozak wint_t
     90   1.3  tshiozak fgetwc(FILE *fp)
     91   1.3  tshiozak {
     92   1.3  tshiozak 	wint_t r;
     93   1.3  tshiozak 
     94   1.3  tshiozak 	_DIAGASSERT(fp != NULL);
     95   1.3  tshiozak 
     96   1.3  tshiozak 	FLOCKFILE(fp);
     97   1.3  tshiozak 	r = __fgetwc_unlock(fp);
     98   1.3  tshiozak 	FUNLOCKFILE(fp);
     99   1.3  tshiozak 
    100   1.3  tshiozak 	return (r);
    101   1.3  tshiozak }
    102   1.3  tshiozak 
    103