[BACK]Return to catopen.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / nls

File: [cvs.NetBSD.org] / src / lib / libc / nls / catopen.c (download)

Revision 1.25.6.1, Thu Jan 15 03:24:08 2009 UTC (15 years, 3 months ago) by snj
Branch: netbsd-5
CVS Tags: netbsd-5-2-RELEASE, netbsd-5-2-RC1, netbsd-5-2-3-RELEASE, netbsd-5-2-2-RELEASE, netbsd-5-2-1-RELEASE, netbsd-5-2, netbsd-5-1-RELEASE, netbsd-5-1-RC4, netbsd-5-1-RC3, netbsd-5-1-RC2, netbsd-5-1-RC1, netbsd-5-1-5-RELEASE, netbsd-5-1-4-RELEASE, netbsd-5-1-3-RELEASE, netbsd-5-1-2-RELEASE, netbsd-5-1-1-RELEASE, netbsd-5-1, netbsd-5-0-RELEASE, netbsd-5-0-RC4, netbsd-5-0-RC3, netbsd-5-0-RC2, netbsd-5-0-RC1, netbsd-5-0-2-RELEASE, netbsd-5-0-1-RELEASE, netbsd-5-0, matt-nb5-pq3-base, matt-nb5-pq3, matt-nb5-mips64-u2-k2-k4-k7-k8-k9, matt-nb5-mips64-u1-k1-k5, matt-nb5-mips64-premerge-20101231, matt-nb5-mips64-premerge-20091211, matt-nb5-mips64-k15, matt-nb5-mips64, matt-nb4-mips64-k7-u2a-k9b
Changes since 1.25: +14 -12 lines

