--- old/usr/src/lib/libc/port/locale/lmonetary.c	Sat Jul 12 19:07:44 2014
+++ new/usr/src/lib/libc/port/locale/lmonetary.c	Sat Jul 12 19:07:44 2014
@@ -156,10 +156,10 @@
 		char sign = '\0';
 		switch (lmon->p_cs_precedes[0]) {
 		case 0:
-			sign = '-';
+			sign = '+';
 			break;
 		case 1:
-			sign = '+';
+			sign = '-';
 			break;
 		case CHAR_MAX:
 			/*
--- old/usr/src/pkg/manifests/system-test-libctest.mf	Sat Jul 12 19:07:44 2014
+++ new/usr/src/pkg/manifests/system-test-libctest.mf	Sat Jul 12 19:07:44 2014
@@ -29,9 +29,19 @@
 file path=opt/libc-tests/bin/libctest mode=0555
 file path=opt/libc-tests/runfiles/default.run mode=0444
 file path=opt/libc-tests/tests/newlocale_test mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/newlocale_test.amd64 mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/newlocale_test.i386 mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/newlocale_test.sparc mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/newlocale_test.sparcv9 mode=0555
+file path=opt/libc-tests/tests/nl_langinfo_test mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.amd64 mode=0555
+$(i386_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.i386 mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.sparc mode=0555
+$(sparc_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.sparcv9 mode=0555
 license lic_CDDL license=lic_CDDL
 depend fmri=locale/de type=require
 depend fmri=locale/en type=require
+depend fmri=locale/en-extra type=require
 depend fmri=locale/ja type=require
 depend fmri=locale/ru type=require
 depend fmri=system/test/testrunner type=require
--- old/usr/src/test/libc-tests/doc/README	Sat Jul 12 19:07:44 2014
+++ new/usr/src/test/libc-tests/doc/README	Sat Jul 12 19:07:44 2014
@@ -25,7 +25,9 @@
 
 1. What this Unit Test Suite tests
 
-This Unit Test Suite is for testing various libc interfaces.
+This Unit Test Suite is for testing various libc interfaces.  The suite
+will test both 32 and 64 bit versions, provided that your kernel supports
+both.
 
 2. Building and installing this Unit Test Suite
 
@@ -55,12 +57,12 @@
 
 The pre-requisites for running the this Unit Test Suite are:
 	- Any user may perform these tests.
-	- The en_US.UTF-8, ja_JP.UTF-8, de_DE.UTF-8, and ru_RU.UTF-8 locales
-          must be installed.
+	- The en_US.UTF-8, en_GB.ISO8859-15, ja_JP.UTF-8, de_DE.UTF-8, and
+	  ru_RU.UTF-8 locales must be installed.
 
-Once the pre-requisites are satisfied, simply run the ostest script:
+Once the pre-requisites are satisfied, simply run the libctest script:
 
-	test_machine$ /opt/util-tests/bin/libctest
+	test_machine$ /opt/libc-tests/bin/libctest
 
 4. Test results
 
--- old/usr/src/test/libc-tests/runfiles/default.run	Sat Jul 12 19:07:44 2014
+++ new/usr/src/test/libc-tests/runfiles/default.run	Sat Jul 12 19:07:44 2014
@@ -23,3 +23,5 @@
 outputdir = /var/tmp/test_results
 
 [/opt/libc-tests/tests/newlocale_test]
+
+[/opt/libc-tests/tests/nl_langinfo_test]
--- old/usr/src/test/libc-tests/tests/Makefile	Sat Jul 12 19:07:44 2014
+++ new/usr/src/test/libc-tests/tests/Makefile	Sat Jul 12 19:07:44 2014
@@ -14,6 +14,7 @@
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
 #
 
-SUBDIRS = newlocale
+SUBDIRS = newlocale nl_langinfo
 
+include $(SRC)/Makefile.master
 include $(SRC)/test/Makefile.com
--- /dev/null	Sat Jul 12 19:07:44 2014
+++ new/usr/src/test/libc-tests/tests/Makefile.com	Sat Jul 12 19:07:44 2014
@@ -0,0 +1,85 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+include $(SRC)/Makefile.master
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+OBJS32 = $(PROG:%=%.$(MACH).o)
+PROG32 = $(PROG).$(MACH)
+
+$(BUILD64) OBJS64 = $(PROG:%=%.$(MACH64).o)
+$(BUILD64) PROG64= $(PROG).$(MACH64)
+
+SRCS = $(PROG).c
+
+C99MODE = -xc99=%all
+CFLAGS_amd64 = -m64
+CFLAGS_i386 = -m32
+CFLAGS_sparc = -m32
+CFLAGS_sparcv9 = -m64
+LINTFLAGS += -DARCH=\"ARCH\"
+
+ROOTOPTPKG = $(ROOT)/opt/libc-tests
+TESTDIR = $(ROOTOPTPKG)/tests
+
+CMDS = $(PROG32:%=$(TESTDIR)/%) $(PROG64:%=$(TESTDIR)/%) \
+	$(KSHPROG:%=$(TESTDIR)/%) $(ARCHPROG:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+all: $(PROG32) $(PROG64) $(KSHPROG) $(ARCHPROG) $(SUBDIRS)
+
+$(PROG32): $(OBJS32)
+	$(LINK.c) $(CFLAGS_$(MACH)) $(OBJS32) -o $@ $(LDLIBS)
+	$(POST_PROCESS)
+
+$(PROG64): $(OBJS64)
+	$(LINK.c) $(CFLAGS_$(MACH64)) $(OBJS64) -o $@ $(LDLIBS)
+	$(POST_PROCESS)
+
+$(KSHPROG): $(KSHPROG).ksh
+	$(RM) $@
+	$(CP) $(KSHPROG).ksh $(@)
+	$(CHMOD) +x $@
+
+$(ARCHPROG): ../common/run_arch_tests.ksh
+	$(RM) $@
+	$(CP) ../common/run_arch_tests.ksh $(@)
+	$(CHMOD) +x $@
+
+%.$(MACH).o: %.c
+	$(COMPILE.c) -o $@ $(CFLAGS_$(MACH)) -DARCH=\"$(MACH)\" $<
+
+%.$(MACH64).o: %.c
+	$(COMPILE.c) -o $@ $(CFLAGS_$(MACH64)) -DARCH=\"$(MACH64)\" $<
+
+install: $(SUBDIRS) $(CMDS)
+
+lint: lint_SRCS
+
+clobber: clean
+	-$(RM) $(PROG32) $(PROG64) $(KSHPROG) $(ARCHPROG)
+
+clean:
+	-$(RM) $(OBJS32) $(OBJS64)
+
+$(CMDS): $(TESTDIR) $(PROG32) $(PROG64) $(KSHPROG) $(ARCHPROG)
+
+$(TESTDIR):
+	$(INS.dir)
+
+$(TESTDIR)/%: %
+	$(INS.file)
--- /dev/null	Sat Jul 12 19:07:44 2014
+++ new/usr/src/test/libc-tests/tests/common/run_arch_tests.ksh	Sat Jul 12 19:07:45 2014
@@ -0,0 +1,65 @@
+#!/usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+# First we set $dir to dirname $0, and $prog to basename $0 .ksh,
+# using efficient ksh builtins.
+case $0 in
+*/*)	
+	dir=${0%/*}
+	prog=${0##*/}
+	;;
+*)
+	dir=.
+	prog=${0}
+	;;
+esac
+prog=${prog%.ksh}
+
+for a in $* 
+do
+	if [[ $a == "-d" ]]
+	then
+		debug=yes
+	fi
+done
+
+# We look for architecture specific versions of the program,
+# searching in several candidate directories.  We run each one as
+# we find it.
+for f in $(/usr/bin/isainfo)
+do
+	found=
+	[[ -n $debug ]] && print "Checking for arch $f:"
+	for p in \
+		${dir}/${prog}.${f} \
+		${dir}/${f}/${prog}.${f} \
+		${dir}/${f}/${prog}
+	do
+		[[ -n $found ]] && continue
+		[[ -n $debug ]] && print -n "     $p"
+		if [[ -f $p ]]; then
+			[[ -n $debug ]] && print " FOUND"
+			[[ -n $debug ]] && print "Executing $p $*"
+			found=yes
+			$p $* || exit 1
+		else
+			[[ -n $debug ]] && print
+		fi
+	done
+	[[ -z $found ]] && [[ -n $debug ]] && print "NOT PRESENT"
+done
+exit 0
--- old/usr/src/test/libc-tests/tests/newlocale/Makefile	Sat Jul 12 19:07:45 2014
+++ new/usr/src/test/libc-tests/tests/newlocale/Makefile	Sat Jul 12 19:07:45 2014
@@ -10,48 +10,12 @@
 #
 
 #
