Home | History | Annotate | Line # | Download | only in locale
newlocale.c revision 1.3.20.1
      1  1.3.20.1  martin /* $NetBSD: newlocale.c,v 1.3.20.1 2023/05/02 17:26:34 martin Exp $ */
      2       1.1   joerg 
      3       1.1   joerg /*-
      4       1.1   joerg  * Copyright (c)2008, 2011 Citrus Project,
      5       1.1   joerg  * All rights reserved.
      6       1.1   joerg  *
      7       1.1   joerg  * Redistribution and use in source and binary forms, with or without
      8       1.1   joerg  * modification, are permitted provided that the following conditions
      9       1.1   joerg  * are met:
     10       1.1   joerg  * 1. Redistributions of source code must retain the above copyright
     11       1.1   joerg  *    notice, this list of conditions and the following disclaimer.
     12       1.1   joerg  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1   joerg  *    notice, this list of conditions and the following disclaimer in the
     14       1.1   joerg  *    documentation and/or other materials provided with the distribution.
     15       1.1   joerg  *
     16       1.1   joerg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17       1.1   joerg  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18       1.1   joerg  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19       1.1   joerg  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20       1.1   joerg  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21       1.1   joerg  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22       1.1   joerg  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23       1.1   joerg  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24       1.1   joerg  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25       1.1   joerg  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26       1.1   joerg  * SUCH DAMAGE.
     27       1.1   joerg  */
     28       1.1   joerg 
     29       1.1   joerg #include <sys/cdefs.h>
     30  1.3.20.1  martin __RCSID("$NetBSD: newlocale.c,v 1.3.20.1 2023/05/02 17:26:34 martin Exp $");
     31       1.1   joerg 
     32       1.1   joerg #include "namespace.h"
     33       1.1   joerg #include <assert.h>
     34       1.1   joerg #include <errno.h>
     35       1.1   joerg #include <locale.h>
     36       1.1   joerg #include <stdlib.h>
     37       1.1   joerg #include <string.h>
     38       1.1   joerg 
     39       1.1   joerg #include "setlocale_local.h"
     40       1.1   joerg 
     41       1.1   joerg __weak_alias(newlocale, _newlocale)
     42       1.1   joerg 
     43       1.1   joerg locale_t
     44       1.1   joerg newlocale(int mask, const char *name, locale_t src)
     45       1.1   joerg {
     46       1.1   joerg 	struct _locale *dst;
     47       1.1   joerg 	char head[_LOCALENAME_LEN_MAX * (_LC_LAST - 1)], *tail;
     48       1.1   joerg 	const char *tokens[_LC_LAST - 1];
     49       1.1   joerg 	_locale_set_t l;
     50       1.1   joerg 	int i, howmany, categories[_LC_LAST - 1];
     51       1.1   joerg 
     52       1.1   joerg 	if (name == NULL)
     53       1.1   joerg 		name = _C_LOCALE;
     54       1.1   joerg 	dst = malloc(sizeof(*dst));
     55       1.1   joerg 	if (dst == NULL)
     56       1.1   joerg 		return (locale_t)NULL;
     57       1.1   joerg 	if (src == NULL)
     58       1.2   joerg 		src = _current_locale();
     59       1.1   joerg 	memcpy(dst, src, sizeof(*src));
     60  1.3.20.1  martin 	if (strlcpy(&head[0], name, sizeof(head)) >= sizeof(head)) {
     61  1.3.20.1  martin 		free(dst);
     62  1.3.20.1  martin 		return (locale_t)NULL;
     63  1.3.20.1  martin 	}
     64       1.1   joerg 	tokens[0] = (const char *)&head[0];
     65       1.1   joerg 	tail = strchr(tokens[0], '/');
     66       1.1   joerg 	if (tail == NULL) {
     67       1.1   joerg 		for (i = 1; i < _LC_LAST; ++i) {
     68       1.1   joerg 			if (mask & (1 << i)) {
     69       1.1   joerg 				l = _find_category(i);
     70       1.1   joerg 				_DIAGASSERT(l != NULL);
     71       1.1   joerg 				(*l)(tokens[0], dst);
     72       1.1   joerg 			}
     73       1.1   joerg 		}
     74       1.1   joerg 	} else {
     75       1.1   joerg 		*tail++ = '\0';
     76       1.1   joerg 		howmany = 0;
     77       1.1   joerg 		for (i = 1; i < _LC_LAST; ++i) {
     78       1.1   joerg 			if (mask & (1 << i))
     79       1.1   joerg 				categories[howmany++] = i;
     80       1.1   joerg 		}
     81       1.1   joerg 		if (howmany-- > 0) {
     82       1.1   joerg 			for (i = 1; i < howmany; ++i) {
     83  1.3.20.1  martin 				*tail++ = '\0';
     84       1.1   joerg 				tokens[i] = (const char *)tail;
     85       1.1   joerg 				tail = strchr(tokens[i], '/');
     86       1.1   joerg 				if (tail == NULL) {
     87       1.1   joerg 					free(dst);
     88       1.1   joerg 					return NULL;
     89       1.1   joerg 				}
     90       1.1   joerg 			}
     91  1.3.20.1  martin 			*tail++ = '\0';
     92       1.1   joerg 			tokens[howmany] = tail;
     93       1.1   joerg 			tail = strchr(tokens[howmany], '/');
     94       1.1   joerg 			if (tail != NULL) {
     95       1.1   joerg 				free(dst);
     96       1.1   joerg 				return NULL;
     97       1.1   joerg 			}
     98       1.1   joerg 			for (i = 0; i <= howmany; ++i) {
     99       1.1   joerg 				l = _find_category(categories[i]);
    100       1.1   joerg 				_DIAGASSERT(l != NULL);
    101       1.1   joerg 				(*l)(tokens[i], dst);
    102       1.1   joerg 			}
    103       1.1   joerg 		}
    104       1.1   joerg 	}
    105       1.3   joerg 	if (_setlocale_cache(dst, NULL)) {
    106       1.3   joerg 		free(dst);
    107       1.3   joerg 		return NULL;
    108       1.3   joerg 	}
    109       1.1   joerg 	return (locale_t)dst;
    110       1.1   joerg }
    111