summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarmelo Amoroso <carmelo.amoroso@st.com>2008-07-09 15:05:36 +0000
committerCarmelo Amoroso <carmelo.amoroso@st.com>2008-07-09 15:05:36 +0000
commita691312d8794d5516402bb6bb0d3e90c40ba188b (patch)
treedcac242fcad7d24a4f452722de26c56cfaf8c98a
parent56df95fe5d0778352abe09225d6587b88643d135 (diff)
Added several tests for locale support (8 bit and multibyte UTF-8)
Basically all tests have been taken from glibc. For testing multibyte encoding EUC_JP parts have been commented out and added new section for UTF-8 that is the only multibyte codeset currently supported on uCLibc. Some tests are still failing due to unsupported/missing features, other have been fixed. Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com> Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
-rw-r--r--test/locale/Makefile31
-rw-r--r--test/locale/bug-iconv-trans.c68
-rw-r--r--test/locale/bug-usesetlocale.c38
-rw-r--r--test/locale/collate-test.c133
-rw-r--r--test/locale/dump-ctype.c164
-rw-r--r--test/locale/gen-unicode-ctype.c785
-rw-r--r--test/locale/show-ucs-data.c62
-rw-r--r--test/locale/tst-C-locale.c498
-rw-r--r--test/locale/tst-ctype-de_DE.ISO-8859-1.in56
-rw-r--r--test/locale/tst-ctype.c447
-rw-r--r--test/locale/tst-digits.c249
-rw-r--r--test/locale/tst-fmon.c68
-rw-r--r--test/locale/tst-langinfo.c284
-rw-r--r--test/locale/tst-langinfo.input303
-rw-r--r--test/locale/tst-leaks.c18
-rw-r--r--test/locale/tst-mbswcs1.c63
-rw-r--r--test/locale/tst-mbswcs2.c65
-rw-r--r--test/locale/tst-mbswcs3.c76
-rw-r--r--test/locale/tst-mbswcs4.c63
-rw-r--r--test/locale/tst-mbswcs5.c75
-rw-r--r--test/locale/tst-mbswcs6.c74
-rw-r--r--test/locale/tst-numeric.c74
-rw-r--r--test/locale/tst-rpmatch.c37
-rw-r--r--test/locale/tst-setlocale.c25
-rw-r--r--test/locale/tst-sscanf.c56
-rw-r--r--test/locale/tst-strfmon1.c42
-rw-r--r--test/locale/tst-trans.c71
-rw-r--r--test/locale/tst-wctype.c144
-rw-r--r--test/locale/tst-xlocale1.c75
-rw-r--r--test/locale/tst-xlocale2.c64
-rw-r--r--test/locale/tst_nl_langinfo.c296
-rw-r--r--test/locale/xfrm-test.c144
32 files changed, 4648 insertions, 0 deletions
diff --git a/test/locale/Makefile b/test/locale/Makefile
new file mode 100644
index 000000000..0ab07f7aa
--- /dev/null
+++ b/test/locale/Makefile
@@ -0,0 +1,31 @@
+# uClibc locale tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+# tst_mbtowc tst_strcoll tst_strfmon tst_strxfrm \
+
+TESTS := bug-iconv-trans bug-usesetlocale collate-test dump-ctype \
+ gen-unicode-ctype show-ucs-data tst-ctype \
+ tst-digits tst-fmon tst-langinfo tst-leaks tst-mbswcs1 \
+ tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 tst-mbswcs6 \
+ tst_nl_langinfo tst-numeric tst-rpmatch tst-setlocale \
+ tst-sscanf tst-strfmon1 tst-trans tst-wctype tst-xlocale1 \
+ tst-xlocale2 xfrm-test
+
+
+# NOTE: For now disabled some tests that are known not build
+TESTS_DISABLED := tst-ctype tst-fmon tst-leaks tst-rpmatch tst-strfmon1
+
+ifneq ($(UCLIBC_HAS_XLOCALE),y)
+TESTS_DISABLED += bug-usesetlocale tst-xlocale1 tst-xlocale2 xfrm-test tst-C-locale
+endif
+
+include ../Test.mak
+
+DODIFF_rint := 1
+
+EXTRA_CFLAGS := -D__USE_GNU -fno-builtin
+
+OPTS_dump-ctype = C
+OPTS_tst-ctype = < tst-ctype-de_DE.ISO-8859-1.in
+OPTS_tst-langinfo = < tst-langinfo.input
+
+EXTRA_CLEAN := C
diff --git a/test/locale/bug-iconv-trans.c b/test/locale/bug-iconv-trans.c
new file mode 100644
index 000000000..3886247c3
--- /dev/null
+++ b/test/locale/bug-iconv-trans.c
@@ -0,0 +1,68 @@
+#include <iconv.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main (void)
+{
+ iconv_t cd;
+ const char str[] = "ÄäÖöÜüß";
+ const char expected[] = "AEaeOEoeUEuess";
+ char *inptr = (char *) str;
+ size_t inlen = strlen (str) + 1;
+ char outbuf[500];
+ char *outptr = outbuf;
+ size_t outlen = sizeof (outbuf);
+ int result = 0;
+ size_t n;
+
+ if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
+ {
+ puts ("setlocale failed");
+ return 1;
+ }
+
+ cd = iconv_open ("ANSI_X3.4-1968//TRANSLIT", "ISO-8859-1");
+ if (cd == (iconv_t) -1)
+ {
+ puts ("iconv_open failed");
+ return 1;
+ }
+
+ n = iconv (cd, &inptr, &inlen, &outptr, &outlen);
+ if (n != 7)
+ {
+ if (n == (size_t) -1)
+ printf ("iconv() returned error: %m\n");
+ else
+ printf ("iconv() returned %Zd, expected 7\n", n);
+ result = 1;
+ }
+ if (inlen != 0)
+ {
+ puts ("not all input consumed");
+ result = 1;
+ }
+ else if (inptr - str != strlen (str) + 1)
+ {
+ printf ("inptr wrong, advanced by %td\n", inptr - str);
+ result = 1;
+ }
+ if (memcmp (outbuf, expected, sizeof (expected)) != 0)
+ {
+ printf ("result wrong: \"%.*s\", expected: \"%s\"\n",
+ (int) (sizeof (outbuf) - outlen), outbuf, expected);
+ result = 1;
+ }
+ else if (outlen != sizeof (outbuf) - sizeof (expected))
+ {
+ printf ("outlen wrong: %Zd, expected %Zd\n", outlen,
+ sizeof (outbuf) - 15);
+ result = 1;
+ }
+ else
+ printf ("output is \"%s\" which is OK\n", outbuf);
+
+ return result;
+}
diff --git a/test/locale/bug-usesetlocale.c b/test/locale/bug-usesetlocale.c
new file mode 100644
index 000000000..0637067de
--- /dev/null
+++ b/test/locale/bug-usesetlocale.c
@@ -0,0 +1,38 @@
+/* Test case for setlocale vs uselocale (LC_GLOBAL_LOCALE) bug. */
+
+#define _GNU_SOURCE 1
+#include <locale.h>
+#include <stdio.h>
+#include <ctype.h>
+
+static int
+do_test (void)
+{
+ __locale_t loc_new, loc_old;
+
+ int first = !!isalpha(0xE4);
+
+ setlocale (LC_ALL, "de_DE");
+
+ int global_de = !!isalpha(0xE4);
+
+ loc_new = newlocale (1 << LC_ALL, "C", 0);
+ loc_old = uselocale (loc_new);
+
+ int used_c = !!isalpha(0xE4);
+
+ uselocale (loc_old);
+
+ int used_global = !!isalpha(0xE4);
+
+ printf ("started %d, after setlocale %d\n", first, global_de);
+ printf ("after uselocale %d, after LC_GLOBAL_LOCALE %d\n",
+ used_c, used_global);
+
+ freelocale (loc_new);
+ return !(used_c == first && used_global == global_de);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "test-skeleton.c"
diff --git a/test/locale/collate-test.c b/test/locale/collate-test.c
new file mode 100644
index 000000000..e8f43218f
--- /dev/null
+++ b/test/locale/collate-test.c
@@ -0,0 +1,133 @@
+/* Test collation function using real data.
+ Copyright (C) 1997, 1999, 2000, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <ctype.h>
+#include <error.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+struct lines
+{
+ char *key;
+ char *line;
+};
+
+static int xstrcoll (const void *, const void *);
+
+int
+main (int argc, char *argv[])
+{
+ int result = 0;
+ size_t nstrings, nstrings_max;
+ struct lines *strings;
+ char *line = NULL;
+ size_t len = 0;
+ size_t n;
+
+ if (argc < 2)
+ error (1, 0, "usage: %s <random seed>", argv[0]);
+
+ setlocale (LC_ALL, "");
+
+ nstrings_max = 100;
+ nstrings = 0;
+ strings = (struct lines *) malloc (nstrings_max * sizeof (struct lines));
+ if (strings == NULL)
+ {
+ perror (argv[0]);
+ exit (1);
+ }
+
+ while (1)
+ {
+ int l;
+ if (getline (&line, &len, stdin) < 0)
+ break;
+
+ if (nstrings == nstrings_max)
+ {
+ strings = (struct lines *) realloc (strings,
+ (nstrings_max *= 2)
+ * sizeof (*strings));
+ if (strings == NULL)
+ {
+ perror (argv[0]);
+ exit (1);
+ }
+ }
+ strings[nstrings].line = strdup (line);
+ l = strcspn (line, ":(;");
+ while (l > 0 && isspace (line[l - 1]))
+ --l;
+ strings[nstrings].key = strndup (line, l);
+ ++nstrings;
+ }
+ free (line);
+
+ /* First shuffle. */
+ srandom (atoi (argv[1]));
+ for (n = 0; n < 10 * nstrings; ++n)
+ {
+ int r1, r2, r;
+ size_t idx1 = random () % nstrings;
+ size_t idx2 = random () % nstrings;
+ struct lines tmp = strings[idx1];
+ strings[idx1] = strings[idx2];
+ strings[idx2] = tmp;
+
+ /* While we are at it a first little test. */
+ r1 = strcoll (strings[idx1].key, strings[idx2].key);
+ r2 = strcoll (strings[idx2].key, strings[idx1].key);
+ r = r1 * r2;
+
+ if (r > 0 || (r == 0 && r1 != 0) || (r == 0 && r2 != 0))
+ printf ("`%s' and `%s' collate wrong: %d vs. %d\n",
+ strings[idx1].key, strings[idx2].key, r1, r2);
+ }
+
+ /* Now sort. */
+ qsort (strings, nstrings, sizeof (struct lines), xstrcoll);
+
+ /* Print the result. */
+ for (n = 0; n < nstrings; ++n)
+ {
+ fputs (strings[n].line, stdout);
+ free (strings[n].line);
+ free (strings[n].key);
+ }
+ free (strings);
+
+ return result;
+}
+
+
+static int
+xstrcoll (ptr1, ptr2)
+ const void *ptr1;
+ const void *ptr2;
+{
+ const struct lines *l1 = (const struct lines *) ptr1;
+ const struct lines *l2 = (const struct lines *) ptr2;
+
+ return strcoll (l1->key, l2->key);
+}
diff --git a/test/locale/dump-ctype.c b/test/locale/dump-ctype.c
new file mode 100644
index 000000000..a1f24c656
--- /dev/null
+++ b/test/locale/dump-ctype.c
@@ -0,0 +1,164 @@
+/* Dump the character classes and character maps of a locale to a bunch
+ of individual files which can be processed with diff, sed etc.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <haible@clisp.cons.org>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Usage example:
+ $ dump-ctype de_DE.UTF-8
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <wctype.h>
+#include <locale.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+static const char *program_name = "dump-ctype";
+static const char *locale;
+
+static const char *class_names[] =
+ {
+ "alnum", "alpha", "blank", "cntrl", "digit", "graph", "lower",
+ "print", "punct", "space", "upper", "xdigit"
+ };
+
+static const char *map_names[] =
+ {
+ "tolower", "toupper", "totitle"
+ };
+
+static void dump_class (const char *class_name)
+{
+ wctype_t class;
+ FILE *f;
+ unsigned int ch;
+
+ class = wctype (class_name);
+ if (class == (wctype_t) 0)
+ {
+ fprintf (stderr, "%s %s: noexistent class %s\n", program_name,
+ locale, class_name);
+ return;
+ }
+
+ f = fopen (class_name, "w");
+ if (f == NULL)
+ {
+ fprintf (stderr, "%s %s: cannot open file %s/%s\n", program_name,
+ locale, locale, class_name);
+ exit (1);
+ }
+
+ for (ch = 0; ch < 0x10000; ch++)
+ if (iswctype (ch, class))
+ fprintf (f, "0x%04X\n", ch);
+
+ if (ferror (f) || fclose (f))
+ {
+ fprintf (stderr, "%s %s: I/O error on file %s/%s\n", program_name,
+ locale, locale, class_name);
+ exit (1);
+ }
+}
+
+static void dump_map (const char *map_name)
+{
+ wctrans_t map;
+ FILE *f;
+ unsigned int ch;
+
+ map = wctrans (map_name);
+ if (map == (wctrans_t) 0)
+ {
+ fprintf (stderr, "%s %s: noexistent map %s\n", program_name,
+ locale, map_name);
+ return;
+ }
+
+ f = fopen (map_name, "w");
+ if (f == NULL)
+ {
+ fprintf (stderr, "%s %s: cannot open file %s/%s\n", program_name,
+ locale, locale, map_name);
+ exit (1);
+ }
+
+ for (ch = 0; ch < 0x10000; ch++)
+ if (towctrans (ch, map) != ch)
+ fprintf (f, "0x%04X\t0x%04X\n", ch, towctrans (ch, map));
+
+ if (ferror (f) || fclose (f))
+ {
+ fprintf (stderr, "%s %s: I/O error on file %s/%s\n", program_name,
+ locale, locale, map_name);
+ exit (1);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ size_t i;
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage: dump-ctype locale\n");
+ exit (1);
+ }
+ locale = argv[1];
+
+ if (setlocale (LC_ALL, locale) == NULL)
+ {
+ fprintf (stderr, "%s: setlocale cannot switch to locale %s\n",
+ program_name, locale);
+ exit (1);
+ }
+
+ if (mkdir (locale, 0777) < 0)
+ {
+ char buf[100];
+ int save_errno = errno;
+
+ sprintf (buf, "%s: cannot create directory %s", program_name, locale);
+ errno = save_errno;
+ perror (buf);
+ exit (1);
+ }
+
+ if (chdir (locale) < 0)
+ {
+ char buf[100];
+ int save_errno = errno;
+
+ sprintf (buf, "%s: cannot chdir to %s", program_name, locale);
+ errno = save_errno;
+ perror (buf);
+ exit (1);
+ }
+
+ for (i = 0; i < sizeof (class_names) / sizeof (class_names[0]); i++)
+ dump_class (class_names[i]);
+
+ for (i = 0; i < sizeof (map_names) / sizeof (map_names[0]); i++)
+ dump_map (map_names[i]);
+
+ return 0;
+}
diff --git a/test/locale/gen-unicode-ctype.c b/test/locale/gen-unicode-ctype.c
new file mode 100644
index 000000000..849f272ed
--- /dev/null
+++ b/test/locale/gen-unicode-ctype.c
@@ -0,0 +1,785 @@
+/* Generate a Unicode conforming LC_CTYPE category from a UnicodeData file.
+ Copyright (C) 2000-2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <haible@clisp.cons.org>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Usage example:
+ $ gen-unicode /usr/local/share/Unidata/UnicodeData.txt 3.1
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+
+/* This structure represents one line in the UnicodeData.txt file. */
+struct unicode_attribute
+{
+ const char *name; /* Character name */
+ const char *category; /* General category */
+ const char *combining; /* Canonical combining classes */
+ const char *bidi; /* Bidirectional category */
+ const char *decomposition; /* Character decomposition mapping */
+ const char *decdigit; /* Decimal digit value */
+ const char *digit; /* Digit value */
+ const char *numeric; /* Numeric value */
+ int mirrored; /* mirrored */
+ const char *oldname; /* Old Unicode 1.0 name */
+ const char *comment; /* Comment */
+ unsigned int upper; /* Uppercase mapping */
+ unsigned int lower; /* Lowercase mapping */
+ unsigned int title; /* Titlecase mapping */
+};
+
+/* Missing fields are represented with "" for strings, and NONE for
+ characters. */
+#define NONE (~(unsigned int)0)
+
+/* The entire contents of the UnicodeData.txt file. */
+struct unicode_attribute unicode_attributes [0x110000];
+
+/* Stores in unicode_attributes[i] the values from the given fields. */
+static void
+fill_attribute (unsigned int i,
+ const char *field1, const char *field2,
+ const char *field3, const char *field4,
+ const char *field5, const char *field6,
+ const char *field7, const char *field8,
+ const char *field9, const char *field10,
+ const char *field11, const char *field12,
+ const char *field13, const char *field14)
+{
+ struct unicode_attribute * uni;
+
+ if (i >= 0x110000)
+ {
+ fprintf (stderr, "index too large\n");
+ exit (1);
+ }
+ if (strcmp (field2, "Cs") == 0)
+ /* Surrogates are UTF-16 artefacts, not real characters. Ignore them. */
+ return;
+ uni = &unicode_attributes[i];
+ /* Copy the strings. */
+ uni->name = strdup (field1);
+ uni->category = (field2[0] == '\0' ? "" : strdup (field2));
+ uni->combining = (field3[0] == '\0' ? "" : strdup (field3));
+ uni->bidi = (field4[0] == '\0' ? "" : strdup (field4));
+ uni->decomposition = (field5[0] == '\0' ? "" : strdup (field5));
+ uni->decdigit = (field6[0] == '\0' ? "" : strdup (field6));
+ uni->digit = (field7[0] == '\0' ? "" : strdup (field7));
+ uni->numeric = (field8[0] == '\0' ? "" : strdup (field8));
+ uni->mirrored = (field9[0] == 'Y');
+ uni->oldname = (field10[0] == '\0' ? "" : strdup (field10));
+ uni->comment = (field11[0] == '\0' ? "" : strdup (field11));
+ uni->upper = (field12[0] =='\0' ? NONE : strtoul (field12, NULL, 16));
+ uni->lower = (field13[0] =='\0' ? NONE : strtoul (field13, NULL, 16));
+ uni->title = (field14[0] =='\0' ? NONE : strtoul (field14, NULL, 16));
+}
+
+/* Maximum length of a field in the UnicodeData.txt file. */
+#define FIELDLEN 120
+
+/* Reads the next field from STREAM. The buffer BUFFER has size FIELDLEN.
+ Reads up to (but excluding) DELIM.
+ Returns 1 when a field was successfully read, otherwise 0. */
+static int
+getfield (FILE *stream, char *buffer, int delim)
+{
+ int count = 0;
+ int c;
+
+ for (; (c = getc (stream)), (c != EOF && c != delim); )
+ {
+ /* The original unicode.org UnicodeData.txt file happens to have
+ CR/LF line terminators. Silently convert to LF. */
+ if (c == '\r')
+ continue;
+
+ /* Put c into the buffer. */
+ if (++count >= FIELDLEN - 1)
+ {
+ fprintf (stderr, "field too long\n");
+ exit (1);
+ }
+ *buffer++ = c;
+ }
+
+ if (c == EOF)
+ return 0;
+
+ *buffer = '\0';
+ return 1;
+}
+
+/* Stores in unicode_attributes[] the entire contents of the UnicodeData.txt
+ file. */
+static void
+fill_attributes (const char *unicodedata_filename)
+{
+ unsigned int i, j;
+ FILE *stream;
+ char field0[FIELDLEN];
+ char field1[FIELDLEN];
+ char field2[FIELDLEN];
+ char field3[FIELDLEN];
+ char field4[FIELDLEN];
+ char field5[FIELDLEN];
+ char field6[FIELDLEN];
+ char field7[FIELDLEN];
+ char field8[FIELDLEN];
+ char field9[FIELDLEN];
+ char field10[FIELDLEN];
+ char field11[FIELDLEN];
+ char field12[FIELDLEN];
+ char field13[FIELDLEN];
+ char field14[FIELDLEN];
+ int lineno = 0;
+
+ for (i = 0; i < 0x110000; i++)
+ unicode_attributes[i].name = NULL;
+
+ stream = fopen (unicodedata_filename, "r");
+ if (stream == NULL)
+ {
+ fprintf (stderr, "error during fopen of '%s'\n", unicodedata_filename);
+ exit (1);
+ }
+
+ for (;;)
+ {
+ int n;
+
+ lineno++;
+ n = getfield (stream, field0, ';');
+ n += getfield (stream, field1, ';');
+ n += getfield (stream, field2, ';');
+ n += getfield (stream, field3, ';');
+ n += getfield (stream, field4, ';');
+ n += getfield (stream, field5, ';');
+ n += getfield (stream, field6, ';');
+ n += getfield (stream, field7, ';');
+ n += getfield (stream, field8, ';');
+ n += getfield (stream, field9, ';');
+ n += getfield (stream, field10, ';');
+ n += getfield (stream, field11, ';');
+ n += getfield (stream, field12, ';');
+ n += getfield (stream, field13, ';');
+ n += getfield (stream, field14, '\n');
+ if (n == 0)
+ break;
+ if (n != 15)
+ {
+ fprintf (stderr, "short line in'%s':%d\n",
+ unicodedata_filename, lineno);
+ exit (1);
+ }
+ i = strtoul (field0, NULL, 16);
+ if (field1[0] == '<'
+ && strlen (field1) >= 9
+ && !strcmp (field1 + strlen(field1) - 8, ", First>"))
+ {
+ /* Deal with a range. */
+ lineno++;
+ n = getfield (stream, field0, ';');
+ n += getfield (stream, field1, ';');
+ n += getfield (stream, field2, ';');
+ n += getfield (stream, field3, ';');
+ n += getfield (stream, field4, ';');
+ n += getfield (stream, field5, ';');
+ n += getfield (stream, field6, ';');
+ n += getfield (stream, field7, ';');
+ n += getfield (stream, field8, ';');
+ n += getfield (stream, field9, ';');
+ n += getfield (stream, field10, ';');
+ n += getfield (stream, field11, ';');
+ n += getfield (stream, field12, ';');
+ n += getfield (stream, field13, ';');
+ n += getfield (stream, field14, '\n');
+ if (n != 15)
+ {
+ fprintf (stderr, "missing end range in '%s':%d\n",
+ unicodedata_filename, lineno);
+ exit (1);
+ }
+ if (!(field1[0] == '<'
+ && strlen (field1) >= 8
+ && !strcmp (field1 + strlen (field1) - 7, ", Last>")))
+ {
+ fprintf (stderr, "missing end range in '%s':%d\n",
+ unicodedata_filename, lineno);
+ exit (1);
+ }
+ field1[strlen (field1) - 7] = '\0';
+ j = strtoul (field0, NULL, 16);
+ for (; i <= j; i++)
+ fill_attribute (i, field1+1, field2, field3, field4, field5,
+ field6, field7, field8, field9, field10,
+ field11, field12, field13, field14);
+ }
+ else
+ {
+ /* Single character line */
+ fill_attribute (i, field1, field2, field3, field4, field5,
+ field6, field7, field8, field9, field10,
+ field11, field12, field13, field14);
+ }
+ }
+ if (ferror (stream) || fclose (stream))
+ {
+ fprintf (stderr, "error reading from '%s'\n", unicodedata_filename);
+ exit (1);
+ }
+}
+
+/* Character mappings. */
+
+static unsigned int
+to_upper (unsigned int ch)
+{
+ if (unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].upper != NONE)
+ return unicode_attributes[ch].upper;
+ else
+ return ch;
+}
+
+static unsigned int
+to_lower (unsigned int ch)
+{
+ if (unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].lower != NONE)
+ return unicode_attributes[ch].lower;
+ else
+ return ch;
+}
+
+static unsigned int
+to_title (unsigned int ch)
+{
+ if (unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].title != NONE)
+ return unicode_attributes[ch].title;
+ else
+ return ch;
+}
+
+/* Character class properties. */
+
+static bool
+is_upper (unsigned int ch)
+{
+ return (to_lower (ch) != ch);
+}
+
+static bool
+is_lower (unsigned int ch)
+{
+ return (to_upper (ch) != ch)
+ /* <U00DF> is lowercase, but without simple to_upper mapping. */
+ || (ch == 0x00DF);
+}
+
+static bool
+is_alpha (unsigned int ch)
+{
+ return (unicode_attributes[ch].name != NULL
+ && ((unicode_attributes[ch].category[0] == 'L'
+ /* Theppitak Karoonboonyanan <thep@links.nectec.or.th> says
+ <U0E2F>, <U0E46> should belong to is_punct. */
+ && (ch != 0x0E2F) && (ch != 0x0E46))
+ /* Theppitak Karoonboonyanan <thep@links.nectec.or.th> says
+ <U0E31>, <U0E34>..<U0E3A>, <U0E47>..<U0E4E> are is_alpha. */
+ || (ch == 0x0E31)
+ || (ch >= 0x0E34 && ch <= 0x0E3A)
+ || (ch >= 0x0E47 && ch <= 0x0E4E)
+ /* Avoid warning for <U0345>. */
+ || (ch == 0x0345)
+ /* Avoid warnings for <U2160>..<U217F>. */
+ || (unicode_attributes[ch].category[0] == 'N'
+ && unicode_attributes[ch].category[1] == 'l')
+ /* Avoid warnings for <U24B6>..<U24E9>. */
+ || (unicode_attributes[ch].category[0] == 'S'
+ && unicode_attributes[ch].category[1] == 'o'
+ && strstr (unicode_attributes[ch].name, " LETTER ")
+ != NULL)
+ /* Consider all the non-ASCII digits as alphabetic.
+ ISO C 99 forbids us to have them in category "digit",
+ but we want iswalnum to return true on them. */
+ || (unicode_attributes[ch].category[0] == 'N'
+ && unicode_attributes[ch].category[1] == 'd'
+ && !(ch >= 0x0030 && ch <= 0x0039))));
+}
+
+static bool
+is_digit (unsigned int ch)
+{
+#if 0
+ return (unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].category[0] == 'N'
+ && unicode_attributes[ch].category[1] == 'd');
+ /* Note: U+0BE7..U+0BEF and U+1369..U+1371 are digit systems without
+ a zero. Must add <0> in front of them by hand. */
+#else
+ /* SUSV2 gives us some freedom for the "digit" category, but ISO C 99
+ takes it away:
+ 7.25.2.1.5:
+ The iswdigit function tests for any wide character that corresponds
+ to a decimal-digit character (as defined in 5.2.1).
+ 5.2.1:
+ the 10 decimal digits 0 1 2 3 4 5 6 7 8 9
+ */
+ return (ch >= 0x0030 && ch <= 0x0039);
+#endif
+}
+
+static bool
+is_outdigit (unsigned int ch)
+{
+ return (ch >= 0x0030 && ch <= 0x0039);
+}
+
+static bool
+is_blank (unsigned int ch)
+{
+ return (ch == 0x0009 /* '\t' */
+ /* Category Zs without mention of "<noBreak>" */
+ || (unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].category[0] == 'Z'
+ && unicode_attributes[ch].category[1] == 's'
+ && !strstr (unicode_attributes[ch].decomposition, "<noBreak>")));
+}
+
+static bool
+is_space (unsigned int ch)
+{
+ /* Don't make U+00A0 a space. Non-breaking space means that all programs
+ should treat it like a punctuation character, not like a space. */
+ return (ch == 0x0020 /* ' ' */
+ || ch == 0x000C /* '\f' */
+ || ch == 0x000A /* '\n' */
+ || ch == 0x000D /* '\r' */
+ || ch == 0x0009 /* '\t' */
+ || ch == 0x000B /* '\v' */
+ /* Categories Zl, Zp, and Zs without mention of "<noBreak>" */
+ || (unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].category[0] == 'Z'
+ && (unicode_attributes[ch].category[1] == 'l'
+ || unicode_attributes[ch].category[1] == 'p'
+ || (unicode_attributes[ch].category[1] == 's'
+ && !strstr (unicode_attributes[ch].decomposition,
+ "<noBreak>")))));
+}
+
+static bool
+is_cntrl (unsigned int ch)
+{
+ return (unicode_attributes[ch].name != NULL
+ && (!strcmp (unicode_attributes[ch].name, "<control>")
+ /* Categories Zl and Zp */
+ || (unicode_attributes[ch].category[0] == 'Z'
+ && (unicode_attributes[ch].category[1] == 'l'
+ || unicode_attributes[ch].category[1] == 'p'))));
+}
+
+static bool
+is_xdigit (unsigned int ch)
+{
+#if 0
+ return is_digit (ch)
+ || (ch >= 0x0041 && ch <= 0x0046)
+ || (ch >= 0x0061 && ch <= 0x0066);
+#else
+ /* SUSV2 gives us some freedom for the "xdigit" category, but ISO C 99
+ takes it away:
+ 7.25.2.1.12:
+ The iswxdigit function tests for any wide character that corresponds
+ to a hexadecimal-digit character (as defined in 6.4.4.1).
+ 6.4.4.1:
+ hexadecimal-digit: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
+ */
+ return (ch >= 0x0030 && ch <= 0x0039)
+ || (ch >= 0x0041 && ch <= 0x0046)
+ || (ch >= 0x0061 && ch <= 0x0066);
+#endif
+}
+
+static bool
+is_graph (unsigned int ch)
+{
+ return (unicode_attributes[ch].name != NULL
+ && strcmp (unicode_attributes[ch].name, "<control>")
+ && !is_space (ch));
+}
+
+static bool
+is_print (unsigned int ch)
+{
+ return (unicode_attributes[ch].name != NULL
+ && strcmp (unicode_attributes[ch].name, "<control>")
+ /* Categories Zl and Zp */
+ && !(unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].category[0] == 'Z'
+ && (unicode_attributes[ch].category[1] == 'l'
+ || unicode_attributes[ch].category[1] == 'p')));
+}
+
+static bool
+is_punct (unsigned int ch)
+{
+#if 0
+ return (unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].category[0] == 'P');
+#else
+ /* The traditional POSIX definition of punctuation is every graphic,
+ non-alphanumeric character. */
+ return (is_graph (ch) && !is_alpha (ch) && !is_digit (ch));
+#endif
+}
+
+static bool
+is_combining (unsigned int ch)
+{
+ /* Up to Unicode 3.0.1 we took the Combining property from the PropList.txt
+ file. In 3.0.1 it was identical to the union of the general categories
+ "Mn", "Mc", "Me". In Unicode 3.1 this property has been dropped from the
+ PropList.txt file, so we take the latter definition. */
+ return (unicode_attributes[ch].name != NULL
+ && unicode_attributes[ch].category[0] == 'M'
+ && (unicode_attributes[ch].category[1] == 'n'
+ || unicode_attributes[ch].category[1] == 'c'
+ || unicode_attributes[ch].category[1] == 'e'));
+}
+
+static bool
+is_combining_level3 (unsigned int ch)
+{
+ return is_combining (ch)
+ && !(unicode_attributes[ch].combining[0] != '\0'
+ && unicode_attributes[ch].combining[0] != '0'
+ && strtoul (unicode_attributes[ch].combining, NULL, 10) >= 200);
+}
+
+/* Return the UCS symbol string for a Unicode character. */
+static const char *
+ucs_symbol (unsigned int i)
+{
+ static char buf[11+1];
+
+ sprintf (buf, (i < 0x10000 ? "<U%04X>" : "<U%08X>"), i);
+ return buf;
+}
+
+/* Return the UCS symbol range string for a Unicode characters interval. */
+static const char *
+ucs_symbol_range (unsigned int low, unsigned int high)
+{
+ static char buf[24+1];
+
+ strcpy (buf, ucs_symbol (low));
+ strcat (buf, "..");
+ strcat (buf, ucs_symbol (high));
+ return buf;
+}
+
+/* Output a character class (= property) table. */
+
+static void
+output_charclass (FILE *stream, const char *classname,
+ bool (*func) (unsigned int))
+{
+ char table[0x110000];
+ unsigned int i;
+ bool need_semicolon;
+ const int max_column = 75;
+ int column;
+
+ for (i = 0; i < 0x110000; i++)
+ table[i] = (int) func (i);
+
+ fprintf (stream, "%s ", classname);
+ need_semicolon = false;
+ column = 1000;
+ for (i = 0; i < 0x110000; )
+ {
+ if (!table[i])
+ i++;
+ else
+ {
+ unsigned int low, high;
+ char buf[25];
+
+ low = i;
+ do
+ i++;
+ while (i < 0x110000 && table[i]);
+ high = i - 1;
+
+ if (low == high)
+ strcpy (buf, ucs_symbol (low));
+ else
+ strcpy (buf, ucs_symbol_range (low, high));
+
+ if (need_semicolon)
+ {
+ fprintf (stream, ";");
+ column++;
+ }
+
+ if (column + strlen (buf) > max_column)
+ {
+ fprintf (stream, "/\n ");
+ column = 3;
+ }
+
+ fprintf (stream, "%s", buf);
+ column += strlen (buf);
+ need_semicolon = true;
+ }
+ }
+ fprintf (stream, "\n");
+}
+
+/* Output a character mapping table. */
+
+static void
+output_charmap (FILE *stream, const char *mapname,
+ unsigned int (*func) (unsigned int))
+{
+ char table[0x110000];
+ unsigned int i;
+ bool need_semicolon;
+ const int max_column = 75;
+ int column;
+
+ for (i = 0; i < 0x110000; i++)
+ table[i] = (func (i) != i);
+
+ fprintf (stream, "%s ", mapname);
+ need_semicolon = false;
+ column = 1000;
+ for (i = 0; i < 0x110000; i++)
+ if (table[i])
+ {
+ char buf[25+1];
+
+ strcpy (buf, "(");
+ strcat (buf, ucs_symbol (i));
+ strcat (buf, ",");
+ strcat (buf, ucs_symbol (func (i)));
+ strcat (buf, ")");
+
+ if (need_semicolon)
+ {
+ fprintf (stream, ";");
+ column++;
+ }
+
+ if (column + strlen (buf) > max_column)
+ {
+ fprintf (stream, "/\n ");
+ column = 3;
+ }
+
+ fprintf (stream, "%s", buf);
+ column += strlen (buf);
+ need_semicolon = true;
+ }
+ fprintf (stream, "\n");
+}
+
+/* Output the width table. */
+
+static void
+output_widthmap (FILE *stream)
+{
+}
+
+/* Output the tables to the given file. */
+
+static void
+output_tables (const char *filename, const char *version)
+{
+ FILE *stream;
+ unsigned int ch;
+
+ stream = fopen (filename, "w");
+ if (stream == NULL)
+ {
+ fprintf (stderr, "cannot open '%s' for writing\n", filename);
+ exit (1);
+ }
+
+ fprintf (stream, "escape_char /\n");
+ fprintf (stream, "comment_char %%\n");
+ fprintf (stream, "\n");
+ fprintf (stream, "%% Generated automatically by gen-unicode-ctype for Unicode %s.\n",
+ version);
+ fprintf (stream, "\n");
+
+ fprintf (stream, "LC_IDENTIFICATION\n");
+ fprintf (stream, "title \"Unicode %s FDCC-set\"\n", version);
+ fprintf (stream, "source \"UnicodeData.txt, PropList.txt\"\n");
+ fprintf (stream, "address \"\"\n");
+ fprintf (stream, "contact \"\"\n");
+ fprintf (stream, "email \"bug-glibc-locales@gnu.org\"\n");
+ fprintf (stream, "tel \"\"\n");
+ fprintf (stream, "fax \"\"\n");
+ fprintf (stream, "language \"\"\n");
+ fprintf (stream, "territory \"Earth\"\n");
+ fprintf (stream, "revision \"%s\"\n", version);
+ {
+ time_t now;
+ char date[11];
+ now = time (NULL);
+ strftime (date, sizeof (date), "%Y-%m-%d", gmtime (&now));
+ fprintf (stream, "date \"%s\"\n", date);
+ }
+ fprintf (stream, "category \"unicode:2001\";LC_CTYPE\n");
+ fprintf (stream, "END LC_IDENTIFICATION\n");
+ fprintf (stream, "\n");
+
+ /* Verifications. */
+ for (ch = 0; ch < 0x110000; ch++)
+ {
+ /* toupper restriction: "Only characters specified for the keywords
+ lower and upper shall be specified. */
+ if (to_upper (ch) != ch && !(is_lower (ch) || is_upper (ch)))
+ fprintf (stderr,
+ "%s is not upper|lower but toupper(0x%04X) = 0x%04X\n",
+ ucs_symbol (ch), ch, to_upper (ch));
+
+ /* tolower restriction: "Only characters specified for the keywords
+ lower and upper shall be specified. */
+ if (to_lower (ch) != ch && !(is_lower (ch) || is_upper (ch)))
+ fprintf (stderr,
+ "%s is not upper|lower but tolower(0x%04X) = 0x%04X\n",
+ ucs_symbol (ch), ch, to_lower (ch));
+
+ /* alpha restriction: "Characters classified as either upper or lower
+ shall automatically belong to this class. */
+ if ((is_lower (ch) || is_upper (ch)) && !is_alpha (ch))
+ fprintf (stderr, "%s is upper|lower but not alpha\n", ucs_symbol (ch));
+
+ /* alpha restriction: "No character specified for the keywords cntrl,
+ digit, punct or space shall be specified." */
+ if (is_alpha (ch) && is_cntrl (ch))
+ fprintf (stderr, "%s is alpha and cntrl\n", ucs_symbol (ch));
+ if (is_alpha (ch) && is_digit (ch))
+ fprintf (stderr, "%s is alpha and digit\n", ucs_symbol (ch));
+ if (is_alpha (ch) && is_punct (ch))
+ fprintf (stderr, "%s is alpha and punct\n", ucs_symbol (ch));
+ if (is_alpha (ch) && is_space (ch))
+ fprintf (stderr, "%s is alpha and space\n", ucs_symbol (ch));
+
+ /* space restriction: "No character specified for the keywords upper,
+ lower, alpha, digit, graph or xdigit shall be specified."
+ upper, lower, alpha already checked above. */
+ if (is_space (ch) && is_digit (ch))
+ fprintf (stderr, "%s is space and digit\n", ucs_symbol (ch));
+ if (is_space (ch) && is_graph (ch))
+ fprintf (stderr, "%s is space and graph\n", ucs_symbol (ch));
+ if (is_space (ch) && is_xdigit (ch))
+ fprintf (stderr, "%s is space and xdigit\n", ucs_symbol (ch));
+
+ /* cntrl restriction: "No character specified for the keywords upper,
+ lower, alpha, digit, punct, graph, print or xdigit shall be
+ specified." upper, lower, alpha already checked above. */
+ if (is_cntrl (ch) && is_digit (ch))
+ fprintf (stderr, "%s is cntrl and digit\n", ucs_symbol (ch));
+ if (is_cntrl (ch) && is_punct (ch))
+ fprintf (stderr, "%s is cntrl and punct\n", ucs_symbol (ch));
+ if (is_cntrl (ch) && is_graph (ch))
+ fprintf (stderr, "%s is cntrl and graph\n", ucs_symbol (ch));
+ if (is_cntrl (ch) && is_print (ch))
+ fprintf (stderr, "%s is cntrl and print\n", ucs_symbol (ch));
+ if (is_cntrl (ch) && is_xdigit (ch))
+ fprintf (stderr, "%s is cntrl and xdigit\n", ucs_symbol (ch));
+
+ /* punct restriction: "No character specified for the keywords upper,
+ lower, alpha, digit, cntrl, xdigit or as the <space> character shall
+ be specified." upper, lower, alpha, cntrl already checked above. */
+ if (is_punct (ch) && is_digit (ch))
+ fprintf (stderr, "%s is punct and digit\n", ucs_symbol (ch));
+ if (is_punct (ch) && is_xdigit (ch))
+ fprintf (stderr, "%s is punct and xdigit\n", ucs_symbol (ch));
+ if (is_punct (ch) && (ch == 0x0020))
+ fprintf (stderr, "%s is punct\n", ucs_symbol (ch));
+
+ /* graph restriction: "No character specified for the keyword cntrl
+ shall be specified." Already checked above. */
+
+ /* print restriction: "No character specified for the keyword cntrl
+ shall be specified." Already checked above. */
+
+ /* graph - print relation: differ only in the <space> character.
+ How is this possible if there are more than one space character?!
+ I think susv2/xbd/locale.html should speak of "space characters",
+ not "space character". */
+ if (is_print (ch) && !(is_graph (ch) || /* ch == 0x0020 */ is_space (ch)))
+ fprintf (stderr,
+ "%s is print but not graph|<space>\n", ucs_symbol (ch));
+ if (!is_print (ch) && (is_graph (ch) || ch == 0x0020))
+ fprintf (stderr,
+ "%s is graph|<space> but not print\n", ucs_symbol (ch));
+ }
+
+ fprintf (stream, "LC_CTYPE\n");
+ output_charclass (stream, "upper", is_upper);
+ output_charclass (stream, "lower", is_lower);
+ output_charclass (stream, "alpha", is_alpha);
+ output_charclass (stream, "digit", is_digit);
+ output_charclass (stream, "outdigit", is_outdigit);
+ output_charclass (stream, "blank", is_blank);
+ output_charclass (stream, "space", is_space);
+ output_charclass (stream, "cntrl", is_cntrl);
+ output_charclass (stream, "punct", is_punct);
+ output_charclass (stream, "xdigit", is_xdigit);
+ output_charclass (stream, "graph", is_graph);
+ output_charclass (stream, "print", is_print);
+ output_charclass (stream, "class \"combining\";", is_combining);
+ output_charclass (stream, "class \"combining_level3\";", is_combining_level3);
+ output_charmap (stream, "toupper", to_upper);
+ output_charmap (stream, "tolower", to_lower);
+ output_charmap (stream, "map \"totitle\";", to_title);
+ output_widthmap (stream);
+ fprintf (stream, "END LC_CTYPE\n");
+
+ if (ferror (stream) || fclose (stream))
+ {
+ fprintf (stderr, "error writing to '%s'\n", filename);
+ exit (1);
+ }
+}
+
+int
+main (int argc, char * argv[])
+{
+ if (argc != 3)
+ {
+ fprintf (stderr, "Usage: %s UnicodeData.txt version\n", argv[0]);
+ exit (1);
+ }
+
+ fill_attributes (argv[1]);
+
+ output_tables ("unicode", argv[2]);
+
+ return 0;
+}
diff --git a/test/locale/show-ucs-data.c b/test/locale/show-ucs-data.c
new file mode 100644
index 000000000..9992ece42
--- /dev/null
+++ b/test/locale/show-ucs-data.c
@@ -0,0 +1,62 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+int
+main (int argc, char *argv[])
+{
+ int n;
+ char *line = NULL;
+ size_t len = 0;
+
+ for (n = 1; n < argc; ++n)
+ {
+ FILE *fp = fopen (argv[n], "r");
+ if (fp == NULL)
+ continue;
+
+ while (! feof (fp))
+ {
+ ssize_t cnt = getline (&line, &len, fp);
+ char *runp;
+ if (cnt <= 0)
+ break;
+
+ runp = line;
+ do
+ {
+ if (runp[0] == '<' && runp[1] == 'U' && isxdigit (runp[2])
+ && isxdigit (runp[3]) && isxdigit (runp[4])
+ && isxdigit (runp[5]) && runp[6] == '>')
+ {
+ unsigned int val = strtoul (runp + 2, NULL, 16);
+
+ //putchar ('<');
+ if (val < 128)
+ putchar (val);
+ else if (val < 0x800)
+ {
+ putchar (0xc0 | (val >> 6));
+ putchar (0x80 | (val & 0x3f));
+ }
+ else
+ {
+ putchar (0xe0 | (val >> 12));
+ putchar (0x80 | ((val >> 6) & 0x3f));
+ putchar (0x80 | (val & 0x3f));
+ }
+ //putchar ('>');
+ runp += 7;
+ }
+ else
+ putchar (*runp++);
+ }
+ while (runp < &line[cnt]);
+ }
+
+ fclose (fp);
+ }
+
+ return 0;
+}
diff --git a/test/locale/tst-C-locale.c b/test/locale/tst-C-locale.c
new file mode 100644
index 000000000..c568cf404
--- /dev/null
+++ b/test/locale/tst-C-locale.c
@@ -0,0 +1,498 @@
+/* Tests of C and POSIX locale contents.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <ctype.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+
+static int
+run_test (const char *locname)
+{
+ struct lconv *lc;
+ const char *str;
+ const wchar_t *wstr;
+ int result = 0;
+ locale_t loc;
+
+ /* ISO C stuff. */
+ lc = localeconv ();
+ if (lc == NULL)
+ {
+ printf ("localeconv failed for locale %s\n", locname);
+ result = 1;
+ }
+ else
+ {
+#define STRTEST(name, exp) \
+ do \
+ if (strcmp (lc->name, exp) != 0) \
+ { \
+ printf (#name " in locale %s wrong (is \"%s\", should be \"%s\")\n",\
+ locname, lc->name, exp); \
+ result = 1; \
+ } \
+ while (0)
+ STRTEST (decimal_point, ".");
+ STRTEST (thousands_sep, "");
+ STRTEST (grouping, "");
+ STRTEST (mon_decimal_point, "");
+ STRTEST (mon_thousands_sep, "");
+ STRTEST (mon_grouping, "");
+ STRTEST (positive_sign, "");
+ STRTEST (negative_sign, "");
+ STRTEST (currency_symbol, "");
+ STRTEST (int_curr_symbol, "");
+
+#define CHARTEST(name, exp) \
+ do \
+ if (lc->name != exp) \
+ { \
+ printf (#name " in locale %s wrong (is %d, should be %d)\n", \
+ locname, lc->name, CHAR_MAX); \
+ result = 1; \
+ } \
+ while (0)
+ CHARTEST (frac_digits, CHAR_MAX);
+ CHARTEST (p_cs_precedes, CHAR_MAX);
+ CHARTEST (n_cs_precedes, CHAR_MAX);
+ CHARTEST (p_sep_by_space, CHAR_MAX);
+ CHARTEST (n_sep_by_space, CHAR_MAX);
+ CHARTEST (p_sign_posn, CHAR_MAX);
+ CHARTEST (n_sign_posn, CHAR_MAX);
+ CHARTEST (int_frac_digits, CHAR_MAX);
+ CHARTEST (int_p_cs_precedes, CHAR_MAX);
+ CHARTEST (int_n_cs_precedes, CHAR_MAX);
+ CHARTEST (int_p_sep_by_space, CHAR_MAX);
+ CHARTEST (int_n_sep_by_space, CHAR_MAX);
+ CHARTEST (int_p_sign_posn, CHAR_MAX);
+ CHARTEST (int_n_sign_posn, CHAR_MAX);
+ }
+
+#undef STRTEST
+#define STRTEST(name, exp) \
+ str = nl_langinfo (name); \
+ if (strcmp (str, exp) != 0) \
+ { \
+ printf ("nl_langinfo(" #name ") in locale %s wrong " \
+ "(is \"%s\", should be \"%s\")\n", locname, str, exp); \
+ result = 1; \
+ }
+#define WSTRTEST(name, exp) \
+ wstr = (wchar_t *) nl_langinfo (name); \
+ if (wcscmp (wstr, exp) != 0) \
+ { \
+ printf ("nl_langinfo(" #name ") in locale %s wrong " \
+ "(is \"%S\", should be \"%S\")\n", locname, wstr, exp); \
+ result = 1; \
+ }
+
+ /* Unix stuff. */
+ STRTEST (ABDAY_1, "Sun");
+ STRTEST (ABDAY_2, "Mon");
+ STRTEST (ABDAY_3, "Tue");
+ STRTEST (ABDAY_4, "Wed");
+ STRTEST (ABDAY_5, "Thu");
+ STRTEST (ABDAY_6, "Fri");
+ STRTEST (ABDAY_7, "Sat");
+ STRTEST (DAY_1, "Sunday");
+ STRTEST (DAY_2, "Monday");
+ STRTEST (DAY_3, "Tuesday");
+ STRTEST (DAY_4, "Wednesday");
+ STRTEST (DAY_5, "Thursday");
+ STRTEST (DAY_6, "Friday");
+ STRTEST (DAY_7, "Saturday");
+ STRTEST (ABMON_1, "Jan");
+ STRTEST (ABMON_2, "Feb");
+ STRTEST (ABMON_3, "Mar");
+ STRTEST (ABMON_4, "Apr");
+ STRTEST (ABMON_5, "May");
+ STRTEST (ABMON_6, "Jun");
+ STRTEST (ABMON_7, "Jul");
+ STRTEST (ABMON_8, "Aug");
+ STRTEST (ABMON_9, "Sep");
+ STRTEST (ABMON_10, "Oct");
+ STRTEST (ABMON_11, "Nov");
+ STRTEST (ABMON_12, "Dec");
+ STRTEST (MON_1, "January");
+ STRTEST (MON_2, "February");
+ STRTEST (MON_3, "March");
+ STRTEST (MON_4, "April");
+ STRTEST (MON_5, "May");
+ STRTEST (MON_6, "June");
+ STRTEST (MON_7, "July");
+ STRTEST (MON_8, "August");
+ STRTEST (MON_9, "September");
+ STRTEST (MON_10, "October");
+ STRTEST (MON_11, "November");
+ STRTEST (MON_12, "December");
+ STRTEST (AM_STR, "AM");
+ STRTEST (PM_STR, "PM");
+ STRTEST (D_T_FMT, "%a %b %e %H:%M:%S %Y");
+ STRTEST (D_FMT, "%m/%d/%y");
+ STRTEST (T_FMT, "%H:%M:%S");
+ STRTEST (T_FMT_AMPM, "%I:%M:%S %p");
+ STRTEST (ERA, "");
+ STRTEST (ERA_D_FMT, "");
+ STRTEST (ERA_T_FMT, "");
+ STRTEST (ERA_D_T_FMT, "");
+ STRTEST (ALT_DIGITS, "");
+
+ STRTEST (RADIXCHAR, ".");
+ STRTEST (THOUSEP, "");
+
+ STRTEST (YESEXPR, "^[yY]");
+ STRTEST (NOEXPR, "^[nN]");
+
+ /* Extensions. */
+ WSTRTEST (_NL_WABDAY_1, L"Sun");
+ WSTRTEST (_NL_WABDAY_2, L"Mon");
+ WSTRTEST (_NL_WABDAY_3, L"Tue");
+ WSTRTEST (_NL_WABDAY_4, L"Wed");
+ WSTRTEST (_NL_WABDAY_5, L"Thu");
+ WSTRTEST (_NL_WABDAY_6, L"Fri");
+ WSTRTEST (_NL_WABDAY_7, L"Sat");
+ WSTRTEST (_NL_WDAY_1, L"Sunday");
+ WSTRTEST (_NL_WDAY_2, L"Monday");
+ WSTRTEST (_NL_WDAY_3, L"Tuesday");
+ WSTRTEST (_NL_WDAY_4, L"Wednesday");
+ WSTRTEST (_NL_WDAY_5, L"Thursday");
+ WSTRTEST (_NL_WDAY_6, L"Friday");
+ WSTRTEST (_NL_WDAY_7, L"Saturday");
+ WSTRTEST (_NL_WABMON_1, L"Jan");
+ WSTRTEST (_NL_WABMON_2, L"Feb");
+ WSTRTEST (_NL_WABMON_3, L"Mar");
+ WSTRTEST (_NL_WABMON_4, L"Apr");
+ WSTRTEST (_NL_WABMON_5, L"May");
+ WSTRTEST (_NL_WABMON_6, L"Jun");
+ WSTRTEST (_NL_WABMON_7, L"Jul");
+ WSTRTEST (_NL_WABMON_8, L"Aug");
+ WSTRTEST (_NL_WABMON_9, L"Sep");
+ WSTRTEST (_NL_WABMON_10, L"Oct");
+ WSTRTEST (_NL_WABMON_11, L"Nov");
+ WSTRTEST (_NL_WABMON_12, L"Dec");
+ WSTRTEST (_NL_WMON_1, L"January");
+ WSTRTEST (_NL_WMON_2, L"February");
+ WSTRTEST (_NL_WMON_3, L"March");
+ WSTRTEST (_NL_WMON_4, L"April");
+ WSTRTEST (_NL_WMON_5, L"May");
+ WSTRTEST (_NL_WMON_6, L"June");
+ WSTRTEST (_NL_WMON_7, L"July");
+ WSTRTEST (_NL_WMON_8, L"August");
+ WSTRTEST (_NL_WMON_9, L"September");
+ WSTRTEST (_NL_WMON_10, L"October");
+ WSTRTEST (_NL_WMON_11, L"November");
+ WSTRTEST (_NL_WMON_12, L"December");
+ WSTRTEST (_NL_WAM_STR, L"AM");
+ WSTRTEST (_NL_WPM_STR, L"PM");
+ WSTRTEST (_NL_WD_T_FMT, L"%a %b %e %H:%M:%S %Y");
+ WSTRTEST (_NL_WD_FMT, L"%m/%d/%y");
+ WSTRTEST (_NL_WT_FMT, L"%H:%M:%S");
+ WSTRTEST (_NL_WT_FMT_AMPM, L"%I:%M:%S %p");
+ WSTRTEST (_NL_WERA_D_FMT, L"");
+ WSTRTEST (_NL_WERA_T_FMT, L"");
+ WSTRTEST (_NL_WERA_D_T_FMT, L"");
+ WSTRTEST (_NL_WALT_DIGITS, L"");
+
+ STRTEST (_DATE_FMT, "%a %b %e %H:%M:%S %Z %Y");
+ WSTRTEST (_NL_W_DATE_FMT, L"%a %b %e %H:%M:%S %Z %Y");
+
+ STRTEST (INT_CURR_SYMBOL, "");
+ STRTEST (CURRENCY_SYMBOL, "");
+ STRTEST (MON_DECIMAL_POINT, "");
+ STRTEST (MON_THOUSANDS_SEP, "");
+ STRTEST (MON_GROUPING, "");
+ STRTEST (POSITIVE_SIGN, "");
+ STRTEST (NEGATIVE_SIGN, "");
+ STRTEST (GROUPING, "");
+
+ STRTEST (YESSTR, "");
+ STRTEST (NOSTR, "");
+
+ /* Test the new locale mechanisms. */
+ loc = newlocale (LC_ALL_MASK, locname, NULL);
+ if (loc == NULL)
+ {
+ printf ("cannot create locale object for locale %s\n", locname);
+ result = 1;
+ }
+ else
+ {
+ int c;
+
+#undef STRTEST
+#define STRTEST(name, exp) \
+ str = nl_langinfo_l (name, loc); \
+ if (strcmp (str, exp) != 0) \
+ { \
+ printf ("nl_langinfo_l(" #name ") in locale %s wrong " \
+ "(is \"%s\", should be \"%s\")\n", locname, str, exp); \
+ result = 1; \
+ }
+#undef WSTRTEST
+#define WSTRTEST(name, exp) \
+ wstr = (wchar_t *) nl_langinfo_l (name, loc); \
+ if (wcscmp (wstr, exp) != 0) \
+ { \
+ printf ("nl_langinfo_l(" #name ") in locale %s wrong " \
+ "(is \"%S\", should be \"%S\")\n", locname, wstr, exp); \
+ result = 1; \
+ }
+
+ /* Unix stuff. */
+ STRTEST (ABDAY_1, "Sun");
+ STRTEST (ABDAY_2, "Mon");
+ STRTEST (ABDAY_3, "Tue");
+ STRTEST (ABDAY_4, "Wed");
+ STRTEST (ABDAY_5, "Thu");
+ STRTEST (ABDAY_6, "Fri");
+ STRTEST (ABDAY_7, "Sat");
+ STRTEST (DAY_1, "Sunday");
+ STRTEST (DAY_2, "Monday");
+ STRTEST (DAY_3, "Tuesday");
+ STRTEST (DAY_4, "Wednesday");
+ STRTEST (DAY_5, "Thursday");
+ STRTEST (DAY_6, "Friday");
+ STRTEST (DAY_7, "Saturday");
+ STRTEST (ABMON_1, "Jan");
+ STRTEST (ABMON_2, "Feb");
+ STRTEST (ABMON_3, "Mar");
+ STRTEST (ABMON_4, "Apr");
+ STRTEST (ABMON_5, "May");
+ STRTEST (ABMON_6, "Jun");
+ STRTEST (ABMON_7, "Jul");
+ STRTEST (ABMON_8, "Aug");
+ STRTEST (ABMON_9, "Sep");
+ STRTEST (ABMON_10, "Oct");
+ STRTEST (ABMON_11, "Nov");
+ STRTEST (ABMON_12, "Dec");
+ STRTEST (MON_1, "January");
+ STRTEST (MON_2, "February");
+ STRTEST (MON_3, "March");
+ STRTEST (MON_4, "April");
+ STRTEST (MON_5, "May");
+ STRTEST (MON_6, "June");
+ STRTEST (MON_7, "July");
+ STRTEST (MON_8, "August");
+ STRTEST (MON_9, "September");
+ STRTEST (MON_10, "October");
+ STRTEST (MON_11, "November");
+ STRTEST (MON_12, "December");
+ STRTEST (AM_STR, "AM");
+ STRTEST (PM_STR, "PM");
+ STRTEST (D_T_FMT, "%a %b %e %H:%M:%S %Y");
+ STRTEST (D_FMT, "%m/%d/%y");
+ STRTEST (T_FMT, "%H:%M:%S");
+ STRTEST (T_FMT_AMPM, "%I:%M:%S %p");
+ STRTEST (ERA, "");
+ STRTEST (ERA_D_FMT, "");
+ STRTEST (ERA_T_FMT, "");
+ STRTEST (ERA_D_T_FMT, "");
+ STRTEST (ALT_DIGITS, "");
+
+ STRTEST (RADIXCHAR, ".");
+ STRTEST (THOUSEP, "");
+
+ STRTEST (YESEXPR, "^[yY]");
+ STRTEST (NOEXPR, "^[nN]");
+
+ /* Extensions. */
+ WSTRTEST (_NL_WABDAY_1, L"Sun");
+ WSTRTEST (_NL_WABDAY_2, L"Mon");
+ WSTRTEST (_NL_WABDAY_3, L"Tue");
+ WSTRTEST (_NL_WABDAY_4, L"Wed");
+ WSTRTEST (_NL_WABDAY_5, L"Thu");
+ WSTRTEST (_NL_WABDAY_6, L"Fri");
+ WSTRTEST (_NL_WABDAY_7, L"Sat");
+ WSTRTEST (_NL_WDAY_1, L"Sunday");
+ WSTRTEST (_NL_WDAY_2, L"Monday");
+ WSTRTEST (_NL_WDAY_3, L"Tuesday");
+ WSTRTEST (_NL_WDAY_4, L"Wednesday");
+ WSTRTEST (_NL_WDAY_5, L"Thursday");
+ WSTRTEST (_NL_WDAY_6, L"Friday");
+ WSTRTEST (_NL_WDAY_7, L"Saturday");
+ WSTRTEST (_NL_WABMON_1, L"Jan");
+ WSTRTEST (_NL_WABMON_2, L"Feb");
+ WSTRTEST (_NL_WABMON_3, L"Mar");
+ WSTRTEST (_NL_WABMON_4, L"Apr");
+ WSTRTEST (_NL_WABMON_5, L"May");
+ WSTRTEST (_NL_WABMON_6, L"Jun");
+ WSTRTEST (_NL_WABMON_7, L"Jul");
+ WSTRTEST (_NL_WABMON_8, L"Aug");
+ WSTRTEST (_NL_WABMON_9, L"Sep");
+ WSTRTEST (_NL_WABMON_10, L"Oct");
+ WSTRTEST (_NL_WABMON_11, L"Nov");
+ WSTRTEST (_NL_WABMON_12, L"Dec");
+ WSTRTEST (_NL_WMON_1, L"January");
+ WSTRTEST (_NL_WMON_2, L"February");
+ WSTRTEST (_NL_WMON_3, L"March");
+ WSTRTEST (_NL_WMON_4, L"April");
+ WSTRTEST (_NL_WMON_5, L"May");
+ WSTRTEST (_NL_WMON_6, L"June");
+ WSTRTEST (_NL_WMON_7, L"July");
+ WSTRTEST (_NL_WMON_8, L"August");
+ WSTRTEST (_NL_WMON_9, L"September");
+ WSTRTEST (_NL_WMON_10, L"October");
+ WSTRTEST (_NL_WMON_11, L"November");
+ WSTRTEST (_NL_WMON_12, L"December");
+ WSTRTEST (_NL_WAM_STR, L"AM");
+ WSTRTEST (_NL_WPM_STR, L"PM");
+ WSTRTEST (_NL_WD_T_FMT, L"%a %b %e %H:%M:%S %Y");
+ WSTRTEST (_NL_WD_FMT, L"%m/%d/%y");
+ WSTRTEST (_NL_WT_FMT, L"%H:%M:%S");
+ WSTRTEST (_NL_WT_FMT_AMPM, L"%I:%M:%S %p");
+ WSTRTEST (_NL_WERA_D_FMT, L"");
+ WSTRTEST (_NL_WERA_T_FMT, L"");
+ WSTRTEST (_NL_WERA_D_T_FMT, L"");
+ WSTRTEST (_NL_WALT_DIGITS, L"");
+
+ STRTEST (_DATE_FMT, "%a %b %e %H:%M:%S %Z %Y");
+ WSTRTEST (_NL_W_DATE_FMT, L"%a %b %e %H:%M:%S %Z %Y");
+
+ STRTEST (INT_CURR_SYMBOL, "");
+ STRTEST (CURRENCY_SYMBOL, "");
+ STRTEST (MON_DECIMAL_POINT, "");
+ STRTEST (MON_THOUSANDS_SEP, "");
+ STRTEST (MON_GROUPING, "");
+ STRTEST (POSITIVE_SIGN, "");
+ STRTEST (NEGATIVE_SIGN, "");
+ STRTEST (GROUPING, "");
+
+ STRTEST (YESSTR, "");
+ STRTEST (NOSTR, "");
+
+ /* Character class tests. */
+ for (c = 0; c < 128; ++c)
+ {
+#define CLASSTEST(name) \
+ if (is##name (c) != is##name##_l (c, loc)) \
+ { \
+ printf ("is%s('\\%o') != is%s_l('\\%o')\n", \
+ #name, c, #name, c); \
+ result = 1; \
+ }
+ CLASSTEST (alnum);
+ CLASSTEST (alpha);
+ CLASSTEST (blank);
+ CLASSTEST (cntrl);
+ CLASSTEST (digit);
+ CLASSTEST (lower);
+ CLASSTEST (graph);
+ CLASSTEST (print);
+ CLASSTEST (punct);
+ CLASSTEST (space);
+ CLASSTEST (upper);
+ CLASSTEST (xdigit);
+
+ /* Character mapping tests. */
+#define MAPTEST(name) \
+ if (to##name (c) != to##name##_l (c, loc)) \
+ { \
+ printf ("to%s('\\%o') != to%s_l('\\%o'): '\\%o' vs '\\%o'\n", \
+ #name, c, #name, c, \
+ to##name (c), to##name##_l (c, loc)); \
+ result = 1; \
+ }
+ MAPTEST (lower);
+ MAPTEST (upper);
+ }
+
+ /* Character class tests, this time for wide characters. Note that
+ this only works because we know that the internal encoding is
+ UCS4. */
+ for (c = 0; c < 128; ++c)
+ {
+#undef CLASSTEST
+#define CLASSTEST(name) \
+ if (isw##name (c) != isw##name##_l (c, loc)) \
+ { \
+ printf ("isw%s('\\%o') != isw%s_l('\\%o')\n", \
+ #name, c, #name, c); \
+ result = 1; \
+ }
+ CLASSTEST (alnum);
+ CLASSTEST (alpha);
+ CLASSTEST (blank);
+ CLASSTEST (cntrl);
+ CLASSTEST (digit);
+ CLASSTEST (lower);
+ CLASSTEST (graph);
+ CLASSTEST (print);
+ CLASSTEST (punct);
+ CLASSTEST (space);
+ CLASSTEST (upper);
+ CLASSTEST (xdigit);
+
+ /* Character mapping tests. Note that
+ this only works because we know that the internal encoding is
+ UCS4. */
+#undef MAPTEST
+#define MAPTEST(name) \
+ if (tow##name (c) != tow##name##_l (c, loc)) \
+ { \
+ printf ("tow%s('\\%o') != tow%s_l('\\%o'): '\\%o' vs '\\%o'\n",\
+ #name, c, #name, c, \
+ tow##name (c), tow##name##_l (c, loc)); \
+ result = 1; \
+ }
+ MAPTEST (lower);
+ MAPTEST (upper);
+ }
+
+ freelocale (loc);
+ }
+
+ return result;
+}
+
+
+static int
+do_test (void)
+{
+ int result;
+
+ /* First use the name "C". */
+ if (setlocale (LC_ALL, "C") == NULL)
+ {
+ puts ("cannot set C locale");
+ result = 1;
+ }
+ else
+ result = run_test ("C");
+
+ /* Then the name "POSIX". */
+ if (setlocale (LC_ALL, "POSIX") == NULL)
+ {
+ puts ("cannot set POSIX locale");
+ result = 1;
+ }
+ else
+ result |= run_test ("POSIX");
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/locale/tst-ctype-de_DE.ISO-8859-1.in b/test/locale/tst-ctype-de_DE.ISO-8859-1.in
new file mode 100644
index 000000000..f71d76cc2
--- /dev/null
+++ b/test/locale/tst-ctype-de_DE.ISO-8859-1.in
@@ -0,0 +1,56 @@
+lower  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000000000000000100000000000000000000000000
+lower ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 000000000000000111111111111111111111111011111111
+upper  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000000000000000000000000001111111111111111
+upper ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 111111101111111000000000000000000000000000000000
+alpha  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000010000000000100001000001111111111111111
+alpha ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 111111101111111111111111111111111111111011111111
+digit  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000000000000000000000000000000000000000000
+digit ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 000000000000000000000000000000000000000000000000
+xdigit  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000000000000000000000000000000000000000000
+xdigit ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 000000000000000000000000000000000000000000000000
+space  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000000000000000000000000000000000000000000
+space ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 000000000000000000000000000000000000000000000000
+print  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 111111111111111111111111111111111111111111111111
+print ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 111111111111111111111111111111111111111111111111
+graph  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 111111111111111111111111111111111111111111111111
+graph ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 111111111111111111111111111111111111111111111111
+blank  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000000000000000000000000000000000000000000
+blank ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 000000000000000000000000000000000000000000000000
+cntrl  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000000000000000000000000000000000000000000
+cntrl ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 000000000000000000000000000000000000000000000000
+punct  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 111111111101111111111011110111110000000000000000
+punct ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 000000010000000000000000000000000000000100000000
+alnum  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+ 000000000010000000000100001000001111111111111111
+alnum ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ 111111101111111111111111111111111111111011111111
+tolower  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿àáâãäåæçèéêëìíîï
+tolower ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ ðñòóôõö×øùúûüýþßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+toupper  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+toupper ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+ ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ÷ØÙÚÛÜÝÞÿ
diff --git a/test/locale/tst-ctype.c b/test/locale/tst-ctype.c
new file mode 100644
index 000000000..c03c2dab3
--- /dev/null
+++ b/test/locale/tst-ctype.c
@@ -0,0 +1,447 @@
+/* Copyright (C) 2000,02, 05 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <ctype.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static const char lower[] = "abcdefghijklmnopqrstuvwxyz";
+static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+static const char digits[] = "0123456789";
+static const char cntrl[] = "\
+\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\
+\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ";
+
+
+static struct classes
+{
+ const char *name;
+ int mask;
+} classes[] =
+{
+#define ENTRY(name) { #name, _IS##name }
+ ENTRY (upper),
+ ENTRY (lower),
+ ENTRY (alpha),
+ ENTRY (digit),
+ ENTRY (xdigit),
+ ENTRY (space),
+ ENTRY (print),
+ ENTRY (graph),
+ ENTRY (blank),
+ ENTRY (cntrl),
+ ENTRY (punct),
+ ENTRY (alnum)
+};
+#define nclasses (sizeof (classes) / sizeof (classes[0]))
+
+
+#define FAIL(str, args...) \
+ { \
+ printf (" " str "\n", ##args); \
+ ++errors; \
+ }
+
+
+int
+main (void)
+{
+ const char *cp;
+ const char *cp2;
+ int errors = 0;
+ char *inpline = NULL;
+ size_t inplinelen = 0;
+ char *resline = NULL;
+ size_t reslinelen = 0;
+ size_t n;
+
+ setlocale (LC_ALL, "");
+
+ printf ("Testing the ctype data of the `%s' locale\n",
+ setlocale (LC_CTYPE, NULL));
+
+#if 0
+ /* Just for debugging. */
+
+ /* Contents of the class array. */
+ printf ("\
+upper = %04x lower = %04x alpha = %04x digit = %04x xdigit = %04x\n\
+space = %04x print = %04x graph = %04x blank = %04x cntrl = %04x\n\
+punct = %04x alnum = %04x\n",
+ _ISupper, _ISlower, _ISalpha, _ISdigit, _ISxdigit,
+ _ISspace, _ISprint, _ISgraph, _ISblank, _IScntrl,
+ _ISpunct, _ISalnum);
+
+ while (n < 256)
+ {
+ if (n % 8 == 0)
+ printf ("%02x: ", n);
+ printf ("%04x%s", __ctype_b[n], (n + 1) % 8 == 0 ? "\n" : " ");
+ ++n;
+ }
+#endif
+
+ puts (" Test of ASCII character range\n special NUL byte handling");
+ if (isupper ('\0'))
+ FAIL ("isupper ('\\0') is true");
+ if (islower ('\0'))
+ FAIL ("islower ('\\0') is true");
+ if (isalpha ('\0'))
+ FAIL ("isalpha ('\\0') is true");
+ if (isdigit ('\0'))
+ FAIL ("isdigit ('\\0') is true");
+ if (isxdigit ('\0'))
+ FAIL ("isxdigit ('\\0') is true");
+ if (isspace ('\0'))
+ FAIL ("isspace ('\\0') is true");
+ if (isprint ('\0'))
+ FAIL ("isprint ('\\0') is true");
+ if (isgraph ('\0'))
+ FAIL ("isgraph ('\\0') is true");
+ if (isblank ('\0'))
+ FAIL ("isblank ('\\0') is true");
+ if (! iscntrl ('\0'))
+ FAIL ("iscntrl ('\\0') not true");
+ if (ispunct ('\0'))
+ FAIL ("ispunct ('\\0') is true");
+ if (isalnum ('\0'))
+ FAIL ("isalnum ('\\0') is true");
+
+ puts (" islower()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (! islower (*cp))
+ FAIL ("islower ('%c') not true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (islower (*cp))
+ FAIL ("islower ('%c') is true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (islower (*cp))
+ FAIL ("islower ('%c') is true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (islower (*cp))
+ FAIL ("islower ('\\x%02x') is true", *cp);
+
+ puts (" isupper()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (isupper (*cp))
+ FAIL ("isupper ('%c') is true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (! isupper (*cp))
+ FAIL ("isupper ('%c') not true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (isupper (*cp))
+ FAIL ("isupper ('%c') is true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (isupper (*cp))
+ FAIL ("isupper ('\\x%02x') is true", *cp);
+
+ puts (" isalpha()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (! isalpha (*cp))
+ FAIL ("isalpha ('%c') not true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (! isalpha (*cp))
+ FAIL ("isalpha ('%c') not true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (isalpha (*cp))
+ FAIL ("isalpha ('%c') is true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (isalpha (*cp))
+ FAIL ("isalpha ('\\x%02x') is true", *cp);
+
+ puts (" isdigit()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (isdigit (*cp))
+ FAIL ("isdigit ('%c') is true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (isdigit (*cp))
+ FAIL ("isdigit ('%c') is true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (! isdigit (*cp))
+ FAIL ("isdigit ('%c') not true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (isdigit (*cp))
+ FAIL ("isdigit ('\\x%02x') is true", *cp);
+
+ puts (" isxdigit()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if ((! isxdigit (*cp) && cp - lower < 6)
+ || (isxdigit (*cp) && cp - lower >= 6))
+ FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is");
+ for (cp = upper; *cp != '\0'; ++cp)
+ if ((! isxdigit (*cp) && cp - upper < 6)
+ || (isxdigit (*cp) && cp - upper >= 6))
+ FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is");
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (! isxdigit (*cp))
+ FAIL ("isxdigit ('%c') not true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (isxdigit (*cp))
+ FAIL ("isxdigit ('\\x%02x') is true", *cp);
+
+ puts (" isspace()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (isspace (*cp))
+ FAIL ("isspace ('%c') is true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (isspace (*cp))
+ FAIL ("isspace ('%c') is true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (isspace (*cp))
+ FAIL ("isspace ('%c') is true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if ((isspace (*cp) && ((*cp < '\x09' || *cp > '\x0d') && *cp != ' '))
+ || (! isspace (*cp)
+ && ((*cp >= '\x09' && *cp <= '\x0d') || *cp == ' ')))
+ FAIL ("isspace ('\\x%02x') %s true", *cp,
+ (*cp < '\x09' || *cp > '\x0d') ? "is" : "not");
+
+ puts (" isprint()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (! isprint (*cp))
+ FAIL ("isprint ('%c') not true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (! isprint (*cp))
+ FAIL ("isprint ('%c') not true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (! isprint (*cp))
+ FAIL ("isprint ('%c') not true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if ((isprint (*cp) && *cp != ' ')
+ || (! isprint (*cp) && *cp == ' '))
+ FAIL ("isprint ('\\x%02x') is true", *cp);
+
+ puts (" isgraph()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (! isgraph (*cp))
+ FAIL ("isgraph ('%c') not true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (! isgraph (*cp))
+ FAIL ("isgraph ('%c') not true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (! isgraph (*cp))
+ FAIL ("isgraph ('%c') not true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (isgraph (*cp))
+ FAIL ("isgraph ('\\x%02x') is true", *cp);
+
+ puts (" isblank()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (isblank (*cp))
+ FAIL ("isblank ('%c') is true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (isblank (*cp))
+ FAIL ("isblank ('%c') is true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (isblank (*cp))
+ FAIL ("isblank ('%c') is true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if ((isblank (*cp) && *cp != '\x09' && *cp != ' ')
+ || (! isblank (*cp) && (*cp == '\x09' || *cp == ' ')))
+ FAIL ("isblank ('\\x%02x') %s true", *cp, *cp != '\x09' ? "is" : "not");
+
+ puts (" iscntrl()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (iscntrl (*cp))
+ FAIL ("iscntrl ('%c') is true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (iscntrl (*cp))
+ FAIL ("iscntrl ('%c') is true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (iscntrl (*cp))
+ FAIL ("iscntrl ('%c') is true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if ((iscntrl (*cp) && *cp == ' ')
+ || (! iscntrl (*cp) && *cp != ' '))
+ FAIL ("iscntrl ('\\x%02x') not true", *cp);
+
+ puts (" ispunct()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (ispunct (*cp))
+ FAIL ("ispunct ('%c') is true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (ispunct (*cp))
+ FAIL ("ispunct ('%c') is true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (ispunct (*cp))
+ FAIL ("ispunct ('%c') is true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (ispunct (*cp))
+ FAIL ("ispunct ('\\x%02x') is true", *cp);
+
+ puts (" isalnum()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (! isalnum (*cp))
+ FAIL ("isalnum ('%c') not true", *cp);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (! isalnum (*cp))
+ FAIL ("isalnum ('%c') not true", *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (! isalnum (*cp))
+ FAIL ("isalnum ('%c') not true", *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (isalnum (*cp))
+ FAIL ("isalnum ('\\x%02x') is true", *cp);
+
+
+ puts (" tolower()");
+ for (cp = lower; *cp != '\0'; ++cp)
+ if (tolower (*cp) != *cp)
+ FAIL ("tolower ('%c') != '%c'", *cp, *cp);
+ for (cp = upper, cp2 = lower; *cp != '\0'; ++cp, ++cp2)
+ if (tolower (*cp) != *cp2)
+ FAIL ("tolower ('%c') != '%c'", *cp, *cp2);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (tolower (*cp) != *cp)
+ FAIL ("tolower ('%c') != '%c'", *cp, *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (tolower (*cp) != *cp)
+ FAIL ("tolower ('\\x%02x') != '\\x%02x'", *cp, *cp);
+
+ puts (" toupper()");
+ for (cp = lower, cp2 = upper; *cp != '\0'; ++cp, ++cp2)
+ if (toupper (*cp) != *cp2)
+ FAIL ("toupper ('%c') != '%c'", *cp, *cp2);
+ for (cp = upper; *cp != '\0'; ++cp)
+ if (toupper (*cp) != *cp)
+ FAIL ("toupper ('%c') != '%c'", *cp, *cp);
+ for (cp = digits; *cp != '\0'; ++cp)
+ if (toupper (*cp) != *cp)
+ FAIL ("toupper ('%c') != '%c'", *cp, *cp);
+ for (cp = cntrl; *cp != '\0'; ++cp)
+ if (toupper (*cp) != *cp)
+ FAIL ("toupper ('\\x%02x') != '\\x%02x'", *cp, *cp);
+
+
+ /* Now some locale specific tests. */
+ while (! feof (stdin))
+ {
+ unsigned char *inp;
+ unsigned char *resp;
+
+ if (getline (&inpline, &inplinelen, stdin) <= 0
+ || getline (&resline, &reslinelen, stdin) <= 0)
+ break;
+
+ inp = (unsigned char *) strchr (inpline, '\n');
+ if (inp != NULL)
+ *inp = '\0';
+ resp = (unsigned char *) strchr (resline, '\n');
+ if (resp != NULL)
+ *resp = '\0';
+
+ inp = (unsigned char *) inpline;
+ while (*inp != ' ' && *inp != '\t' && *inp && *inp != '\n'
+ && *inp != '\0')
+ ++inp;
+
+ if (*inp == '\0')
+ {
+ printf ("line \"%s\" is without content\n", inpline);
+ continue;
+ }
+ *inp++ = '\0';
+ while (*inp == ' ' || *inp == '\t')
+ ++inp;
+
+ /* Try all classes. */
+ for (n = 0; n < nclasses; ++n)
+ if (strcmp (inpline, classes[n].name) == 0)
+ break;
+
+ resp = (unsigned char *) resline;
+ while (*resp == ' ' || *resp == '\t')
+ ++resp;
+
+ if (strlen ((char *) inp) != strlen ((char *) resp))
+ {
+ printf ("lines \"%.20s\"... and \"%.20s\" have not the same length\n",
+ inp, resp);
+ continue;
+ }
+
+ if (n < nclasses)
+ {
+ if (strspn ((char *) resp, "01") != strlen ((char *) resp))
+ {
+ printf ("result string \"%s\" malformed\n", resp);
+ continue;
+ }
+
+ printf (" Locale-specific tests for `%s'\n", inpline);
+
+ while (*inp != '\0' && *inp != '\n')
+ {
+ if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0)
+ != (*resp != '0'))
+ {
+ printf (" is%s('%c' = '\\x%02x') %s true\n", inpline,
+ *inp, *inp, *resp == '1' ? "not" : "is");
+ ++errors;
+ }
+ ++inp;
+ ++resp;
+ }
+ }
+ else if (strcmp (inpline, "tolower") == 0)
+ {
+ while (*inp != '\0')
+ {
+ if (tolower (*inp) != *resp)
+ {
+ printf (" tolower('%c' = '\\x%02x') != '%c'\n",
+ *inp, *inp, *resp);
+ ++errors;
+ }
+ ++inp;
+ ++resp;
+ }
+ }
+ else if (strcmp (inpline, "toupper") == 0)
+ {
+ while (*inp != '\0')
+ {
+ if (toupper (*inp) != *resp)
+ {
+ printf (" toupper('%c' = '\\x%02x') != '%c'\n",
+ *inp, *inp, *resp);
+ ++errors;
+ }
+ ++inp;
+ ++resp;
+ }
+ }
+ else
+ printf ("\"%s\": unknown class or map\n", inpline);
+ }
+
+
+ if (errors != 0)
+ {
+ printf (" %d error%s for `%s' locale\n\n\n", errors,
+ errors == 1 ? "" : "s", setlocale (LC_ALL, NULL));
+ return 1;
+ }
+
+ printf (" No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
+ return 0;
+}
diff --git a/test/locale/tst-digits.c b/test/locale/tst-digits.c
new file mode 100644
index 000000000..8414a4b51
--- /dev/null
+++ b/test/locale/tst-digits.c
@@ -0,0 +1,249 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <ctype.h>
+#include <langinfo.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <sys/types.h>
+
+
+#define ZERO "\xe2\x82\x80"
+#define ONE "\xe2\x82\x81"
+#define TWO "\xe2\x82\x82"
+#define THREE "\xe2\x82\x83"
+#define FOUR "\xe2\x82\x84"
+#define FIVE "\xe2\x82\x85"
+#define SIX "\xe2\x82\x86"
+#define SEVEN "\xe2\x82\x87"
+#define EIGHT "\xe2\x82\x88"
+#define NINE "\xe2\x82\x89"
+
+static struct printf_int_test
+{
+ int n;
+ const char *format;
+ const char *expected;
+} printf_int_tests[] =
+{
+ { 0, "%I'10d", " " ZERO },
+ { 1, "%I'10d", " " ONE },
+ { 2, "%I'10d", " " TWO },
+ { 3, "%I'10d", " " THREE },
+ { 4, "%I'10d", " " FOUR },
+ { 5, "%I'10d", " " FIVE },
+ { 6, "%I'10d", " " SIX },
+ { 7, "%I'10d", " " SEVEN },
+ { 8, "%I'10d", " " EIGHT },
+ { 9, "%I'10d", " " NINE },
+ { 11, "%I'10d", " " ONE ONE },
+ { 12, "%I'10d", " " ONE TWO },
+ { 123, "%I10d", " " ONE TWO THREE },
+ { 123, "%I'10d", " " ONE TWO THREE },
+ { 1234, "%I10d", ONE TWO THREE FOUR },
+ { 1234, "%I'10d", ONE "," TWO THREE FOUR },
+ { 12345, "%I'10d", ONE TWO "," THREE FOUR FIVE },
+ { 123456, "%I'10d", ONE TWO THREE "," FOUR FIVE SIX },
+ { 1234567, "%I'10d", ONE "," TWO THREE FOUR "," FIVE SIX SEVEN }
+};
+#define nprintf_int_tests \
+ (sizeof (printf_int_tests) / sizeof (printf_int_tests[0]))
+
+#define WZERO L"\x2080"
+#define WONE L"\x2081"
+#define WTWO L"\x2082"
+#define WTHREE L"\x2083"
+#define WFOUR L"\x2084"
+#define WFIVE L"\x2085"
+#define WSIX L"\x2086"
+#define WSEVEN L"\x2087"
+#define WEIGHT L"\x2088"
+#define WNINE L"\x2089"
+
+static struct wprintf_int_test
+{
+ int n;
+ const wchar_t *format;
+ const wchar_t *expected;
+} wprintf_int_tests[] =
+{
+ { 0, L"%I'10d", L" " WZERO },
+ { 1, L"%I'10d", L" " WONE },
+ { 2, L"%I'10d", L" " WTWO },
+ { 3, L"%I'10d", L" " WTHREE },
+ { 4, L"%I'10d", L" " WFOUR },
+ { 5, L"%I'10d", L" " WFIVE },
+ { 6, L"%I'10d", L" " WSIX },
+ { 7, L"%I'10d", L" " WSEVEN },
+ { 8, L"%I'10d", L" " WEIGHT },
+ { 9, L"%I'10d", L" " WNINE },
+ { 11, L"%I'10d", L" " WONE WONE },
+ { 12, L"%I'10d", L" " WONE WTWO },
+ { 123, L"%I10d", L" " WONE WTWO WTHREE },
+ { 123, L"%I'10d", L" " WONE WTWO WTHREE },
+ { 1234, L"%I10d", L" " WONE WTWO WTHREE WFOUR },
+ { 1234, L"%I'10d", L" " WONE L"," WTWO WTHREE WFOUR },
+ { 12345, L"%I'10d", L" " WONE WTWO L"," WTHREE WFOUR WFIVE },
+ { 123456, L"%I'10d", L" " WONE WTWO WTHREE L"," WFOUR WFIVE WSIX },
+ { 1234567, L"%I'10d", L" " WONE L"," WTWO WTHREE WFOUR L"," WFIVE WSIX WSEVEN }
+};
+#define nwprintf_int_tests \
+ (sizeof (wprintf_int_tests) / sizeof (wprintf_int_tests[0]))
+
+
+int
+main (void)
+{
+ int cnt;
+ int failures;
+ int status;
+
+ if (setlocale (LC_ALL, "test7") == NULL)
+ {
+ puts ("cannot set locale `test7'");
+ exit (1);
+ }
+ printf ("CODESET = \"%s\"\n", nl_langinfo (CODESET));
+
+ /* First: printf tests. */
+ failures = 0;
+ for (cnt = 0; cnt < (int) nprintf_int_tests; ++cnt)
+ {
+ char buf[100];
+ ssize_t n;
+
+ n = snprintf (buf, sizeof buf, printf_int_tests[cnt].format,
+ printf_int_tests[cnt].n);
+
+ printf ("%3d: got \"%s\", expected \"%s\"",
+ cnt, buf, printf_int_tests[cnt].expected);
+
+ if (n != (ssize_t) strlen (printf_int_tests[cnt].expected)
+ || strcmp (buf, printf_int_tests[cnt].expected) != 0)
+ {
+ puts (" -> FAILED");
+ ++failures;
+ }
+ else
+ puts (" -> OK");
+ }
+
+ printf ("%d failures in printf tests\n", failures);
+ status = failures != 0;
+
+ /* wprintf tests. */
+ failures = 0;
+ for (cnt = 0; cnt < (int) nwprintf_int_tests; ++cnt)
+ {
+ wchar_t buf[100];
+ ssize_t n;
+
+ n = swprintf (buf, sizeof buf / sizeof (buf[0]),
+ wprintf_int_tests[cnt].format,
+ wprintf_int_tests[cnt].n);
+
+ printf ("%3d: got \"%ls\", expected \"%ls\"",
+ cnt, buf, wprintf_int_tests[cnt].expected);
+
+ if (n != (ssize_t) wcslen (wprintf_int_tests[cnt].expected)
+ || wcscmp (buf, wprintf_int_tests[cnt].expected) != 0)
+ {
+ puts (" -> FAILED");
+ ++failures;
+ }
+ else
+ puts (" -> OK");
+ }
+
+ printf ("%d failures in wprintf tests\n", failures);
+ status = failures != 0;
+
+ /* ctype tests. This makes sure that the multibyte chracter digit
+ representations are not handle in this table. */
+ failures = 0;
+ for (cnt = 0; cnt < 256; ++cnt)
+ if (cnt >= '0' && cnt <= '9')
+ {
+ if (! isdigit (cnt))
+ {
+ printf ("isdigit ('%c') == 0\n", cnt);
+ ++failures;
+ }
+ }
+ else
+ {
+ if (isdigit (cnt))
+ {
+ printf ("isdigit (%d) != 0\n", cnt);
+ ++failures;
+ }
+ }
+
+ printf ("%d failures in ctype tests\n", failures);
+ status = failures != 0;
+
+ /* wctype tests. This makes sure the second set of digits is also
+ recorded. */
+ failures = 0;
+ for (cnt = 0; cnt < 256; ++cnt)
+ if (cnt >= '0' && cnt <= '9')
+ {
+ if (! iswdigit (cnt))
+ {
+ printf ("iswdigit (L'%c') == 0\n", cnt);
+ ++failures;
+ }
+ }
+ else
+ {
+ if (iswdigit (cnt))
+ {
+ printf ("iswdigit (%d) != 0\n", cnt);
+ ++failures;
+ }
+ }
+
+ for (cnt = 0x2070; cnt < 0x2090; ++cnt)
+ if (cnt >= 0x2080 && cnt <= 0x2089)
+ {
+ if (! iswdigit (cnt))
+ {
+ printf ("iswdigit (U%04X) == 0\n", cnt);
+ ++failures;
+ }
+ }
+ else
+ {
+ if (iswdigit (cnt))
+ {
+ printf ("iswdigit (U%04X) != 0\n", cnt);
+ ++failures;
+ }
+ }
+
+ printf ("%d failures in wctype tests\n", failures);
+ status = failures != 0;
+
+ return status;
+}
diff --git a/test/locale/tst-fmon.c b/test/locale/tst-fmon.c
new file mode 100644
index 000000000..11093ce6c
--- /dev/null
+++ b/test/locale/tst-fmon.c
@@ -0,0 +1,68 @@
+/* Testing the implementation of strfmon(3).
+ Copyright (C) 1996, 1997, 2000, 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jochen Hein <jochen.hein@delphi.central.de>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <locale.h>
+#include <monetary.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ test-strfmon gets called with three parameters:
+ - the locale
+ - the format-string to be used
+ - the actual number to be formatted
+ - the expected string
+ If the test passes, test-strfmon terminates with returncode 0,
+ otherwise with 1
+*/
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#define EXIT_SETLOCALE 2
+#define EXIT_STRFMON 3
+
+int
+main (int argc, char *argv[])
+{
+ char *s = malloc (201);
+
+ if (setlocale (LC_MONETARY, argv[1]) == NULL)
+ {
+ fprintf (stderr, "setlocale(LC_MONETARY, \"%s\"): %m\n", argv[1]);
+ exit (EXIT_SETLOCALE);
+ }
+
+ if (strfmon (s, 200, argv[2], (double) atof (argv[3])) == -1)
+ {
+ perror ("strfmon");
+ exit (EXIT_STRFMON);
+ }
+
+ if (strcmp (s, argv[4]) != 0)
+ {
+ printf ("\
+Locale: \"%s\" Format: \"%s\" Value: \"%s\" Received: \"%s\" Expected: \"%s\" => %s\n",
+ argv[1], argv[2], argv[3], s, argv[4],
+ strcmp (s, argv[4]) != 0 ? "false" : "correct");
+ exit (EXIT_FAILURE);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/test/locale/tst-langinfo.c b/test/locale/tst-langinfo.c
new file mode 100644
index 000000000..e95f0da53
--- /dev/null
+++ b/test/locale/tst-langinfo.c
@@ -0,0 +1,284 @@
+/* Test program for nl_langinfo() function.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <langinfo.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+
+struct map
+{
+ const char *str;
+ int val;
+} map[] =
+{
+#define VAL(name) { #name, name }
+ VAL (ABDAY_1),
+ VAL (ABDAY_2),
+ VAL (ABDAY_3),
+ VAL (ABDAY_4),
+ VAL (ABDAY_5),
+ VAL (ABDAY_6),
+ VAL (ABDAY_7),
+ VAL (ABMON_1),
+ VAL (ABMON_10),
+ VAL (ABMON_11),
+ VAL (ABMON_12),
+ VAL (ABMON_2),
+ VAL (ABMON_3),
+ VAL (ABMON_4),
+ VAL (ABMON_5),
+ VAL (ABMON_6),
+ VAL (ABMON_7),
+ VAL (ABMON_8),
+ VAL (ABMON_9),
+ VAL (ALT_DIGITS),
+ VAL (AM_STR),
+ VAL (CRNCYSTR),
+ VAL (CURRENCY_SYMBOL),
+ VAL (DAY_1),
+ VAL (DAY_2),
+ VAL (DAY_3),
+ VAL (DAY_4),
+ VAL (DAY_5),
+ VAL (DAY_6),
+ VAL (DAY_7),
+ VAL (DECIMAL_POINT),
+ VAL (D_FMT),
+ VAL (D_T_FMT),
+ VAL (ERA),
+ VAL (ERA_D_FMT),
+ VAL (ERA_D_T_FMT),
+ VAL (ERA_T_FMT),
+ VAL (ERA_YEAR),
+ VAL (FRAC_DIGITS),
+ VAL (GROUPING),
+ VAL (INT_CURR_SYMBOL),
+ VAL (INT_FRAC_DIGITS),
+ VAL (MON_1),
+ VAL (MON_10),
+ VAL (MON_11),
+ VAL (MON_12),
+ VAL (MON_2),
+ VAL (MON_3),
+ VAL (MON_4),
+ VAL (MON_5),
+ VAL (MON_6),
+ VAL (MON_7),
+ VAL (MON_8),
+ VAL (MON_9),
+ VAL (MON_DECIMAL_POINT),
+ VAL (MON_GROUPING),
+ VAL (MON_THOUSANDS_SEP),
+ VAL (NEGATIVE_SIGN),
+ VAL (NOEXPR),
+ VAL (NOSTR),
+ VAL (N_CS_PRECEDES),
+ VAL (N_SEP_BY_SPACE),
+ VAL (N_SIGN_POSN),
+ VAL (PM_STR),
+ VAL (POSITIVE_SIGN),
+ VAL (P_CS_PRECEDES),
+ VAL (P_SEP_BY_SPACE),
+ VAL (P_SIGN_POSN),
+ VAL (RADIXCHAR),
+ VAL (THOUSANDS_SEP),
+ VAL (THOUSEP),
+ VAL (T_FMT),
+ VAL (T_FMT_AMPM),
+ VAL (YESEXPR),
+ VAL (YESSTR)
+};
+
+
+static int
+map_paramstr (const char *str)
+{
+ int low = 0;
+ int high = sizeof (map) / sizeof (map[0]);
+
+ while (low < high)
+ {
+ int med = (low + high) / 2;
+ int cmpres;
+
+ cmpres = strcmp (str, map[med].str);
+ if (cmpres == 0)
+ return map[med].val;
+ else if (cmpres > 0)
+ low = med + 1;
+ else
+ high = med;
+ }
+
+ return -1;
+}
+
+
+#ifdef DEBUG
+# define REASON(str) printf ("\"%s\" ignored: %s\n", buf, str)
+#else
+# define REASON(str)
+#endif
+
+int
+main (void)
+{
+ int result = 0;
+
+ while (! feof (stdin))
+ {
+ char buf[1000];
+ char *rp;
+ char *locale;
+ char *paramstr;
+ char *expected;
+ char *actual;
+ int param;
+
+ if (fgets (buf, sizeof (buf), stdin) == NULL)
+ break;
+
+ /* Split the fields. There are three is them:
+ 1. locale
+ 2. langinfo() parameter
+ 3. expected result; this can be a string with white space etc.
+ */
+ rp = buf;
+ while (*rp == ' ' || *rp == '\t')
+ ++rp;
+
+ if (*rp == '#')
+ {
+ /* It's a comment line. Ignore it. */
+ REASON ("comment");
+ continue;
+ }
+ locale = rp;
+
+ while (*rp != '\0' && *rp != ' ' && *rp != '\t' && *rp != '\n')
+ ++rp;
+ if (*rp == '\0' || *rp == '\n')
+ {
+ /* Incomplete line. */
+ REASON ("incomplete line");
+ continue;
+ }
+ *rp++ = '\0';
+
+ while (*rp == ' ' || *rp == '\t')
+ ++rp;
+ paramstr = rp;
+
+ while (*rp != '\0' && *rp != ' ' && *rp != '\t' && *rp != '\n')
+ ++rp;
+ if (*rp == '\0' || *rp == '\n')
+ {
+ /* Incomplete line. */
+ REASON ("incomplete line");
+ continue;
+ }
+ *rp++ = '\0';
+
+ while (*rp == ' ' || *rp == '\t')
+ ++rp;
+
+ if (*rp == '"')
+ {
+ char *wp;
+
+ expected = wp = ++rp;
+ while (*rp != '"' && *rp != '\n' && *rp != '\0')
+ {
+ if (*rp == '\\')
+ {
+ ++rp;
+ if (*rp == '\0')
+ break;
+ if (*rp >= '0' && *rp <= '9')
+ {
+ int val = *rp - '0';
+ if (rp[1] >= '0' && rp[1] <= '9')
+ {
+ ++rp;
+ val *= 10;
+ val += *rp - '0';
+ if (rp[1] >= '0' && rp[1] <= '9')
+ {
+ ++rp;
+ val *= 10;
+ val += *rp - '0';
+ }
+ }
+ *rp = val;
+ }
+ }
+ *wp++ = *rp++;
+ }
+
+ if (*rp != '"')
+ {
+ REASON ("missing '\"'");
+ continue;
+ }
+
+ *wp = '\0';
+ }
+ else
+ {
+ expected = rp;
+ while (*rp != '\0' && *rp != '\n')
+ ++rp;
+ *rp = '\0';
+ }
+
+ param = map_paramstr (paramstr);
+ if (param == -1)
+ {
+ /* Invalid parameter. */
+ REASON ("invalid parameter");
+ continue;
+ }
+
+ /* Set the locale and check whether it worked. */
+ printf ("LC_ALL=%s nl_langinfo(%s)", locale, paramstr);
+ setlocale (LC_ALL, locale);
+ if (strcmp (locale, setlocale (LC_ALL, NULL)) != 0)
+ {
+ puts (": failed to set locale");
+ result = 1;
+ continue;
+ }
+
+ actual = nl_langinfo (param);
+ printf (" = \"%s\", ", actual);
+
+ if (strcmp (actual, expected) == 0)
+ puts ("OK");
+ else
+ {
+ printf ("FAILED (expected: %s)\n", expected);
+ result = 1;
+ }
+ }
+
+ return result;
+}
diff --git a/test/locale/tst-langinfo.input b/test/locale/tst-langinfo.input
new file mode 100644
index 000000000..0a05ab862
--- /dev/null
+++ b/test/locale/tst-langinfo.input
@@ -0,0 +1,303 @@
+#! /bin/sh
+# Input file for tst-langinfo.
+# Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+# 02111-1307 USA.
+
+
+# Run the test program.
+# Only decimal numerical escape sequences allowed in strings.
+C ABDAY_1 Sun
+C ABDAY_2 Mon
+C ABDAY_3 Tue
+C ABDAY_4 Wed
+C ABDAY_5 Thu
+C ABDAY_6 Fri
+C ABDAY_7 Sat
+C DAY_1 Sunday
+C DAY_2 Monday
+C DAY_3 Tuesday
+C DAY_4 Wednesday
+C DAY_5 Thursday
+C DAY_6 Friday
+C DAY_7 Saturday
+C ABMON_1 Jan
+C ABMON_2 Feb
+C ABMON_3 Mar
+C ABMON_4 Apr
+C ABMON_5 May
+C ABMON_6 Jun
+C ABMON_7 Jul
+C ABMON_8 Aug
+C ABMON_9 Sep
+C ABMON_10 Oct
+C ABMON_11 Nov
+C ABMON_12 Dec
+C MON_1 January
+C MON_2 February
+C MON_3 March
+C MON_4 April
+C MON_5 May
+C MON_6 June
+C MON_7 July
+C MON_8 August
+C MON_9 September
+C MON_10 October
+C MON_11 November
+C MON_12 December
+C AM_STR AM
+C PM_STR PM
+C D_T_FMT "%a %b %e %H:%M:%S %Y"
+C D_FMT "%m/%d/%y"
+C T_FMT "%H:%M:%S"
+C T_FMT_AMPM "%I:%M:%S %p"
+C ABDAY_1 Sun
+C ABDAY_2 Mon
+C ABDAY_3 Tue
+C ABDAY_4 Wed
+C ABDAY_5 Thu
+C ABDAY_6 Fri
+C ABDAY_7 Sat
+C DAY_1 Sunday
+C DAY_2 Monday
+C DAY_3 Tuesday
+C DAY_4 Wednesday
+C DAY_5 Thursday
+C DAY_6 Friday
+C DAY_7 Saturday
+C RADIXCHAR .
+C THOUSEP ""
+C YESEXPR ^[yY]
+C NOEXPR ^[nN]
+en_US.ISO-8859-1 ABMON_1 Jan
+en_US.ISO-8859-1 ABMON_2 Feb
+en_US.ISO-8859-1 ABMON_3 Mar
+en_US.ISO-8859-1 ABMON_4 Apr
+en_US.ISO-8859-1 ABMON_5 May
+en_US.ISO-8859-1 ABMON_6 Jun
+en_US.ISO-8859-1 ABMON_7 Jul
+en_US.ISO-8859-1 ABMON_8 Aug
+en_US.ISO-8859-1 ABMON_9 Sep
+en_US.ISO-8859-1 ABMON_10 Oct
+en_US.ISO-8859-1 ABMON_11 Nov
+en_US.ISO-8859-1 ABMON_12 Dec
+en_US.ISO-8859-1 MON_1 January
+en_US.ISO-8859-1 MON_2 February
+en_US.ISO-8859-1 MON_3 March
+en_US.ISO-8859-1 MON_4 April
+en_US.ISO-8859-1 MON_5 May
+en_US.ISO-8859-1 MON_6 June
+en_US.ISO-8859-1 MON_7 July
+en_US.ISO-8859-1 MON_8 August
+en_US.ISO-8859-1 MON_9 September
+en_US.ISO-8859-1 MON_10 October
+en_US.ISO-8859-1 MON_11 November
+en_US.ISO-8859-1 MON_12 December
+en_US.ISO-8859-1 AM_STR AM
+en_US.ISO-8859-1 PM_STR PM
+en_US.ISO-8859-1 D_T_FMT "%a %d %b %Y %r %Z"
+en_US.ISO-8859-1 D_FMT "%m/%d/%Y"
+en_US.ISO-8859-1 T_FMT "%r"
+en_US.ISO-8859-1 T_FMT_AMPM "%I:%M:%S %p"
+en_US.ISO-8859-1 RADIXCHAR .
+en_US.ISO-8859-1 THOUSEP ,
+en_US.ISO-8859-1 YESEXPR ^[yY].*
+en_US.ISO-8859-1 NOEXPR ^[nN].*
+de_DE.ISO-8859-1 ABDAY_1 So
+de_DE.ISO-8859-1 ABDAY_2 Mo
+de_DE.ISO-8859-1 ABDAY_3 Di
+de_DE.ISO-8859-1 ABDAY_4 Mi
+de_DE.ISO-8859-1 ABDAY_5 Do
+de_DE.ISO-8859-1 ABDAY_6 Fr
+de_DE.ISO-8859-1 ABDAY_7 Sa
+de_DE.ISO-8859-1 DAY_1 Sonntag
+de_DE.ISO-8859-1 DAY_2 Montag
+de_DE.ISO-8859-1 DAY_3 Dienstag
+de_DE.ISO-8859-1 DAY_4 Mittwoch
+de_DE.ISO-8859-1 DAY_5 Donnerstag
+de_DE.ISO-8859-1 DAY_6 Freitag
+de_DE.ISO-8859-1 DAY_7 Samstag
+de_DE.ISO-8859-1 ABMON_1 Jan
+de_DE.ISO-8859-1 ABMON_2 Feb
+de_DE.ISO-8859-1 ABMON_3 Mär
+de_DE.ISO-8859-1 ABMON_4 Apr
+de_DE.ISO-8859-1 ABMON_5 Mai
+de_DE.ISO-8859-1 ABMON_6 Jun
+de_DE.ISO-8859-1 ABMON_7 Jul
+de_DE.ISO-8859-1 ABMON_8 Aug
+de_DE.ISO-8859-1 ABMON_9 Sep
+de_DE.ISO-8859-1 ABMON_10 Okt
+de_DE.ISO-8859-1 ABMON_11 Nov
+de_DE.ISO-8859-1 ABMON_12 Dez
+de_DE.ISO-8859-1 MON_1 Januar
+de_DE.ISO-8859-1 MON_2 Februar
+de_DE.ISO-8859-1 MON_3 März
+de_DE.ISO-8859-1 MON_4 April
+de_DE.ISO-8859-1 MON_5 Mai
+de_DE.ISO-8859-1 MON_6 Juni
+de_DE.ISO-8859-1 MON_7 Juli
+de_DE.ISO-8859-1 MON_8 August
+de_DE.ISO-8859-1 MON_9 September
+de_DE.ISO-8859-1 MON_10 Oktober
+de_DE.ISO-8859-1 MON_11 November
+de_DE.ISO-8859-1 MON_12 Dezember
+de_DE.ISO-8859-1 D_T_FMT "%a %d %b %Y %T %Z"
+de_DE.ISO-8859-1 D_FMT "%d.%m.%Y"
+de_DE.ISO-8859-1 T_FMT "%T"
+de_DE.ISO-8859-1 RADIXCHAR ,
+de_DE.ISO-8859-1 THOUSEP .
+de_DE.ISO-8859-1 YESEXPR ^[jJyY].*
+de_DE.ISO-8859-1 NOEXPR ^[nN].*
+de_DE.UTF-8 ABDAY_1 So
+de_DE.UTF-8 ABDAY_2 Mo
+de_DE.UTF-8 ABDAY_3 Di
+de_DE.UTF-8 ABDAY_4 Mi
+de_DE.UTF-8 ABDAY_5 Do
+de_DE.UTF-8 ABDAY_6 Fr
+de_DE.UTF-8 ABDAY_7 Sa
+de_DE.UTF-8 DAY_1 Sonntag
+de_DE.UTF-8 DAY_2 Montag
+de_DE.UTF-8 DAY_3 Dienstag
+de_DE.UTF-8 DAY_4 Mittwoch
+de_DE.UTF-8 DAY_5 Donnerstag
+de_DE.UTF-8 DAY_6 Freitag
+de_DE.UTF-8 DAY_7 Samstag
+de_DE.UTF-8 ABMON_1 Jan
+de_DE.UTF-8 ABMON_2 Feb
+de_DE.UTF-8 ABMON_3 Mär
+de_DE.UTF-8 ABMON_4 Apr
+de_DE.UTF-8 ABMON_5 Mai
+de_DE.UTF-8 ABMON_6 Jun
+de_DE.UTF-8 ABMON_7 Jul
+de_DE.UTF-8 ABMON_8 Aug
+de_DE.UTF-8 ABMON_9 Sep
+de_DE.UTF-8 ABMON_10 Okt
+de_DE.UTF-8 ABMON_11 Nov
+de_DE.UTF-8 ABMON_12 Dez
+de_DE.UTF-8 MON_1 Januar
+de_DE.UTF-8 MON_2 Februar
+de_DE.UTF-8 MON_3 März
+de_DE.UTF-8 MON_4 April
+de_DE.UTF-8 MON_5 Mai
+de_DE.UTF-8 MON_6 Juni
+de_DE.UTF-8 MON_7 Juli
+de_DE.UTF-8 MON_8 August
+de_DE.UTF-8 MON_9 September
+de_DE.UTF-8 MON_10 Oktober
+de_DE.UTF-8 MON_11 November
+de_DE.UTF-8 MON_12 Dezember
+de_DE.UTF-8 D_T_FMT "%a %d %b %Y %T %Z"
+de_DE.UTF-8 D_FMT "%d.%m.%Y"
+de_DE.UTF-8 T_FMT "%T"
+de_DE.UTF-8 RADIXCHAR ,
+de_DE.UTF-8 THOUSEP .
+de_DE.UTF-8 YESEXPR ^[jJyY].*
+de_DE.UTF-8 NOEXPR ^[nN].*
+fr_FR.ISO-8859-1 ABDAY_1 dim
+fr_FR.ISO-8859-1 ABDAY_2 lun
+fr_FR.ISO-8859-1 ABDAY_3 mar
+fr_FR.ISO-8859-1 ABDAY_4 mer
+fr_FR.ISO-8859-1 ABDAY_5 jeu
+fr_FR.ISO-8859-1 ABDAY_6 ven
+fr_FR.ISO-8859-1 ABDAY_7 sam
+fr_FR.ISO-8859-1 DAY_1 dimanche
+fr_FR.ISO-8859-1 DAY_2 lundi
+fr_FR.ISO-8859-1 DAY_3 mardi
+fr_FR.ISO-8859-1 DAY_4 mercredi
+fr_FR.ISO-8859-1 DAY_5 jeudi
+fr_FR.ISO-8859-1 DAY_6 vendredi
+fr_FR.ISO-8859-1 DAY_7 samedi
+fr_FR.ISO-8859-1 ABMON_1 jan
+fr_FR.ISO-8859-1 ABMON_2 fév
+fr_FR.ISO-8859-1 ABMON_3 mar
+fr_FR.ISO-8859-1 ABMON_4 avr
+fr_FR.ISO-8859-1 ABMON_5 mai
+fr_FR.ISO-8859-1 ABMON_6 jun
+fr_FR.ISO-8859-1 ABMON_7 jui
+fr_FR.ISO-8859-1 ABMON_8 aoû
+fr_FR.ISO-8859-1 ABMON_9 sep
+fr_FR.ISO-8859-1 ABMON_10 oct
+fr_FR.ISO-8859-1 ABMON_11 nov
+fr_FR.ISO-8859-1 ABMON_12 déc
+fr_FR.ISO-8859-1 MON_1 janvier
+fr_FR.ISO-8859-1 MON_2 février
+fr_FR.ISO-8859-1 MON_3 mars
+fr_FR.ISO-8859-1 MON_4 avril
+fr_FR.ISO-8859-1 MON_5 mai
+fr_FR.ISO-8859-1 MON_6 juin
+fr_FR.ISO-8859-1 MON_7 juillet
+fr_FR.ISO-8859-1 MON_8 août
+fr_FR.ISO-8859-1 MON_9 septembre
+fr_FR.ISO-8859-1 MON_10 octobre
+fr_FR.ISO-8859-1 MON_11 novembre
+fr_FR.ISO-8859-1 MON_12 décembre
+fr_FR.ISO-8859-1 D_T_FMT "%a %d %b %Y %T %Z"
+fr_FR.ISO-8859-1 D_FMT "%d.%m.%Y"
+fr_FR.ISO-8859-1 T_FMT "%T"
+fr_FR.ISO-8859-1 RADIXCHAR ,
+fr_FR.ISO-8859-1 THOUSEP ""
+fr_FR.ISO-8859-1 YESEXPR ^[oOyY].*
+fr_FR.ISO-8859-1 NOEXPR ^[nN].*
+ja_JP.EUC-JP ABDAY_1 Æü
+ja_JP.EUC-JP ABDAY_2 ·î
+ja_JP.EUC-JP ABDAY_3 ²Ð
+ja_JP.EUC-JP ABDAY_4 ¿å
+ja_JP.EUC-JP ABDAY_5 ÌÚ
+ja_JP.EUC-JP ABDAY_6 ¶â
+ja_JP.EUC-JP ABDAY_7 ÅÚ
+ja_JP.EUC-JP DAY_1 ÆüÍËÆü
+ja_JP.EUC-JP DAY_2 ·îÍËÆü
+ja_JP.EUC-JP DAY_3 ²ÐÍËÆü
+ja_JP.EUC-JP DAY_4 ¿åÍËÆü
+ja_JP.EUC-JP DAY_5 ÌÚÍËÆü
+ja_JP.EUC-JP DAY_6 ¶âÍËÆü
+ja_JP.EUC-JP DAY_7 ÅÚÍËÆü
+ja_JP.EUC-JP ABMON_1 " 1·î"
+ja_JP.EUC-JP ABMON_2 " 2·î"
+ja_JP.EUC-JP ABMON_3 " 3·î"
+ja_JP.EUC-JP ABMON_4 " 4·î"
+ja_JP.EUC-JP ABMON_5 " 5·î"
+ja_JP.EUC-JP ABMON_6 " 6·î"
+ja_JP.EUC-JP ABMON_7 " 7·î"
+ja_JP.EUC-JP ABMON_8 " 8·î"
+ja_JP.EUC-JP ABMON_9 " 9·î"
+ja_JP.EUC-JP ABMON_10 "10·î"
+ja_JP.EUC-JP ABMON_11 "11·î"
+ja_JP.EUC-JP ABMON_12 "12·î"
+ja_JP.EUC-JP MON_1 "1·î"
+ja_JP.EUC-JP MON_2 "2·î"
+ja_JP.EUC-JP MON_3 "3·î"
+ja_JP.EUC-JP MON_4 "4·î"
+ja_JP.EUC-JP MON_5 "5·î"
+ja_JP.EUC-JP MON_6 "6·î"
+ja_JP.EUC-JP MON_7 "7·î"
+ja_JP.EUC-JP MON_8 "8·î"
+ja_JP.EUC-JP MON_9 "9·î"
+ja_JP.EUC-JP MON_10 "10·î"
+ja_JP.EUC-JP MON_11 "11·î"
+ja_JP.EUC-JP MON_12 "12·î"
+ja_JP.EUC-JP T_FMT_AMPM "%p%I»þ%Mʬ%SÉÃ"
+ja_JP.EUC-JP ERA_D_FMT "%EY%m·î%dÆü"
+ja_JP.EUC-JP ERA_D_T_FMT "%EY%m·î%dÆü %H»þ%Mʬ%SÉÃ"
+ja_JP.EUC-JP RADIXCHAR .
+ja_JP.EUC-JP THOUSEP ,
+ja_JP.EUC-JP YESEXPR ^([yY£ù£Ù]|¤Ï¤¤|¥Ï¥¤)
+ja_JP.EUC-JP NOEXPR ^([nN£î£Î]|¤¤¤¤¤¨|¥¤¥¤¥¨)
+# Is CRNCYSTR supposed to be the national or international sign?
+# ja_JP.EUC-JP CRNCYSTR JPY
+ja_JP.EUC-JP CODESET EUC-JP
diff --git a/test/locale/tst-leaks.c b/test/locale/tst-leaks.c
new file mode 100644
index 000000000..7a4b557f5
--- /dev/null
+++ b/test/locale/tst-leaks.c
@@ -0,0 +1,18 @@
+#include <locale.h>
+#include <mcheck.h>
+
+int
+main (void)
+{
+ int cnt;
+
+ mtrace ();
+
+ for (cnt = 0; cnt < 100; ++cnt)
+ {
+ setlocale (LC_ALL, "de_DE.ISO-8859-1");
+ setlocale (LC_ALL, "de_DE.UTF-8");
+ }
+
+ return 0;
+}
diff --git a/test/locale/tst-mbswcs1.c b/test/locale/tst-mbswcs1.c
new file mode 100644
index 000000000..fb2ea84cd
--- /dev/null
+++ b/test/locale/tst-mbswcs1.c
@@ -0,0 +1,63 @@
+/* Test restarting behaviour of mbrtowc.
+ Copyright (C) 2000, 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <haible@ilog.fr>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <locale.h>
+
+#define show(expr, nexp, wcexp) \
+ n = expr; \
+ printf (#expr " -> %Zd", n); \
+ printf (", wc = %lu", (unsigned long int) wc); \
+ if (n != (size_t) nexp || wc != wcexp) \
+ { \
+ printf (", expected %Zd and %lu", nexp, (unsigned long int) wcexp); \
+ result = 1; \
+ } \
+ putc ('\n', stdout)
+
+int
+main (void)
+{
+ const unsigned char buf[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb };
+ mbstate_t state;
+ wchar_t wc = 42;
+ size_t n;
+ int result = 0;
+ const char *used_locale;
+
+ setlocale (LC_CTYPE, "de_DE.UTF-8");
+ /* Double check. */
+ used_locale = setlocale (LC_CTYPE, NULL);
+ printf ("used locale: \"%s\"\n", used_locale);
+ result = strcmp (used_locale, "de_DE.UTF-8");
+
+ memset (&state, '\0', sizeof (state));
+
+ show (mbrtowc (&wc, (const char *) buf + 0, 1, &state), 1, 37);
+ show (mbrtowc (&wc, (const char *) buf + 1, 1, &state), -2, 37);
+ show (mbrtowc (&wc, (const char *) buf + 2, 3, &state), 2, 8364);
+ show (mbrtowc (&wc, (const char *) buf + 4, 1, &state), -2, 8364);
+ show (mbrtowc (&wc, (const char *) buf + 5, 1, &state), 1, 955);
+ show (mbrtowc (&wc, (const char *) buf + 5, 1, &state), -1, 955);
+
+ return result;
+}
diff --git a/test/locale/tst-mbswcs2.c b/test/locale/tst-mbswcs2.c
new file mode 100644
index 000000000..49f13cc87
--- /dev/null
+++ b/test/locale/tst-mbswcs2.c
@@ -0,0 +1,65 @@
+/* Test restarting behaviour of mbsnrtowcs.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <haible@ilog.fr>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <locale.h>
+
+#define show(expr, nexp, wcexp, end) \
+ n = expr; \
+ printf (#expr " -> %Zd", n); \
+ printf (", wc = %lu, src = buf+%d", (unsigned long int) wc, \
+ src - (const char *) buf); \
+ if (n != (size_t) nexp || wc != wcexp || src != (const char *) (end)) \
+ { \
+ printf (", expected %Zd and %lu and buf+%d", nexp, \
+ (unsigned long int) wcexp, (end) - buf); \
+ result = 1; \
+ } \
+ putc ('\n', stdout)
+
+int
+main (void)
+{
+ unsigned char buf[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb };
+ mbstate_t state;
+ const char *src;
+ wchar_t wc = 42;
+ size_t n;
+ int result = 0;
+ const char *used_locale;
+
+ setlocale (LC_CTYPE,"de_DE.UTF-8");
+ /* Double check. */
+ used_locale = setlocale (LC_CTYPE, NULL);
+ printf ("used locale: \"%s\"\n", used_locale);
+ result = strcmp (used_locale, "de_DE.UTF-8");
+
+ memset (&state, '\0', sizeof (state));
+
+ src = (const char *) buf;
+ show (mbsnrtowcs (&wc, &src, 1, 1, &state), 1, 37, buf + 1);
+ show (mbsnrtowcs (&wc, &src, 3, 1, &state), 1, 8364, buf + 4);
+ show (mbsnrtowcs (&wc, &src, 1, 1, &state), 0, 8364, buf + 5);
+ show (mbsnrtowcs (&wc, &src, 1, 1, &state), 1, 955, buf + 6);
+
+ return result;
+}
diff --git a/test/locale/tst-mbswcs3.c b/test/locale/tst-mbswcs3.c
new file mode 100644
index 000000000..0c4af4c14
--- /dev/null
+++ b/test/locale/tst-mbswcs3.c
@@ -0,0 +1,76 @@
+/* Test restarting behaviour of wcsrtombs.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <haible@ilog.fr>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <locale.h>
+
+#define show(expr, nexp, srcexp, bufexp) \
+ { \
+ size_t res = expr; \
+ printf (#expr " -> %Zd", res); \
+ dst += res; \
+ printf (", src = srcbuf+%td, dst = buf+%td", \
+ src - srcbuf, dst - (char *) buf); \
+ if (res != nexp || src != (srcexp) || dst != (char *) (bufexp)) \
+ { \
+ printf (", expected %Zd and srcbuf+%td and buf+%td", nexp, \
+ (srcexp) - srcbuf, (bufexp) - (unsigned char *) buf); \
+ result = 1; \
+ } \
+ putc ('\n', stdout); \
+ }
+
+int
+main (void)
+{
+ unsigned char buf[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ const unsigned char bufcheck[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb };
+ const wchar_t srcbuf[4] = { 0x25, 0x20ac, 0x03bb, 0 };
+ mbstate_t state;
+ const wchar_t *src;
+ char *dst;
+ int result = 0;
+ const char *used_locale;
+
+ setlocale (LC_CTYPE, "de_DE.UTF-8");
+ /* Double check. */
+ used_locale = setlocale (LC_CTYPE, NULL);
+ printf ("used locale: \"%s\"\n", used_locale);
+ result = strcmp (used_locale, "de_DE.UTF-8");
+
+ memset (&state, '\0', sizeof (state));
+
+ src = srcbuf;
+ dst = (char *) buf;
+ show (wcsrtombs (dst, &src, 1, &state), 1, srcbuf + 1, buf + 1);
+ show (wcsrtombs (dst, &src, 1, &state), 0, srcbuf + 1, buf + 1);
+ show (wcsrtombs (dst, &src, 4, &state), 3, srcbuf + 2, buf + 4);
+ show (wcsrtombs (dst, &src, 2, &state), 2, srcbuf + 3, buf + 6);
+
+ if (memcmp (buf, bufcheck, 6))
+ {
+ puts ("wrong results");
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/test/locale/tst-mbswcs4.c b/test/locale/tst-mbswcs4.c
new file mode 100644
index 000000000..e02b67569
--- /dev/null
+++ b/test/locale/tst-mbswcs4.c
@@ -0,0 +1,63 @@
+/* Test restarting behaviour of mbsrtowcs.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <locale.h>
+
+#define show(expr, nexp, wcexp, end) \
+ n = expr; \
+ printf (#expr " -> %Zd", n); \
+ printf (", wc = %lu, src = buf+%d", (unsigned long int) wc, \
+ src - (const char *) buf); \
+ if (n != (size_t) nexp || wc != wcexp || src != (const char *) (end)) \
+ { \
+ printf (", expected %Zd and %lu and buf+%d", nexp, \
+ (unsigned long int) wcexp, (end) - buf); \
+ result = 1; \
+ } \
+ putc ('\n', stdout)
+
+int
+main (void)
+{
+ unsigned char buf[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb };
+ mbstate_t state;
+ const char *src;
+ wchar_t wc = 42;
+ size_t n;
+ int result = 0;
+ const char *used_locale;
+
+ setlocale (LC_CTYPE,"de_DE.UTF-8");
+ /* Double check. */
+ used_locale = setlocale (LC_CTYPE, NULL);
+ printf ("used locale: \"%s\"\n", used_locale);
+ result = strcmp (used_locale, "de_DE.UTF-8");
+
+ memset (&state, '\0', sizeof (state));
+
+ src = (const char *) buf;
+ show (mbsrtowcs (&wc, &src, 1, &state), 1, 37, buf + 1);
+ show (mbsrtowcs (&wc, &src, 1, &state), 1, 8364, buf + 4);
+ show (mbsrtowcs (&wc, &src, 1, &state), 1, 955, buf + 6);
+
+ return result;
+}
diff --git a/test/locale/tst-mbswcs5.c b/test/locale/tst-mbswcs5.c
new file mode 100644
index 000000000..7cab97e72
--- /dev/null
+++ b/test/locale/tst-mbswcs5.c
@@ -0,0 +1,75 @@
+/* Test restarting behaviour of wcrtomb.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bruno Haible <haible@ilog.fr>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <locale.h>
+
+#define show(expr, nexp, bufexp) \
+ { \
+ size_t res = expr; \
+ printf (#expr " -> %Zd", res); \
+ dst += res; \
+ printf (", dst = buf+%td", dst - (char *) buf); \
+ if (res != nexp || dst != (char *) (bufexp)) \
+ { \
+ printf (", expected %Zd and buf+%td", nexp, \
+ (bufexp) - (unsigned char *) buf); \
+ result = 1; \
+ } \
+ putc ('\n', stdout); \
+ }
+
+int
+main (void)
+{
+ unsigned char buf[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ const unsigned char bufcheck[7] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb, 0 };
+ const wchar_t srcbuf[4] = { 0x25, 0x20ac, 0x03bb, 0 };
+ mbstate_t state;
+ const wchar_t *src;
+ char *dst;
+ int result = 0;
+ const char *used_locale;
+
+ setlocale (LC_CTYPE, "de_DE.UTF-8");
+ /* Double check. */
+ used_locale = setlocale (LC_CTYPE, NULL);
+ printf ("used locale: \"%s\"\n", used_locale);
+ result = strcmp (used_locale, "de_DE.UTF-8");
+
+ memset (&state, '\0', sizeof (state));
+
+ src = srcbuf;
+ dst = (char *) buf;
+ show (wcrtomb (dst, *src++, &state), 1, buf + 1);
+ show (wcrtomb (dst, *src++, &state), 3, buf + 4);
+ show (wcrtomb (dst, *src++, &state), 2, buf + 6);
+ show (wcrtomb (dst, *src, &state), 1, buf + 7);
+
+ if (memcmp (buf, bufcheck, 7))
+ {
+ puts ("wrong results");
+ result = 1;
+ }
+
+ return result;
+}
diff --git a/test/locale/tst-mbswcs6.c b/test/locale/tst-mbswcs6.c
new file mode 100644
index 000000000..eb383ac87
--- /dev/null
+++ b/test/locale/tst-mbswcs6.c
@@ -0,0 +1,74 @@
+/* Test for invalid input to wcrtomb.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+
+
+static int
+do_test (const char *loc)
+{
+ char buf[100];
+ size_t n;
+ mbstate_t state;
+ const char *nloc;
+ int res;
+
+ nloc = setlocale (LC_ALL, loc);
+ if (nloc == NULL)
+ {
+ printf ("could not set locale \"%s\"\n", loc);
+ return 1;
+ }
+ printf ("new locale: %s\n", nloc);
+
+ memset (&state, '\0', sizeof (state));
+ errno = 0;
+ n = wcrtomb (buf, (wchar_t) -15l, &state);
+
+ printf ("n = %zd, errno = %d (%s)\n", n, errno, strerror (errno));
+
+ res = n != (size_t) -1 || errno != EILSEQ;
+ if (res)
+ puts ("*** FAIL");
+ putchar ('\n');
+
+ return res;
+}
+
+
+int
+main (void)
+{
+ int res;
+
+ res = do_test ("C");
+ res |= do_test ("de_DE.ISO-8859-1");
+ res |= do_test ("de_DE.UTF-8");
+ res |= do_test ("en_US.ISO-8859-1");
+ res |= do_test ("ja_JP.UTF-8");
+ res |= do_test ("hr_HR.ISO-8859-2");
+ //res |= do_test ("ru_RU.KOI8-R");
+
+ return res;
+}
diff --git a/test/locale/tst-numeric.c b/test/locale/tst-numeric.c
new file mode 100644
index 000000000..9d3c91d15
--- /dev/null
+++ b/test/locale/tst-numeric.c
@@ -0,0 +1,74 @@
+/* Testing the implementation of LC_NUMERIC and snprintf().
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Petter Reinholdtsen <pere@hungry.com>, 2003
+
+ Based on tst-fmon.c by Jochen Hein <jochen.hein@delphi.central.de>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <locale.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ test-numeric gets called with three parameters:
+ - the locale
+ - the format-string to be used
+ - the actual number to be formatted
+ - the expected string
+ If the test passes, test-numeric terminates with returncode 0,
+ otherwise with 1
+*/
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#define EXIT_SETLOCALE 2
+#define EXIT_SNPRINTF 3
+
+int
+main (int argc, char *argv[])
+{
+ char *s = malloc (201);
+ double val;
+
+ /* Make sure to read the value before setting of the locale, as
+ strtod() is locale-dependent. */
+ val = strtod (argv[3], NULL);
+
+ if (setlocale (LC_ALL, argv[1]) == NULL)
+ {
+ fprintf (stderr, "setlocale(LC_ALL, \"%s\"): %m\n", argv[1]);
+ exit (EXIT_SETLOCALE);
+ }
+
+ if (snprintf (s, 200, argv[2], val) == -1)
+ {
+ perror ("snprintf");
+ exit (EXIT_SNPRINTF);
+ }
+
+ if (strcmp (s, argv[4]) != 0)
+ {
+ printf ("\
+locale: \"%s\", format: \"%s\", expected: \"%s\", got: \"%s\" => %s\n",
+ argv[1], argv[2], argv[4], s,
+ strcmp (s, argv[4]) != 0 ? "false" : "correct");
+ exit (EXIT_FAILURE);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/test/locale/tst-rpmatch.c b/test/locale/tst-rpmatch.c
new file mode 100644
index 000000000..d751a43bf
--- /dev/null
+++ b/test/locale/tst-rpmatch.c
@@ -0,0 +1,37 @@
+/* Test program for rpmatch function.
+ Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jochen Hein <jochen.hein@delphi.central.de>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (int argc, char* argv[])
+{
+ setlocale (LC_ALL, argv[1]);
+
+ if (rpmatch (argv[2]) != atol (argv[3]))
+ {
+ fprintf (stderr,"Failed: Locale %s, String %s, Exp: %s, got %d\n",
+ argv[1], argv[2], argv[3], rpmatch (argv[2]));
+ exit (EXIT_FAILURE);
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/test/locale/tst-setlocale.c b/test/locale/tst-setlocale.c
new file mode 100644
index 000000000..1f8e68d88
--- /dev/null
+++ b/test/locale/tst-setlocale.c
@@ -0,0 +1,25 @@
+/* Test case by Jakub Jelinek <jakub@redhat.com>. */
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main (void)
+{
+ char q[30];
+ char *s;
+
+ setlocale (LC_ALL, "");
+ printf ("after setlocale (LC_ALL, \"\"): %s\n", setlocale(LC_NUMERIC, NULL));
+
+ strcpy (q, "de_DE.UTF-8");
+ setlocale (LC_NUMERIC, q);
+ printf ("after setlocale (LC_NUMERIC, \"%s\"): %s\n",
+ q, setlocale(LC_NUMERIC, NULL));
+
+ strcpy (q, "de_DE.ISO-8859-1");
+ s = setlocale (LC_NUMERIC, NULL);
+ printf ("after overwriting string: %s\n", s);
+
+ return strcmp (s, "de_DE.UTF-8") != 0;
+}
diff --git a/test/locale/tst-sscanf.c b/test/locale/tst-sscanf.c
new file mode 100644
index 000000000..32c13285a
--- /dev/null
+++ b/test/locale/tst-sscanf.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <locale.h>
+#include <assert.h>
+
+#define P0 "\xDB\xB0"
+#define P1 "\xDB\xB1"
+#define P2 "\xDB\xB2"
+#define P3 "\xDB\xB3"
+#define P4 "\xDB\xB4"
+#define P5 "\xDB\xB5"
+#define P6 "\xDB\xB6"
+#define P7 "\xDB\xB7"
+#define P8 "\xDB\xB8"
+#define P9 "\xDB\xB9"
+#define PD "\xd9\xab"
+#define PT "\xd9\xac"
+
+static int
+check_sscanf (const char *s, const char *format, const float n)
+{
+ float f;
+
+ if (sscanf (s, format, &f) != 1)
+ {
+ printf ("nothing found for \"%s\"\n", s);
+ return 1;
+ }
+ if (f != n)
+ {
+ printf ("got %f expected %f from \"%s\"\n", f, n, s);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ if (setlocale (LC_ALL, "fa_IR.UTF-8") == NULL)
+ {
+ puts ("cannot set fa_IR locale");
+ return 1;
+ }
+
+ int r = check_sscanf (P3 PD P1 P4, "%I8f", 3.14);
+ r |= check_sscanf (P3 PT P1 P4 P5, "%I'f", 3145);
+ r |= check_sscanf (P3 PD P1 P4 P1 P5 P9, "%If", 3.14159);
+ r |= check_sscanf ("-" P3 PD P1 P4 P1 P5, "%If", -3.1415);
+ r |= check_sscanf ("+" PD P1 P4 P1 P5, "%If", +.1415);
+ r |= check_sscanf (P3 PD P1 P4 P1 P5 "e+" P2, "%Ie", 3.1415e+2);
+
+ return r;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/locale/tst-strfmon1.c b/test/locale/tst-strfmon1.c
new file mode 100644
index 000000000..e30aa1b20
--- /dev/null
+++ b/test/locale/tst-strfmon1.c
@@ -0,0 +1,42 @@
+#include <monetary.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+static const struct
+{
+ const char *locale;
+ const char *expected;
+} tests[] =
+ {
+ { "de_DE.ISO-8859-1", "|-12,34 EUR|-12,34|" },
+ { "da_DK.ISO-8859-1", "|kr -12,34|-12,34|" },
+ { "zh_TW.EUC-TW", "|-NT$12.34|-12.34|" },
+ { "sv_SE.ISO-8859-1", "|-12,34 kr|-12,34|" }
+ };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+ int res = 0;
+ for (int i = 0; i < ntests; ++i)
+ {
+ char buf[500];
+ if (setlocale (LC_ALL, tests[i].locale) == NULL)
+ {
+ printf ("failed to set locale %s\n", tests[i].locale);
+ res = 1;
+ continue;
+ }
+ strfmon (buf, sizeof (buf), "|%n|%!n|", -12.34, -12.34);
+ int fail = strcmp (buf, tests[i].expected) != 0;
+ printf ("%s%s\n", buf, fail ? " *** FAIL ***" : "");
+ res |= fail;
+ }
+ return res;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/locale/tst-trans.c b/test/locale/tst-trans.c
new file mode 100644
index 000000000..034a36216
--- /dev/null
+++ b/test/locale/tst-trans.c
@@ -0,0 +1,71 @@
+/* Test program for user-defined character maps.
+ Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+int
+main (void)
+{
+ char buf[30];
+ wchar_t wbuf[30];
+ wctrans_t t;
+ wint_t wch;
+ int errors = 0;
+ int len;
+
+ setlocale (LC_ALL, "");
+
+ t = wctrans ("test");
+ if (t == (wctrans_t) 0)
+ {
+ puts ("locale data files probably not loaded");
+ exit (1);
+ }
+
+ wch = towctrans (L'A', t);
+ printf ("towctrans (L'A', t) = %c\n", wch);
+ if (wch != L'B')
+ errors = 1;
+
+ wch = towctrans (L'B', t);
+ printf ("towctrans (L'B', t) = %c\n", wch);
+ if (wch != L'C')
+ errors = 1;
+
+ /* Test the output digit handling. */
+ swprintf (wbuf, sizeof (wbuf) / sizeof (wbuf[0]), L"%Id", 0x499602D2);
+ errors |= wcscmp (wbuf, L"bcdefghija") != 0;
+ len = wcslen (wbuf);
+ errors |= len != 10;
+ printf ("len = %d, wbuf = L\"%ls\"\n", len, wbuf);
+
+ snprintf (buf, sizeof buf, "%Id", 0x499602D2);
+ errors |= strcmp (buf, "bcdefghija") != 0;
+ len = strlen (buf);
+ errors |= len != 10;
+ printf ("len = %d, buf = \"%s\"\n", len, buf);
+
+ return errors;
+}
diff --git a/test/locale/tst-wctype.c b/test/locale/tst-wctype.c
new file mode 100644
index 000000000..8fd8ce518
--- /dev/null
+++ b/test/locale/tst-wctype.c
@@ -0,0 +1,144 @@
+/* Test program for iswctype() function in ja_JP locale.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <error.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+int
+main (void)
+{
+ wctype_t wct;
+ wchar_t buf[1000];
+ int result = 1;
+
+ setlocale (LC_ALL, "");
+ wprintf (L"locale = %s\n", setlocale (LC_CTYPE, NULL));
+
+ wct = wctype ("jhira");
+ if (wct == 0)
+ error (EXIT_FAILURE, 0, "jhira: no such character class");
+
+ if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+ {
+ int n;
+
+ wprintf (L"buf[] = \"%ls\"\n", buf);
+
+ result = 0;
+
+ for (n = 0; buf[n] != L'\0'; ++n)
+ {
+ wprintf (L"jhira(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+ iswctype (buf[n], wct));
+ result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+ || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+ }
+ }
+
+ wct = wctype ("jkata");
+ if (wct == 0)
+ error (EXIT_FAILURE, 0, "jkata: no such character class");
+
+ if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+ {
+ int n;
+
+ wprintf (L"buf[] = \"%ls\"\n", buf);
+
+ result = 0;
+
+ for (n = 0; buf[n] != L'\0'; ++n)
+ {
+ wprintf (L"jkata(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+ iswctype (buf[n], wct));
+ result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+ || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+ }
+ }
+
+ wct = wctype ("jdigit");
+ if (wct == 0)
+ error (EXIT_FAILURE, 0, "jdigit: no such character class");
+
+ if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+ {
+ int n;
+
+ wprintf (L"buf[] = \"%ls\"\n", buf);
+
+ result = 0;
+
+ for (n = 0; buf[n] != L'\0'; ++n)
+ {
+ wprintf (L"jdigit(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+ iswctype (buf[n], wct));
+ result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+ || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+ }
+ }
+
+ wct = wctype ("jspace");
+ if (wct == 0)
+ error (EXIT_FAILURE, 0, "jspace: no such character class");
+
+ if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+ {
+ int n;
+
+ wprintf (L"buf[] = \"%ls\"\n", buf);
+
+ result = 0;
+
+ for (n = 0; buf[n] != L'\0'; ++n)
+ {
+ wprintf (L"jspace(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+ iswctype (buf[n], wct));
+ result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+ || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+ }
+ }
+
+ wct = wctype ("jkanji");
+ if (wct == 0)
+ error (EXIT_FAILURE, 0, "jkanji: no such character class");
+
+ if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+ {
+ int n;
+
+ wprintf (L"buf[] = \"%ls\"\n", buf);
+
+ result = 0;
+
+ for (n = 0; buf[n] != L'\0'; ++n)
+ {
+ wprintf (L"jkanji(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+ iswctype (buf[n], wct));
+ result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+ || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+ }
+ }
+
+ return result;
+}
diff --git a/test/locale/tst-xlocale1.c b/test/locale/tst-xlocale1.c
new file mode 100644
index 000000000..297c9ad7e
--- /dev/null
+++ b/test/locale/tst-xlocale1.c
@@ -0,0 +1,75 @@
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static struct
+{
+ const char *locale;
+ const char *str1;
+ const char *str2;
+ int result;
+} tests[] =
+ {
+ { "C", "TRANSLIT", "translit", 0 },
+ { "de_DE.ISO-8859-1", "TRANSLIT", "translit", 0 },
+ { "de_DE.ISO-8859-1", "TRANSLIT", "trÄnslit", -1 },
+ { "de_DE.UTF-8", "TRANSLIT", "translit", 0 },
+ { "de_DE.ISO-8859-1", "ä", "Ä", 1 }
+ };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+int
+main (void)
+{
+ size_t cnt;
+ int result = 0;
+ locale_t loc = newlocale (1 << LC_ALL, "C", NULL);
+
+ for (cnt = 0; cnt < ntests; ++cnt)
+ {
+ int r;
+
+ if (setlocale (LC_ALL, tests[cnt].locale) == NULL)
+ {
+ printf ("cannot set locale \"%s\": %m\n", tests[cnt].locale);
+ result = 1;
+ continue;
+ }
+
+ printf ("\nstrcasecmp_l (\"%s\", \"%s\", loc)\n",
+ tests[cnt].str1, tests[cnt].str2);
+
+ r = strcasecmp_l (tests[cnt].str1, tests[cnt].str2, loc);
+ if (tests[cnt].result == 0)
+ {
+ if (r != 0)
+ {
+ printf ("\"%s\" and \"%s\" expected to be the same, result %d\n",
+ tests[cnt].str1, tests[cnt].str2, r);
+ result = 1;
+ }
+ }
+ else if (tests[cnt].result < 0)
+ {
+ if (r >= 0)
+ {
+ printf ("\"%s\" expected to be smaller than \"%s\", result %d\n",
+ tests[cnt].str1, tests[cnt].str2, r);
+ result = 1;
+ }
+ }
+ else
+ {
+ if (r <= 0)
+ {
+ printf ("\"%s\" expected to be larger than \"%s\", result %d\n",
+ tests[cnt].str1, tests[cnt].str2, r);
+ result = 1;
+ }
+ }
+ }
+
+ return result;
+}
diff --git a/test/locale/tst-xlocale2.c b/test/locale/tst-xlocale2.c
new file mode 100644
index 000000000..30d87de72
--- /dev/null
+++ b/test/locale/tst-xlocale2.c
@@ -0,0 +1,64 @@
+#include <ctype.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static int do_test (__locale_t l);
+
+int
+main (void)
+{
+ locale_t l;
+ locale_t l2;
+ int result;
+
+ l = newlocale (1 << LC_ALL, "de_DE.ISO-8859-1", NULL);
+ if (l == NULL)
+ {
+ printf ("newlocale failed: %m\n");
+ exit (EXIT_FAILURE);
+ }
+ puts ("Running tests of created locale");
+ result = do_test (l);
+
+ l2 = duplocale (l);
+ if (l2 == NULL)
+ {
+ printf ("duplocale failed: %m\n");
+ exit (EXIT_FAILURE);
+ }
+ freelocale (l);
+ puts ("Running tests of duplicated locale");
+ result |= do_test (l2);
+
+ return result;
+}
+
+
+static const char str[] = "0123456789abcdef ABCDEF ghijklmnopqrstuvwxyzäÄöÖüÜ";
+static const char exd[] = "11111111110000000000000000000000000000000000000000";
+static const char exa[] = "00000000001111110111111011111111111111111111111111";
+static const char exx[] = "11111111111111110111111000000000000000000000000000";
+
+
+static int
+do_test (locale_t l)
+{
+ int result = 0;
+size_t n;
+
+#define DO_TEST(TEST, RES) \
+ for (n = 0; n < sizeof (str) - 1; ++n) \
+ if ('0' + (TEST (str[n], l) != 0) != RES[n]) \
+ { \
+ printf ("%s(%c) failed\n", #TEST, str[n]); \
+ result = 1; \
+ }
+
+ DO_TEST (isdigit_l, exd);
+ DO_TEST (isalpha_l, exa);
+ DO_TEST (isxdigit_l, exx);
+
+ return result;
+}
diff --git a/test/locale/tst_nl_langinfo.c b/test/locale/tst_nl_langinfo.c
new file mode 100644
index 000000000..fcf2fe2eb
--- /dev/null
+++ b/test/locale/tst_nl_langinfo.c
@@ -0,0 +1,296 @@
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <langinfo.h>
+#include <nl_types.h>
+
+#if !defined(__UCLIBC__) && 0
+#define DO_EXTRA
+#endif
+
+int main(int argc, char **argv)
+{
+ char *l;
+ const unsigned char *x;
+/* const unsigned char *y; */
+ const unsigned char *p;
+
+ if (argc > 2) {
+ printf("invalid args\n");
+ return EXIT_FAILURE;
+ }
+ if (argc == 1) {
+ l = "";
+ } else {
+ l = *++argv;
+ }
+
+ if (!(x = setlocale(LC_ALL,l))) {
+ printf("couldn't set locale %s\n", l);
+ return EXIT_FAILURE;
+ }
+
+/* printf("\nsetlocale returned:\n "); */
+/* do { */
+/* printf("\\x%02x", *x); */
+/* } while (*x++); */
+/* printf("\n"); */
+
+#ifndef __BCC__
+#define STR(X) #X
+#else
+#define STR(X) __STR(X)
+#endif
+#define __PASTE2(A,B) A.B
+
+#define DO_NL_I(X) \
+ printf( STR(X) " = %d\n", (int) nl_langinfo(X) );
+#define DO_NL_S(X) \
+ printf( STR(X) " = \"%s\"\n", nl_langinfo(X) );
+#define DO_NL_C(X) \
+ printf( STR(X) " = \"\\x%02x\"\n", *((unsigned char *) nl_langinfo(X)) );
+
+ printf("ctype\n");
+
+ DO_NL_S(CODESET);
+#ifdef DO_EXTRA
+ DO_NL_I(_NL_CTYPE_INDIGITS_MB_LEN);
+ DO_NL_S(_NL_CTYPE_INDIGITS0_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS1_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS2_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS3_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS4_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS5_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS6_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS7_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS8_MB);
+ DO_NL_S(_NL_CTYPE_INDIGITS9_MB);
+#endif
+ DO_NL_S(_NL_CTYPE_OUTDIGIT0_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT1_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT2_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT3_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT4_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT5_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT6_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT7_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT8_MB);
+ DO_NL_S(_NL_CTYPE_OUTDIGIT9_MB);
+
+
+ printf("numeric\n");
+
+ DO_NL_S(RADIXCHAR); /* DECIMAL_POINT */
+ DO_NL_S(THOUSEP); /* THOUSANDS_SEP */
+/* DO_NL_S(GROUPING); */
+
+ printf("GROUPING = \"");
+ for (p = (unsigned char *) nl_langinfo(GROUPING) ; *p ; p++) {
+ printf("\\x%02x", *p);
+ }
+ printf("\"\n\n");
+
+ printf("monetary\n");
+
+ DO_NL_S(INT_CURR_SYMBOL);
+ DO_NL_S(CURRENCY_SYMBOL);
+ DO_NL_S(MON_DECIMAL_POINT);
+ DO_NL_S(MON_THOUSANDS_SEP);
+/* DO_NL_S(MON_GROUPING); */
+
+ printf("MON_GROUPING = \"");
+ for (p = (unsigned char *) nl_langinfo(MON_GROUPING) ; *p ; p++) {
+ printf("\\x%02x", *p);
+ }
+ printf("\"\n\n");
+
+ DO_NL_S(POSITIVE_SIGN);
+ DO_NL_S(NEGATIVE_SIGN);
+ DO_NL_C(INT_FRAC_DIGITS);
+ DO_NL_C(FRAC_DIGITS);
+ DO_NL_C(P_CS_PRECEDES);
+ DO_NL_C(P_SEP_BY_SPACE);
+ DO_NL_C(N_CS_PRECEDES);
+ DO_NL_C(N_SEP_BY_SPACE);
+ DO_NL_C(P_SIGN_POSN);
+ DO_NL_C(N_SIGN_POSN);
+ DO_NL_C(INT_P_CS_PRECEDES);
+ DO_NL_C(INT_P_SEP_BY_SPACE);
+ DO_NL_C(INT_N_CS_PRECEDES);
+ DO_NL_C(INT_N_SEP_BY_SPACE);
+ DO_NL_C(INT_P_SIGN_POSN);
+ DO_NL_C(INT_N_SIGN_POSN);
+
+ DO_NL_S(CRNCYSTR); /* CURRENCY_SYMBOL */
+
+
+ printf("time\n");
+
+ DO_NL_S(ABDAY_1);
+ DO_NL_S(ABDAY_2);
+ DO_NL_S(ABDAY_3);
+ DO_NL_S(ABDAY_4);
+ DO_NL_S(ABDAY_5);
+ DO_NL_S(ABDAY_6);
+ DO_NL_S(ABDAY_7);
+
+ DO_NL_S(DAY_1);
+ DO_NL_S(DAY_2);
+ DO_NL_S(DAY_3);
+ DO_NL_S(DAY_4);
+ DO_NL_S(DAY_5);
+ DO_NL_S(DAY_6);
+ DO_NL_S(DAY_7);
+
+ DO_NL_S(ABMON_1);
+ DO_NL_S(ABMON_2);
+ DO_NL_S(ABMON_3);
+ DO_NL_S(ABMON_4);
+ DO_NL_S(ABMON_5);
+ DO_NL_S(ABMON_6);
+ DO_NL_S(ABMON_7);
+ DO_NL_S(ABMON_8);
+ DO_NL_S(ABMON_9);
+ DO_NL_S(ABMON_10);
+ DO_NL_S(ABMON_11);
+ DO_NL_S(ABMON_12);
+
+ DO_NL_S(MON_1);
+ DO_NL_S(MON_2);
+ DO_NL_S(MON_3);
+ DO_NL_S(MON_4);
+ DO_NL_S(MON_5);
+ DO_NL_S(MON_6);
+ DO_NL_S(MON_7);
+ DO_NL_S(MON_8);
+ DO_NL_S(MON_9);
+ DO_NL_S(MON_10);
+ DO_NL_S(MON_11);
+ DO_NL_S(MON_12);
+
+ DO_NL_S(AM_STR);
+ DO_NL_S(PM_STR);
+
+ DO_NL_S(D_T_FMT);
+ DO_NL_S(D_FMT);
+ DO_NL_S(T_FMT);
+ DO_NL_S(T_FMT_AMPM);
+/* DO_NL_S(ERA); */
+ {
+ const char *p = nl_langinfo(ERA);
+ if (!p || !*p) {
+ printf("ERA = (none)\n");
+ } else {
+ int i;
+ printf("ERA:\n");
+ for (i=0 ; i < 100 ; i++) {
+ printf(" %3d: \"%s\"\n", i, p);
+ while (*p) ++p;
+ ++p;
+ if (!*p) break;
+ }
+ }
+ }
+
+ DO_NL_S(ERA_YEAR); /* non SuSv3 */
+ DO_NL_S(ERA_D_FMT);
+/* DO_NL_S(ALT_DIGITS); */
+ {
+ const char *p = nl_langinfo(ALT_DIGITS);
+ if (!p || !*p) {
+ printf("ALT_DIGITS = (none)\n");
+ } else {
+ int i;
+ printf("ALT_DIGITS:\n");
+ for (i=0 ; i < 100 ; i++) {
+ printf(" %3d: \"%s\"\n", i, p);
+ while (*p) ++p;
+ ++p;
+ }
+ }
+ }
+ DO_NL_S(ERA_D_T_FMT);
+ DO_NL_S(ERA_T_FMT);
+
+#ifdef DO_EXTRA
+ DO_NL_C(_NL_TIME_WEEK_NDAYS);
+ DO_NL_I(_NL_TIME_WEEK_1STDAY); /* grr... this won't work with 16bit ptrs */
+ DO_NL_C(_NL_TIME_WEEK_1STWEEK);
+ DO_NL_C(_NL_TIME_FIRST_WEEKDAY);
+ DO_NL_C(_NL_TIME_FIRST_WORKDAY);
+ DO_NL_C(_NL_TIME_CAL_DIRECTION);
+ DO_NL_S(_NL_TIME_TIMEZONE);
+ DO_NL_S(_DATE_FMT);
+#endif
+
+ printf("messages\n");
+
+ DO_NL_S(YESEXPR);
+ DO_NL_S(NOEXPR);
+ DO_NL_S(YESSTR);
+ DO_NL_S(NOSTR);
+
+#ifdef DO_EXTRA
+
+ printf("paper\n");
+
+ DO_NL_I(_NL_PAPER_HEIGHT);
+ DO_NL_I(_NL_PAPER_WIDTH);
+
+ printf("name\n");
+
+ DO_NL_S(_NL_NAME_NAME_FMT);
+ DO_NL_S(_NL_NAME_NAME_GEN);
+ DO_NL_S(_NL_NAME_NAME_MR);
+ DO_NL_S(_NL_NAME_NAME_MRS);
+ DO_NL_S(_NL_NAME_NAME_MISS);
+ DO_NL_S(_NL_NAME_NAME_MS);
+
+ printf("address\n");
+
+ DO_NL_S(_NL_ADDRESS_POSTAL_FMT);
+ DO_NL_S(_NL_ADDRESS_COUNTRY_NAME);
+ DO_NL_S(_NL_ADDRESS_COUNTRY_POST);
+ DO_NL_S(_NL_ADDRESS_COUNTRY_AB2);
+ DO_NL_S(_NL_ADDRESS_COUNTRY_AB3);
+ DO_NL_S(_NL_ADDRESS_COUNTRY_CAR);
+ DO_NL_I(_NL_ADDRESS_COUNTRY_NUM);
+ DO_NL_S(_NL_ADDRESS_COUNTRY_ISBN);
+ DO_NL_S(_NL_ADDRESS_LANG_NAME);
+ DO_NL_S(_NL_ADDRESS_LANG_AB);
+ DO_NL_S(_NL_ADDRESS_LANG_TERM);
+ DO_NL_S(_NL_ADDRESS_LANG_LIB);
+
+ printf("telephone\n");
+
+ DO_NL_S(_NL_TELEPHONE_TEL_INT_FMT);
+ DO_NL_S(_NL_TELEPHONE_TEL_DOM_FMT);
+ DO_NL_S(_NL_TELEPHONE_INT_SELECT);
+ DO_NL_S(_NL_TELEPHONE_INT_PREFIX);
+
+ printf("measurement\n");
+
+ DO_NL_C(_NL_MEASUREMENT_MEASUREMENT); /* 1 is metric, 2 is US */
+
+ printf("identification\n");
+
+ DO_NL_S(_NL_IDENTIFICATION_TITLE);
+ DO_NL_S(_NL_IDENTIFICATION_SOURCE);
+ DO_NL_S(_NL_IDENTIFICATION_ADDRESS);
+ DO_NL_S(_NL_IDENTIFICATION_CONTACT);
+ DO_NL_S(_NL_IDENTIFICATION_EMAIL);
+ DO_NL_S(_NL_IDENTIFICATION_TEL);
+ DO_NL_S(_NL_IDENTIFICATION_FAX);
+ DO_NL_S(_NL_IDENTIFICATION_LANGUAGE);
+ DO_NL_S(_NL_IDENTIFICATION_TERRITORY);
+ DO_NL_S(_NL_IDENTIFICATION_AUDIENCE);
+ DO_NL_S(_NL_IDENTIFICATION_APPLICATION);
+ DO_NL_S(_NL_IDENTIFICATION_ABBREVIATION);
+ DO_NL_S(_NL_IDENTIFICATION_REVISION);
+ DO_NL_S(_NL_IDENTIFICATION_DATE);
+ DO_NL_S(_NL_IDENTIFICATION_CATEGORY);
+
+#endif
+
+ return EXIT_SUCCESS;
+}
diff --git a/test/locale/xfrm-test.c b/test/locale/xfrm-test.c
new file mode 100644
index 000000000..199bb6b5a
--- /dev/null
+++ b/test/locale/xfrm-test.c
@@ -0,0 +1,144 @@
+/* Test collation function via transformation using real data.
+ Copyright (C) 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <ctype.h>
+#include <error.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+struct lines
+{
+ char *xfrm;
+ char *line;
+};
+
+static int xstrcmp (const void *, const void *);
+
+int
+main (int argc, char *argv[])
+{
+ int result = 0;
+ size_t nstrings, nstrings_max;
+ struct lines *strings;
+ char *line = NULL;
+ size_t len = 0;
+ size_t n;
+
+ if (argc < 2)
+ error (1, 0, "usage: %s <random seed>", argv[0]);
+
+ setlocale (LC_ALL, "");
+
+ nstrings_max = 100;
+ nstrings = 0;
+ strings = (struct lines *) malloc (nstrings_max * sizeof (struct lines));
+ if (strings == NULL)
+ {
+ perror (argv[0]);
+ exit (1);
+ }
+
+ while (1)
+ {
+ char saved, *newp;
+ int needed;
+ int l;
+ if (getline (&line, &len, stdin) < 0)
+ break;
+
+ if (nstrings == nstrings_max)
+ {
+ strings = (struct lines *) realloc (strings,
+ (nstrings_max *= 2)
+ * sizeof (*strings));
+ if (strings == NULL)
+ {
+ perror (argv[0]);
+ exit (1);
+ }
+ }
+ strings[nstrings].line = strdup (line);
+ l = strcspn (line, ":(;");
+ while (l > 0 && isspace (line[l - 1]))
+ --l;
+
+ saved = line[l];
+ line[l] = '\0';
+ needed = strxfrm (NULL, line, 0);
+ newp = malloc (needed + 1);
+ strxfrm (newp, line, needed + 1);
+ strings[nstrings].xfrm = newp;
+ line[l] = saved;
+ ++nstrings;
+ }
+ free (line);
+
+ /* First shuffle. */
+ srandom (atoi (argv[1]));
+ for (n = 0; n < 10 * nstrings; ++n)
+ {
+ int r1, r2, r;
+ size_t idx1 = random () % nstrings;
+ size_t idx2 = random () % nstrings;
+ struct lines tmp = strings[idx1];
+ strings[idx1] = strings[idx2];
+ strings[idx2] = tmp;
+
+ /* While we are at it a first little test. */
+ r1 = strcmp (strings[idx1].xfrm, strings[idx2].xfrm);
+ r2 = strcmp (strings[idx2].xfrm, strings[idx1].xfrm);
+ r = -(r1 ^ r2);
+ if (r)
+ r /= abs (r1 ^ r2);
+
+ if (r < 0 || (r == 0 && (r1 != 0 || r2 != 0))
+ || (r > 0 && (r1 ^ r2) >= 0))
+ printf ("collate wrong: %d vs. %d\n", r1, r2);
+ }
+
+ /* Now sort. */
+ qsort (strings, nstrings, sizeof (struct lines), xstrcmp);
+
+ /* Print the result. */
+ for (n = 0; n < nstrings; ++n)
+ {
+ fputs (strings[n].line, stdout);
+ free (strings[n].line);
+ free (strings[n].xfrm);
+ }
+ free (strings);
+
+ return result;
+}
+
+
+static int
+xstrcmp (ptr1, ptr2)
+ const void *ptr1;
+ const void *ptr2;
+{
+ const struct lines *l1 = (const struct lines *) ptr1;
+ const struct lines *l2 = (const struct lines *) ptr2;
+
+ return strcmp (l1->xfrm, l2->xfrm);
+}