1/*	$OpenBSD: iswctype_l.c,v 1.3 2024/02/04 12:46:01 jca Exp $ */
2/*	$NetBSD: iswctype.c,v 1.15 2005/02/09 21:35:46 kleink Exp $ */
3
4/*
5 * Copyright (c) 1989 The Regents of the University of California.
6 * All rights reserved.
7 * (c) UNIX System Laboratories, Inc.
8 * All or some portions of this file are derived from material licensed
9 * to the University of California by American Telephone and Telegraph
10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11 * the permission of UNIX System Laboratories, Inc.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#include <ctype.h>
39#include <errno.h>
40#include <locale.h>
41#include <string.h>
42#include <wchar.h>
43#include <wctype.h>
44
45#include "rune.h"
46#include "runetype.h"
47#include "rune_local.h"
48#include "_wctrans_local.h"
49
50static _RuneLocale	*__runelocale(locale_t);
51static int		 __isctype_wl(wint_t, _RuneType, locale_t);
52
53/*
54 * For all these functions, POSIX says that behaviour is undefined
55 * for LC_GLOBAL_LOCALE and for invalid locale arguments.
56 * The choice made here is to use the C locale in that case.
57 */
58static _RuneLocale *
59__runelocale(locale_t locale)
60{
61	_RuneLocale	*rl;
62
63	rl = NULL;
64	if (locale == _LOCALE_UTF8)
65		rl = _Utf8RuneLocale;
66	if (rl == NULL)
67		rl = &_DefaultRuneLocale;
68	return rl;
69}
70
71static int
72__isctype_wl(wint_t c, _RuneType f, locale_t locale)
73{
74	_RuneLocale	*rl;
75	_RuneType	 rt;
76
77	rl = __runelocale(locale);
78	rt = _RUNE_ISCACHED(c) ? rl->rl_runetype[c] : ___runetype_mb(c, rl);
79	return (rt & f) != 0;
80}
81
82int
83iswalnum_l(wint_t c, locale_t locale)
84{
85	return __isctype_wl(c, _RUNETYPE_A|_RUNETYPE_D, locale);
86}
87
88int
89iswalpha_l(wint_t c, locale_t locale)
90{
91	return __isctype_wl(c, _RUNETYPE_A, locale);
92}
93
94int
95iswblank_l(wint_t c, locale_t locale)
96{
97	return __isctype_wl(c, _RUNETYPE_B, locale);
98}
99
100int
101iswcntrl_l(wint_t c, locale_t locale)
102{
103	return __isctype_wl(c, _RUNETYPE_C, locale);
104}
105
106int
107iswdigit_l(wint_t c, locale_t locale)
108{
109	return __isctype_wl(c, _RUNETYPE_D, locale);
110}
111
112int
113iswgraph_l(wint_t c, locale_t locale)
114{
115	return __isctype_wl(c, _RUNETYPE_G, locale);
116}
117
118int
119iswlower_l(wint_t c, locale_t locale)
120{
121	return __isctype_wl(c, _RUNETYPE_L, locale);
122}
123
124int
125iswprint_l(wint_t c, locale_t locale)
126{
127	return __isctype_wl(c, _RUNETYPE_R, locale);
128}
129
130int
131iswpunct_l(wint_t c, locale_t locale)
132{
133	return __isctype_wl(c, _RUNETYPE_P, locale);
134}
135
136int
137iswspace_l(wint_t c, locale_t locale)
138{
139	return __isctype_wl(c, _RUNETYPE_S, locale);
140}
141
142int
143iswupper_l(wint_t c, locale_t locale)
144{
145	return __isctype_wl(c, _RUNETYPE_U, locale);
146}
147
148int
149iswxdigit_l(wint_t c, locale_t locale)
150{
151	return __isctype_wl(c, _RUNETYPE_X, locale);
152}
153
154wint_t
155towupper_l(wint_t c, locale_t locale)
156{
157	return _towctrans(c, _wctrans_upper(__runelocale(locale)));
158}
159
160wint_t
161towlower_l(wint_t c, locale_t locale)
162{
163	return _towctrans(c, _wctrans_lower(__runelocale(locale)));
164}
165DEF_WEAK(towlower_l);
166
167wctrans_t
168wctrans_l(const char *charclass, locale_t locale)
169{
170	_RuneLocale	*rl;
171	int		 i;
172
173	rl = __runelocale(locale);
174	if (rl->rl_wctrans[_WCTRANS_INDEX_LOWER].te_name == NULL)
175		_wctrans_init(rl);
176
177	for (i = 0; i < _WCTRANS_NINDEXES; i++)
178		if (strcmp(rl->rl_wctrans[i].te_name, charclass) == 0)
179			return &rl->rl_wctrans[i];
180
181	return NULL;
182}
183
184/*
185 * POSIX says that the behaviour is unspecified if the LC_CTYPE in
186 * the locale argument does not match what was used to get desc.
187 * The choice made here is to simply ignore the locale argument
188 * and rely on the desc argument only.
189 */
190wint_t
191towctrans_l(wint_t c, wctrans_t desc,
192    locale_t locale __attribute__((__unused__)))
193{
194	return towctrans(c, desc);
195}
196
197int
198iswctype_l(wint_t c, wctype_t charclass, locale_t locale)
199{
200	if (charclass == (wctype_t)0)
201		return 0;  /* Required by SUSv3. */
202
203	return __isctype_wl(c, ((_WCTypeEntry *)charclass)->te_mask, locale);
204}
205