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