xref: /openbsd/lib/libc/locale/newlocale.c (revision 274d7c50)
1 /*	$OpenBSD: newlocale.c,v 1.2 2019/03/29 12:34:44 schwarze Exp $ */
2 /*
3  * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <errno.h>
19 #include <locale.h>
20 #include <string.h>
21 
22 #include "rune.h"
23 
24 locale_t
25 newlocale(int mask, const char *locname, locale_t oldloc)
26 {
27 	int	 ic, flag;
28 
29 	/* Invalid input. */
30 	if (locname == NULL || mask & ~LC_ALL_MASK) {
31 		errno = EINVAL;
32 		return _LOCALE_NONE;
33 	}
34 
35 	/* Check the syntax for all selected categories. */
36 	for (ic = flag = 1; ic < _LC_LAST; ic++) {
37 		flag <<= 1;
38 		if (ic != LC_CTYPE && mask & flag &&
39 		    _get_locname(ic, locname) == NULL) {
40 			errno = ENOENT;
41 			return _LOCALE_NONE;
42 		}
43 	}
44 
45 	/* Only character encoding has thread-specific effects. */
46 	if ((mask & LC_CTYPE_MASK) == 0)
47 		return oldloc == _LOCALE_UTF8 ? _LOCALE_UTF8 : _LOCALE_C;
48 
49 	/* The following may initialize UTF-8 for later use. */
50 	if ((locname = _get_locname(LC_CTYPE, locname)) == NULL) {
51 		errno = ENOENT;
52 		return _LOCALE_NONE;
53 	}
54 	return strchr(locname, '.') == NULL ? _LOCALE_C : _LOCALE_UTF8;
55 }
56