1 /* 2 * Copyright 2013 Garrett D'Amore <garrett@damore.org> 3 * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 4 * Copyright (c) 2002-2004 Tim J. Robbins. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "lint.h" 30 #include "mse_int.h" 31 #include "file64.h" 32 #include "mtlib.h" 33 #include <errno.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <wchar.h> 37 #include "mblocal.h" 38 #include "stdiom.h" 39 #include "localeimpl.h" 40 #include "lctype.h" 41 42 /* 43 * Non-MT-safe version. 44 */ 45 wint_t 46 _fgetwc_unlocked_l(FILE *fp, locale_t loc) 47 { 48 wchar_t wc; 49 size_t nconv; 50 int c; 51 mbstate_t *statep; 52 const struct lc_ctype *lct; 53 54 if ((c = GETC(fp)) == EOF) 55 return (WEOF); 56 57 lct = loc->ctype; 58 if (lct->lc_max_mblen == 1) { 59 /* Fast path for single-byte encodings. */ 60 return ((wint_t)c); 61 } 62 if ((statep = _getmbstate(fp)) == NULL) { 63 fp->_flag = _IOERR; 64 errno = EBADF; 65 return (WEOF); 66 } 67 do { 68 char x = (char)c; 69 nconv = lct->lc_mbrtowc(&wc, &x, 1, statep); 70 if (nconv == (size_t)-1) { 71 break; 72 } else if (nconv == (size_t)-2) { 73 /* Incompletely decoded, consume another char */ 74 continue; 75 } else if (nconv == 0) { 76 /* 77 * Assume that the only valid representation of 78 * the null wide character is a single null byte. 79 */ 80 return (L'\0'); 81 } else { 82 return (wc); 83 } 84 } while ((c = GETC(fp)) != EOF); 85 86 /* 87 * If we got here it means we got truncated in a character, or 88 * the character did not decode properly. Note that in the case 89 * of a botched decoding, we don't UNGETC the bad bytes. Should 90 * we? 91 */ 92 fp->_flag |= _IOERR; 93 errno = EILSEQ; 94 return (WEOF); 95 } 96 97 wint_t 98 _fgetwc_unlocked(FILE *fp) 99 { 100 return (_fgetwc_unlocked_l(fp, uselocale(NULL))); 101 } 102 103 104 /* 105 * MT safe version 106 */ 107 #undef getwc 108 #pragma weak getwc = fgetwc 109 wint_t 110 fgetwc(FILE *fp) 111 { 112 wint_t r; 113 rmutex_t *l; 114 locale_t loc = uselocale(NULL); 115 116 FLOCKFILE(l, fp); 117 r = _fgetwc_unlocked_l(fp, loc); 118 FUNLOCKFILE(l); 119 120 return (r); 121 } 122 123 /* 124 * XPG5 version. 125 */ 126 #undef __getwc_xpg5 127 #pragma weak __getwc_xpg5 = __fgetwc_xpg5 128 wint_t 129 __fgetwc_xpg5(FILE *fp) 130 { 131 wint_t r; 132 rmutex_t *l; 133 locale_t loc = uselocale(NULL); 134 135 FLOCKFILE(l, fp); 136 if (GET_NO_MODE(fp)) 137 _setorientation(fp, _WC_MODE); 138 r = _fgetwc_unlocked_l(fp, loc); 139 FUNLOCKFILE(l); 140 141 return (r); 142 } 143 144 #pragma weak getwc_l = fgetwc_l 145 wint_t 146 fgetwc_l(FILE *fp, locale_t loc) 147 { 148 wint_t r; 149 rmutex_t *l; 150 FLOCKFILE(l, fp); 151 if (GET_NO_MODE(fp)) 152 _setorientation(fp, _WC_MODE); 153 r = _fgetwc_unlocked_l(fp, loc); 154 FUNLOCKFILE(l); 155 156 return (r); 157 }