Pull up following revision(s) (requested by tnozaki in ticket #222):
	distrib/sets/lists/base/mi: revision 1.788
	distrib/utils/libhack/Makefile.inc: revision 1.23
	distrib/utils/libhack/Makefile: revision 1.22
	etc/mtree/NetBSD.dist: revision 1.387
	include/locale.h: revision 1.15
	lib/libc/citrus/Makefile.inc: revision 1.6
	lib/libc/citrus/citrus_aliasname_local.h: revision 1.1
	lib/libc/citrus/citrus_bcs.h: revision 1.5
	lib/libc/citrus/citrus_bcs_strtol.c: revision 1.1
	lib/libc/citrus/citrus_bcs_strtoul.c: revision 1.1
	lib/libc/citrus/citrus_csmapper.c: revision 1.9
	lib/libc/citrus/citrus_fix_grouping.h: revision 1.1
	lib/libc/citrus/citrus_lc_ctype.c: revision 1.1
	lib/libc/citrus/citrus_lc_messages.c: revision 1.1
	lib/libc/citrus/citrus_lc_messages.h: revision 1.1
	lib/libc/citrus/citrus_lc_monetary.c: revision 1.1
	lib/libc/citrus/citrus_lc_monetary.h: revision 1.1
	lib/libc/citrus/citrus_lc_numeric.c: revision 1.1
	lib/libc/citrus/citrus_lc_numeric.h: revision 1.1
	lib/libc/citrus/citrus_lc_template.h: revision 1.1
	lib/libc/citrus/citrus_lc_template_decl.h: revision 1.1
	lib/libc/citrus/citrus_lc_time.c: revision 1.1
	lib/libc/citrus/citrus_lc_time.h: revision 1.1
	lib/libc/citrus/citrus_module.c: revision 1.8
	lib/libc/citrus/citrus_namespace.h: revision 1.7
	lib/libc/citrus/modules/citrus_euc.c: revision 1.13
	lib/libc/gen/Makefile.inc: revision 1.166
	lib/libc/gen/isctype.c: revision 1.17 via patch
	lib/libc/gen/tolower_.c: revision 1.10
	lib/libc/gen/toupper_.c: revision 1.10
	lib/libc/iconv/Makefile.inc: revision 1.3
	lib/libc/iconv/iconv.c: revision 1.7
	lib/libc/locale/Makefile.inc: revision 1.53
	lib/libc/locale/___runetype_mb.c: file removal
	lib/libc/locale/_wctrans.c: revision 1.7
	lib/libc/locale/_wctrans_local.h: revision 1.3
	lib/libc/locale/_wctype.c: revision 1.1
	lib/libc/locale/_wctype_local.h: revision 1.1
	lib/libc/locale/aliasname.c: revision 1.3
	lib/libc/locale/aliasname_local.h: revision 1.2
	lib/libc/locale/bsdctype.c: revision 1.1
	lib/libc/locale/bsdctype.h: revision 1.1
	lib/libc/locale/ctypeio.c: revision 1.8
	lib/libc/locale/ctypeio.h: revision 1.2
	lib/libc/locale/current_locale.c: revision 1.1
	lib/libc/locale/dummy_lc_collate.c: revision 1.1
	lib/libc/locale/dummy_lc_template.h: revision 1.1
	lib/libc/locale/fix_grouping.c: revision 1.1
	lib/libc/locale/fix_grouping.h: revision 1.1
	lib/libc/locale/generic_lc_all.c: revision 1.1
	lib/libc/locale/generic_lc_template.h: revision 1.1
	lib/libc/locale/generic_lc_template_decl.h: revision 1.1
	lib/libc/locale/global_locale.c: revision 1.1
	lib/libc/locale/iswctype.c: file removal
	lib/libc/locale/iswctype_mb.c: revision 1.1
	lib/libc/locale/iswctype_sb.c: revision 1.6
	lib/libc/locale/lcmessages.c: file removal
	lib/libc/locale/lcmessages.h: file removal
	lib/libc/locale/lcmonetary.c: file removal
	lib/libc/locale/lcmonetary.h: file removal
	lib/libc/locale/lcnumeric.c: file removal
	lib/libc/locale/lcnumeric.h: file removal
	lib/libc/locale/lctime.c: file removal
	lib/libc/locale/lctime.h: file removal
	lib/libc/locale/localeconv.c: revision 1.15
	lib/libc/locale/localeio.c: revision 1.2
	lib/libc/locale/localeio.h: revision 1.2
	lib/libc/locale/localeio_lc_ctype.c: revision 1.1
	lib/libc/locale/localeio_lc_messages.c: revision 1.1
	lib/libc/locale/localeio_lc_monetary.c: revision 1.1
	lib/libc/locale/localeio_lc_numeric.c: revision 1.1
	lib/libc/locale/localeio_lc_time.c: revision 1.1
	lib/libc/locale/multibyte.h: revision 1.4
	lib/libc/locale/multibyte_amd1.c: revision 1.6
	lib/libc/locale/multibyte_c90.c: revision 1.5
	lib/libc/locale/nb_lc_messages_misc.h: revision 1.1
	lib/libc/locale/nb_lc_monetary_misc.h: revision 1.1
	lib/libc/locale/nb_lc_numeric_misc.h: revision 1.1
	lib/libc/locale/nb_lc_template.h: revision 1.1
	lib/libc/locale/nb_lc_template_decl.h: revision 1.1
	lib/libc/locale/nb_lc_time_misc.h: revision 1.1
	lib/libc/locale/nl_langinfo.c: revision 1.12
	lib/libc/locale/rune.c: revision 1.31
	lib/libc/locale/rune.h: revision 1.13
	lib/libc/locale/rune_local.h: revision 1.11
	lib/libc/locale/runeglue.c: revision 1.14
	lib/libc/locale/runetable.c: revision 1.18
	lib/libc/locale/setlocale.c: revision 1.55 via patch
	lib/libc/locale/setlocale_local.h: revision 1.1
	lib/libc/locale/setrunelocale.c: file removal
	lib/libc/nls/Makefile.inc: revision 1.9
	lib/libc/nls/catopen.c: revision 1.26
	lib/libc/string/Makefile.inc: revision 1.68
	lib/libc/string/wcscmp.c: revision 1.6
	lib/libc/string/wcsncmp.c: revision 1.6
	lib/libc/string/wcswidth.c: file removal
	lib/libc/string/wmemcmp.c: revision 1.4
	regress/lib/libc/locale/Makefile: revision 1.4
	regress/lib/libc/locale/ctype1/Makefile: revision 1.4
	regress/lib/libc/locale/ctype1/en_US.UTF-8.exp.uue: revision 1.2
	regress/lib/libc/locale/ctype1/ja_JP.ISO-2022-JP.exp.uue: revision 1.1
	regress/lib/libc/locale/ctype1/ja_JP.ISO-2022-JP.in.uue: revision 1.1
	regress/lib/libc/locale/ctype1/ja_JP.ISO2022-JP.exp.uue: file removal
	regress/lib/libc/locale/ctype1/ja_JP.ISO2022-JP.in.uue: file removal
	regress/lib/libc/locale/ctype1/ja_JP.SJIS.exp.uue: revision 1.2
	regress/lib/libc/locale/ctype1/ja_JP.eucJP.exp.uue: revision 1.2
	regress/lib/libc/locale/ctype2/Makefile: revision 1.5
	regress/lib/libc/locale/ctype2/ja_JP.ISO-2022-JP-2.in.uue: revision 1.1
	regress/lib/libc/locale/ctype2/ja_JP.ISO2022-JP2.in.uue: file removal
	regress/lib/libc/locale/ctype3/Makefile: revision 1.5
	regress/lib/libc/locale/mbtowc/Makefile: revision 1.3
	regress/lib/libc/locale/mbtowc/ja_JP.ISO-2022-JP: revision 1.1
	regress/lib/libc/locale/mbtowc/ja_JP.ISO2022-JP: file removal
	regress/lib/libc/locale/wcstod/wcstod_test.c: revision 1.2
	share/locale/Makefile.locale: revision 1.1
	share/locale/Makefile: revision 1.5
	share/locale/ctype/Makefile: revision 1.28
	share/locale/locale.alias: revision 1.11
	share/locale/messages/Makefile: revision 1.5
	share/locale/messages/en_US.ISO8859-1.src: file removal
	share/locale/messages/en_US.US-ASCII.src: revision 1.1
	share/locale/messages/ja_JP.ISO-2022-JP.src: revision 1.1
	share/locale/messages/ja_JP.ct.src: revision 1.1
	share/locale/messages/sr_ME.ISO8859-2.src: revision 1.1
	share/locale/messages/sr_ME.ISO8859-5.src: revision 1.1
	share/locale/messages/sr_YU.ISO8859-2.src: file removal
	share/locale/messages/sr_YU.ISO8859-5.src: file removal
	share/locale/messages/sr_YU.UTF-8.src: file removal
	share/locale/messages/zh_CN.GB18030.src: file removal
	share/locale/messages/zh_TW.eucTW.src: revision 1.1
	share/locale/monetary/Makefile: revision 1.5
	share/locale/monetary/af_ZA.ISO8859-1.src: revision 1.2
	share/locale/monetary/am_ET.UTF-8.src: revision 1.2
	share/locale/monetary/be_BY.CP1131.src: file removal
	share/locale/monetary/be_BY.CP1251.src: revision 1.2
	share/locale/monetary/be_BY.ISO8859-5.src: revision 1.2
	share/locale/monetary/be_BY.UTF-8.src: revision 1.2
	share/locale/monetary/bg_BG.CP1251.src: revision 1.2
	share/locale/monetary/bg_BG.UTF-8.src: revision 1.2
	share/locale/monetary/ca_ES.ISO8859-1.src: revision 1.2
	share/locale/monetary/cs_CZ.ISO8859-2.src: revision 1.2
	share/locale/monetary/cs_CZ.UTF-8.src: revision 1.2
	share/locale/monetary/da_DK.ISO8859-1.src: revision 1.2
	share/locale/monetary/de_AT.ISO8859-1.src: revision 1.2
	share/locale/monetary/de_CH.ISO8859-1.src: revision 1.2
	share/locale/monetary/de_DE.ISO8859-1.src: revision 1.2
	share/locale/monetary/el_GR.ISO8859-7.src: revision 1.2
	share/locale/monetary/en_AU.ISO8859-1.src: revision 1.2
	share/locale/monetary/en_CA.ISO8859-1.src: revision 1.2
	share/locale/monetary/en_GB.ISO8859-1.src: revision 1.2
	share/locale/monetary/en_GB.UTF-8.src: revision 1.2
	share/locale/monetary/en_IE.UTF-8.src: revision 1.2
	share/locale/monetary/en_NZ.ISO8859-1.src: revision 1.2
	share/locale/monetary/en_US.ISO8859-1.src: revision 1.2
	share/locale/monetary/en_US.US-ASCII.src: revision 1.1
	share/locale/monetary/es_ES.ISO8859-1.src: revision 1.2
	share/locale/monetary/et_EE.ISO8859-15.src: revision 1.2
	share/locale/monetary/fi_FI.ISO8859-1.src: revision 1.2
	share/locale/monetary/fr_BE.ISO8859-1.src: revision 1.2
	share/locale/monetary/fr_CA.ISO8859-1.src: revision 1.2
	share/locale/monetary/fr_FR.ISO8859-1.src: revision 1.2
	share/locale/monetary/he_IL.UTF-8.src: revision 1.2
	share/locale/monetary/hi_IN.ISCII-DEV.src: revision 1.2
	share/locale/monetary/hr_HR.ISO8859-2.src: revision 1.2
	share/locale/monetary/hu_HU.ISO8859-2.src: revision 1.2
	share/locale/monetary/hy_AM.ARMSCII-8.src: revision 1.2
	share/locale/monetary/hy_AM.UTF-8.src: revision 1.2
	share/locale/monetary/is_IS.ISO8859-1.src: revision 1.2
	share/locale/monetary/it_IT.ISO8859-1.src: revision 1.2
	share/locale/monetary/ja_JP.ISO-2022-JP.src: revision 1.1
	share/locale/monetary/ja_JP.UTF-8.src: revision 1.2
	share/locale/monetary/ja_JP.eucJP.src: revision 1.2
	share/locale/monetary/kk_KZ.PT154.src: revision 1.2
	share/locale/monetary/kk_KZ.UTF-8.src: revision 1.2
	share/locale/monetary/ko_KR.UTF-8.src: revision 1.2
	share/locale/monetary/ko_KR.eucKR.src: revision 1.2
	share/locale/monetary/lt_LT.ISO8859-13.src: revision 1.2
	share/locale/monetary/mn_MN.UTF-8.src: revision 1.2
	share/locale/monetary/nl_BE.ISO8859-1.src: revision 1.2
	share/locale/monetary/nl_NL.ISO8859-1.src: revision 1.2
	share/locale/monetary/no_NO.ISO8859-1.src: revision 1.2
	share/locale/monetary/pl_PL.ISO8859-2.src: revision 1.2
	share/locale/monetary/pl_PL.UTF-8.src: revision 1.2
	share/locale/monetary/pt_BR.ISO8859-1.src: revision 1.2
	share/locale/monetary/pt_PT.ISO8859-1.src: revision 1.2
	share/locale/monetary/ro_RO.ISO8859-2.src: revision 1.2
	share/locale/monetary/ru_RU.CP1251.src: revision 1.2
	share/locale/monetary/ru_RU.CP866.src: revision 1.2
	share/locale/monetary/ru_RU.ISO8859-5.src: revision 1.2
	share/locale/monetary/ru_RU.KOI8-R.src: revision 1.2
	share/locale/monetary/ru_RU.UTF-8.src: revision 1.2
	share/locale/monetary/sk_SK.ISO8859-2.src: revision 1.2
	share/locale/monetary/sl_SI.ISO8859-2.src: revision 1.2
	share/locale/monetary/sr_ME.ISO8859-2.src: revision 1.1
	share/locale/monetary/sr_RS.ISO8859-2.src: revision 1.1
	share/locale/monetary/sr_YU.ISO8859-2.src: revision 1.2
	share/locale/monetary/sr_YU.ISO8859-5.src: revision 1.2
	share/locale/monetary/sr_YU.UTF-8.src: revision 1.2
	share/locale/monetary/sv_SE.ISO8859-1.src: revision 1.2
	share/locale/monetary/tr_TR.ISO8859-9.src: revision 1.2
	share/locale/monetary/uk_UA.CP1251.src: revision 1.2
	share/locale/monetary/uk_UA.ISO8859-5.src: revision 1.2
	share/locale/monetary/uk_UA.KOI8-U.src: revision 1.2
	share/locale/monetary/uk_UA.UTF-8.src: revision 1.2
	share/locale/monetary/zh_CN.GB18030.src: revision 1.2
	share/locale/monetary/zh_CN.UTF-8.src: revision 1.2
	share/locale/monetary/zh_CN.eucCN.src: revision 1.2
	share/locale/monetary/zh_HK.Big5hkscs.src: revision 1.1
	share/locale/monetary/zh_HK.UTF-8.src: revision 1.2
	share/locale/monetary/zh_TW.Big5.src: revision 1.2
	share/locale/numeric/Makefile: revision 1.4
	share/locale/numeric/am_ET.UTF-8.src: file removal
	share/locale/numeric/en_US.ISO8859-1.src: file removal
	share/locale/numeric/en_US.US-ASCII.src: revision 1.1
	share/locale/numeric/ja_JP.eucJP.src: file removal
	share/locale/numeric/ko_KR.eucKR.src: file removal
	share/locale/numeric/mn_MN.UTF-8.src: file removal
	share/locale/numeric/sr_ME.ISO8859-2.src: revision 1.1
	share/locale/numeric/sr_YU.ISO8859-2.src: file removal
	share/locale/numeric/sr_YU.ISO8859-5.src: file removal
	share/locale/numeric/zh_CN.eucCN.src: file removal
	share/locale/time/Makefile: revision 1.5
	share/locale/time/en_US.ISO8859-1.src: file removal
	share/locale/time/en_US.US-ASCII.src: revision 1.1
	share/locale/time/ja_JP.ISO-2022-JP.src: revision 1.1
	share/locale/time/ja_JP.ct.src: revision 1.1
	share/locale/time/sr_ME.ISO8859-2.src: revision 1.1
	share/locale/time/sr_ME.ISO8859-5.src: revision 1.1
	share/locale/time/sr_ME.UTF-8.src: revision 1.1
	share/locale/time/sr_YU.ISO8859-2.src: file removal
	share/locale/time/sr_YU.ISO8859-5.src: file removal
	share/locale/time/sr_YU.UTF-8.src: file removal
	share/locale/time/zh_CN.GB18030.src: file removal
	share/locale/time/zh_TW.eucTW.src: revision 1.1
	usr.bin/locale/locale.c: revision 1.6
	usr.bin/mklocale/Makefile: revision 1.12
	usr.bin/mklocale/lex.l: revision 1.14
	usr.bin/mklocale/mklocaledb.c: revision 1.1
	usr.bin/mklocale/yacc.y: revision 1.25
	usr.sbin/chrtbl/Makefile: revision 1.8
	usr.sbin/chrtbl/ctypeio.c: revision 1.1
	usr.sbin/chrtbl/ctypeio.h: revision 1.1
Fixes PR lib/39662, shortcomings in LC_{MONETARY,NUMERIC,TIME,MESSAGES}
db format.
ok'ed by core and releng.
(thanks for agc@, snj@ and i'm sorry for long time patience).
[libc]
- localeio.[ch] and lc*.[ch] in src/lib/libc/locale was replaced by
  new locale-db implementation using citrus_db backend,
  see src/lib/libc/citrus/citrus_lc_*.[ch].
- add citrus_bcs_strtou?l.c. don't use strtou?l locale implementation
  internally, because they're locale-aware function.
- add some stubs for multi-locale issue, see {current,global}_locale.c.
- remove some obsolete file, setrunelocale.c, ___runetype_mb.c.
- remove __savectype() from ctypeio.[ch].
[tools]
- mklocale(1): add new option ``-t'' that generates new style
  LC_{MONETARY,NUMERIC,TIME,MESSAGES} locale-db format.
- chrtbl(1): added ctypeio.[ch] for __savectype().
[locale-db]
- added en_US.US-ASCII locale.
- removed some shareable locale definition file:
    en_US.US-ASCII -> en_US.ISO8859-1, en_US.UTF-8
    zh_CN.eucCN -> zh_CN.GB18030
    and more...see src/share/locale/*/Makefile.
- remove obsoleted locale sr_YU, added new locale sr_ME, sr_RS.
- change locale name ja_JP.ISO2022-JP* -> ja_JP.ISO-2022-JP*
  for X11's locale.alias file alignments.
- fix regression test, wrong wcs?width(3), NAN/INF usage.

i tested release-build following arch:
  i386, amd64, hpc{mips,arm,sh}, sparc64, vax.

citrus_lc_*.[ch] also can read old-plain-text style locale-db.
so that backward compatibility is keeped, but lc*.[ch] can't read
new citrus_db'ed locale-db and localeio.c never check sanity,
so forward compatibility is broken ;-<
old mklocale(1) doesn't know -t option, so you have to rebuild toolchain.

/*	$NetBSD: catopen.c,v 1.25.6.1 2009/01/15 03:24:08 snj Exp $	*/

/*-
 * Copyright (c) 1996 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by J.T. Conklin.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: catopen.c,v 1.25.6.1 2009/01/15 03:24:08 snj Exp $");
#endif /* LIBC_SCCS and not lint */

#define _NLS_PRIVATE

#include "namespace.h"
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include <assert.h>
#include <fcntl.h>
#include <limits.h>
#include <locale.h>
#include <nl_types.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#ifdef HAVE_CITRUS
#include "citrus_namespace.h"
#include "citrus_bcs.h"
#include "citrus_region.h"
#include "citrus_lookup.h"
#include "citrus_aliasname_local.h"
#else
#include "aliasname_local.h"
#endif

#define NLS_ALIAS_DB "/usr/share/nls/nls.alias"

#define NLS_DEFAULT_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L"
#define NLS_DEFAULT_LANG "C"

#ifdef __weak_alias
__weak_alias(catopen, _catopen)
#endif

static nl_catd load_msgcat __P((const char *));

nl_catd
_catopen(name, oflag)
	const char *name;
	int oflag;
{
	char tmppath[PATH_MAX+1];
	const char *nlspath;
	const char *lang, *reallang;
	char *t;
	const char *s, *u;
	nl_catd catd;
	char langbuf[PATH_MAX];

	if (name == NULL || *name == '\0')
		return (nl_catd)-1;

	/* absolute or relative path? */
	if (strchr(name, '/'))
		return load_msgcat(name);

	if (issetugid() || (nlspath = getenv("NLSPATH")) == NULL)
		nlspath = NLS_DEFAULT_PATH;
	if (oflag == NL_CAT_LOCALE) {
		lang = setlocale(LC_MESSAGES, NULL);
	}
	else {
		lang = getenv("LANG");
	}
	if (lang == NULL || strchr(lang, '/'))
		lang = NLS_DEFAULT_LANG;

	reallang = __unaliasname(NLS_ALIAS_DB, lang, langbuf, sizeof(langbuf));
	if (reallang == NULL)
		reallang = lang;

	s = nlspath;
	t = tmppath;
	do {
		while (*s && *s != ':') {
			if (*s == '%') {
				switch (*(++s)) {
				case 'L':	/* locale */
					u = reallang;
					while (*u && t < tmppath + PATH_MAX)
						*t++ = *u++;
					break;
				case 'N':	/* name */
					u = name;
					while (*u && t < tmppath + PATH_MAX)
						*t++ = *u++;
					break;
				case 'l':	/* lang */
				case 't':	/* territory */
				case 'c':	/* codeset */
					break;
				default:
					if (t < tmppath + PATH_MAX)
						*t++ = *s;
				}
			} else {
				if (t < tmppath + PATH_MAX)
					*t++ = *s;
			}
			s++;
		}

		*t = '\0';
		catd = load_msgcat(tmppath);
		if (catd != (nl_catd)-1)
			return catd;

		if (*s)
			s++;
		t = tmppath;
	} while (*s);

	return (nl_catd)-1;
}

static nl_catd
load_msgcat(path)
	const char *path;
{
	struct stat st;
	nl_catd catd;
	void *data;
	int fd;

	_DIAGASSERT(path != NULL);

	if ((fd = open(path, O_RDONLY)) == -1)
		return (nl_catd)-1;

	if (fstat(fd, &st) != 0) {
		close (fd);
		return (nl_catd)-1;
	}

	data = mmap(0, (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd,
	    (off_t)0);
	close (fd);

	if (data == (void *)-1) {
		return (nl_catd)-1;
	}

	if (ntohl((u_int32_t)((struct _nls_cat_hdr *)data)->__magic) !=
	    _NLS_MAGIC) {
		munmap(data, (size_t)st.st_size);
		return (nl_catd)-1;
	}

	if ((catd = malloc(sizeof (*catd))) == 0) {
		munmap(data, (size_t)st.st_size);
		return (nl_catd)-1;
	}

	catd->__data = data;
	catd->__size = (int)st.st_size;
	return catd;
}