-# Copyright (c) 2012 by Delphix. All rights reserved.
 # Copyright 2014 Garrett D'Amore <garrett@damore.org>
 #
 
-include $(SRC)/cmd/Makefile.cmd
-include $(SRC)/test/Makefile.com
+include $(SRC)/Makefile.master
 
 PROG = newlocale_test
-OBJS = $(PROG:%=%.o)
-SRCS = $(OBJS:%.o=%.c)
+ARCHPROG = newlocale_test
 
-C99MODE = -xc99=%all
-
-ROOTOPTPKG = $(ROOT)/opt/libc-tests
-TESTDIR = $(ROOTOPTPKG)/tests
-
-CMDS = $(PROG:%=$(TESTDIR)/%)
-$(CMDS) := FILEMODE = 0555
-
-all: $(PROG)
-
-$(PROG): $(OBJS)
-	$(LINK.c) $(OBJS) -o $@ $(LDLIBS)
-	$(POST_PROCESS)
-
-%.o: ../%.c
-	$(COMPILE.c) $<
-
-install: all $(CMDS)
-
-lint: lint_SRCS
-
-clobber: clean
-	-$(RM) $(PROG)
-
-clean:
-	-$(RM) $(OBJS)
-
-$(CMDS): $(TESTDIR) $(PROG)
-
-$(TESTDIR):
-	$(INS.dir)
-
-$(TESTDIR)/%: %
-	$(INS.file)
+include ../Makefile.com
--- old/usr/src/test/libc-tests/tests/newlocale/newlocale_test.c	Sat Jul 12 19:07:45 2014
+++ new/usr/src/test/libc-tests/tests/newlocale/newlocale_test.c	Sat Jul 12 19:07:45 2014
@@ -58,7 +58,7 @@
 {
 	va_list args;
 
-	(void) printf("TEST STARTING %s: ", testName);
+	(void) printf("TEST STARTING %s (%s): ", testName, ARCH);
 
 	va_start(args, format);
 	(void) vprintf(format, args);
@@ -71,11 +71,12 @@
 {
 	va_list args;
 
-	(void) printf("TEST FAILED %s: ", testName);
+	(void) printf("TEST FAILED %s (%s): ", testName, ARCH);
 
 	va_start(args, format);
 	(void) vprintf(format, args);
 	va_end(args);
+	(void) printf("\n");
 
 	(void) exit(-1);
 }
@@ -83,12 +84,12 @@
 static void
 test_passed(const char *testName)
 {
-	(void) printf("TEST PASS: %s\n", testName);
+	(void) printf("TEST PASS: %s (%s)\n", testName, ARCH);
 	(void) fflush(stdout);
 }
 
 void *
-testlocale_thr(void *ptr)
+testlocale_thr_one(void *ptr)
 {
 	locale_t	cloc, loc;
 	struct lconv	*lc;
@@ -156,15 +157,15 @@
 
 
 void
-testlocale(void)
+test_newlocale_threaded(void)
 {
-	char		*tname = "newlocale/uselocale";
+	char		*tname = "newlocale_threaded";
 	pthread_t	tid[NUMTHR];
 
 	test_start(tname, "running %d threads %d iterations\n", NUMTHR, NUMITR);
 
 	for (int i = 0; i < NUMTHR; i++) {
-		(void) pthread_create(&tid[i], NULL, testlocale_thr, tname);
+		(void) pthread_create(&tid[i], NULL, testlocale_thr_one, tname);
 	}
 
 	for (int i = 0; i < NUMTHR; i++) {
@@ -173,6 +174,102 @@
 	test_passed(tname);
 }
 
+void
+test_newlocale_negative(void)
+{
+	
+	locale_t loc, bad;
+	char *day;
+	char *tname = "newlocale_negative";
+
+	test_start(tname, "verify proper failure handling\n");
+	loc = newlocale(LC_ALL_MASK, "de_DE.UTF-8", NULL);
+	if (loc == NULL) {
+		test_failed(tname, "cannot set de_DE.UTF-8");
+	}
+	day = nl_langinfo_l(DAY_1, loc);
+	if (strcmp(day, "Sonntag") != 0) {
+		test_failed(tname, "incorrect Sonntag != %s", day);
+	}
+
+	bad = newlocale(LC_ALL_MASK, "cn_US.BIZRRE", loc);
+	if (bad != NULL) {
+		test_failed(tname, "passed setting bogus locale");
+	}
+	day = nl_langinfo_l(DAY_1, loc);
+	if (strcmp(day, "Sonntag") != 0) {
+		test_failed(tname, "incorrect Sonntag != %s", day);
+	}
+	test_passed(tname);
+}
+
+void
+test_newlocale_categories(void)
+{
+	locale_t loc;
+	char *day, *cur, *yes;
+	char *tname = "newlocale_categories";
+
+	test_start(tname, "verify different category behavior\n");
+
+	loc = NULL;
+	loc = newlocale(LC_TIME_MASK, "de_DE.UTF-8", loc);
+	loc = newlocale(LC_MESSAGES_MASK, "ru_RU.UTF-8", loc);
+	loc = newlocale(LC_MONETARY_MASK, "en_US.UTF-8", loc);
+
+	if (loc == NULL) {
+		test_failed(tname, "failed to set locale");
+	}
+
+	day = nl_langinfo_l(DAY_1, loc);
+	if ((day == NULL) || (strcmp(day, "Sonntag") != 0)) {
+		test_failed(tname, "day1 mismatch %s != %s", day, "Sonntag");
+	}
+	yes = nl_langinfo_l(YESSTR, loc);
+	if ((yes == NULL) || (strcmp(yes, "да") != 0)) {
+		test_failed(tname, "currency mismatch");
+	}
+	cur = nl_langinfo_l(CRNCYSTR, loc);
+	if ((cur == NULL) || (strcmp(cur, "-$") != 0)) {
+		test_failed(tname, "currency mismatch [%s] != [%s]", cur, "-$");
+	}
+
+	test_passed(tname);
+}
+
+void
+test_newlocale_composite(void)
+{
+	locale_t loc;
+	char *day, *cur, *yes;
+	char *tname = "newlocale_composite";
+
+	test_start(tname, "verify composite locale behavior\n");
+
+	/* order: CTYPE/NUMERIC/TIME/COLLATE/MONETARY/MESSAGES */
+	loc = newlocale(LC_ALL_MASK,
+	    "C/C/de_DE.UTF-8/C/en_US.UTF-8/ru_RU.UTF-8", NULL);
+
+	if (loc == NULL) {
+		test_failed(tname, "failed to set composite locale");
+	}
+
+	day = nl_langinfo_l(DAY_1, loc);
+	if ((day == NULL) || (strcmp(day, "Sonntag") != 0)) {
+		test_failed(tname, "day1 mismatch %s != %s", day, "Sonntag");
+	}
+	yes = nl_langinfo_l(YESSTR, loc);
+	if ((yes == NULL) || (strcmp(yes, "да") != 0)) {
+		test_failed(tname, "currency mismatch");
+	}
+	cur = nl_langinfo_l(CRNCYSTR, loc);
+	if ((cur == NULL) || (strcmp(cur, "-$") != 0)) {
+		test_failed(tname, "currency mismatch [%s] != [%s]", cur, "-$");
+	}
+
+	test_passed(tname);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -189,7 +286,10 @@
 		}
 	}
 
-	testlocale();
+	test_newlocale_threaded();
+	test_newlocale_negative();
+	test_newlocale_categories();
+	test_newlocale_composite();
 
 	exit(0);
 }
--- /dev/null	Sat Jul 12 19:07:45 2014
+++ new/usr/src/test/libc-tests/tests/nl_langinfo/Makefile	Sat Jul 12 19:07:45 2014
@@ -0,0 +1,21 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2014 Garrett D'Amore <garrett@damore.org>
+#
+
+include $(SRC)/Makefile.master
+
+PROG = nl_langinfo_test
+ARCHPROG = nl_langinfo_test
+
+include ../Makefile.com
--- /dev/null	Sat Jul 12 19:07:45 2014
+++ new/usr/src/test/libc-tests/tests/nl_langinfo/nl_langinfo_test.c	Sat Jul 12 19:07:45 2014
@@ -0,0 +1,319 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ */
+
+/*
+ * This program tests that newlocale and uselocale work properly in
+ * multi-threaded programs.  In order for it to work, it requires that
+ * some additional locales be installed.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <libintl.h>
+#include <langinfo.h>
+#include <nl_types.h>
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+
+int debug = 0;
+int force = 0;
+
+/*
+ * Note that on some platforms, different symbols are used.  For example,
+ * MacOS Mavericks uses "Eu" for Euro symbol, instead of €.  If the locale
+ * data changes, then this program will need to update to reflect that.
+ *
+ * Note also that this file is easiest edited with a UTF-8 capable editor,
+ * as there are embedded UTF-8 symbols in some of the strings.
+ */
+struct langinfo_test {
+	nl_item		param;
+	const char	*value;
+};
+
+struct langinfo_test C_data[] = {
+	{ CODESET,	"646" },
+	{ D_T_FMT,	"%a %b %e %H:%M:%S %Y" },
+	{ D_FMT,	"%m/%d/%y" },
+	{ T_FMT,	"%H:%M:%S" },
+	{ T_FMT_AMPM,	"%I:%M:%S %p" },
+	{ AM_STR,	"AM" },
+	{ PM_STR,	"PM" },
+	{ ERA,		"" },
+	{ ERA_D_FMT,	"" },
+	{ ERA_D_T_FMT,	"" },
+	{ ERA_T_FMT,	"" },
+	{ DAY_1,	"Sunday" },
+	{ DAY_7,	"Saturday" },
+	{ ABDAY_1,	"Sun" },
+	{ ABDAY_7,	"Sat" },
+	{ MON_1,	"January" },
+	{ MON_12,	"December" },
+	{ ABMON_1,	"Jan" },
+	{ ABMON_12,	"Dec" },
+	{ RADIXCHAR,	"." },
+	{ THOUSEP,	"" },
+	{ YESSTR,	"yes" },
+	{ NOSTR,	"no" },
+	{ YESEXPR,	"^[yY]" },
+	{ NOEXPR,	"^[nN]" },
+	{ CRNCYSTR,	"" },
+	{ -1,		NULL }
+};
+
+struct langinfo_test en_us_utf8_data[] = {
+	{ CODESET,	"UTF-8" },
+	{ D_T_FMT,	"%B %e, %Y %I:%M:%S %p %Z" },
+	{ D_FMT,	"%m/%e/%y" },
+	{ T_FMT,	"%I:%M:%S %p" },
+	{ T_FMT_AMPM,	"%I:%M:%S %p" },
+	{ AM_STR,	"AM" },
+	{ PM_STR,	"PM" },
+	{ ERA,		"" },
+	{ ERA_D_FMT,	"" },
+	{ ERA_D_T_FMT,	"" },
+	{ ERA_T_FMT,	"" },
+	{ DAY_1,	"Sunday" },
+	{ DAY_7,	"Saturday" },
+	{ ABDAY_1,	"Sun" },
+	{ ABDAY_7,	"Sat" },
+	{ MON_1,	"January" },
+	{ MON_12,	"December" },
+	{ ABMON_1,	"Jan" },
+	{ ABMON_12,	"Dec" },
+	{ RADIXCHAR,	"." },
+	{ THOUSEP,	"," },
+	{ YESSTR,	"yes" },
+	{ NOSTR,	"no" },
+	{ YESEXPR,	"^(([yY]([eE][sS])?))" },
+	{ NOEXPR,	"^(([nN]([oO])?))" },
+	{ CRNCYSTR,	"-$" },
+	{ -1,		NULL }
+};
+
+struct langinfo_test en_gb_latin15_data[] = {
+	{ CODESET,	"ISO8859-15" },
+	{ D_T_FMT,	"%e %B %Y %H:%M:%S %Z" },
+	{ D_FMT,	"%d/%m/%Y" },
+	{ T_FMT,	"%H:%M:%S" },
+	{ T_FMT_AMPM,	"%I:%M:%S %p" },
+	{ AM_STR,	"AM" },
+	{ PM_STR,	"PM" },
+	{ ERA,		"" },
+	{ ERA_D_FMT,	"" },
+	{ ERA_D_T_FMT,	"" },
+	{ ERA_T_FMT,	"" },
+	{ DAY_1,	"Sunday" },
+	{ DAY_7,	"Saturday" },
+	{ ABDAY_1,	"Sun" },
+	{ ABDAY_7,	"Sat" },
+	{ MON_1,	"January" },
+	{ MON_12,	"December" },
+	{ ABMON_1,	"Jan" },
+	{ ABMON_12,	"Dec" },
+	{ RADIXCHAR,	"." },
+	{ THOUSEP,	"," },
+	{ YESSTR,	"yes" },
+	{ NOSTR,	"no" },
+	{ YESEXPR,	"^(([yY]([eE][sS])?))" },
+	{ NOEXPR,	"^(([nN]([oO])?))" },
+	{ CRNCYSTR,	"-\243" },
+	{ -1,		NULL }
+};
+
+struct langinfo_test ru_ru_utf8_data[] = {
+	{ CODESET,	"UTF-8" },
+	{ D_T_FMT,	"%e %B %Y г. %H:%M:%S %Z"},
+	{ D_FMT,	"%d.%m.%y" },
+	{ T_FMT,	"%H:%M:%S" },
+	{ T_FMT_AMPM,	"%I:%M:%S %p" },
+	{ AM_STR,	"до полудня" },
+	{ PM_STR,	"после полудня" },
+	{ ERA,		"" },
+	{ ERA_D_FMT,	"" },
+	{ ERA_D_T_FMT,	"" },
+	{ ERA_T_FMT,	"" },
+	{ DAY_1,	"воскресенье" },
+	{ DAY_7,	"суббота" },
+	{ ABDAY_1,	"вс" },
+	{ ABDAY_7,	"сб" },
+	{ MON_1,	"января" },
+	{ MON_12,	"декабря" },
+	{ ABMON_1,	"янв" },
+	{ ABMON_12,	"дек" },
+	{ RADIXCHAR,	"," },
+	{ THOUSEP,	" " },
+	{ YESSTR,	"да" },
+	{ NOSTR,	"нет" },
+	{ YESEXPR,	"^(([дД]([аА])?)|([yY]([eE][sS])?))" },
+	{ NOEXPR,	"^(([нН]([еЕ][тТ])?)|([nN]([oO])?))" },
+	{ CRNCYSTR,	"+руб." },
+	{ -1,		NULL }
+};
+
+struct {
+	const char *locale;
+	struct langinfo_test *loctest;
+} locales[] =  {
+	{ "C",			C_data },
+	{ "en_US.UTF-8",	en_us_utf8_data },
+	{ "en_GB.ISO8859-15",	en_gb_latin15_data },
+	{ "ru_RU.UTF-8",	ru_ru_utf8_data },
+	{ NULL, 		NULL }
+};
+
+static void
+test_start(const char *testName, const char *format, ...)
+{
+	va_list args;
+
+	(void) printf("TEST STARTING %s (%s): ", testName, ARCH);
+
+	va_start(args, format);
+	(void) vprintf(format, args);
+	va_end(args);
+	(void) fflush(stdout);
+}
+
+static void
+test_failed(const char *testName, const char *format, ...)
+{
+	va_list args;
+
+	(void) printf("TEST FAILED %s (%s): ", testName, ARCH);
+
+	va_start(args, format);
+	(void) vprintf(format, args);
+	va_end(args);
+	(void) printf("\n");
+
+	if (!force)
+		(void) exit(-1);
+}
+
+static void
+test_passed(const char *testName)
+{
+	(void) printf("TEST PASS: %s (%s)\n", testName, ARCH);
+	(void) fflush(stdout);
+}
+
+void
+test_nl_langinfo_1(const char *locale, struct langinfo_test *test)
+{
+	char 	tname[128];
+	char 	*v;
+
+	(void) snprintf(tname, sizeof (tname), "nl_langinfo (locale %s)",
+	    locale);
+	test_start(tname, "\n");
+
+	v = setlocale(LC_ALL, locale);
+	if (v == NULL) {
+		test_failed(tname, "setlocale failed: %s", strerror(errno));
+	}
+	if (strcmp(v, locale) != 0) {
+		test_failed(tname, "setlocale returned %s instead of %s",
+		    v, locale);
+	}
+
+	for (int i = 0; test[i].value != NULL; i++) {
+		v = nl_langinfo(test[i].param);
+		if (debug)
+			(void) printf("%d: expect [%s], got [%s]\n",
+			    test[i].param, test[i].value, v);
+		if (strcmp(v, test[i].value) != 0) {
+			test_failed(tname,
+			    "param %d wrong, expected [%s], got [%s]",
+			    test[i].param, test[i].value, v);
+		}
+	}
+	test_passed(tname);
+}
+
+void
+test_nl_langinfo_l(const char *locale, struct langinfo_test *test)
+{
+	char 		tname[128];
+	char 		*v;
+	locale_t	loc;
+
+	(void) snprintf(tname, sizeof (tname), "nl_langinfo_l (locale %s)",
+	    locale);
+	test_start(tname, "\n");
+
+	v = setlocale(LC_ALL, "C");
+	if (v == NULL) {
+		test_failed(tname, "setlocale failed: %s", strerror(errno));
+	}
+	if (strcmp(v, "C") != 0) {
+		test_failed(tname, "setlocale returned %s instead of %s",
+		    v, "C");
+	}
+
+	loc = newlocale(LC_ALL_MASK, locale, NULL);
+	if (loc == NULL) {
+		test_failed(tname, "newlocale failed: %s", strerror(errno));
+	}
+	
+	for (int i = 0; test[i].value != NULL; i++) {
+		v = nl_langinfo_l(test[i].param, loc);
+		if (debug)
+			(void) printf("%d: expect [%s], got [%s]\n",
+			    test[i].param, test[i].value, v);
+		if (strcmp(v, test[i].value) != 0) {
+			test_failed(tname,
+			    "param %d wrong, expected [%s], got [%s]",
+			    test[i].param, test[i].value, v);
+		}
+	}
+	test_passed(tname);
+}
+void
+test_nl_langinfo(void)
+{
+	for (int i = 0; locales[i].locale != NULL; i++) {
+		test_nl_langinfo_1(locales[i].locale, locales[i].loctest);
+		test_nl_langinfo_l(locales[i].locale, locales[i].loctest);
+	}
+	
+}
+
+int
+main(int argc, char **argv)
+{
+	int optc;
+
+	while ((optc = getopt(argc, argv, "df")) != EOF) {
+		switch (optc) {
+		case 'd':
+			debug++;
+			break;
+		case 'f':
+			force++;
+			break;
+		default:
+			(void) fprintf(stderr, "Usage: %s [-d]\n", argv[0]);
+			exit(1);
+		}
+	}
+
+	test_nl_langinfo();
+
+	exit(0);
+}
