1 1.29 riastrad /* $NetBSD: isctype.c,v 1.29 2025/09/15 00:11:54 riastradh Exp $ */ 2 1.13 cgd 3 1.17 tnozaki /*- 4 1.17 tnozaki * Copyright (c)2008 Citrus Project, 5 1.12 cgd * All rights reserved. 6 1.12 cgd * 7 1.12 cgd * Redistribution and use in source and binary forms, with or without 8 1.12 cgd * modification, are permitted provided that the following conditions 9 1.12 cgd * are met: 10 1.12 cgd * 1. Redistributions of source code must retain the above copyright 11 1.12 cgd * notice, this list of conditions and the following disclaimer. 12 1.12 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.12 cgd * notice, this list of conditions and the following disclaimer in the 14 1.12 cgd * documentation and/or other materials provided with the distribution. 15 1.12 cgd * 16 1.17 tnozaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.12 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.12 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.17 tnozaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.12 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.12 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.12 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.12 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.12 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.12 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.12 cgd * SUCH DAMAGE. 27 1.12 cgd */ 28 1.12 cgd 29 1.14 christos #include <sys/cdefs.h> 30 1.12 cgd #if defined(LIBC_SCCS) && !defined(lint) 31 1.29 riastrad __RCSID("$NetBSD: isctype.c,v 1.29 2025/09/15 00:11:54 riastradh Exp $"); 32 1.12 cgd #endif /* LIBC_SCCS and not lint */ 33 1.12 cgd 34 1.17 tnozaki #include "namespace.h" 35 1.17 tnozaki #include <sys/types.h> 36 1.20 tnozaki #include <sys/ctype_bits.h> 37 1.20 tnozaki #define _CTYPE_NOINLINE 38 1.12 cgd #include <ctype.h> 39 1.17 tnozaki #include <langinfo.h> 40 1.17 tnozaki #define __SETLOCALE_SOURCE__ 41 1.17 tnozaki #include <locale.h> 42 1.17 tnozaki #include <stdio.h> 43 1.27 riastrad #include <stdlib.h> 44 1.27 riastrad #include <string.h> 45 1.27 riastrad #include <unistd.h> 46 1.27 riastrad 47 1.17 tnozaki #if EOF != -1 48 1.17 tnozaki #error "EOF != -1" 49 1.17 tnozaki #endif 50 1.17 tnozaki 51 1.29 riastrad #include "ctype_guard.h" 52 1.25 joerg #include "runetype_local.h" 53 1.17 tnozaki #include "setlocale_local.h" 54 1.17 tnozaki 55 1.25 joerg #define _RUNE_LOCALE(loc) \ 56 1.26 riastrad ((_RuneLocale *)((loc)->part_impl[LC_CTYPE])) 57 1.12 cgd 58 1.29 riastrad static int __noinline 59 1.27 riastrad ctype_nasaldemon(const char *func, int c) 60 1.27 riastrad { 61 1.27 riastrad char buf[128]; 62 1.27 riastrad 63 1.27 riastrad snprintf_ss(buf, sizeof(buf), "ctype(3) %s: invalid input: %d\n", func, 64 1.27 riastrad c); 65 1.27 riastrad (void)write(STDERR_FILENO, buf, strlen(buf)); 66 1.29 riastrad if (allow_ctype_abuse()) 67 1.29 riastrad return -1; 68 1.27 riastrad abort(); 69 1.27 riastrad } 70 1.27 riastrad 71 1.29 riastrad #define CTYPE_CHECK(c) do \ 72 1.29 riastrad { \ 73 1.29 riastrad if (__predict_false(((c) != EOF && (c) < 0) || (c) > UCHAR_MAX)) \ 74 1.29 riastrad return ctype_nasaldemon(__func__, c); \ 75 1.29 riastrad } while (0) 76 1.27 riastrad 77 1.17 tnozaki #define _ISCTYPE_FUNC(name, bit) \ 78 1.17 tnozaki int \ 79 1.17 tnozaki is##name(int c) \ 80 1.17 tnozaki { \ 81 1.27 riastrad CTYPE_CHECK(c); \ 82 1.25 joerg return (int)_ctype_tab_[c + 1] & (bit); \ 83 1.23 joerg } \ 84 1.23 joerg int \ 85 1.23 joerg is##name ## _l(int c, locale_t loc) \ 86 1.23 joerg { \ 87 1.27 riastrad CTYPE_CHECK(c); \ 88 1.25 joerg return (int)((_RUNE_LOCALE(loc)->rl_ctype_tab[c + 1]) & (bit)); \ 89 1.17 tnozaki } 90 1.17 tnozaki 91 1.22 joerg _ISCTYPE_FUNC(alnum, (_CTYPE_A|_CTYPE_D)) 92 1.22 joerg _ISCTYPE_FUNC(alpha, _CTYPE_A) 93 1.22 joerg _ISCTYPE_FUNC(blank, _CTYPE_BL) 94 1.21 joerg _ISCTYPE_FUNC(cntrl, _CTYPE_C ) 95 1.22 joerg _ISCTYPE_FUNC(digit, _CTYPE_D) 96 1.22 joerg _ISCTYPE_FUNC(graph, _CTYPE_G) 97 1.21 joerg _ISCTYPE_FUNC(lower, _CTYPE_L ) 98 1.22 joerg _ISCTYPE_FUNC(print, _CTYPE_R) 99 1.21 joerg _ISCTYPE_FUNC(punct, _CTYPE_P ) 100 1.21 joerg _ISCTYPE_FUNC(space, _CTYPE_S ) 101 1.21 joerg _ISCTYPE_FUNC(upper, _CTYPE_U ) 102 1.22 joerg _ISCTYPE_FUNC(xdigit, _CTYPE_X) 103 1.12 cgd 104 1.12 cgd int 105 1.17 tnozaki toupper(int c) 106 1.12 cgd { 107 1.27 riastrad CTYPE_CHECK(c); 108 1.25 joerg return (int)_toupper_tab_[c + 1]; 109 1.12 cgd } 110 1.12 cgd 111 1.12 cgd int 112 1.23 joerg toupper_l(int c, locale_t loc) 113 1.23 joerg { 114 1.27 riastrad CTYPE_CHECK(c); 115 1.25 joerg return (int)(_RUNE_LOCALE(loc)->rl_toupper_tab[c + 1]); 116 1.23 joerg } 117 1.23 joerg 118 1.23 joerg int 119 1.17 tnozaki tolower(int c) 120 1.12 cgd { 121 1.27 riastrad CTYPE_CHECK(c); 122 1.25 joerg return (int)_tolower_tab_[c + 1]; 123 1.12 cgd } 124 1.12 cgd 125 1.12 cgd int 126 1.23 joerg tolower_l(int c, locale_t loc) 127 1.23 joerg { 128 1.27 riastrad CTYPE_CHECK(c); 129 1.25 joerg return (int)(_RUNE_LOCALE(loc)->rl_tolower_tab[c + 1]); 130 1.23 joerg } 131 1.23 joerg 132 1.23 joerg int 133 1.17 tnozaki _toupper(int c) 134 1.12 cgd { 135 1.12 cgd return (c - 'a' + 'A'); 136 1.12 cgd } 137 1.12 cgd 138 1.12 cgd int 139 1.17 tnozaki _tolower(int c) 140 1.12 cgd { 141 1.12 cgd return (c - 'A' + 'a'); 142 1.12 cgd } 143