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 statep = _getmbstate(fp); 63 if (statep == NULL) { 64 fp->_flag = _IOERR; 65 errno = EBADF; 66 return (WEOF); 67 } 68 do { 69 char x = (char)c; 70 nconv = lct->lc_mbrtowc(&wc, &x, 1, statep, B_FALSE); 71 if (nconv == (size_t)-1) { 72 break; 73 } else if (nconv == (size_t)-2) { 74 /* Incompletely decoded, consume another char */ 75 continue; 76 } else if (nconv == 0) { 77 /* 78 * Assume that the only valid representation of 79 * the null wide character is a single null byte. 80 */ 81 return (L'\0'); 82 } else { 83 return (wc); 84 } 85 } while ((c = GETC(fp)) != EOF); 86 87 /* 88 * If we got here it means we got truncated in a character, or 89 * the character did not decode properly. Note that in the case 90 * of a botched decoding, we don't UNGETC the bad bytes. Should 91 * we? 92 */ 93 fp->_flag |= _IOERR; 94 errno = EILSEQ; 95 return (WEOF); 96 } 97 98 wint_t 99 _fgetwc_unlocked(FILE *fp) 100 { 101 return (_fgetwc_unlocked_l(fp, uselocale(NULL))); 102 } 103 104 105 /* 106 * MT safe version 107 */ 108 #undef getwc 109 #pragma weak getwc = fgetwc 110 wint_t 111 fgetwc(FILE *fp) 112 { 113 wint_t r; 114 rmutex_t *l; 115 locale_t loc = uselocale(NULL); 116 117 FLOCKFILE(l, fp); 118 r = _fgetwc_unlocked_l(fp, loc); 119 FUNLOCKFILE(l); 120 121 return (r); 122 } 123 124 /* 125 * XPG5 version. 126 */ 127 #undef __getwc_xpg5 128 #pragma weak __getwc_xpg5 = __fgetwc_xpg5 129 wint_t 130 __fgetwc_xpg5(FILE *fp) 131 { 132 wint_t r; 133 rmutex_t *l; 134 locale_t loc = uselocale(NULL); 135 136 FLOCKFILE(l, fp); 137 if (GET_NO_MODE(fp)) 138 _setorientation(fp, _WC_MODE); 139 r = _fgetwc_unlocked_l(fp, loc); 140 FUNLOCKFILE(l); 141 142 return (r); 143 } 144 145 #pragma weak getwc_l = fgetwc_l 146 wint_t 147 fgetwc_l(FILE *fp, locale_t loc) 148 { 149 wint_t r; 150 rmutex_t *l; 151 FLOCKFILE(l, fp); 152 if (GET_NO_MODE(fp)) 153 _setorientation(fp, _WC_MODE); 154 r = _fgetwc_unlocked_l(fp, loc); 155 FUNLOCKFILE(l); 156 157 return (r); 158 } 159