xref: /netbsd/lib/libc/locale/generic_lc_all.c (revision f54fea0f)
1*f54fea0fSkamil /* $NetBSD: generic_lc_all.c,v 1.6 2018/01/04 20:57:29 kamil Exp $ */
252ed7b03Stnozaki 
352ed7b03Stnozaki /*-
452ed7b03Stnozaki  * Copyright (c)2008 Citrus Project,
552ed7b03Stnozaki  * All rights reserved.
652ed7b03Stnozaki  *
752ed7b03Stnozaki  * Redistribution and use in source and binary forms, with or without
852ed7b03Stnozaki  * modification, are permitted provided that the following conditions
952ed7b03Stnozaki  * are met:
1052ed7b03Stnozaki  * 1. Redistributions of source code must retain the above copyright
1152ed7b03Stnozaki  *    notice, this list of conditions and the following disclaimer.
1252ed7b03Stnozaki  * 2. Redistributions in binary form must reproduce the above copyright
1352ed7b03Stnozaki  *    notice, this list of conditions and the following disclaimer in the
1452ed7b03Stnozaki  *    documentation and/or other materials provided with the distribution.
1552ed7b03Stnozaki  *
1652ed7b03Stnozaki  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1752ed7b03Stnozaki  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1852ed7b03Stnozaki  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1952ed7b03Stnozaki  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2052ed7b03Stnozaki  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2152ed7b03Stnozaki  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2252ed7b03Stnozaki  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2352ed7b03Stnozaki  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2452ed7b03Stnozaki  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2552ed7b03Stnozaki  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2652ed7b03Stnozaki  * SUCH DAMAGE.
2752ed7b03Stnozaki  */
2852ed7b03Stnozaki 
2952ed7b03Stnozaki #include <sys/cdefs.h>
3052ed7b03Stnozaki #if defined(LIBC_SCCS) && !defined(lint)
31*f54fea0fSkamil __RCSID("$NetBSD: generic_lc_all.c,v 1.6 2018/01/04 20:57:29 kamil Exp $");
3252ed7b03Stnozaki #endif /* LIBC_SCCS and not lint */
3352ed7b03Stnozaki 
34*f54fea0fSkamil #include "namespace.h"
3552ed7b03Stnozaki #include <sys/types.h>
3652ed7b03Stnozaki #include <assert.h>
3752ed7b03Stnozaki #include <langinfo.h>
3852ed7b03Stnozaki #define __SETLOCALE_SOURCE__
3952ed7b03Stnozaki #include <locale.h>
4052ed7b03Stnozaki #include <stdio.h>
4152ed7b03Stnozaki #include <stdlib.h>
4252ed7b03Stnozaki #include <string.h>
4352ed7b03Stnozaki 
4452ed7b03Stnozaki #include "setlocale_local.h"
4552ed7b03Stnozaki 
4652ed7b03Stnozaki /*
4752ed7b03Stnozaki  * macro required by all template headers
4852ed7b03Stnozaki  */
4952ed7b03Stnozaki #define _PREFIX(name)	__CONCAT(_generic_LC_ALL_, name)
5052ed7b03Stnozaki 
5152ed7b03Stnozaki #include "generic_lc_template_decl.h"
5252ed7b03Stnozaki 
5352ed7b03Stnozaki const char *
_generic_LC_ALL_setlocale(const char * __restrict name,struct _locale * __restrict locale)5452ed7b03Stnozaki _generic_LC_ALL_setlocale(const char * __restrict name,
5577239e4dSjoerg     struct _locale * __restrict locale)
5652ed7b03Stnozaki {
577fd2545fStnozaki 	_locale_set_t sl;
5852ed7b03Stnozaki 	char head[_LOCALENAME_LEN_MAX * (_LC_LAST - 1)], *tail;
5952ed7b03Stnozaki 	const char *tokens[_LC_LAST], *s, *t;
606c81c0d8Stnozaki 	int load_locale_success, i, j;
6152ed7b03Stnozaki 
627fd2545fStnozaki 	sl = _find_category(1);
637fd2545fStnozaki 	_DIAGASSERT(sl != NULL);
646c81c0d8Stnozaki 	load_locale_success = 0;
6552ed7b03Stnozaki 	if (name != NULL) {
6652ed7b03Stnozaki 		strlcpy(&head[0], name, sizeof(head));
6752ed7b03Stnozaki 		tokens[1] = &head[0];
6852ed7b03Stnozaki 		tail = strchr(tokens[1], '/');
6952ed7b03Stnozaki 		if (tail == NULL) {
7052ed7b03Stnozaki 			for (i = 2; i < _LC_LAST; ++i)
7152ed7b03Stnozaki 				tokens[i] = tokens[1];
7252ed7b03Stnozaki 		} else {
7352ed7b03Stnozaki 			*tail++ = '\0';
7452ed7b03Stnozaki 			for (i = 2; i < _LC_LAST - 1; ++i) {
7552ed7b03Stnozaki 				tokens[i] = (const char *)tail;
7652ed7b03Stnozaki 				tail = strchr(tokens[i], '/');
7752ed7b03Stnozaki 				if (tail == NULL)
7852ed7b03Stnozaki 					return NULL;
7952ed7b03Stnozaki 				*tail++ = '\0';
8052ed7b03Stnozaki 			}
8152ed7b03Stnozaki 			tokens[_LC_LAST - 1] = (const char *)tail;
8252ed7b03Stnozaki 			tail = strchr(tokens[i], '/');
836c81c0d8Stnozaki 			if (tail != NULL)
8452ed7b03Stnozaki 				return NULL;
8552ed7b03Stnozaki 		}
867fd2545fStnozaki 		if ((*sl)(tokens[1], locale) != NULL)
876c81c0d8Stnozaki 			load_locale_success = 1;
8852ed7b03Stnozaki 	}
897fd2545fStnozaki 	s = (*sl)(NULL, locale);
9052ed7b03Stnozaki 	_DIAGASSERT(s != NULL);
9152ed7b03Stnozaki 	strlcpy(&locale->query[0], s, sizeof(locale->query));
9252ed7b03Stnozaki 	for (i = 2, j = 0; i < _LC_LAST; ++i) {
937fd2545fStnozaki 		sl = _find_category(i);
947fd2545fStnozaki 		_DIAGASSERT(sl != NULL);
956c81c0d8Stnozaki 		if (name != NULL) {
967fd2545fStnozaki 			if ((*sl)(tokens[i], locale) != NULL)
976c81c0d8Stnozaki 				load_locale_success = 1;
986c81c0d8Stnozaki 		}
997fd2545fStnozaki 		t = (*sl)(NULL, locale);
10052ed7b03Stnozaki 		_DIAGASSERT(t != NULL);
10152ed7b03Stnozaki 		if (j == 0) {
10252ed7b03Stnozaki 			if (!strcmp(s, t))
10352ed7b03Stnozaki 				continue;
10452ed7b03Stnozaki 			for (j = 2; j < i; ++j) {
10552ed7b03Stnozaki 				strlcat(&locale->query[0], "/",
10652ed7b03Stnozaki 				    sizeof(locale->query));
10752ed7b03Stnozaki 				strlcat(&locale->query[0], s,
10852ed7b03Stnozaki 				    sizeof(locale->query));
10952ed7b03Stnozaki 			}
11052ed7b03Stnozaki 		}
11152ed7b03Stnozaki 		strlcat(&locale->query[0], "/", sizeof(locale->query));
11252ed7b03Stnozaki 		strlcat(&locale->query[0], t, sizeof(locale->query));
11352ed7b03Stnozaki 	}
1146c81c0d8Stnozaki 	if (name != NULL && !load_locale_success)
1156c81c0d8Stnozaki 		return NULL;
11652ed7b03Stnozaki 	return (const char *)&locale->query[0];
11752ed7b03Stnozaki }
118