aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog76
-rw-r--r--locale/C-address.c47
-rw-r--r--locale/C-ctype.c291
-rw-r--r--locale/C-identification.c54
-rw-r--r--locale/C-measurement.c36
-rw-r--r--locale/C-messages.c6
-rw-r--r--locale/C-monetary.c37
-rw-r--r--locale/C-name.c41
-rw-r--r--locale/C-paper.c39
-rw-r--r--locale/C-telephone.c39
-rw-r--r--locale/C-time.c116
-rw-r--r--locale/Makefile36
-rw-r--r--locale/categories.def277
-rw-r--r--locale/findlocale.c47
-rw-r--r--locale/iso-3166.def245
-rw-r--r--locale/iso-639.def133
-rw-r--r--locale/langinfo.h371
-rw-r--r--locale/lc-address.c22
-rw-r--r--locale/lc-collate.c18
-rw-r--r--locale/lc-ctype.c17
-rw-r--r--locale/lc-identification.c22
-rw-r--r--locale/lc-measurement.c22
-rw-r--r--locale/lc-monetary.c23
-rw-r--r--locale/lc-name.c22
-rw-r--r--locale/lc-paper.c22
-rw-r--r--locale/lc-telephone.c22
-rw-r--r--locale/lc-time.c117
-rw-r--r--locale/loadlocale.c77
-rw-r--r--locale/locale.h20
-rw-r--r--locale/localeinfo.h59
-rw-r--r--locale/newlocale.c34
-rw-r--r--locale/programs/charmap-kw.gperf7
-rw-r--r--locale/programs/charmap-kw.h120
-rw-r--r--locale/programs/charmap.c284
-rw-r--r--locale/programs/charmap.h (renamed from locale/programs/charset.h)50
-rw-r--r--locale/programs/config.h30
-rw-r--r--locale/programs/ld-address.c514
-rw-r--r--locale/programs/ld-collate.c1819
-rw-r--r--locale/programs/ld-ctype.c3042
-rw-r--r--locale/programs/ld-identification.c376
-rw-r--r--locale/programs/ld-measurement.c206
-rw-r--r--locale/programs/ld-messages.c252
-rw-r--r--locale/programs/ld-monetary.c757
-rw-r--r--locale/programs/ld-name.c276
-rw-r--r--locale/programs/ld-numeric.c293
-rw-r--r--locale/programs/ld-paper.c235
-rw-r--r--locale/programs/ld-telephone.c283
-rw-r--r--locale/programs/ld-time.c1155
-rw-r--r--locale/programs/linereader.c452
-rw-r--r--locale/programs/linereader.h34
-rw-r--r--locale/programs/locale-spec.c2
-rw-r--r--locale/programs/locale.c8
-rw-r--r--locale/programs/localedef.c299
-rw-r--r--locale/programs/localedef.h131
-rw-r--r--locale/programs/locfile-kw.gperf250
-rw-r--r--locale/programs/locfile-kw.h482
-rw-r--r--locale/programs/locfile-token.h111
-rw-r--r--locale/programs/locfile.c1088
-rw-r--r--locale/programs/locfile.h264
-rw-r--r--locale/programs/repertoire.c225
-rw-r--r--locale/programs/repertoire.h31
-rw-r--r--locale/programs/simple-hash.h30
-rw-r--r--locale/programs/stringtrans.c10
-rw-r--r--locale/setlocale.c147
-rw-r--r--locale/weight.h54
-rw-r--r--string/strcoll.c20
-rw-r--r--string/strxfrm.c18
-rw-r--r--time/strftime.c36
-rw-r--r--time/strptime.c1
-rw-r--r--wctype/cname-lookup.h32
70 files changed, 11953 insertions, 3859 deletions
diff --git a/ChangeLog b/ChangeLog
index 1e39c44efd..69c03f7ae3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,81 @@
1999-08-30 Ulrich Drepper <drepper@cygnus.com>
+ * locale/Makefile (distribute): Add iso-639.def and iso-3166.def.
+ Change charset.h to charmap.h.
+ (categories): Add new categories. Leave out collate for now.
+ Update build rules.
+ * locale/categories.def: Add definitions for new categories.
+ * locale/langinfo.h: Likewise.
+ * locale/locale.h: Likewise.
+ * locale/C-address.c: New file.
+ * locale/C-identification.c: New file.
+ * locale/C-measurement.c: New file.
+ * locale/C-name.c: New file.
+ * locale/C-paper.c: New file.
+ * locale/C-telephone.c: New file.
+ * locale/lc-address.c: Likewise.
+ * locale/lc-identification.c: Likewise.
+ * locale/lc-measurement.c: Likewise.
+ * locale/lc-name.c: Likewise.
+ * locale/lc-paper.c: Likewise.
+ * locale/lc-telephone.c: Likewise.
+ * locale/C-ctype.c: Update for locale rewrite.
+ * locale/C-messages.c: Likewise.
+ * locale/C-monetary.c: Likewise.
+ * locale/C-time.c: Likewise.
+ * locale/lc-collate.c: Likewise.
+ * locale/lc-ctype.c: Likewise.
+ * locale/lc-monetary.c: Likewise.
+ * locale/lc-time.c: Likewise.
+ * locale/localeinfo.h: Likewise.
+ * locale/newlocale.c: Likewise.
+ * locale/setlocale.c: Likewise.
+ * locale/weight.h: Likewise.
+ * locale/findlocale.c: Unconditionally use mmap.
+ Handle new categories.
+ * locale/loadlocale.c: Likewise.
+ * locale/iso-3166.def: New file.
+ * locale/iso-639.def: New file.
+ * locale/programs/charmap-kw.gperf: Add new keywords.
+ * locale/programs/locfile-kw.gperf: Likewise.
+ * locale/programs/locfile-token.h: Define new tokens.
+ * locale/programs/charmap.c: Rewrite to handle multibyte charsets.
+ * locale/programs/charmap.h: New file.
+ * locale/programs/charset.h: Removed.
+ * locale/programs/config.h: Add __LC_LAST.
+ * locale/programs/lc-address.c: New file.
+ * locale/programs/lc-identification.c: New file.
+ * locale/programs/lc-measurement.c: New file.
+ * locale/programs/lc-name.c: New file.
+ * locale/programs/lc-paper.c: New file.
+ * locale/programs/lc-telephone.c: New file.
+ * locale/programs/lc-collate.c: Update for locale rewrite.
+ * locale/programs/lc-ctype.c: Likewise.
+ * locale/programs/lc-messages.c: Likewise.
+ * locale/programs/lc-monetary.c: Likewise.
+ * locale/programs/lc-numeric.c: Likewise.
+ * locale/programs/lc-time.c: Likewise.
+ * locale/programs/locale.c: Likewise.
+ * locale/programs/localedef.c: Likewise.
+ * locale/programs/locfile.c: Likewise.
+ * locale/programs/repertoire.c: Likewise.
+ * locale/programs/repertoire.h: Likewise.
+ * locale/programs/locfile.c: Update prototypes.
+ Update handle_copy definition.
+ * locale/programs/linereader.c: Add handling of wide char strings and
+ new definition file syntax.
+ * locale/programs/linereader.h (struct token): Add elements for wide
+ character strings.
+ * locale/programs/locale-spec.c: Disable handling of collation
+ elements for now.
+ * locale/programs/simple-hash.h: Cleanup.
+ * locale/programs/stringtrans.h: Handle quite of end of line.
+ * string/strcoll.c: Fall back on strcmp for now.
+ * string/strxfrm.c: Fall back on strncpy/strlen for now.
+ * time/strftime.c: Use new wide character data for wcsftime.
+ * time/strptime.c: Remove _nl_C_LC_TIME declaration.
+ * wctype/cname-lookup.h: Update for new LC_CTYPE data.
+
* sysdeps/i386/Makefile [csu]: Define CFLAGS-initfini.s to force
compiling for i386 to avoid i686-like GOT pointer computation.
diff --git a/locale/C-address.c b/locale/C-address.c
new file mode 100644
index 0000000000..8b37639d89
--- /dev/null
+++ b/locale/C-address.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <endian.h>
+
+#include "localeinfo.h"
+
+/* This table's entries are taken from ISO 14652, the table in section
+ 4.10 "LC_ADDRESS". */
+
+const struct locale_data _nl_C_LC_ADDRESS =
+{
+ _nl_C_name,
+ NULL, 0, 0, /* no file mapped */
+ UNDELETABLE,
+ 12,
+ {
+ { string: "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" }
+ }
+};
diff --git a/locale/C-ctype.c b/locale/C-ctype.c
index 9dd122b3f6..77281b0095 100644
--- a/locale/C-ctype.c
+++ b/locale/C-ctype.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -29,28 +29,28 @@
is set to always return 0 and the conversion arrays return EOF. */
const char _nl_C_LC_CTYPE_class[768] =
- /* 0x80 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x86 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x8c */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x92 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x98 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x9e */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xa4 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xaa */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xb0 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xb6 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xbc */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xc2 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xc8 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xce */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xd4 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xda */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xe0 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xe6 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xec */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xf2 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xf8 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xfe */ "\000\000" "\000\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x80 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x86 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x8c */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x92 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x98 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x9e */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xa4 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xaa */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xb0 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xb6 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xbc */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xc2 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xc8 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xce */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xd4 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xda */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xe0 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xe6 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xec */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xf2 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xf8 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xfe */ "\002\000" "\000\000" "\002\000" "\002\000" "\002\000" "\002\000"
/* 0x04 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\003\040"
/* 0x0a */ "\002\040" "\002\040" "\002\040" "\002\040" "\002\000" "\002\000"
/* 0x10 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
@@ -71,28 +71,28 @@ const char _nl_C_LC_CTYPE_class[768] =
/* 0x6a */ "\010\306" "\010\306" "\010\306" "\010\306" "\010\306" "\010\306"
/* 0x70 */ "\010\306" "\010\306" "\010\306" "\010\306" "\010\306" "\010\306"
/* 0x76 */ "\010\306" "\010\306" "\010\306" "\010\306" "\010\306" "\004\300"
- /* 0x7c */ "\004\300" "\004\300" "\004\300" "\002\000" "\000\000" "\000\000"
- /* 0x82 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x88 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x8e */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x94 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0x9a */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xa0 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xa6 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xac */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xb2 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xb8 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xbe */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xc4 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xca */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xd0 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xd6 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xdc */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xe2 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xe8 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xee */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xf4 */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
- /* 0xfa */ "\000\000" "\000\000" "\000\000" "\000\000" "\000\000" "\000\000"
+ /* 0x7c */ "\004\300" "\004\300" "\004\300" "\002\000" "\002\000" "\002\000"
+ /* 0x82 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x88 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x8e */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x94 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0x9a */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xa0 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xa6 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xac */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xb2 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xb8 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xbe */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xc4 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xca */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xd0 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xd6 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xdc */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xe2 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xe8 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xee */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xf4 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
+ /* 0xfa */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
;
const char _nl_C_LC_CTYPE_class32[1024] =
/* 0x00 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
@@ -137,50 +137,50 @@ const char _nl_C_LC_CTYPE_class32[1024] =
/* 0x75 */ "\000\000\010\306" "\000\000\010\306" "\000\000\010\306"
/* 0x78 */ "\000\000\010\306" "\000\000\010\306" "\000\000\010\306"
/* 0x7b */ "\000\000\004\300" "\000\000\004\300" "\000\000\004\300"
- /* 0x7e */ "\000\000\004\300" "\000\000\002\000" "\000\000\000\000"
- /* 0x81 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x84 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x87 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x8a */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x8d */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x90 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x93 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x96 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x99 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x9c */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0x9f */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xa2 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xa5 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xa8 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xab */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xae */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xb1 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xb4 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xb7 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xba */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xbd */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xc0 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xc3 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xc6 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xc9 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xcc */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xcf */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xd2 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xd5 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xd8 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xdb */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xde */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xe1 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xe4 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xe7 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xea */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xed */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xf0 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xf3 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xf6 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xf9 */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xfc */ "\000\000\000\000" "\000\000\000\000" "\000\000\000\000"
- /* 0xff */ "\000\000\000\000"
+ /* 0x7e */ "\000\000\004\300" "\000\000\002\000" "\000\000\002\000"
+ /* 0x81 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x84 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x87 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x8a */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x8d */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x90 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x93 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x96 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x99 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x9c */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0x9f */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xa2 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xa5 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xa8 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xab */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xae */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xb1 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xb4 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xb7 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xba */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xbd */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xc0 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xc3 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xc6 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xc9 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xcc */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xcf */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xd2 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xd5 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xd8 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xdb */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xde */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xe1 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xe4 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xe7 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xea */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xed */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xf0 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xf3 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xf6 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xf9 */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xfc */ "\000\000\002\000" "\000\000\002\000" "\000\000\002\000"
+ /* 0xff */ "\000\000\002\000"
;
const u_int32_t _nl_C_LC_CTYPE_toupper[384] =
{
@@ -364,10 +364,115 @@ const struct locale_data _nl_C_LC_CTYPE =
#endif
{ word: 256 }, { word: 1 },
{ string: "upper\0" "lower\0" "alpha\0" "digit\0" "xdigit\0" "space\0"
- "print\0" "graph\0" "blank\0" "cntrl\0" "punct\0" "alnum\0" },
- { string: "tolower\0" "toupper\0" },
+ "print\0" "graph\0" "blank\0" "cntrl\0" "punct\0" "alnum\0"
+ "left_to_right\0" "right_to_left\0" "num_terminator\0"
+ "num_separator\0" "segment_separator\0" "block_separator\0"
+ "direction_control\0" "sym_swap_layout\0" "char_shape_selector\0"
+ "num_share_selector\0" "non_spacing\0" "non_spacing_level3\0"
+ "r_connect\0" "no_connect\0" "no_connect-space\0"
+ "vowel_connect\0" },
+ { string: "tolower\0" "toupper\0" "tosymmetric\0" },
{ string: _nl_C_LC_CTYPE_width },
{ word: 1 },
- { string: "ANSI_X3.4-1968" }
+ { string: "ANSI_X3.4-1968" },
+ { word: 1 },
+ { string: "0" },
+ { string: "1" },
+ { string: "2" },
+ { string: "3" },
+ { string: "4" },
+ { string: "5" },
+ { string: "6" },
+ { string: "7" },
+ { string: "8" },
+ { string: "9" },
+#if BYTE_ORDER == LITTLE_ENDIAN
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+#endif
+ { wstr: (uint32_t *) L"0" },
+ { wstr: (uint32_t *) L"1" },
+ { wstr: (uint32_t *) L"2" },
+ { wstr: (uint32_t *) L"3" },
+ { wstr: (uint32_t *) L"4" },
+ { wstr: (uint32_t *) L"5" },
+ { wstr: (uint32_t *) L"6" },
+ { wstr: (uint32_t *) L"7" },
+ { wstr: (uint32_t *) L"8" },
+ { wstr: (uint32_t *) L"9" },
+#if BYTE_ORDER == BIG_ENDIAN
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+ { wstr: (uint32_t *) L"" },
+#endif
+ { string: "0" },
+ { string: "1" },
+ { string: "2" },
+ { string: "3" },
+ { string: "4" },
+ { string: "5" },
+ { string: "6" },
+ { string: "7" },
+ { string: "8" },
+ { string: "9" },
+#if BYTE_ORDER == LITTLE_ENDIAN
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+#endif
+ { word: L'0' },
+ { word: L'1' },
+ { word: L'2' },
+ { word: L'3' },
+ { word: L'4' },
+ { word: L'5' },
+ { word: L'6' },
+ { word: L'7' },
+ { word: L'8' },
+ { word: L'9' },
+#if BYTE_ORDER == BIG_ENDIAN
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+ { word: L'\0' },
+#endif
+ { word: 0 },
+ { word: 0 },
+ { word: 0 },
+ { word: 0 },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" }
}
};
diff --git a/locale/C-identification.c b/locale/C-identification.c
new file mode 100644
index 0000000000..10d9ae9b8d
--- /dev/null
+++ b/locale/C-identification.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <endian.h>
+
+#include "localeinfo.h"
+
+/* This table's entries are taken from ISO 14652, the table in section
+ 4.12 "LC_IDENTIFICATION". */
+
+const struct locale_data _nl_C_LC_IDENTIFICATION =
+{
+ _nl_C_name,
+ NULL, 0, 0, /* no file mapped */
+ UNDELETABLE,
+ 15,
+ {
+ { string: "ISO/IEC 14652 i18n FDCC-set" },
+ { string: "ISO/IEC JTC1/SC22/WG20 - internationalization" },
+ { string: "C/o Keld Simonsen, Skt. Jorgens Alle 8, DK-1615 Kobenhavn V" },
+ { string: "Keld Simonsen" },
+ { string: "keld@dkuug.dk" },
+ { string: "+45 3122-6543" },
+ { string: "+45 3325-6543" },
+ { string: "" },
+ { string: "ISO" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "1.0" },
+ { string: "1997-12-20" },
+ { string: "i18n:1999\0" "i18n:1999\0" "i18n:1999\0" "i18n:1999\0"
+ "i18n:1999\0" "i18n:1999\0" "\0" "i18n:1999\0"
+ "i18n:1999\0" "i18n:1999\0" "i18n:1999\0" "i18n:1999\0"
+ "i18n:1999\0" "i18n:1999\0" "i18n:1999\0" "i18n:1999\0"
+ "i18n:1999" }
+ }
+};
diff --git a/locale/C-measurement.c b/locale/C-measurement.c
new file mode 100644
index 0000000000..37db30d939
--- /dev/null
+++ b/locale/C-measurement.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <endian.h>
+
+#include "localeinfo.h"
+
+/* This table's entries are taken from ISO 14652, the table in section
+ 4.12 "LC_MEASUREMENT". */
+
+const struct locale_data _nl_C_LC_MEASUREMENT =
+{
+ _nl_C_name,
+ NULL, 0, 0, /* no file mapped */
+ UNDELETABLE,
+ 1,
+ {
+ { string: "\1" }
+ }
+};
diff --git a/locale/C-messages.c b/locale/C-messages.c
index 87e40e508f..0363020476 100644
--- a/locale/C-messages.c
+++ b/locale/C-messages.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
@@ -33,7 +33,7 @@ const struct locale_data _nl_C_LC_MESSAGES =
{
{ string: "^[yY]" },
{ string: "^[nN]" },
- { string: "yes" },
- { string: "no" }
+ { string: "" },
+ { string: "" }
}
};
diff --git a/locale/C-monetary.c b/locale/C-monetary.c
index 0133319740..3cb1a57b4e 100644
--- a/locale/C-monetary.c
+++ b/locale/C-monetary.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
@@ -20,7 +20,8 @@
#include "localeinfo.h"
/* This table's entries are taken from POSIX.2 Table 2-9
- ``LC_MONETARY Category Definition in the POSIX Locale''. */
+ ``LC_MONETARY Category Definition in the POSIX Locale'',
+ with additions from ISO 14652, section 4.4. */
#ifdef __CHAR_UNSIGNED__
static const char not_available[] = "\377";
#else
@@ -32,7 +33,7 @@ const struct locale_data _nl_C_LC_MONETARY =
_nl_C_name,
NULL, 0, 0, /* no file mapped */
UNDELETABLE,
- 15,
+ 49,
{
{ string: "" },
{ string: "" },
@@ -48,6 +49,34 @@ const struct locale_data _nl_C_LC_MONETARY =
{ string: not_available },
{ string: not_available },
{ string: not_available },
- { string: not_available }
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: "" },
+ { string: "" },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { string: not_available },
+ { word: 10101 },
+ { word: 99991231 },
+ { word: 10101 },
+ { word: 99991231 },
+ { word: 1 },
+ { word: 1 }
}
};
diff --git a/locale/C-name.c b/locale/C-name.c
new file mode 100644
index 0000000000..4b31370a8c
--- /dev/null
+++ b/locale/C-name.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <endian.h>
+
+#include "localeinfo.h"
+
+/* This table's entries are taken from ISO 14652, the table in section
+ 4.9 "LC_NAME". */
+
+const struct locale_data _nl_C_LC_NAME =
+{
+ _nl_C_name,
+ NULL, 0, 0, /* no file mapped */
+ UNDELETABLE,
+ 6,
+ {
+ { string: "%p%t%g%t%m%t%f" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" },
+ { string: "" }
+ }
+};
diff --git a/locale/C-paper.c b/locale/C-paper.c
new file mode 100644
index 0000000000..9bd1cdcbdb
--- /dev/null
+++ b/locale/C-paper.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <endian.h>
+
+#include "localeinfo.h"
+
+/* This table's entries are taken from ISO 14652, the table in section
+ 4.8 "LC_PAPER". */
+
+const struct locale_data _nl_C_LC_PAPER =
+{
+ _nl_C_name,
+ NULL, 0, 0, /* no file mapped */
+ UNDELETABLE,
+ 4,
+ {
+ { word: 297 },
+ { word: 297 },
+ { word: 210 },
+ { word: 210 }
+ }
+};
diff --git a/locale/C-telephone.c b/locale/C-telephone.c
new file mode 100644
index 0000000000..9647ac0da4
--- /dev/null
+++ b/locale/C-telephone.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <endian.h>
+
+#include "localeinfo.h"
+
+/* This table's entries are taken from ISO 14652, the table in section
+ 4.11 "LC_TELEPHONE". */
+
+const struct locale_data _nl_C_LC_TELEPHONE =
+{
+ _nl_C_name,
+ NULL, 0, 0, /* no file mapped */
+ UNDELETABLE,
+ 4,
+ {
+ { string: "+%c %a %l" },
+ { string: "" },
+ { string: "" },
+ { string: "" }
+ }
+};
diff --git a/locale/C-time.c b/locale/C-time.c
index 6a846e4cae..34ed40507f 100644
--- a/locale/C-time.c
+++ b/locale/C-time.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
@@ -20,14 +20,15 @@
#include "localeinfo.h"
/* This table's entries are taken from POSIX.2 Table 2-11
- ``LC_TIME Category Definition in the POSIX Locale''. */
+ ``LC_TIME Category Definition in the POSIX Locale'',
+ with additions from ISO 14652, section 4.6. */
const struct locale_data _nl_C_LC_TIME =
{
_nl_C_name,
NULL, 0, 0, /* no file mapped */
UNDELETABLE,
- 104,
+ 62,
{
{ string: "Sun" },
{ string: "Mon" },
@@ -80,58 +81,65 @@ const struct locale_data _nl_C_LC_TIME =
{ string: "" },
{ string: "" },
{ word: 0 },
- { word: 0 },
- { string: "" },
- { string: "" },
- { wstr: L"Sun" },
- { wstr: L"Mon" },
- { wstr: L"Tue" },
- { wstr: L"Wed" },
- { wstr: L"Thu" },
- { wstr: L"Fri" },
- { wstr: L"Sat" },
- { wstr: L"Sunday" },
- { wstr: L"Monday" },
- { wstr: L"Tuesday" },
- { wstr: L"Wednesday" },
- { wstr: L"Thursday" },
- { wstr: L"Friday" },
- { wstr: L"Saturday" },
- { wstr: L"Jan" },
- { wstr: L"Feb" },
- { wstr: L"Mar" },
- { wstr: L"Apr" },
- { wstr: L"May" },
- { wstr: L"Jun" },
- { wstr: L"Jul" },
- { wstr: L"Aug" },
- { wstr: L"Sep" },
- { wstr: L"Oct" },
- { wstr: L"Nov" },
- { wstr: L"Dec" },
- { wstr: L"January" },
- { wstr: L"February" },
- { wstr: L"March" },
- { wstr: L"April" },
- { wstr: L"May" },
- { wstr: L"June" },
- { wstr: L"July" },
- { wstr: L"August" },
- { wstr: L"September" },
- { wstr: L"October" },
- { wstr: L"November" },
- { wstr: L"December" },
- { wstr: L"AM" },
- { wstr: L"PM" },
- { wstr: L"%a %b %e %H:%M:%S %Y" },
- { wstr: L"%m/%d/%y" },
- { wstr: L"%H:%M:%S" },
- { wstr: L"%I:%M:%S %p" },
- { string: NULL },
- { string: "" },
- { string: "" },
- { string: "" },
{ string: "" },
{ string: "" },
+ { wstr: (const uint32_t *) L"Sun" },
+ { wstr: (const uint32_t *) L"Mon" },
+ { wstr: (const uint32_t *) L"Tue" },
+ { wstr: (const uint32_t *) L"Wed" },
+ { wstr: (const uint32_t *) L"Thu" },
+ { wstr: (const uint32_t *) L"Fri" },
+ { wstr: (const uint32_t *) L"Sat" },
+ { wstr: (const uint32_t *) L"Sunday" },
+ { wstr: (const uint32_t *) L"Monday" },
+ { wstr: (const uint32_t *) L"Tuesday" },
+ { wstr: (const uint32_t *) L"Wednesday" },
+ { wstr: (const uint32_t *) L"Thursday" },
+ { wstr: (const uint32_t *) L"Friday" },
+ { wstr: (const uint32_t *) L"Saturday" },
+ { wstr: (const uint32_t *) L"Jan" },
+ { wstr: (const uint32_t *) L"Feb" },
+ { wstr: (const uint32_t *) L"Mar" },
+ { wstr: (const uint32_t *) L"Apr" },
+ { wstr: (const uint32_t *) L"May" },
+ { wstr: (const uint32_t *) L"Jun" },
+ { wstr: (const uint32_t *) L"Jul" },
+ { wstr: (const uint32_t *) L"Aug" },
+ { wstr: (const uint32_t *) L"Sep" },
+ { wstr: (const uint32_t *) L"Oct" },
+ { wstr: (const uint32_t *) L"Nov" },
+ { wstr: (const uint32_t *) L"Dec" },
+ { wstr: (const uint32_t *) L"January" },
+ { wstr: (const uint32_t *) L"February" },
+ { wstr: (const uint32_t *) L"March" },
+ { wstr: (const uint32_t *) L"April" },
+ { wstr: (const uint32_t *) L"May" },
+ { wstr: (const uint32_t *) L"June" },
+ { wstr: (const uint32_t *) L"July" },
+ { wstr: (const uint32_t *) L"August" },
+ { wstr: (const uint32_t *) L"September" },
+ { wstr: (const uint32_t *) L"October" },
+ { wstr: (const uint32_t *) L"November" },
+ { wstr: (const uint32_t *) L"December" },
+ { wstr: (const uint32_t *) L"AM" },
+ { wstr: (const uint32_t *) L"PM" },
+ { wstr: (const uint32_t *) L"%a %b %e %H:%M:%S %Y" },
+ { wstr: (const uint32_t *) L"%m/%d/%y" },
+ { wstr: (const uint32_t *) L"%H:%M:%S" },
+ { wstr: (const uint32_t *) L"%I:%M:%S %p" },
+ { wstr: NULL },
+ { wstr: (const uint32_t *) L"" },
+ { wstr: (const uint32_t *) L"" },
+ { wstr: (const uint32_t *) L"" },
+ { wstr: (const uint32_t *) L"" },
+ { wstr: (const uint32_t *) L"" },
+ { string: "\7" },
+ { word: 19971130 },
+ { word: 19971130 },
+ { string: "\7" },
+ { string: "\1" },
+ { string: "\7" },
+ { string: "\1" },
+ { string: "" }
}
};
diff --git a/locale/Makefile b/locale/Makefile
index 0f97c0aa66..622d7f1873 100644
--- a/locale/Makefile
+++ b/locale/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991, 92, 95, 96, 97, 98 Free Software Foundation, Inc.
+# Copyright (C) 1991, 92, 95, 96, 97, 98, 99 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
@@ -22,22 +22,26 @@
subdir := locale
headers = locale.h langinfo.h xlocale.h
-distribute = localeinfo.h categories.def iso-4217.def weight.h \
- strlen-hash.h \
+distribute = localeinfo.h categories.def iso-639.def iso-3166.def \
+ iso-4217.def weight.h strlen-hash.h \
$(addprefix programs/, \
locale.c localedef.c \
$(localedef-modules:=.c) $(locale-modules:=.c) \
$(lib-modules:=.c) config.h simple-hash.h \
charmap-kw.gperf charmap-kw.h locfile-token.h \
locfile-kw.gperf locfile-kw.h linereader.h \
- locales.h locfile.h stringtrans.h charset.h \
+ locales.h locfile.h stringtrans.h charmap.h \
repertoire.h)
routines = setlocale findlocale loadlocale localeconv nl_langinfo \
mb_cur_max codeset_name \
newlocale duplocale freelocale
-categories = ctype messages monetary numeric time collate
+#categories = ctype messages monetary numeric time collate paper name \
+# address telephone measurement versions
+categories = ctype messages monetary numeric time paper name \
+ address telephone measurement identification collate
aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name
-others = localedef locale
+# XXX For testing this is now others-static instead of others.
+others-static = localedef locale
install-bin = localedef locale
extra-objs = $(localedef-modules:=.o) $(locale-modules:=.o) \
$(lib-modules:=.o)
@@ -52,14 +56,14 @@ vpath %.c programs
vpath %.h programs
vpath %.gperf programs
-localedef-modules := $(categories:%=ld-%) charmap charset linereader \
- locfile stringtrans repertoire
+localedef-modules := $(categories:%=ld-%) charmap linereader locfile \
+ repertoire
locale-modules := locale-spec
lib-modules := simple-hash xmalloc xstrdup
GPERF = gperf
-GPERFFLAGS = -acCgopt -k1,2,5,$$
+GPERFFLAGS = -acCgopt -k1,2,5,9,$$ -L ANSI-C
include ../Rules
@@ -73,13 +77,13 @@ $(objpfx)localedef $(objpfx)locale: $(lib-modules:%=$(objpfx)%.o)
localepath = "$(localedir):$(i18ndir)"
-locale-CPPFLAGS := -DLOCALE_PATH='$(localepath)' \
- -DLOCALEDIR='"$(localedir)"' \
- -DLOCALE_ALIAS_PATH='"$(localedir):$(i18ndir)"' \
- -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \
- -DREPERTOIREMAP_PATH='"$(i18ndir)/repertoiremaps"' \
- -DLOCSRCDIR='"$(i18ndir)/locales"' -DHAVE_CONFIG_H \
- -Iprograms
+CPPFLAGS := -DLOCALE_PATH='$(localepath)' \
+ -DLOCALEDIR='"$(localedir)"' \
+ -DLOCALE_ALIAS_PATH='"$(localedir):$(i18ndir)"' \
+ -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \
+ -DREPERTOIREMAP_PATH='"$(i18ndir)/repertoiremaps"' \
+ -DLOCSRCDIR='"$(i18ndir)/locales"' -DHAVE_CONFIG_H \
+ -Iprograms $(CPPFLAGS)
CFLAGS-charmap.c = -Wno-write-strings -Wno-char-subscripts
CFLAGS-locfile.c = -Wno-write-strings -Wno-char-subscripts
diff --git a/locale/categories.def b/locale/categories.def
index 160331fb0d..36020cf1a6 100644
--- a/locale/categories.def
+++ b/locale/categories.def
@@ -1,5 +1,5 @@
/* Definition of all available locale categories and their items. -*- C -*-
- Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -21,8 +21,7 @@
The general format of the descriptions is like this:
- DEFINE_CATEGORY (ID, name, ( items ), setlocale-postload,
- locale-input, locale-check, locale-output)
+ DEFINE_CATEGORY (ID, name, ( items ), setlocale-postload)
where items itself is an array of entries in the form
@@ -43,28 +42,28 @@ DEFINE_CATEGORY
(
LC_COLLATE, "LC_COLLATE",
(
- DEFINE_ELEMENT (_NL_COLLATE_NRULES, "collate-nrules", std, word)
- DEFINE_ELEMENT (_NL_COLLATE_RULES, "collate-rules", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_HASH_SIZE, "collate-hash-size", std, word)
+ DEFINE_ELEMENT (_NL_COLLATE_NRULES, "collate-nrules", std, word)
+ DEFINE_ELEMENT (_NL_COLLATE_RULES, "collate-rules", std, string)
+ DEFINE_ELEMENT (_NL_COLLATE_HASH_SIZE, "collate-hash-size", std, word)
DEFINE_ELEMENT (_NL_COLLATE_HASH_LAYERS, "collate-hash-layers", std, word)
- DEFINE_ELEMENT (_NL_COLLATE_TABLE_EB, "collate-table-eb", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_TABLE_EL, "collate-table-el", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_UNDEFINED, "collate-undefined", std, word)
- DEFINE_ELEMENT (_NL_COLLATE_EXTRA_EB, "collate-extra-eb", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_EXTRA_EL, "collate-extra-el", std, string)
+ DEFINE_ELEMENT (_NL_COLLATE_TABLEWC_EB, "collate-tablewc-eb", std, string)
+ DEFINE_ELEMENT (_NL_COLLATE_TABLEWC_EL, "collate-tablewc-el", std, string)
+ DEFINE_ELEMENT (_NL_COLLATE_UNDEFINED_WC, "collate-undefined-wc", std, word)
+ DEFINE_ELEMENT (_NL_COLLATE_EXTRAWC_EB, "collate-extrawc-eb", std, string)
+ DEFINE_ELEMENT (_NL_COLLATE_EXTRAWC_EL, "collate-extrawc-el", std, string)
DEFINE_ELEMENT (_NL_COLLATE_ELEM_HASH_SIZE, "collate-elem-hash-size", std, word)
DEFINE_ELEMENT (_NL_COLLATE_ELEM_HASH_EB, "collate-elem-hash-eb", std, string)
DEFINE_ELEMENT (_NL_COLLATE_ELEM_HASH_EL, "collate-elem-hash-el", std, string)
DEFINE_ELEMENT (_NL_COLLATE_ELEM_STR_POOL, "collate-elem-str-pool", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_ELEM_VAL_EB, "collate-elem-val-eb", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_ELEM_VAL_EL, "collate-elem-val-el", std, string)
+ DEFINE_ELEMENT (_NL_COLLATE_ELEM_VAL_EB, "collate-elem-val-eb", std, string)
+ DEFINE_ELEMENT (_NL_COLLATE_ELEM_VAL_EL, "collate-elem-val-el", std, string)
DEFINE_ELEMENT (_NL_COLLATE_SYMB_HASH_SIZE, "collate-symb-hash-size", std, word)
DEFINE_ELEMENT (_NL_COLLATE_SYMB_HASH_EB, "collate-symb-hash-eb", std, string)
DEFINE_ELEMENT (_NL_COLLATE_SYMB_HASH_EL, "collate-symb-hash-el", std, string)
DEFINE_ELEMENT (_NL_COLLATE_SYMB_STR_POOL, "collate-symb-str-pool", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_SYMB_CLASS_EB, "collate-symb-class-eb", std, string)
- DEFINE_ELEMENT (_NL_COLLATE_SYMB_CLASS_EL, "collate-symb-class-el", std, string)
- ), _nl_postload_collate, collate_input, NULL, NULL)
+ DEFINE_ELEMENT (_NL_COLLATE_SYMB_CLASSWC_EB, "collate-symb-classwc-eb", std, string)
+ DEFINE_ELEMENT (_NL_COLLATE_SYMB_CLASSWC_EL, "collate-symb-classwc-el", std, string)
+ ), _nl_postload_collate)
/* The actual definition of ctype is meaningless here. It is hard coded in
@@ -74,44 +73,79 @@ DEFINE_CATEGORY
(
LC_CTYPE, "LC_CTYPE",
(
- DEFINE_ELEMENT (_NL_CTYPE_CLASS, "ctype-class", std, string)
- DEFINE_ELEMENT (_NL_CTYPE_TOUPPER_EB, "ctype-toupper-eb", std, string)
- DEFINE_ELEMENT (_NL_CTYPE_TOLOWER_EB, "ctype-tolower-eb", std, string)
- DEFINE_ELEMENT (_NL_CTYPE_TOUPPER_EL, "ctype-toupper-el", std, string)
- DEFINE_ELEMENT (_NL_CTYPE_TOLOWER_EL, "ctype-tolower-el", std, string)
- DEFINE_ELEMENT (_NL_CTYPE_CLASS32, "ctype-class32", std, string)
- DEFINE_ELEMENT (_NL_CTYPE_NAMES_EB, "ctype-names-eb", std, string)
- DEFINE_ELEMENT (_NL_CTYPE_NAMES_EL, "ctype-names-el", std, string)
- DEFINE_ELEMENT (_NL_CTYPE_HASH_SIZE, "ctype-hash-size", std, word)
- DEFINE_ELEMENT (_NL_CTYPE_HASH_LAYERS, "ctype-hash-layers", std, word)
- DEFINE_ELEMENT (_NL_CTYPE_CLASS_NAMES, "ctype-class-names", std, stringlist)
- DEFINE_ELEMENT (_NL_CTYPE_MAP_NAMES, "ctype-map-names", std, stringlist)
- DEFINE_ELEMENT (_NL_CTYPE_WIDTH, "ctype-width", std, bytearray)
- DEFINE_ELEMENT (_NL_CTYPE_MB_CUR_MAX, "ctype-mb-cur-max", std, word)
- DEFINE_ELEMENT (_NL_CTYPE_CODESET_NAME, "charmap", std, string)
- ), _nl_postload_ctype, ctype_input, ctype_check, ctype_output)
+ DEFINE_ELEMENT (_NL_CTYPE_CLASS, "ctype-class", std, string)
+ DEFINE_ELEMENT (_NL_CTYPE_TOUPPER_EB, "ctype-toupper-eb", std, string)
+ DEFINE_ELEMENT (_NL_CTYPE_TOLOWER_EB, "ctype-tolower-eb", std, string)
+ DEFINE_ELEMENT (_NL_CTYPE_TOUPPER_EL, "ctype-toupper-el", std, string)
+ DEFINE_ELEMENT (_NL_CTYPE_TOLOWER_EL, "ctype-tolower-el", std, string)
+ DEFINE_ELEMENT (_NL_CTYPE_CLASS32, "ctype-class32", std, string)
+ DEFINE_ELEMENT (_NL_CTYPE_NAMES_EB, "ctype-names-eb", std, string)
+ DEFINE_ELEMENT (_NL_CTYPE_NAMES_EL, "ctype-names-el", std, string)
+ DEFINE_ELEMENT (_NL_CTYPE_HASH_SIZE_EB, "ctype-hash-size-eb", std, word)
+ DEFINE_ELEMENT (_NL_CTYPE_HASH_SIZE_EL, "ctype-hash-size-el", std, word)
+ DEFINE_ELEMENT (_NL_CTYPE_HASH_LAYERS_EB, "ctype-hash-layers-eb", std, word)
+ DEFINE_ELEMENT (_NL_CTYPE_HASH_LAYERS_EL, "ctype-hash-layers-el", std, word)
+ DEFINE_ELEMENT (_NL_CTYPE_CLASS_NAMES, "ctype-class-names", std, stringlist)
+ DEFINE_ELEMENT (_NL_CTYPE_MAP_NAMES, "ctype-map-names", std, stringlist)
+ DEFINE_ELEMENT (_NL_CTYPE_WIDTH, "ctype-width", std, bytearray)
+ DEFINE_ELEMENT (_NL_CTYPE_MB_CUR_MAX, "ctype-mb-cur-max", std, word)
+ DEFINE_ELEMENT (_NL_CTYPE_CODESET_NAME, "charmap", std, string)
+ ), _nl_postload_ctype)
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define _NL_MONETARY_CONVERSION_RATE _NL_MONETARY_CONVERSION_RATE_EB
+#else
+# define _NL_MONETARY_CONVERSION_RATE _NL_MONETARY_CONVERSION_RATE_EL
+#endif
DEFINE_CATEGORY
(
LC_MONETARY, "LC_MONETARY",
(
- DEFINE_ELEMENT (INT_CURR_SYMBOL, "int_curr_symbol", std, string)
- DEFINE_ELEMENT (CURRENCY_SYMBOL, "currency_symbol", std, string)
- DEFINE_ELEMENT (MON_DECIMAL_POINT, "mon_decimal_point", std, string)
- DEFINE_ELEMENT (MON_THOUSANDS_SEP, "mon_thousands_sep", std, string)
- DEFINE_ELEMENT (MON_GROUPING, "mon_grouping", std, bytearray)
- DEFINE_ELEMENT (POSITIVE_SIGN, "positive_sign", std, string)
- DEFINE_ELEMENT (NEGATIVE_SIGN, "negative_sign", std, string)
- DEFINE_ELEMENT (INT_FRAC_DIGITS, "int_frac_digits", std, byte)
- DEFINE_ELEMENT (FRAC_DIGITS, "frac_digits", std, byte)
- DEFINE_ELEMENT (P_CS_PRECEDES, "p_cs_precedes", std, byte, 0, 1)
- DEFINE_ELEMENT (P_SEP_BY_SPACE, "p_sep_by_space", std, byte, 0, 2)
- DEFINE_ELEMENT (N_CS_PRECEDES, "n_cs_precedes", std, byte, 0, 1)
- DEFINE_ELEMENT (N_SEP_BY_SPACE, "n_sep_by_space", std, byte, 0, 2)
- DEFINE_ELEMENT (P_SIGN_POSN, "p_sign_posn", std, byte, 0, 4)
- DEFINE_ELEMENT (N_SIGN_POSN, "n_sign_posn", std, byte, 0, 4)
- ), NO_POSTLOAD, NULL, monetary_check, NULL)
+ DEFINE_ELEMENT (INT_CURR_SYMBOL, "int_curr_symbol", std, string)
+ DEFINE_ELEMENT (CURRENCY_SYMBOL, "currency_symbol", std, string)
+ DEFINE_ELEMENT (MON_DECIMAL_POINT, "mon_decimal_point", std, string)
+ DEFINE_ELEMENT (MON_THOUSANDS_SEP, "mon_thousands_sep", std, string)
+ DEFINE_ELEMENT (MON_GROUPING, "mon_grouping", std, bytearray)
+ DEFINE_ELEMENT (POSITIVE_SIGN, "positive_sign", std, string)
+ DEFINE_ELEMENT (NEGATIVE_SIGN, "negative_sign", std, string)
+ DEFINE_ELEMENT (INT_FRAC_DIGITS, "int_frac_digits", std, byte)
+ DEFINE_ELEMENT (FRAC_DIGITS, "frac_digits", std, byte)
+ DEFINE_ELEMENT (P_CS_PRECEDES, "p_cs_precedes", std, byte, 0, 1)
+ DEFINE_ELEMENT (P_SEP_BY_SPACE, "p_sep_by_space", std, byte, 0, 2)
+ DEFINE_ELEMENT (N_CS_PRECEDES, "n_cs_precedes", std, byte, 0, 1)
+ DEFINE_ELEMENT (N_SEP_BY_SPACE, "n_sep_by_space", std, byte, 0, 2)
+ DEFINE_ELEMENT (P_SIGN_POSN, "p_sign_posn", std, byte, 0, 4)
+ DEFINE_ELEMENT (N_SIGN_POSN, "n_sign_posn", std, byte, 0, 4)
+ DEFINE_ELEMENT (_NL_MONETARY_INT_P_CS_PRECEDES, "int_p_cs_precedes", std, byte, 0, 1)
+ DEFINE_ELEMENT (_NL_MONETARY_INT_P_SEP_BY_SPACE, "int_p_sep_by_space", std, byte, 0, 2)
+ DEFINE_ELEMENT (_NL_MONETARY_INT_N_CS_PRECEDES, "int_n_cs_precedes", std, byte, 0, 1)
+ DEFINE_ELEMENT (_NL_MONETARY_INT_N_SEP_BY_SPACE, "int_n_sep_by_space", std, byte, 0, 2)
+ DEFINE_ELEMENT (_NL_MONETARY_INT_P_SIGN_POSN, "int_p_sign_posn", std, byte, 0, 4)
+ DEFINE_ELEMENT (_NL_MONETARY_INT_N_SIGN_POSN, "int_n_sign_posn", std, byte, 0, 4)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_CURR_SYMBOL, "duo_int_curr_symbol", std, string)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_CURRENCY_SYMBOL, "duo_currency_symbol", std, string)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_FRAC_DIGITS, "duo_int_frac_digits", std, byte)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_FRAC_DIGITS, "duo_frac_digits", std, byte)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_P_CS_PRECEDES, "duo_p_cs_precedes", std, byte, 0, 1)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_P_SEP_BY_SPACE, "duo_p_sep_by_space", std, byte, 0, 2)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_N_CS_PRECEDES, "duo_n_cs_precedes", std, byte, 0, 1)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_N_SEP_BY_SPACE, "duo_n_sep_by_space", std, byte, 0, 2)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_CS_PRECEDES, "duo_int_p_cs_precedes", std, byte, 0, 1)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE, "duo_int_p_sep_by_space", std, byte, 0, 2)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_CS_PRECEDES, "duo_int_n_cs_precedes", std, byte, 0, 1)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE, "duo_int_n_sep_by_space", std, byte, 0, 2)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_P_SIGN_POSN, "duo_p_sign_posn", std, byte, 0, 4)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_N_SIGN_POSN, "duo_n_sign_posn", std, byte, 0, 4)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_SIGN_POSN, "duo_int_p_sign_posn", std, byte, 0, 4)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_SIGN_POSN, "duo_int_n_sign_posn", std, byte, 0, 4)
+ DEFINE_ELEMENT (_NL_MONETARY_UNO_VALID_FROM, "uno_valid_from", std, word)
+ DEFINE_ELEMENT (_NL_MONETARY_UNO_VALID_TO, "uno_valid_to", std, word)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_VALID_FROM, "duo_valid_from", std, word)
+ DEFINE_ELEMENT (_NL_MONETARY_DUO_VALID_TO, "duo_valid_to", std, word)
+ DEFINE_ELEMENT (_NL_MONETARY_CONVERSION_RATE_EB, "conversion_rate-eb", std, wordarray, 2, 2)
+ DEFINE_ELEMENT (_NL_MONETARY_CONVERSION_RATE_EL, "conversion_rate-el", std, wordarray, 2, 2)
+ ), NO_POSTLOAD)
DEFINE_CATEGORY
@@ -121,7 +155,7 @@ DEFINE_CATEGORY
DEFINE_ELEMENT (DECIMAL_POINT, "decimal_point", std, string)
DEFINE_ELEMENT (THOUSANDS_SEP, "thousands_sep", std, string)
DEFINE_ELEMENT (GROUPING, "grouping", std, bytearray)
- ), NO_POSTLOAD, NULL, numeric_check, NULL)
+ ), NO_POSTLOAD)
DEFINE_CATEGORY
@@ -143,34 +177,133 @@ DEFINE_CATEGORY
DEFINE_ELEMENT (ALT_DIGITS, "alt_digits", opt, stringarray, 0, 100)
DEFINE_ELEMENT (ERA_D_T_FMT, "era_d_t_fmt", opt, string)
DEFINE_ELEMENT (ERA_T_FMT, "era_t_fmt", opt, string)
- DEFINE_ELEMENT (_NL_TIME_NUM_ALT_DIGITS, "time-num-alt-digits", opt, word)
- DEFINE_ELEMENT (_NL_TIME_ERA_NUM_ENTRIES, "time-era-num-entries", opt, word)
+ DEFINE_ELEMENT (_NL_TIME_ERA_NUM_ENTRIES_EB, "time-era-num-entries-eb", opt, word)
+ DEFINE_ELEMENT (_NL_TIME_ERA_NUM_ENTRIES_EL, "time-era-num-entries-el", opt, word)
DEFINE_ELEMENT (_NL_TIME_ERA_ENTRIES_EB, "time-era-entries-eb", opt, string)
DEFINE_ELEMENT (_NL_TIME_ERA_ENTRIES_EL, "time-era-entries-el", opt, string)
- DEFINE_ELEMENT (_NL_WABDAY_1, "wide-abday", std, stringarray, 7, 7)
- DEFINE_ELEMENT (_NL_WDAY_1, "wide-day", std, stringarray, 7, 7)
- DEFINE_ELEMENT (_NL_WABMON_1, "wide-abmon", std, stringarray, 12, 12)
- DEFINE_ELEMENT (_NL_WMON_1, "wide-mon", std, stringarray, 12, 12)
- DEFINE_ELEMENT (_NL_WAM_STR, "wide-am_pm", std, stringarray, 2, 2)
- DEFINE_ELEMENT (_NL_WD_T_FMT, "wide-d_t_fmt", std, string)
- DEFINE_ELEMENT (_NL_WD_FMT, "wide-d_fmt", std, string)
- DEFINE_ELEMENT (_NL_WT_FMT, "wide-t_fmt", std, string)
- DEFINE_ELEMENT (_NL_WT_FMT_AMPM, "wide-t_fmt_ampm", std, string)
- DEFINE_ELEMENT (_NL_WERA, "wide-era", opt, stringarray)
- DEFINE_ELEMENT (_NL_WERA_YEAR, "wide-era_year", opt, string)
- DEFINE_ELEMENT (_NL_WERA_D_FMT, "wide-era_d_fmt", opt, string)
- DEFINE_ELEMENT (_NL_WALT_DIGITS, "wide-alt_digits", opt, stringarray, 0, 100)
- DEFINE_ELEMENT (_NL_WERA_D_T_FMT, "wide-era_d_t_fmt", opt, string)
- DEFINE_ELEMENT (_NL_WERA_T_FMT, "wide-era_t_fmt", opt, string)
- ), _nl_postload_time, NULL, NULL, NULL)
+ DEFINE_ELEMENT (_NL_WABDAY_1_EB, "wide-abday-eb", std, stringarray, 7, 7)
+ DEFINE_ELEMENT (_NL_WABDAY_1_EL, "wide-abday-el", std, stringarray, 7, 7)
+ DEFINE_ELEMENT (_NL_WDAY_1_EB, "wide-day-eb", std, stringarray, 7, 7)
+ DEFINE_ELEMENT (_NL_WDAY_1_EL, "wide-day-el", std, stringarray, 7, 7)
+ DEFINE_ELEMENT (_NL_WABMON_1_EB, "wide-abmon-eb", std, stringarray, 12, 12)
+ DEFINE_ELEMENT (_NL_WABMON_1_EL, "wide-abmon-el", std, stringarray, 12, 12)
+ DEFINE_ELEMENT (_NL_WMON_1_EB, "wide-mon-eb", std, stringarray, 12, 12)
+ DEFINE_ELEMENT (_NL_WMON_1_EL, "wide-mon-el", std, stringarray, 12, 12)
+ DEFINE_ELEMENT (_NL_WAM_STR_EB, "wide-am_pm-eb", std, stringarray, 2, 2)
+ DEFINE_ELEMENT (_NL_WAM_STR_EL, "wide-am_pm-el", std, stringarray, 2, 2)
+ DEFINE_ELEMENT (_NL_WD_T_FMT_EB, "wide-d_t_fmt-eb", std, string)
+ DEFINE_ELEMENT (_NL_WD_T_FMT_EL, "wide-d_t_fmt-el", std, string)
+ DEFINE_ELEMENT (_NL_WD_FMT_EB, "wide-d_fmt-eb", std, string)
+ DEFINE_ELEMENT (_NL_WD_FMT_EL, "wide-d_fmt-el", std, string)
+ DEFINE_ELEMENT (_NL_WT_FMT_EB, "wide-t_fmt-eb", std, string)
+ DEFINE_ELEMENT (_NL_WT_FMT_EL, "wide-t_fmt-el", std, string)
+ DEFINE_ELEMENT (_NL_WT_FMT_AMPM_EB, "wide-t_fmt_ampm-eb", std, string)
+ DEFINE_ELEMENT (_NL_WT_FMT_AMPM_EL, "wide-t_fmt_ampm-el", std, string)
+ DEFINE_ELEMENT (_NL_WERA_YEAR_EB, "wide-era_year-eb", opt, string)
+ DEFINE_ELEMENT (_NL_WERA_YEAR_EL, "wide-era_year-el", opt, string)
+ DEFINE_ELEMENT (_NL_WERA_D_FMT_EB, "wide-era_d_fmt-eb", opt, string)
+ DEFINE_ELEMENT (_NL_WERA_D_FMT_EL, "wide-era_d_fmt-el", opt, string)
+ DEFINE_ELEMENT (_NL_WALT_DIGITS_EB, "wide-alt_digits-eb", opt, stringarray, 0, 100)
+ DEFINE_ELEMENT (_NL_WALT_DIGITS_EL, "wide-alt_digits-el", opt, stringarray, 0, 100)
+ DEFINE_ELEMENT (_NL_WERA_D_T_FMT_EB, "wide-era_d_t_fmt-eb", opt, string)
+ DEFINE_ELEMENT (_NL_WERA_D_T_FMT_EL, "wide-era_d_t_fmt-el", opt, string)
+ DEFINE_ELEMENT (_NL_WERA_T_FMT_EB, "wide-era_t_fmt-eb", opt, string)
+ DEFINE_ELEMENT (_NL_WERA_T_FMT_EL, "wide-era_t_fmt-el", opt, string)
+ DEFINE_ELEMENT (_NL_TIME_WEEK_NDAYS, "week-ndays", std, byte)
+ DEFINE_ELEMENT (_NL_TIME_WEEK_1STDAY, "week-1stday", std, word)
+ DEFINE_ELEMENT (_NL_TIME_WEEK_1STWEEK, "week-1stweek", std, byte)
+ DEFINE_ELEMENT (_NL_TIME_FIRST_WEEKDAY, "first_weekday", std, byte)
+ DEFINE_ELEMENT (_NL_TIME_FIRST_WORKDAY, "first_workday", std, byte)
+ DEFINE_ELEMENT (_NL_TIME_CAL_DIRECTION, "cal_direction", std, byte)
+ DEFINE_ELEMENT (_NL_TIME_TIMEZONE, "timezone", std, string)
+ ), _nl_postload_time)
DEFINE_CATEGORY
(
LC_MESSAGES, "LC_MESSAGES",
(
- DEFINE_ELEMENT (YESEXPR, "yesexpr", std, string)
- DEFINE_ELEMENT (NOEXPR, "noexpr", std, string)
- DEFINE_ELEMENT (__YESSTR, "yesstr", opt, string)
- DEFINE_ELEMENT (__NOSTR, "nostr", opt, string)
- ), NO_POSTLOAD, NULL, messages_check, NULL)
+ DEFINE_ELEMENT (YESEXPR, "yesexpr", std, string)
+ DEFINE_ELEMENT (NOEXPR, "noexpr", std, string)
+ DEFINE_ELEMENT (YESSTR, "yesstr", opt, string)
+ DEFINE_ELEMENT (NOSTR, "nostr", opt, string)
+ ), NO_POSTLOAD)
+
+DEFINE_CATEGORY
+(
+ LC_PAPER, "LC_PAPER",
+ (
+ DEFINE_ELEMENT (_NL_PAPER_HEIGHT_EB, "height-eb", std, word)
+ DEFINE_ELEMENT (_NL_PAPER_HEIGHT_EL, "height-el", std, word)
+ DEFINE_ELEMENT (_NL_PAPER_WIDTH_EB, "width-eb", std, word)
+ DEFINE_ELEMENT (_NL_PAPER_WIDTH_EL, "width-el", std, word)
+ ), NO_POSTLOAD)
+
+DEFINE_CATEGORY
+(
+ LC_NAME, "LC_NAME",
+ (
+ DEFINE_ELEMENT (_NL_NAME_NAME_FMT, "name_fmt", std, string)
+ DEFINE_ELEMENT (_NL_NAME_NAME_GEN, "name_gen", std, string)
+ DEFINE_ELEMENT (_NL_NAME_NAME_MR, "name_mr", std, string)
+ DEFINE_ELEMENT (_NL_NAME_NAME_MRS, "name_mrs", std, string)
+ DEFINE_ELEMENT (_NL_NAME_NAME_MISS, "name_miss", std, string)
+ DEFINE_ELEMENT (_NL_NAME_NAME_MS, "name_ms", std, string)
+ ), NO_POSTLOAD)
+
+DEFINE_CATEGORY
+(
+ LC_ADDRESS, "LC_ADDRESS",
+ (
+ DEFINE_ELEMENT (_NL_ADDRESS_POSTAL_FMT, "postal_fmt", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NAME, "country_name", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_POST, "country_post", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_AB2, "country_ab2", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_AB3, "country_ab3", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_CAR, "country_car", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NUM_EB, "country_num-eb", std, word)
+ DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NUM_EL, "country_num-el", std, word)
+ DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_ISBN, "country_isbn", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_LANG_NAME, "lang_name", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_LANG_AB, "lang_ab", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_LANG_TERM, "lang_term", std, string)
+ DEFINE_ELEMENT (_NL_ADDRESS_LANG_LIB, "lang_lib", std, string)
+ ), NO_POSTLOAD)
+
+DEFINE_CATEGORY
+(
+ LC_TELEPHONE, "LC_TELEPHONE",
+ (
+ DEFINE_ELEMENT (_NL_TELEPHONE_TEL_INT_FMT, "tel_int_fmt", std, string)
+ DEFINE_ELEMENT (_NL_TELEPHONE_TEL_DOM_FMT, "tel_dom_fmt", std, string)
+ DEFINE_ELEMENT (_NL_TELEPHONE_INT_SELECT, "int_select", std, string)
+ DEFINE_ELEMENT (_NL_TELEPHONE_INT_PREFIX, "int_prefix", std, string)
+ ), NO_POSTLOAD)
+
+DEFINE_CATEGORY
+(
+ LC_MEASUREMENT, "LC_MEASUREMENT",
+ (
+ DEFINE_ELEMENT (_NL_MEASUREMENT_MEASUREMENT, "measurement", std, byte)
+ ), NO_POSTLOAD)
+
+DEFINE_CATEGORY
+(
+ LC_IDENTIFICATION, "LC_IDENTIFICATION",
+ (
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_TITLE, "title", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_SOURCE, "source", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_ADDRESS, "address", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_CONTACT, "contact", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_EMAIL, "email", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_TEL, "tel", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_FAX, "fax", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_LANGUAGE, "language", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_TERRITORY, "territory", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_AUDIENCE, "audience", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_APPLICATION, "applcation", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_ABBREVIATION, "abbreviation", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_REVISION, "revision", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_DATE, "date", std, string)
+ DEFINE_ELEMENT (_NL_IDENTIFICATION_CATEGORY, "category", std, stringarray, 13, 13)
+ ), NO_POSTLOAD)
diff --git a/locale/findlocale.c b/locale/findlocale.c
index 94f01b4132..c6717f108d 100644
--- a/locale/findlocale.c
+++ b/locale/findlocale.c
@@ -1,6 +1,6 @@
/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -21,9 +21,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#ifdef _POSIX_MAPPED_FILES
-# include <sys/mman.h>
-#endif
+#include <sys/mman.h>
#include "localeinfo.h"
@@ -88,7 +86,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
loc_name = (char *) *name;
/* Make a writable copy of the locale name. */
- loc_name = strdupa (loc_name);
+ loc_name = __strdup (loc_name);
/* LOCALE can consist of up to four recognized parts for the XPG syntax:
@@ -137,6 +135,11 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
/* This means we are out of core. */
return NULL;
}
+ else
+ /* If the addressed locale is already available it should be
+ freed. If we would not do this switching back and force
+ between two locales would slowly eat up all memory. */
+ free ((void *) loc_name);
if (locale_file->decided == 0)
_nl_load_locale (locale_file, category);
@@ -208,7 +211,6 @@ _nl_remove_locale (int locale, struct locale_data *data)
/* Free the name. */
free ((char *) data->name);
-#ifdef _POSIX_MAPPED_FILES
/* Really delete the data. First delete the real data. */
if (data->mmaped)
{
@@ -221,7 +223,6 @@ _nl_remove_locale (int locale, struct locale_data *data)
}
}
else
-#endif /* _POSIX_MAPPED_FILES */
/* The memory was malloced. */
free ((void *) data->filedata);
@@ -235,21 +236,21 @@ free_mem (void)
{
int category;
- for (category = 0; category < LC_ALL; ++category)
- {
- struct loaded_l10nfile *runp = locale_file_list[category];
-
- while (runp != NULL)
- {
- struct loaded_l10nfile *here = runp;
- struct locale_data *data = (struct locale_data *) runp->data;
-
- if (data != NULL && data->usage_count != UNDELETABLE)
- _nl_unload_locale (data);
- runp = runp->next;
- free ((char *) here->filename);
- free (here);
- }
- }
+ for (category = 0; category < __LC_LAST; ++category)
+ if (category != LC_ALL)
+ {
+ struct loaded_l10nfile *runp = locale_file_list[category];
+
+ while (runp != NULL)
+ {
+ struct loaded_l10nfile *here = runp;
+ struct locale_data *data = (struct locale_data *) runp->data;
+
+ if (data != NULL && data->usage_count != UNDELETABLE)
+ _nl_unload_locale (data);
+ runp = runp->next;
+ free (here);
+ }
+ }
}
text_set_element (__libc_subfreeres, free_mem);
diff --git a/locale/iso-3166.def b/locale/iso-3166.def
new file mode 100644
index 0000000000..3a9a45e5b1
--- /dev/null
+++ b/locale/iso-3166.def
@@ -0,0 +1,245 @@
+/*
+ * Defines the country codes and abbreviations according to ISO 3166.
+ * This is used in ld-address.c (address_finish).
+ *
+ * If you find something missing or wrong contact <bug-glibc@gnu.org>
+ */
+DEFINE_COUNTRY_CODE ("AFGHANISTAN", AF, AFG, 4)
+DEFINE_COUNTRY_CODE ("ALBANIA", AL, ALB, 8)
+DEFINE_COUNTRY_CODE ("ALGERIA", DZ, DZA, 12)
+DEFINE_COUNTRY_CODE ("AMERICAN SAMOA", AS, ASM, 16)
+DEFINE_COUNTRY_CODE ("ANDORRA", AD, AND, 20)
+DEFINE_COUNTRY_CODE ("ANGOLA", AO, AGO, 24)
+DEFINE_COUNTRY_CODE ("ANGUILLA", AI, AIA, 660)
+DEFINE_COUNTRY_CODE ("ANTARCTICA", AQ, ATA, 10)
+DEFINE_COUNTRY_CODE ("ANTIGUA AND BARBUDA", AG, ATG, 28)
+DEFINE_COUNTRY_CODE ("ARGENTINA", AR, ARG, 32)
+DEFINE_COUNTRY_CODE ("ARMENIA", AM, ARM, 51)
+DEFINE_COUNTRY_CODE ("ARUBA", AW, ABW, 533)
+DEFINE_COUNTRY_CODE ("AUSTRALIA", AU, AUS, 36)
+DEFINE_COUNTRY_CODE ("AUSTRIA", AT, AUT, 40)
+DEFINE_COUNTRY_CODE ("AZERBAIJAN", AZ, AZE, 31)
+DEFINE_COUNTRY_CODE ("BAHAMAS", BS, BHS, 44)
+DEFINE_COUNTRY_CODE ("BAHRAIN", BH, BHR, 48)
+DEFINE_COUNTRY_CODE ("BANGLADESH", BD, BGD, 50)
+DEFINE_COUNTRY_CODE ("BARBADOS", BB, BRB, 52)
+DEFINE_COUNTRY_CODE ("BELARUS", BY, BLR, 112)
+DEFINE_COUNTRY_CODE ("BELGIUM", BE, BEL, 56)
+DEFINE_COUNTRY_CODE ("BELIZE", BZ, BLZ, 84)
+DEFINE_COUNTRY_CODE ("BENIN", BJ, BEN, 204)
+DEFINE_COUNTRY_CODE ("BERMUDA", BM, BMU, 60)
+DEFINE_COUNTRY_CODE ("BHUTAN", BT, BTN, 64)
+DEFINE_COUNTRY_CODE ("BOLIVIA", BO, BOL, 68)
+DEFINE_COUNTRY_CODE ("BOSNIA AND HERZEGOWINA", BA, BIH, 70)
+DEFINE_COUNTRY_CODE ("BOTSWANA", BW, BWA, 72)
+DEFINE_COUNTRY_CODE ("BOUVET ISLAND", BV, BVT, 74)
+DEFINE_COUNTRY_CODE ("BRAZIL", BR, BRA, 76)
+DEFINE_COUNTRY_CODE ("BRITISH INDIAN OCEAN TERRITORY", IO, IOT, 86)
+DEFINE_COUNTRY_CODE ("BRUNEI DARUSSALAM", BN, BRN, 96)
+DEFINE_COUNTRY_CODE ("BULGARIA", BG, BGR, 100)
+DEFINE_COUNTRY_CODE ("BURKINA FASO", BF, BFA, 854)
+DEFINE_COUNTRY_CODE ("BURUNDI", BI, BDI, 108)
+DEFINE_COUNTRY_CODE ("CAMBODIA", KH, KHM, 116)
+DEFINE_COUNTRY_CODE ("CAMEROON", CM, CMR, 120)
+DEFINE_COUNTRY_CODE ("CANADA", CA, CAN, 124)
+DEFINE_COUNTRY_CODE ("CAPE VERDE", CV, CPV, 132)
+DEFINE_COUNTRY_CODE ("CAYMAN ISLANDS", KY, CYM, 136)
+DEFINE_COUNTRY_CODE ("CENTRAL AFRICAN REPUBLIC", CF, CAF, 140)
+DEFINE_COUNTRY_CODE ("CHAD", TD, TCD, 148)
+DEFINE_COUNTRY_CODE ("CHILE", CL, CHL, 152)
+DEFINE_COUNTRY_CODE ("CHINA", CN, CHN, 156)
+DEFINE_COUNTRY_CODE ("CHRISTMAS ISLAND", CX, CXR, 162)
+DEFINE_COUNTRY_CODE ("COCOS (KEELING) ISLANDS", CC, CCK, 166)
+DEFINE_COUNTRY_CODE ("COLOMBIA", CO, COL, 170)
+DEFINE_COUNTRY_CODE ("COMOROS", KM, COM, 174)
+DEFINE_COUNTRY_CODE ("CONGO", CG, COG, 178)
+DEFINE_COUNTRY_CODE ("CONGO, THE DEMOCRATIC REPUBLIC OF THE", CD, COD, 180)
+DEFINE_COUNTRY_CODE ("COOK ISLANDS", CK, COK, 184)
+DEFINE_COUNTRY_CODE ("COSTA RICA", CR, CRI, 188)
+DEFINE_COUNTRY_CODE ("COTE D'IVOIRE", CI, CIV, 384)
+DEFINE_COUNTRY_CODE ("CROATIA (local name: Hrvatska)", HR, HRV, 191)
+DEFINE_COUNTRY_CODE ("CUBA", CU, CUB, 192)
+DEFINE_COUNTRY_CODE ("CYPRUS", CY, CYP, 196)
+DEFINE_COUNTRY_CODE ("CZECH REPUBLIC", CZ, CZE, 203)
+DEFINE_COUNTRY_CODE ("DENMARK", DK, DNK, 208)
+DEFINE_COUNTRY_CODE ("DJIBOUTI", DJ, DJI, 262)
+DEFINE_COUNTRY_CODE ("DOMINICA", DM, DMA, 212)
+DEFINE_COUNTRY_CODE ("DOMINICAN REPUBLIC", DO, DOM, 214)
+DEFINE_COUNTRY_CODE ("EAST TIMOR", TP, TMP, 626)
+DEFINE_COUNTRY_CODE ("ECUADOR", EC, ECU, 218)
+DEFINE_COUNTRY_CODE ("EGYPT", EG, EGY, 818)
+DEFINE_COUNTRY_CODE ("EL SALVADOR", SV, SLV, 222)
+DEFINE_COUNTRY_CODE ("EQUATORIAL GUINEA", GQ, GNQ, 226)
+DEFINE_COUNTRY_CODE ("ERITREA", ER, ERI, 232)
+DEFINE_COUNTRY_CODE ("ESTONIA", EE, EST, 233)
+DEFINE_COUNTRY_CODE ("ETHIOPIA", ET, ETH, 231)
+DEFINE_COUNTRY_CODE ("FALKLAND ISLANDS (MALVINAS)", FK, FLK, 238)
+DEFINE_COUNTRY_CODE ("FAROE ISLANDS", FO, FRO, 234)
+DEFINE_COUNTRY_CODE ("FIJI", FJ, FJI, 242)
+DEFINE_COUNTRY_CODE ("FINLAND", FI, FIN, 246)
+DEFINE_COUNTRY_CODE ("FRANCE", FR, FRA, 250)
+DEFINE_COUNTRY_CODE ("FRANCE, METROPOLITAN", FX, FXX, 249)
+DEFINE_COUNTRY_CODE ("FRENCH GUIANA", GF, GUF, 254)
+DEFINE_COUNTRY_CODE ("FRENCH POLYNESIA", PF, PYF, 258)
+DEFINE_COUNTRY_CODE ("FRENCH SOUTHERN TERRITORIES", TF, ATF, 260)
+DEFINE_COUNTRY_CODE ("GABON", GA, GAB, 266)
+DEFINE_COUNTRY_CODE ("GAMBIA", GM, GMB, 270)
+DEFINE_COUNTRY_CODE ("GEORGIA", GE, GEO, 268)
+DEFINE_COUNTRY_CODE ("GERMANY", DE, DEU, 276)
+DEFINE_COUNTRY_CODE ("GHANA", GH, GHA, 288)
+DEFINE_COUNTRY_CODE ("GIBRALTAR", GI, GIB, 292)
+DEFINE_COUNTRY_CODE ("GREECE", GR, GRC, 300)
+DEFINE_COUNTRY_CODE ("GREENLAND", GL, GRL, 304)
+DEFINE_COUNTRY_CODE ("GRENADA", GD, GRD, 308)
+DEFINE_COUNTRY_CODE ("GUADELOUPE", GP, GLP, 312)
+DEFINE_COUNTRY_CODE ("GUAM", GU, GUM, 316)
+DEFINE_COUNTRY_CODE ("GUATEMALA", GT, GTM, 320)
+DEFINE_COUNTRY_CODE ("GUINEA", GN, GIN, 324)
+DEFINE_COUNTRY_CODE ("GUINEA-BISSAU", GW, GNB, 624)
+DEFINE_COUNTRY_CODE ("GUYANA", GY, GUY, 328)
+DEFINE_COUNTRY_CODE ("HAITI", HT, HTI, 332)
+DEFINE_COUNTRY_CODE ("HEARD AND MC DONALD ISLANDS", HM, HMD, 334)
+DEFINE_COUNTRY_CODE ("HOLY SEE (VATICAN CITY STATE)", VA, VAT, 336)
+DEFINE_COUNTRY_CODE ("HONDURAS", HN, HND, 340)
+DEFINE_COUNTRY_CODE ("HONG KONG", HK, HKG, 344)
+DEFINE_COUNTRY_CODE ("HUNGARY", HU, HUN, 348)
+DEFINE_COUNTRY_CODE ("ICELAND", IS, ISL, 352)
+DEFINE_COUNTRY_CODE ("INDIA", IN, IND, 356)
+DEFINE_COUNTRY_CODE ("INDONESIA", ID, IDN, 360)
+DEFINE_COUNTRY_CODE ("IRAN (ISLAMIC REPUBLIC OF)", IR, IRN, 364)
+DEFINE_COUNTRY_CODE ("IRAQ", IQ, IRQ, 368)
+DEFINE_COUNTRY_CODE ("IRELAND", IE, IRL, 372)
+DEFINE_COUNTRY_CODE ("ISRAEL", IL, ISR, 376)
+DEFINE_COUNTRY_CODE ("ITALY", IT, ITA, 380)
+DEFINE_COUNTRY_CODE ("JAMAICA", JM, JAM, 388)
+DEFINE_COUNTRY_CODE ("JAPAN", JP, JPN, 392)
+DEFINE_COUNTRY_CODE ("JORDAN", JO, JOR, 400)
+DEFINE_COUNTRY_CODE ("KAZAKHSTAN", KZ, KAZ, 398)
+DEFINE_COUNTRY_CODE ("KENYA", KE, KEN, 404)
+DEFINE_COUNTRY_CODE ("KIRIBATI", KI, KIR, 296)
+DEFINE_COUNTRY_CODE ("KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF", KP, PRK, 408)
+DEFINE_COUNTRY_CODE ("KOREA, REPUBLIC OF", KR, KOR, 410)
+DEFINE_COUNTRY_CODE ("KUWAIT", KW, KWT, 414)
+DEFINE_COUNTRY_CODE ("KYRGYZSTAN", KG, KGZ, 417)
+DEFINE_COUNTRY_CODE ("LAO PEOPLE'S DEMOCRATIC REPUBLIC", LA, LAO, 418)
+DEFINE_COUNTRY_CODE ("LATVIA", LV, LVA, 428)
+DEFINE_COUNTRY_CODE ("LEBANON", LB, LBN, 422)
+DEFINE_COUNTRY_CODE ("LESOTHO", LS, LSO, 426)
+DEFINE_COUNTRY_CODE ("LIBERIA", LR, LBR, 430)
+DEFINE_COUNTRY_CODE ("LIBYAN ARAB JAMAHIRIYA", LY, LBY, 434)
+DEFINE_COUNTRY_CODE ("LIECHTENSTEIN", LI, LIE, 438)
+DEFINE_COUNTRY_CODE ("LITHUANIA", LT, LTU, 440)
+DEFINE_COUNTRY_CODE ("LUXEMBOURG", LU, LUX, 442)
+DEFINE_COUNTRY_CODE ("MACAU", MO, MAC, 446)
+DEFINE_COUNTRY_CODE ("MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF", MK, MKD, 807)
+DEFINE_COUNTRY_CODE ("MADAGASCAR", MG, MDG, 450)
+DEFINE_COUNTRY_CODE ("MALAWI", MW, MWI, 454)
+DEFINE_COUNTRY_CODE ("MALAYSIA", MY, MYS, 458)
+DEFINE_COUNTRY_CODE ("MALDIVES", MV, MDV, 462)
+DEFINE_COUNTRY_CODE ("MALI", ML, MLI, 466)
+DEFINE_COUNTRY_CODE ("MALTA", MT, MLT, 470)
+DEFINE_COUNTRY_CODE ("MARSHALL ISLANDS", MH, MHL, 584)
+DEFINE_COUNTRY_CODE ("MARTINIQUE", MQ, MTQ, 474)
+DEFINE_COUNTRY_CODE ("MAURITANIA", MR, MRT, 478)
+DEFINE_COUNTRY_CODE ("MAURITIUS", MU, MUS, 480)
+DEFINE_COUNTRY_CODE ("MAYOTTE", YT, MYT, 175)
+DEFINE_COUNTRY_CODE ("MEXICO", MX, MEX, 484)
+DEFINE_COUNTRY_CODE ("MICRONESIA, FEDERATED STATES OF", FM, FSM, 583)
+DEFINE_COUNTRY_CODE ("MOLDOVA, REPUBLIC OF", MD, MDA, 498)
+DEFINE_COUNTRY_CODE ("MONACO", MC, MCO, 492)
+DEFINE_COUNTRY_CODE ("MONGOLIA", MN, MNG, 496)
+DEFINE_COUNTRY_CODE ("MONTSERRAT", MS, MSR, 500)
+DEFINE_COUNTRY_CODE ("MOROCCO", MA, MAR, 504)
+DEFINE_COUNTRY_CODE ("MOZAMBIQUE", MZ, MOZ, 508)
+DEFINE_COUNTRY_CODE ("MYANMAR", MM, MMR, 104)
+DEFINE_COUNTRY_CODE ("NAMIBIA", NA, NAM, 516)
+DEFINE_COUNTRY_CODE ("NAURU", NR, NRU, 520)
+DEFINE_COUNTRY_CODE ("NEPAL", NP, NPL, 524)
+DEFINE_COUNTRY_CODE ("NETHERLANDS", NL, NLD, 528)
+DEFINE_COUNTRY_CODE ("NETHERLANDS ANTILLES", AN, ANT, 530)
+DEFINE_COUNTRY_CODE ("NEW CALEDONIA", NC, NCL, 540)
+DEFINE_COUNTRY_CODE ("NEW ZEALAND", NZ, NZL, 554)
+DEFINE_COUNTRY_CODE ("NICARAGUA", NI, NIC, 558)
+DEFINE_COUNTRY_CODE ("NIGER", NE, NER, 562)
+DEFINE_COUNTRY_CODE ("NIGERIA", NG, NGA, 566)
+DEFINE_COUNTRY_CODE ("NIUE", NU, NIU, 570)
+DEFINE_COUNTRY_CODE ("NORFOLK ISLAND", NF, NFK, 574)
+DEFINE_COUNTRY_CODE ("NORTHERN MARIANA ISLANDS", MP, MNP, 580)
+DEFINE_COUNTRY_CODE ("NORWAY", NO, NOR, 578)
+DEFINE_COUNTRY_CODE ("OMAN", OM, OMN, 512)
+DEFINE_COUNTRY_CODE ("PAKISTAN", PK, PAK, 586)
+DEFINE_COUNTRY_CODE ("PALAU", PW, PLW, 585)
+DEFINE_COUNTRY_CODE ("PANAMA", PA, PAN, 591)
+DEFINE_COUNTRY_CODE ("PAPUA NEW GUINEA", PG, PNG, 598)
+DEFINE_COUNTRY_CODE ("PARAGUAY", PY, PRY, 600)
+DEFINE_COUNTRY_CODE ("PERU", PE, PER, 604)
+DEFINE_COUNTRY_CODE ("PHILIPPINES", PH, PHL, 608)
+DEFINE_COUNTRY_CODE ("PITCAIRN", PN, PCN, 612)
+DEFINE_COUNTRY_CODE ("POLAND", PL, POL, 616)
+DEFINE_COUNTRY_CODE ("PORTUGAL", PT, PRT, 620)
+DEFINE_COUNTRY_CODE ("PUERTO RICO", PR, PRI, 630)
+DEFINE_COUNTRY_CODE ("QATAR", QA, QAT, 634)
+DEFINE_COUNTRY_CODE ("REUNION", RE, REU, 638)
+DEFINE_COUNTRY_CODE ("ROMANIA", RO, ROM, 642)
+DEFINE_COUNTRY_CODE ("RUSSIAN FEDERATION", RU, RUS, 643)
+DEFINE_COUNTRY_CODE ("RWANDA", RW, RWA, 646)
+DEFINE_COUNTRY_CODE ("SAINT KITTS AND NEVIS", KN, KNA, 659)
+DEFINE_COUNTRY_CODE ("SAINT LUCIA", LC, LCA, 662)
+DEFINE_COUNTRY_CODE ("SAINT VINCENT AND THE GRENADINES", VC, VCT, 670)
+DEFINE_COUNTRY_CODE ("SAMOA", WS, WSM, 882)
+DEFINE_COUNTRY_CODE ("SAN MARINO", SM, SMR, 674)
+DEFINE_COUNTRY_CODE ("SAO TOME AND PRINCIPE", ST, STP, 678)
+DEFINE_COUNTRY_CODE ("SAUDI ARABIA", SA, SAU, 682)
+DEFINE_COUNTRY_CODE ("SENEGAL", SN, SEN, 686)
+DEFINE_COUNTRY_CODE ("SEYCHELLES", SC, SYC, 690)
+DEFINE_COUNTRY_CODE ("SIERRA LEONE", SL, SLE, 694)
+DEFINE_COUNTRY_CODE ("SINGAPORE", SG, SGP, 702)
+DEFINE_COUNTRY_CODE ("SLOVAKIA (Slovak Republic)", SK, SVK, 703)
+DEFINE_COUNTRY_CODE ("SLOVENIA", SI, SVN, 705)
+DEFINE_COUNTRY_CODE ("SOLOMON ISLANDS", SB, SLB, 90)
+DEFINE_COUNTRY_CODE ("SOMALIA", SO, SOM, 706)
+DEFINE_COUNTRY_CODE ("SOUTH AFRICA", ZA, ZAF, 710)
+DEFINE_COUNTRY_CODE ("SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS", GS, SGS, 239)
+DEFINE_COUNTRY_CODE ("SPAIN", ES, ESP, 724)
+DEFINE_COUNTRY_CODE ("SRI LANKA", LK, LKA, 144)
+DEFINE_COUNTRY_CODE ("ST. HELENA", SH, SHN, 654)
+DEFINE_COUNTRY_CODE ("ST. PIERRE AND MIQUELON", PM, SPM, 666)
+DEFINE_COUNTRY_CODE ("SUDAN", SD, SDN, 736)
+DEFINE_COUNTRY_CODE ("SURINAME", SR, SUR, 740)
+DEFINE_COUNTRY_CODE ("SVALBARD AND JAN MAYEN ISLANDS", SJ, SJM, 744)
+DEFINE_COUNTRY_CODE ("SWAZILAND", SZ, SWZ, 748)
+DEFINE_COUNTRY_CODE ("SWEDEN", SE, SWE, 752)
+DEFINE_COUNTRY_CODE ("SWITZERLAND", CH, CHE, 756)
+DEFINE_COUNTRY_CODE ("SYRIAN ARAB REPUBLIC", SY, SYR, 760)
+DEFINE_COUNTRY_CODE ("TAIWAN, PROVINCE OF CHINA", TW, TWN, 158)
+DEFINE_COUNTRY_CODE ("TAJIKISTAN", TJ, TJK, 762)
+DEFINE_COUNTRY_CODE ("TANZANIA, UNITED REPUBLIC OF", TZ, TZA, 834)
+DEFINE_COUNTRY_CODE ("THAILAND", TH, THA, 764)
+DEFINE_COUNTRY_CODE ("TOGO", TG, TGO, 768)
+DEFINE_COUNTRY_CODE ("TOKELAU", TK, TKL, 772)
+DEFINE_COUNTRY_CODE ("TONGA", TO, TON, 776)
+DEFINE_COUNTRY_CODE ("TRINIDAD AND TOBAGO", TT, TTO, 780)
+DEFINE_COUNTRY_CODE ("TUNISIA", TN, TUN, 788)
+DEFINE_COUNTRY_CODE ("TURKEY", TR, TUR, 792)
+DEFINE_COUNTRY_CODE ("TURKMENISTAN", TM, TKM, 795)
+DEFINE_COUNTRY_CODE ("TURKS AND CAICOS ISLANDS", TC, TCA, 796)
+DEFINE_COUNTRY_CODE ("TUVALU", TV, TUV, 798)
+DEFINE_COUNTRY_CODE ("UGANDA", UG, UGA, 800)
+DEFINE_COUNTRY_CODE ("UKRAINE", UA, UKR, 804)
+DEFINE_COUNTRY_CODE ("UNITED ARAB EMIRATES", AE, ARE, 784)
+DEFINE_COUNTRY_CODE ("UNITED KINGDOM", GB, GBR, 826)
+DEFINE_COUNTRY_CODE ("UNITED STATES", US, USA, 840)
+DEFINE_COUNTRY_CODE ("UNITED STATES MINOR OUTLYING ISLANDS", UM, UMI, 581)
+DEFINE_COUNTRY_CODE ("URUGUAY", UY, URY, 858)
+DEFINE_COUNTRY_CODE ("UZBEKISTAN", UZ, UZB, 860)
+DEFINE_COUNTRY_CODE ("VANUATU", VU, VUT, 548)
+DEFINE_COUNTRY_CODE ("VENEZUELA", VE, VEN, 862)
+DEFINE_COUNTRY_CODE ("VIET NAM", VN, VNM, 704)
+DEFINE_COUNTRY_CODE ("VIRGIN ISLANDS (BRITISH)", VG, VGB, 92)
+DEFINE_COUNTRY_CODE ("VIRGIN ISLANDS (U.S.)", VI, VIR, 850)
+DEFINE_COUNTRY_CODE ("WALLIS AND FUTUNA ISLANDS", WF, WLF, 876)
+DEFINE_COUNTRY_CODE ("WESTERN SAHARA", EH, ESH, 732)
+DEFINE_COUNTRY_CODE ("YEMEN", YE, YEM, 887)
+DEFINE_COUNTRY_CODE ("YUGOSLAVIA", YU, YUG, 891)
+DEFINE_COUNTRY_CODE ("ZAMBIA", ZM, ZMB, 894)
+DEFINE_COUNTRY_CODE ("ZIMBABWE", ZW, ZWE, 716)
diff --git a/locale/iso-639.def b/locale/iso-639.def
new file mode 100644
index 0000000000..28bb74f081
--- /dev/null
+++ b/locale/iso-639.def
@@ -0,0 +1,133 @@
+/*
+ * Defines the languages codes and abbreviations according to ISO 639-[12].
+ * This is used in ld-address.c (address_finish).
+ *
+ * If you find something missing or wrong contact <bug-glibc@gnu.org>
+ */
+DEFINE_LANGUAGE_CODE ("Afar", aa, aar, aar)
+DEFINE_LANGUAGE_CODE ("Abkhazian", ab, abk, abk)
+DEFINE_LANGUAGE_CODE ("Afrikaans", af, afr, afr)
+DEFINE_LANGUAGE_CODE ("Amharic", am, amh, amh)
+DEFINE_LANGUAGE_CODE ("Arabian", ar, ara, ara)
+DEFINE_LANGUAGE_CODE ("Assamese", as, asm, asm)
+DEFINE_LANGUAGE_CODE ("Aymara", ay, aym, aym)
+DEFINE_LANGUAGE_CODE ("Azerbajani", az, aze, aze)
+DEFINE_LANGUAGE_CODE ("Bashkir", ba, bak, bak)
+DEFINE_LANGUAGE_CODE ("Byelorussian", be, bel, bel)
+DEFINE_LANGUAGE_CODE ("Bulgarian", bg, bul, bul)
+DEFINE_LANGUAGE_CODE ("Bihari", bh, bih, bih)
+DEFINE_LANGUAGE_CODE ("Bislama", bi, bis, bis)
+DEFINE_LANGUAGE_CODE ("Bengali", bn, ben, ben)
+DEFINE_LANGUAGE_CODE ("Tibetan", bo, bod, tib)
+DEFINE_LANGUAGE_CODE ("Breton", br, bre, bre)
+DEFINE_LANGUAGE_CODE ("Catalan", ca, cat, cat)
+DEFINE_LANGUAGE_CODE ("Corsican", co, cos, cos)
+DEFINE_LANGUAGE_CODE ("Czech", cs, ces, cze)
+DEFINE_LANGUAGE_CODE ("Welsh", cy, cym, wel)
+DEFINE_LANGUAGE_CODE ("Danish", da, dan, dan)
+DEFINE_LANGUAGE_CODE ("German", de, deu, ger)
+DEFINE_LANGUAGE_CODE ("Greek", el, ell, gre)
+DEFINE_LANGUAGE_CODE ("English", en, eng, eng)
+DEFINE_LANGUAGE_CODE ("Esperanto", eo, epo, epo)
+DEFINE_LANGUAGE_CODE ("Spanish", es, spa, spa)
+DEFINE_LANGUAGE_CODE ("Estonian", et, est, est)
+DEFINE_LANGUAGE_CODE ("Basque", eu, eus, baq)
+DEFINE_LANGUAGE_CODE ("Persian", fa, fas, per)
+DEFINE_LANGUAGE_CODE ("Finnish", fi, fin, fin)
+DEFINE_LANGUAGE_CODE ("Fiji", fj, fij, fij)
+DEFINE_LANGUAGE_CODE ("Faroese", fo, fao, fao)
+DEFINE_LANGUAGE_CODE ("French", fr, fra, fre)
+DEFINE_LANGUAGE_CODE ("Frisian", fy, fry, fry)
+DEFINE_LANGUAGE_CODE ("Irish", ga, gai, iri)
+DEFINE_LANGUAGE_CODE ("Scots Gaelic", gd, gdh, gae)
+DEFINE_LANGUAGE_CODE ("Guarani", gn, grn, grn)
+DEFINE_LANGUAGE_CODE ("Gujarati", gu, guj, guj)
+DEFINE_LANGUAGE_CODE ("Hausa", ha, hau, hau)
+DEFINE_LANGUAGE_CODE ("Hindi", hi, hin, hin)
+DEFINE_LANGUAGE_CODE ("Croatian", hr, hrv, scr)
+DEFINE_LANGUAGE_CODE ("Hungarian", hu, hun, hun)
+DEFINE_LANGUAGE_CODE ("Armenian", hy, hye, arm)
+DEFINE_LANGUAGE_CODE ("Interlingua", ia, ina, ina)
+DEFINE_LANGUAGE_CODE ("Interlingue", ie, ile, ile)
+DEFINE_LANGUAGE_CODE ("Inupiak", ik, ipk, ipk)
+DEFINE_LANGUAGE_CODE ("Indonesian", in, ind, ind)
+DEFINE_LANGUAGE_CODE ("Icelandic", is, isl, ice)
+DEFINE_LANGUAGE_CODE ("Italian", it, ita, ita)
+DEFINE_LANGUAGE_CODE ("Hebrew", iw, heb, heb)
+DEFINE_LANGUAGE_CODE ("Japanese", ja, jpn, jpn)
+DEFINE_LANGUAGE_CODE ("Yiddish", ji, yid, yid)
+DEFINE_LANGUAGE_CODE ("Javanese", jv, jaw, jav)
+DEFINE_LANGUAGE_CODE ("Georgian", ka, kat, geo)
+DEFINE_LANGUAGE_CODE ("Kazakh", kk, kaz, kaz)
+DEFINE_LANGUAGE_CODE ("Kannada", kn, kan, kan)
+DEFINE_LANGUAGE_CODE ("Korean", ko, kor, kor)
+DEFINE_LANGUAGE_CODE ("Kashmiri", ks, kas, kas)
+DEFINE_LANGUAGE_CODE ("Kurdish", ku, kur, kur)
+DEFINE_LANGUAGE_CODE ("Kirghiz", ky, kir, kir)
+DEFINE_LANGUAGE_CODE ("Latin", la, lat, lat)
+DEFINE_LANGUAGE_CODE ("Lingala", ln, lin, lin)
+DEFINE_LANGUAGE_CODE ("Laotian", lo, lao, lao)
+DEFINE_LANGUAGE_CODE ("Lithuanian", lt, lit, lit)
+DEFINE_LANGUAGE_CODE ("Latvian, Lettish", lv, lav, lav)
+DEFINE_LANGUAGE_CODE ("Malagasy", mg, mlg, mlg)
+DEFINE_LANGUAGE_CODE ("Maori", mi, mri, mao)
+DEFINE_LANGUAGE_CODE ("Macedonian", mk, mkd, mac)
+DEFINE_LANGUAGE_CODE ("Malayalam", ml, mal, mal)
+DEFINE_LANGUAGE_CODE ("Mongolian", mn, mon, mon)
+DEFINE_LANGUAGE_CODE ("Moldavian", mo, mol, mol)
+DEFINE_LANGUAGE_CODE ("Marathi", mr, mar, mar)
+DEFINE_LANGUAGE_CODE ("Malay", ms, msa, may)
+DEFINE_LANGUAGE_CODE ("Maltese", mt, mlt, mlt)
+DEFINE_LANGUAGE_CODE ("Burmese", my, mya, bur)
+DEFINE_LANGUAGE_CODE ("Nauru", na, nau, nau)
+DEFINE_LANGUAGE_CODE ("Nepali", ne, nep, nep)
+DEFINE_LANGUAGE_CODE ("Dutch", nl, nld, dut)
+DEFINE_LANGUAGE_CODE ("Norwegian", no, nor, nor)
+DEFINE_LANGUAGE_CODE ("Occitan", oc, oci, oci)
+DEFINE_LANGUAGE_CODE ("(Afan)Oromo", om, orm, orm)
+DEFINE_LANGUAGE_CODE ("Oriya", or, ori, ori)
+DEFINE_LANGUAGE_CODE ("Polish", pl, pol, pol)
+DEFINE_LANGUAGE_CODE ("Pashto, Pushto", ps, pus, pus)
+DEFINE_LANGUAGE_CODE ("Portuguese", pt, por, por)
+DEFINE_LANGUAGE_CODE ("Quechua", qu, que, que)
+DEFINE_LANGUAGE_CODE ("Rhaeto-Romance", rm, roh, roh)
+DEFINE_LANGUAGE_CODE ("Romanian", ro, rom, rom)
+DEFINE_LANGUAGE_CODE ("Russian", ru, rus, rus)
+DEFINE_LANGUAGE_CODE ("Kinyarwanda", rw, kin, kin)
+DEFINE_LANGUAGE_CODE ("Sanskrit", sa, san, san)
+DEFINE_LANGUAGE_CODE ("Sindhi", sd, snd, snd)
+DEFINE_LANGUAGE_CODE ("Sangho", sg, sag, sag)
+DEFINE_LANGUAGE_CODE ("Singhalese", si, sin, sin)
+DEFINE_LANGUAGE_CODE ("Slovak", sk, slk, slo)
+DEFINE_LANGUAGE_CODE ("Slovenian", sl, slv, slv)
+DEFINE_LANGUAGE_CODE ("Samoan", sm, smo, smo)
+DEFINE_LANGUAGE_CODE ("Shona", sn, sna, sna)
+DEFINE_LANGUAGE_CODE ("Somali", so, som, som)
+DEFINE_LANGUAGE_CODE ("Albanian", sq, sqi, alb)
+DEFINE_LANGUAGE_CODE ("Serbian", sr, srq, scc)
+DEFINE_LANGUAGE_CODE ("Siswati", ss, ssw, ssw)
+DEFINE_LANGUAGE_CODE ("Sudanese", su, sun, sun)
+DEFINE_LANGUAGE_CODE ("Swedish", sv, swe, swe)
+DEFINE_LANGUAGE_CODE ("Suahili", sw, swa, swa)
+DEFINE_LANGUAGE_CODE ("Tamil", ta, tam, tam)
+DEFINE_LANGUAGE_CODE ("Telugu", te, tel, tel)
+DEFINE_LANGUAGE_CODE ("Tajik", tg, tgk, tgk)
+DEFINE_LANGUAGE_CODE ("Thai", th, tha, tha)
+DEFINE_LANGUAGE_CODE ("Tigrinya", ti, tir, tir)
+DEFINE_LANGUAGE_CODE ("Turkmen", tk, tuk, tuk)
+DEFINE_LANGUAGE_CODE ("Tagalog", tl, tgl, tgl)
+DEFINE_LANGUAGE_CODE ("Tonga", to, ton, ton)
+DEFINE_LANGUAGE_CODE ("Turkish", tr, tur, tur)
+DEFINE_LANGUAGE_CODE ("Tsonga", ts, tso, tso)
+DEFINE_LANGUAGE_CODE ("Tatar", tt, tat, tat)
+DEFINE_LANGUAGE_CODE ("Twi", tw, twi, twi)
+DEFINE_LANGUAGE_CODE ("Ukrainian", uk, ukr, ukr)
+DEFINE_LANGUAGE_CODE ("Urdu", ur, urd, urd)
+DEFINE_LANGUAGE_CODE ("Uzbek", uz, uzb, uzb)
+DEFINE_LANGUAGE_CODE ("Vietnamese", vi, vie, vie)
+DEFINE_LANGUAGE_CODE ("Volapük", vo, vol, vol)
+DEFINE_LANGUAGE_CODE ("Wolof", wo, wol, wol)
+DEFINE_LANGUAGE_CODE ("Xhosa", xh, xho, xho)
+DEFINE_LANGUAGE_CODE ("Yoruba", yo, yor, yor)
+DEFINE_LANGUAGE_CODE ("Chinese", zh, zho, chi)
+DEFINE_LANGUAGE_CODE ("Zulu", zu, zul, zul)
diff --git a/locale/langinfo.h b/locale/langinfo.h
index 4de5dbecbe..2513adc86d 100644
--- a/locale/langinfo.h
+++ b/locale/langinfo.h
@@ -155,71 +155,126 @@ enum
ERA_T_FMT, /* Time in alternate era format. */
#define ERA_T_FMT ERA_T_FMT
- _NL_TIME_NUM_ALT_DIGITS, /* Number entries in the alt_digits arrays. */
-
- _NL_TIME_ERA_NUM_ENTRIES, /* Number entries in the era arrays. */
+ _NL_TIME_ERA_NUM_ENTRIES_EB, /* Number entries in the era arrays. */
+ _NL_TIME_ERA_NUM_ENTRIES_EL, /* Number entries in the era arrays. */
_NL_TIME_ERA_ENTRIES_EB, /* Structure with era entries in usable form.*/
_NL_TIME_ERA_ENTRIES_EL,
- _NL_WABDAY_1, /* Sun */
- _NL_WABDAY_2,
- _NL_WABDAY_3,
- _NL_WABDAY_4,
- _NL_WABDAY_5,
- _NL_WABDAY_6,
- _NL_WABDAY_7,
+ _NL_WABDAY_1_EB, /* Sun */
+ _NL_WABDAY_2_EB,
+ _NL_WABDAY_3_EB,
+ _NL_WABDAY_4_EB,
+ _NL_WABDAY_5_EB,
+ _NL_WABDAY_6_EB,
+ _NL_WABDAY_7_EB,
+ _NL_WABDAY_1_EL, /* Sun */
+ _NL_WABDAY_2_EL,
+ _NL_WABDAY_3_EL,
+ _NL_WABDAY_4_EL,
+ _NL_WABDAY_5_EL,
+ _NL_WABDAY_6_EL,
+ _NL_WABDAY_7_EL,
/* Long-named days of the week. */
- _NL_WDAY_1, /* Sunday */
- _NL_WDAY_2, /* Monday */
- _NL_WDAY_3, /* Tuesday */
- _NL_WDAY_4, /* Wednesday */
- _NL_WDAY_5, /* Thursday */
- _NL_WDAY_6, /* Friday */
- _NL_WDAY_7, /* Saturday */
+ _NL_WDAY_1_EB, /* Sunday */
+ _NL_WDAY_2_EB, /* Monday */
+ _NL_WDAY_3_EB, /* Tuesday */
+ _NL_WDAY_4_EB, /* Wednesday */
+ _NL_WDAY_5_EB, /* Thursday */
+ _NL_WDAY_6_EB, /* Friday */
+ _NL_WDAY_7_EB, /* Saturday */
+ _NL_WDAY_1_EL, /* Sunday */
+ _NL_WDAY_2_EL, /* Monday */
+ _NL_WDAY_3_EL, /* Tuesday */
+ _NL_WDAY_4_EL, /* Wednesday */
+ _NL_WDAY_5_EL, /* Thursday */
+ _NL_WDAY_6_EL, /* Friday */
+ _NL_WDAY_7_EL, /* Saturday */
/* Abbreviated month names. */
- _NL_WABMON_1, /* Jan */
- _NL_WABMON_2,
- _NL_WABMON_3,
- _NL_WABMON_4,
- _NL_WABMON_5,
- _NL_WABMON_6,
- _NL_WABMON_7,
- _NL_WABMON_8,
- _NL_WABMON_9,
- _NL_WABMON_10,
- _NL_WABMON_11,
- _NL_WABMON_12,
+ _NL_WABMON_1_EB, /* Jan */
+ _NL_WABMON_2_EB,
+ _NL_WABMON_3_EB,
+ _NL_WABMON_4_EB,
+ _NL_WABMON_5_EB,
+ _NL_WABMON_6_EB,
+ _NL_WABMON_7_EB,
+ _NL_WABMON_8_EB,
+ _NL_WABMON_9_EB,
+ _NL_WABMON_10_EB,
+ _NL_WABMON_11_EB,
+ _NL_WABMON_12_EB,
+ _NL_WABMON_1_EL, /* Jan */
+ _NL_WABMON_2_EL,
+ _NL_WABMON_3_EL,
+ _NL_WABMON_4_EL,
+ _NL_WABMON_5_EL,
+ _NL_WABMON_6_EL,
+ _NL_WABMON_7_EL,
+ _NL_WABMON_8_EL,
+ _NL_WABMON_9_EL,
+ _NL_WABMON_10_EL,
+ _NL_WABMON_11_EL,
+ _NL_WABMON_12_EL,
/* Long month names. */
- _NL_WMON_1, /* January */
- _NL_WMON_2,
- _NL_WMON_3,
- _NL_WMON_4,
- _NL_WMON_5,
- _NL_WMON_6,
- _NL_WMON_7,
- _NL_WMON_8,
- _NL_WMON_9,
- _NL_WMON_10,
- _NL_WMON_11,
- _NL_WMON_12,
-
- _NL_WAM_STR, /* Ante meridian string. */
- _NL_WPM_STR, /* Post meridian string. */
-
- _NL_WD_T_FMT, /* Date and time format for strftime. */
- _NL_WD_FMT, /* Date format for strftime. */
- _NL_WT_FMT, /* Time format for strftime. */
- _NL_WT_FMT_AMPM, /* 12-hour time format for strftime. */
-
- _NL_WERA, /* Alternate era. */
- _NL_WERA_YEAR, /* Year in alternate era format. */
- _NL_WERA_D_FMT, /* Date in alternate era format. */
- _NL_WALT_DIGITS, /* Alternate symbols for digits. */
- _NL_WERA_D_T_FMT, /* Date and time in alternate era format. */
- _NL_WERA_T_FMT, /* Time in alternate era format. */
+ _NL_WMON_1_EB, /* January */
+ _NL_WMON_2_EB,
+ _NL_WMON_3_EB,
+ _NL_WMON_4_EB,
+ _NL_WMON_5_EB,
+ _NL_WMON_6_EB,
+ _NL_WMON_7_EB,
+ _NL_WMON_8_EB,
+ _NL_WMON_9_EB,
+ _NL_WMON_10_EB,
+ _NL_WMON_11_EB,
+ _NL_WMON_12_EB,
+ _NL_WMON_1_EL, /* January */
+ _NL_WMON_2_EL,
+ _NL_WMON_3_EL,
+ _NL_WMON_4_EL,
+ _NL_WMON_5_EL,
+ _NL_WMON_6_EL,
+ _NL_WMON_7_EL,
+ _NL_WMON_8_EL,
+ _NL_WMON_9_EL,
+ _NL_WMON_10_EL,
+ _NL_WMON_11_EL,
+ _NL_WMON_12_EL,
+
+ _NL_WAM_STR_EB, /* Ante meridian string. */
+ _NL_WPM_STR_EB, /* Post meridian string. */
+ _NL_WAM_STR_EL, /* Ante meridian string. */
+ _NL_WPM_STR_EL, /* Post meridian string. */
+
+ _NL_WD_T_FMT_EB, /* Date and time format for strftime. */
+ _NL_WD_FMT_EB, /* Date format for strftime. */
+ _NL_WT_FMT_EB, /* Time format for strftime. */
+ _NL_WT_FMT_AMPM_EB, /* 12-hour time format for strftime. */
+ _NL_WD_T_FMT_EL, /* Date and time format for strftime. */
+ _NL_WD_FMT_EL, /* Date format for strftime. */
+ _NL_WT_FMT_EL, /* Time format for strftime. */
+ _NL_WT_FMT_AMPM_EL, /* 12-hour time format for strftime. */
+
+ _NL_WERA_YEAR_EB, /* Year in alternate era format. */
+ _NL_WERA_D_FMT_EB, /* Date in alternate era format. */
+ _NL_WALT_DIGITS_EB, /* Alternate symbols for digits. */
+ _NL_WERA_D_T_FMT_EB, /* Date and time in alternate era format. */
+ _NL_WERA_T_FMT_EB, /* Time in alternate era format. */
+ _NL_WERA_YEAR_EL, /* Year in alternate era format. */
+ _NL_WERA_D_FMT_EL, /* Date in alternate era format. */
+ _NL_WALT_DIGITS_EL, /* Alternate symbols for digits. */
+ _NL_WERA_D_T_FMT_EL, /* Date and time in alternate era format. */
+ _NL_WERA_T_FMT_EL, /* Time in alternate era format. */
+
+ _NL_TIME_WEEK_NDAYS,
+ _NL_TIME_WEEK_1STDAY,
+ _NL_TIME_WEEK_1STWEEK,
+ _NL_TIME_FIRST_WEEKDAY,
+ _NL_TIME_FIRST_WORKDAY,
+ _NL_TIME_CAL_DIRECTION,
+ _NL_TIME_TIMEZONE,
_NL_NUM_LC_TIME, /* Number of indices in LC_TIME category. */
@@ -230,23 +285,34 @@ enum
_NL_COLLATE_RULES,
_NL_COLLATE_HASH_SIZE,
_NL_COLLATE_HASH_LAYERS,
- _NL_COLLATE_TABLE_EB,
- _NL_COLLATE_TABLE_EL,
- _NL_COLLATE_UNDEFINED,
- _NL_COLLATE_EXTRA_EB,
- _NL_COLLATE_EXTRA_EL,
+ _NL_COLLATE_TABLEMB_EB,
+ _NL_COLLATE_TABLEMB_EL,
+ _NL_COLLATE_TABLEWC_EB,
+ _NL_COLLATE_TABLEWC_EL,
+ _NL_COLLATE_UNDEFINED_MB,
+ _NL_COLLATE_UNDEFINED_WC,
+ _NL_COLLATE_EXTRAMB_EB,
+ _NL_COLLATE_EXTRAMB_EL,
+ _NL_COLLATE_EXTRAWC_EB,
+ _NL_COLLATE_EXTRAWC_EL,
_NL_COLLATE_ELEM_HASH_SIZE,
_NL_COLLATE_ELEM_HASH_EB,
_NL_COLLATE_ELEM_HASH_EL,
_NL_COLLATE_ELEM_STR_POOL,
_NL_COLLATE_ELEM_VAL_EB,
_NL_COLLATE_ELEM_VAL_EL,
+ _NL_COLLATE_ELEM_VALMB_EB,
+ _NL_COLLATE_ELEM_VALMB_EL,
+ _NL_COLLATE_ELEM_VALWC_EB,
+ _NL_COLLATE_ELEM_VALWC_EL,
_NL_COLLATE_SYMB_HASH_SIZE,
_NL_COLLATE_SYMB_HASH_EB,
_NL_COLLATE_SYMB_HASH_EL,
_NL_COLLATE_SYMB_STR_POOL,
- _NL_COLLATE_SYMB_CLASS_EB,
- _NL_COLLATE_SYMB_CLASS_EL,
+ _NL_COLLATE_SYMB_CLASSMB_EB,
+ _NL_COLLATE_SYMB_CLASSMB_EL,
+ _NL_COLLATE_SYMB_CLASSWC_EB,
+ _NL_COLLATE_SYMB_CLASSWC_EL,
_NL_NUM_LC_COLLATE,
/* LC_CTYPE category: character classification.
@@ -260,8 +326,8 @@ enum
_NL_CTYPE_CLASS32,
_NL_CTYPE_NAMES_EB,
_NL_CTYPE_NAMES_EL,
- _NL_CTYPE_HASH_SIZE,
- _NL_CTYPE_HASH_LAYERS,
+ _NL_CTYPE_HASH_SIZE_EB,
+ _NL_CTYPE_HASH_LAYERS_EB,
_NL_CTYPE_CLASS_NAMES,
_NL_CTYPE_MAP_NAMES,
_NL_CTYPE_WIDTH,
@@ -270,6 +336,84 @@ enum
#ifdef __USE_XOPEN
CODESET = _NL_CTYPE_CODESET_NAME,
#endif
+ _NL_CTYPE_HASH_SIZE_EL,
+ _NL_CTYPE_HASH_LAYERS_EL,
+ _NL_CTYPE_INDIGITS_MB_LEN_EB,
+ _NL_CTYPE_INDIGITS_MB_LEN_EL,
+ _NL_CTYPE_INDIGITS0_MB,
+ _NL_CTYPE_INDIGITS1_MB,
+ _NL_CTYPE_INDIGITS2_MB,
+ _NL_CTYPE_INDIGITS3_MB,
+ _NL_CTYPE_INDIGITS4_MB,
+ _NL_CTYPE_INDIGITS5_MB,
+ _NL_CTYPE_INDIGITS6_MB,
+ _NL_CTYPE_INDIGITS7_MB,
+ _NL_CTYPE_INDIGITS8_MB,
+ _NL_CTYPE_INDIGITS9_MB,
+ _NL_CTYPE_INDIGITS_WC_LEN_EB,
+ _NL_CTYPE_INDIGITS_WC_LEN_EL,
+ _NL_CTYPE_INDIGITS0_WC_EB,
+ _NL_CTYPE_INDIGITS1_WC_EB,
+ _NL_CTYPE_INDIGITS2_WC_EB,
+ _NL_CTYPE_INDIGITS3_WC_EB,
+ _NL_CTYPE_INDIGITS4_WC_EB,
+ _NL_CTYPE_INDIGITS5_WC_EB,
+ _NL_CTYPE_INDIGITS6_WC_EB,
+ _NL_CTYPE_INDIGITS7_WC_EB,
+ _NL_CTYPE_INDIGITS8_WC_EB,
+ _NL_CTYPE_INDIGITS9_WC_EB,
+ _NL_CTYPE_INDIGITS0_WC_EL,
+ _NL_CTYPE_INDIGITS1_WC_EL,
+ _NL_CTYPE_INDIGITS2_WC_EL,
+ _NL_CTYPE_INDIGITS3_WC_EL,
+ _NL_CTYPE_INDIGITS4_WC_EL,
+ _NL_CTYPE_INDIGITS5_WC_EL,
+ _NL_CTYPE_INDIGITS6_WC_EL,
+ _NL_CTYPE_INDIGITS7_WC_EL,
+ _NL_CTYPE_INDIGITS8_WC_EL,
+ _NL_CTYPE_INDIGITS9_WC_EL,
+ _NL_CTYPE_OUTDIGIT0_MB,
+ _NL_CTYPE_OUTDIGIT1_MB,
+ _NL_CTYPE_OUTDIGIT2_MB,
+ _NL_CTYPE_OUTDIGIT3_MB,
+ _NL_CTYPE_OUTDIGIT4_MB,
+ _NL_CTYPE_OUTDIGIT5_MB,
+ _NL_CTYPE_OUTDIGIT6_MB,
+ _NL_CTYPE_OUTDIGIT7_MB,
+ _NL_CTYPE_OUTDIGIT8_MB,
+ _NL_CTYPE_OUTDIGIT9_MB,
+ _NL_CTYPE_OUTDIGIT0_WC_EB,
+ _NL_CTYPE_OUTDIGIT1_WC_EB,
+ _NL_CTYPE_OUTDIGIT2_WC_EB,
+ _NL_CTYPE_OUTDIGIT3_WC_EB,
+ _NL_CTYPE_OUTDIGIT4_WC_EB,
+ _NL_CTYPE_OUTDIGIT5_WC_EB,
+ _NL_CTYPE_OUTDIGIT6_WC_EB,
+ _NL_CTYPE_OUTDIGIT7_WC_EB,
+ _NL_CTYPE_OUTDIGIT8_WC_EB,
+ _NL_CTYPE_OUTDIGIT9_WC_EB,
+ _NL_CTYPE_OUTDIGIT0_WC_EL,
+ _NL_CTYPE_OUTDIGIT1_WC_EL,
+ _NL_CTYPE_OUTDIGIT2_WC_EL,
+ _NL_CTYPE_OUTDIGIT3_WC_EL,
+ _NL_CTYPE_OUTDIGIT4_WC_EL,
+ _NL_CTYPE_OUTDIGIT5_WC_EL,
+ _NL_CTYPE_OUTDIGIT6_WC_EL,
+ _NL_CTYPE_OUTDIGIT7_WC_EL,
+ _NL_CTYPE_OUTDIGIT8_WC_EL,
+ _NL_CTYPE_OUTDIGIT9_WC_EL,
+ _NL_CTYPE_TRANSLIT_HASH_SIZE_EB,
+ _NL_CTYPE_TRANSLIT_HASH_SIZE_EL,
+ _NL_CTYPE_TRANSLIT_HASH_LAYERS_EB,
+ _NL_CTYPE_TRANSLIT_HASH_LAYERS_EL,
+ _NL_CTYPE_TRANSLIT_FROM_IDX_EB,
+ _NL_CTYPE_TRANSLIT_FROM_IDX_EL,
+ _NL_CTYPE_TRANSLIT_FROM_TBL_EB,
+ _NL_CTYPE_TRANSLIT_FROM_TBL_EL,
+ _NL_CTYPE_TRANSLIT_TO_IDX_EB,
+ _NL_CTYPE_TRANSLIT_TO_IDX_EL,
+ _NL_CTYPE_TRANSLIT_TO_TBL_EB,
+ _NL_CTYPE_TRANSLIT_TO_TBL_EL,
_NL_NUM_LC_CTYPE,
/* LC_MONETARY category: formatting of monetary quantities.
@@ -281,7 +425,7 @@ enum
#define CURRENCY_SYMBOL CURRENCY_SYMBOL
#ifdef __USE_XOPEN
CRNCYSTR = CURRENCY_SYMBOL,
-# define CRNCYSTR CRNCYSTR
+# define CRNCYSTR CRNCYSTR
#endif
MON_DECIMAL_POINT,
#define MON_DECIMAL_POINT MON_DECIMAL_POINT
@@ -309,6 +453,34 @@ enum
#define P_SIGN_POSN P_SIGN_POSN
N_SIGN_POSN,
#define N_SIGN_POSN N_SIGN_POSN
+ _NL_MONETARY_INT_P_CS_PRECEDES,
+ _NL_MONETARY_INT_P_SEP_BY_SPACE,
+ _NL_MONETARY_INT_N_CS_PRECEDES,
+ _NL_MONETARY_INT_N_SEP_BY_SPACE,
+ _NL_MONETARY_INT_P_SIGN_POSN,
+ _NL_MONETARY_INT_N_SIGN_POSN,
+ _NL_MONETARY_DUO_INT_CURR_SYMBOL,
+ _NL_MONETARY_DUO_CURRENCY_SYMBOL,
+ _NL_MONETARY_DUO_INT_FRAC_DIGITS,
+ _NL_MONETARY_DUO_FRAC_DIGITS,
+ _NL_MONETARY_DUO_P_CS_PRECEDES,
+ _NL_MONETARY_DUO_P_SEP_BY_SPACE,
+ _NL_MONETARY_DUO_N_CS_PRECEDES,
+ _NL_MONETARY_DUO_N_SEP_BY_SPACE,
+ _NL_MONETARY_DUO_INT_P_CS_PRECEDES,
+ _NL_MONETARY_DUO_INT_P_SEP_BY_SPACE,
+ _NL_MONETARY_DUO_INT_N_CS_PRECEDES,
+ _NL_MONETARY_DUO_INT_N_SEP_BY_SPACE,
+ _NL_MONETARY_DUO_P_SIGN_POSN,
+ _NL_MONETARY_DUO_N_SIGN_POSN,
+ _NL_MONETARY_DUO_INT_P_SIGN_POSN,
+ _NL_MONETARY_DUO_INT_N_SIGN_POSN,
+ _NL_MONETARY_UNO_VALID_FROM,
+ _NL_MONETARY_UNO_VALID_TO,
+ _NL_MONETARY_DUO_VALID_FROM,
+ _NL_MONETARY_DUO_VALID_TO,
+ _NL_MONETARY_CONVERSION_RATE_EB,
+ _NL_MONETARY_CONVERSION_RATE_EL,
_NL_NUM_LC_MONETARY,
/* LC_NUMERIC category: formatting of numbers.
@@ -323,7 +495,7 @@ enum
#define THOUSANDS_SEP THOUSANDS_SEP
#ifdef __USE_XOPEN
THOUSEP = THOUSANDS_SEP,
-#define THOUSEP THOUSEP
+# define THOUSANDS_SEP THOUSANDS_SEP
#endif
GROUPING,
#define GROUPING GROUPING
@@ -333,14 +505,67 @@ enum
#define YESEXPR YESEXPR
NOEXPR, /* Regex matching ``no'' input. */
#define NOEXPR NOEXPR
- __YESSTR, /* Output string for ``yes''. */
- __NOSTR, /* Output string for ``no''. */
-#if !defined __USE_XOPEN2K || defined __USE_GNU
-# define YESSTR __YESSTR
-# define NOSTR __NOSTR
-#endif
+ YESSTR, /* Output string for ``yes''. */
+#define YESSTR YESSTR
+ NOSTR, /* Output string for ``no''. */
+#define NOSTR NOSTR
_NL_NUM_LC_MESSAGES,
+ _NL_PAPER_HEIGHT_EB = _NL_ITEM (LC_PAPER, 0),
+ _NL_PAPER_HEIGHT_EL,
+ _NL_PAPER_WIDTH_EB,
+ _NL_PAPER_WIDTH_EL,
+ _NL_NUM_LC_PAPER,
+
+ _NL_NAME_NAME_FMT = _NL_ITEM (LC_NAME, 0),
+ _NL_NAME_NAME_GEN,
+ _NL_NAME_NAME_MR,
+ _NL_NAME_NAME_MRS,
+ _NL_NAME_NAME_MISS,
+ _NL_NAME_NAME_MS,
+ _NL_NUM_LC_NAME,
+
+ _NL_ADDRESS_POSTAL_FMT = _NL_ITEM (LC_ADDRESS, 0),
+ _NL_ADDRESS_COUNTRY_NAME,
+ _NL_ADDRESS_COUNTRY_POST,
+ _NL_ADDRESS_COUNTRY_AB2,
+ _NL_ADDRESS_COUNTRY_AB3,
+ _NL_ADDRESS_COUNTRY_CAR,
+ _NL_ADDRESS_COUNTRY_NUM_EB,
+ _NL_ADDRESS_COUNTRY_NUM_EL,
+ _NL_ADDRESS_COUNTRY_ISBN,
+ _NL_ADDRESS_LANG_NAME,
+ _NL_ADDRESS_LANG_AB,
+ _NL_ADDRESS_LANG_TERM,
+ _NL_ADDRESS_LANG_LIB,
+ _NL_NUM_LC_ADDRESS,
+
+ _NL_TELEPHONE_TEL_INT_FMT = _NL_ITEM (LC_TELEPHONE, 0),
+ _NL_TELEPHONE_TEL_DOM_FMT,
+ _NL_TELEPHONE_INT_SELECT,
+ _NL_TELEPHONE_INT_PREFIX,
+ _NL_NUM_LC_TELEPHONE,
+
+ _NL_MEASUREMENT_MEASUREMENT = _NL_ITEM (LC_MEASUREMENT, 0),
+ _NL_NUM_LC_MEASUREMENT,
+
+ _NL_IDENTIFICATION_TITLE = _NL_ITEM (LC_IDENTIFICATION, 0),
+ _NL_IDENTIFICATION_SOURCE,
+ _NL_IDENTIFICATION_ADDRESS,
+ _NL_IDENTIFICATION_CONTACT,
+ _NL_IDENTIFICATION_EMAIL,
+ _NL_IDENTIFICATION_TEL,
+ _NL_IDENTIFICATION_FAX,
+ _NL_IDENTIFICATION_LANGUAGE,
+ _NL_IDENTIFICATION_TERRITORY,
+ _NL_IDENTIFICATION_AUDIENCE,
+ _NL_IDENTIFICATION_APPLICATION,
+ _NL_IDENTIFICATION_ABBREVIATION,
+ _NL_IDENTIFICATION_REVISION,
+ _NL_IDENTIFICATION_DATE,
+ _NL_IDENTIFICATION_CATEGORY,
+ _NL_NUM_LC_IDENTIFICATION,
+
/* This marks the highest value used. */
_NL_NUM
};
diff --git a/locale/lc-address.c b/locale/lc-address.c
new file mode 100644
index 0000000000..744dea68d8
--- /dev/null
+++ b/locale/lc-address.c
@@ -0,0 +1,22 @@
+/* Define current locale data for LC_ADDRESS category.
+ Copyright (C) 1998 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "localeinfo.h"
+
+_NL_CURRENT_DEFINE (LC_ADDRESS);
diff --git a/locale/lc-collate.c b/locale/lc-collate.c
index 4376286812..2970ec3721 100644
--- a/locale/lc-collate.c
+++ b/locale/lc-collate.c
@@ -1,5 +1,5 @@
/* Define current locale data for LC_COLLATE category.
- Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -28,16 +28,16 @@ extern const u_int32_t _nl_C_LC_COLLATE_symbol_classes[];
_NL_CURRENT_DEFINE (LC_COLLATE);
-const u_int32_t *__collate_table;
-const u_int32_t *__collate_extra;
+const u_int32_t *__collate_tablewc;
+const u_int32_t *__collate_extrawc;
const u_int32_t *__collate_element_hash;
const char *__collate_element_strings;
-const wchar_t *__collate_element_values;
+const uint32_t *__collate_element_values;
const u_int32_t *__collate_symbol_hash = _nl_C_LC_COLLATE_symbol_hash;
const char *__collate_symbol_strings = _nl_C_LC_COLLATE_symbol_strings;
-const u_int32_t *__collate_symbol_classes = _nl_C_LC_COLLATE_symbol_classes;
+const u_int32_t *__collate_symbol_classeswc = _nl_C_LC_COLLATE_symbol_classes;
/* We are called after loading LC_CTYPE data to load it into
@@ -58,14 +58,14 @@ _nl_postload_collate (void)
#define current(x) \
((const unsigned int *) _NL_CURRENT (LC_COLLATE, paste(_NL_COLLATE_,x)))
- __collate_table = current (bo (TABLE));
- __collate_extra = current (bo (EXTRA));
+ __collate_tablewc = current (bo (TABLEWC));
+ __collate_extrawc = current (bo (EXTRAWC));
__collate_element_hash = current (bo (ELEM_HASH));
__collate_element_strings = (const char *) current (ELEM_STR_POOL);
- __collate_element_values = (const wchar_t *) current (bo (ELEM_VAL));
+ __collate_element_values = (const uint32_t *) current (bo (ELEM_VAL));
__collate_symbol_hash = current (bo (SYMB_HASH));
__collate_symbol_strings = (const char *) current (SYMB_STR_POOL);
- __collate_symbol_classes = current (bo (SYMB_CLASS));
+ __collate_symbol_classeswc = current (bo (SYMB_CLASSWC));
}
diff --git a/locale/lc-ctype.c b/locale/lc-ctype.c
index d2139aeb31..be264eaa23 100644
--- a/locale/lc-ctype.c
+++ b/locale/lc-ctype.c
@@ -1,5 +1,5 @@
/* Define current locale data for LC_CTYPE category.
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998 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
@@ -20,6 +20,7 @@
#include "localeinfo.h"
#include <ctype.h>
#include <endian.h>
+#include <stdint.h>
_NL_CURRENT_DEFINE (LC_CTYPE);
@@ -46,14 +47,14 @@ _nl_postload_ctype (void)
#define current(type,x,offset) \
((const type *) _NL_CURRENT (LC_CTYPE, paste(_NL_CTYPE_,x)) + offset)
- extern const unsigned int *__ctype32_b;
- extern const unsigned int *__ctype_names;
+ extern const uint32_t *__ctype32_b;
+ extern const uint32_t *__ctype_names;
extern const unsigned char *__ctype_width;
- __ctype_b = current (unsigned short int, CLASS, 128);
- __ctype_toupper = current (int, bo (TOUPPER), 128);
- __ctype_tolower = current (int, bo (TOLOWER), 128);
- __ctype32_b = current (unsigned int, CLASS32, 0);
- __ctype_names = current (unsigned int, bo (NAMES), 0);
+ __ctype_b = current (uint16_t, CLASS, 128);
+ __ctype_toupper = current (uint32_t, bo (TOUPPER), 128);
+ __ctype_tolower = current (uint32_t, bo (TOLOWER), 128);
+ __ctype32_b = current (uint32_t, CLASS32, 0);
+ __ctype_names = current (uint32_t, bo (NAMES), 0);
__ctype_width = current (unsigned char, WIDTH, 0);
}
diff --git a/locale/lc-identification.c b/locale/lc-identification.c
new file mode 100644
index 0000000000..047033cb03
--- /dev/null
+++ b/locale/lc-identification.c
@@ -0,0 +1,22 @@
+/* Define current locale data for LC_IDENTIFICATION category.
+ Copyright (C) 1998, 1999 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "localeinfo.h"
+
+_NL_CURRENT_DEFINE (LC_IDENTIFICATION);
diff --git a/locale/lc-measurement.c b/locale/lc-measurement.c
new file mode 100644
index 0000000000..fc04357719
--- /dev/null
+++ b/locale/lc-measurement.c
@@ -0,0 +1,22 @@
+/* Define current locale data for LC_MEASUREMENT category.
+ Copyright (C) 1998 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "localeinfo.h"
+
+_NL_CURRENT_DEFINE (LC_MEASUREMENT);
diff --git a/locale/lc-monetary.c b/locale/lc-monetary.c
index b041006259..6af60a5836 100644
--- a/locale/lc-monetary.c
+++ b/locale/lc-monetary.c
@@ -1,5 +1,5 @@
/* Define current locale data for LC_MONETARY category.
- Copyright (C) 1995, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997, 1998 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
@@ -20,3 +20,24 @@
#include "localeinfo.h"
_NL_CURRENT_DEFINE (LC_MONETARY);
+
+const uint32_t *__monetary_conversion_rate;
+
+void
+_nl_postload_monetary (void)
+{
+#if BYTE_ORDER == BIG_ENDIAN
+#define bo(x) x##_EB
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define bo(x) x##_EL
+#else
+#error bizarre byte order
+#endif
+#define paste(a,b) paste1(a,b)
+#define paste1(a,b) a##b
+
+#define current(type,x,offset) \
+ ((const type *) _NL_CURRENT (LC_MONETARY, paste(_NL_MONETARY_,x)) + offset)
+
+ __monetary_conversion_rate = current (uint32_t, bo (CONVERSION_RATE), 0);
+}
diff --git a/locale/lc-name.c b/locale/lc-name.c
new file mode 100644
index 0000000000..404f83f0f4
--- /dev/null
+++ b/locale/lc-name.c
@@ -0,0 +1,22 @@
+/* Define current locale data for LC_NAME category.
+ Copyright (C) 1998 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "localeinfo.h"
+
+_NL_CURRENT_DEFINE (LC_NAME);
diff --git a/locale/lc-paper.c b/locale/lc-paper.c
new file mode 100644
index 0000000000..6e1107c91b
--- /dev/null
+++ b/locale/lc-paper.c
@@ -0,0 +1,22 @@
+/* Define current locale data for LC_PAPER category.
+ Copyright (C) 1998 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "localeinfo.h"
+
+_NL_CURRENT_DEFINE (LC_PAPER);
diff --git a/locale/lc-telephone.c b/locale/lc-telephone.c
new file mode 100644
index 0000000000..d381598b11
--- /dev/null
+++ b/locale/lc-telephone.c
@@ -0,0 +1,22 @@
+/* Define current locale data for LC_TELEPHONE category.
+ Copyright (C) 1998 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "localeinfo.h"
+
+_NL_CURRENT_DEFINE (LC_TELEPHONE);
diff --git a/locale/lc-time.c b/locale/lc-time.c
index a9344fcd33..77888bb666 100644
--- a/locale/lc-time.c
+++ b/locale/lc-time.c
@@ -1,5 +1,5 @@
/* Define current locale data for LC_TIME category.
- Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -18,9 +18,11 @@
Boston, MA 02111-1307, USA. */
#include <bits/libc-lock.h>
+#include <endian.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <wchar.h>
#include "localeinfo.h"
_NL_CURRENT_DEFINE (LC_TIME);
@@ -36,7 +38,10 @@ static size_t num_eras;
static int alt_digits_initialized;
static const char **alt_digits;
-static size_t num_alt_digits;
+
+
+static int walt_digits_initialized;
+static const wchar_t **walt_digits;
void
@@ -45,6 +50,7 @@ _nl_postload_time (void)
/* Prepare lazy initialization of `era' and `alt_digits' array. */
era_initialized = 0;
alt_digits_initialized = 0;
+ walt_digits_initialized = 0;
}
@@ -58,8 +64,13 @@ _nl_get_era_entry (const struct tm *tp)
if (era_initialized == 0)
{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
size_t new_num_eras = _NL_CURRENT_WORD (LC_TIME,
- _NL_TIME_ERA_NUM_ENTRIES);
+ _NL_TIME_ERA_NUM_ENTRIES_EL);
+#else
+ size_t new_num_eras = _NL_CURRENT_WORD (LC_TIME,
+ _NL_TIME_ERA_NUM_ENTRIES_EB);
+#endif
if (eras != NULL && new_num_eras == 0)
{
@@ -88,12 +99,17 @@ _nl_get_era_entry (const struct tm *tp)
/* Skip numeric values. */
ptr += sizeof (struct era_entry);
- /* Skip era name. */
+ /* Skip era name. */
ptr = strchr (ptr, '\0') + 1;
- /* Skip era format. */
+ /* Skip era format. */
ptr = strchr (ptr, '\0') + 1;
ptr += 3 - (((ptr - (const char *) eras[cnt]) + 3) & 3);
+
+ /* Skip wide era name. */
+ ptr = (char *) wcschr ((wchar_t *) ptr, '\0');
+ /* Skip wide era format. */
+ ptr = (char *) wcschr ((wchar_t *) ptr, '\0');
}
}
}
@@ -132,43 +148,28 @@ _nl_get_alt_digit (unsigned int number)
if (alt_digits_initialized == 0)
{
- size_t new_num_alt_digits = _NL_CURRENT_WORD (LC_TIME,
- _NL_TIME_NUM_ALT_DIGITS);
-
- if (alt_digits != NULL && new_num_alt_digits == 0)
- {
- free (alt_digits);
- alt_digits = NULL;
- }
- else if (new_num_alt_digits != 0)
- {
- if (num_alt_digits != new_num_alt_digits)
- alt_digits = realloc (alt_digits, (new_num_alt_digits
- * sizeof (const char *)));
+ alt_digits_initialized = 1;
- if (alt_digits == NULL)
- num_alt_digits = 0;
- else
- {
- const char *ptr = _NL_CURRENT (LC_TIME, ALT_DIGITS);
- size_t cnt;
+ if (alt_digits == NULL)
+ alt_digits = malloc (100 * sizeof (const char *));
- num_alt_digits = new_num_alt_digits;
+ if (alt_digits != NULL)
+ {
+ const char *ptr = _NL_CURRENT (LC_TIME, ALT_DIGITS);
+ size_t cnt;
- for (cnt = 0; cnt < num_alt_digits; ++cnt)
- {
- alt_digits[cnt] = ptr;
+ if (alt_digits != NULL)
+ for (cnt = 0; cnt < 100; ++cnt)
+ {
+ alt_digits[cnt] = ptr;
- /* Skip digit format. */
- ptr = strchr (ptr, '\0') + 1;
- }
- }
+ /* Skip digit format. */
+ ptr = strchr (ptr, '\0') + 1;
+ }
}
-
- alt_digits_initialized = 1;
}
- result = number < num_alt_digits ? alt_digits[number] : NULL;
+ result = alt_digits != NULL && number < 100 ? alt_digits[number] : NULL;
__libc_lock_unlock (__libc_setlocale_lock);
@@ -176,14 +177,42 @@ _nl_get_alt_digit (unsigned int number)
}
-/* Free all resources if necessary. */
-static void __attribute__ ((unused))
-free_mem (void)
+const wchar_t *
+_nl_get_walt_digit (unsigned int number)
{
- if (eras != NULL)
- free (eras);
- if (alt_digits != NULL)
- free (alt_digits);
-}
+ const wchar_t *result;
+
+ __libc_lock_lock (__libc_setlocale_lock);
+
+ if (walt_digits_initialized == 0)
+ {
+ walt_digits_initialized = 1;
+
+ if (walt_digits == NULL)
+ walt_digits = malloc (100 * sizeof (const uint32_t *));
+
+ if (walt_digits != NULL)
+ {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ const wchar_t *ptr = _NL_CURRENT_WSTR (LC_TIME, _NL_WALT_DIGITS_EL);
+#else
+ const wchar_t *ptr = _NL_CURRENT_WSTR (LC_TIME, _NL_WALT_DIGITS_EB);
+#endif
+ size_t cnt;
-text_set_element (__libc_subfreeres, free_mem);
+ for (cnt = 0; cnt < 100; ++cnt)
+ {
+ walt_digits[cnt] = ptr;
+
+ /* Skip digit format. */
+ ptr = wcschr (ptr, L'\0') + 1;
+ }
+ }
+ }
+
+ result = walt_digits != NULL && number < 100 ? walt_digits[number] : NULL;
+
+ __libc_lock_unlock (__libc_setlocale_lock);
+
+ return (wchar_t *) result;
+}
diff --git a/locale/loadlocale.c b/locale/loadlocale.c
index 24d0c3a67d..121798782e 100644
--- a/locale/loadlocale.c
+++ b/locale/loadlocale.c
@@ -1,7 +1,7 @@
/* Functions to read locale data files.
Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -18,14 +18,13 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <byteswap.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#ifdef _POSIX_MAPPED_FILES
-# include <sys/mman.h>
-#endif
+#include <sys/mman.h>
#include <sys/stat.h>
#include "localeinfo.h"
@@ -33,7 +32,7 @@
static const size_t _nl_category_num_items[] =
{
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = _NL_ITEM_INDEX (_NL_NUM_##category),
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -42,7 +41,7 @@ static const size_t _nl_category_num_items[] =
#define NO_PAREN(arg, rest...) arg, ##rest
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
static const enum value_type _nl_value_type_##category[] = { NO_PAREN items };
#define DEFINE_ELEMENT(element, element_name, optstd, type, rest...) \
[_NL_ITEM_INDEX (element)] = type,
@@ -51,7 +50,7 @@ static const enum value_type _nl_value_type_##category[] = { NO_PAREN items };
static const enum value_type *_nl_value_types[] =
{
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = _nl_value_type_##category,
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -76,10 +75,9 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
size_t cnt;
inline unsigned int SWAP (const unsigned int *inw)
{
- const unsigned char *inc = (const unsigned char *) inw;
if (!swap)
return *inw;
- return (inc[3] << 24) | (inc[2] << 16) | (inc[1] << 8) | inc[0];
+ return bswap_32 (*inw);
}
file->decided = 1;
@@ -97,17 +95,13 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
/* LOCALE/LC_foo is a directory; open LOCALE/LC_foo/SYS_LC_foo
instead. */
char *newp;
- size_t filenamelen;
__close (fd);
- filenamelen = strlen (file->filename);
- newp = (char *) alloca (filenamelen
+ newp = (char *) alloca (strlen (file->filename)
+ 5 + _nl_category_name_sizes[category] + 1);
- __mempcpy (__mempcpy (__mempcpy (newp, file->filename, filenamelen),
- "/SYS_", 5),
- _nl_category_names[category],
- _nl_category_name_sizes[category] + 1);
+ __stpcpy (__stpcpy (__stpcpy (newp, file->filename), "/SYS_"),
+ _nl_category_names[category]);
fd = __open (newp, O_RDONLY);
if (fd < 0)
@@ -119,32 +113,24 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
/* Map in the file's data. */
save_err = errno;
-#ifdef _POSIX_MAPPED_FILES
-# ifndef MAP_COPY
+#ifndef MAP_COPY
/* Linux seems to lack read-only copy-on-write. */
-# define MAP_COPY MAP_PRIVATE
-# endif
-# ifndef MAP_FILE
+#define MAP_COPY MAP_PRIVATE
+#endif
+#ifndef MAP_FILE
/* Some systems do not have this flag; it is superfluous. */
-# define MAP_FILE 0
-# endif
-# ifndef MAP_INHERIT
+#define MAP_FILE 0
+#endif
+#ifndef MAP_INHERIT
/* Some systems might lack this; they lose. */
-# define MAP_INHERIT 0
-# endif
+#define MAP_INHERIT 0
+#endif
filedata = (void *) __mmap ((caddr_t) 0, st.st_size, PROT_READ,
MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0);
- if ((void *) filedata != MAP_FAILED)
- {
- if (st.st_size < sizeof (*filedata))
- /* This cannot be a locale data file since it's too small. */
- goto puntfd;
- }
- else
+ if ((void *) filedata == MAP_FAILED)
{
if (errno == ENOSYS)
{
-#endif /* _POSIX_MAPPED_FILES */
/* No mmap; allocate a buffer and read from the file. */
mmaped = 0;
filedata = malloc (st.st_size);
@@ -170,12 +156,13 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
else
goto puntfd;
__set_errno (save_err);
-#ifdef _POSIX_MAPPED_FILES
}
else
goto puntfd;
}
-#endif /* _POSIX_MAPPED_FILES */
+ else if (st.st_size < sizeof (*filedata))
+ /* This cannot be a locale data file since it's too small. */
+ goto puntfd;
if (filedata->magic == LIMAGIC (category))
/* Good data file in our byte order. */
@@ -188,12 +175,7 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
/* Bad data file in either byte order. */
{
puntmap:
-#ifdef _POSIX_MAPPED_FILES
- if (mmaped)
- __munmap ((caddr_t) filedata, st.st_size);
- else
-#endif /* _POSIX_MAPPED_FILES */
- free (filedata);
+ __munmap ((caddr_t) filedata, st.st_size);
puntfd:
__close (fd);
return;
@@ -211,9 +193,9 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
goto puntmap;
}
- newdata = malloc (sizeof *newdata +
- (_nl_category_num_items[category]
- * sizeof (union locale_data_value)));
+ newdata = malloc (sizeof *newdata
+ + (_nl_category_num_items[category]
+ * sizeof (union locale_data_value)));
if (! newdata)
goto puntmap;
@@ -246,14 +228,9 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
void
_nl_unload_locale (struct locale_data *locale)
{
- if (locale->name != NULL)
- free ((void *) locale->name);
-
-#ifdef _POSIX_MAPPED_FILES
if (locale->mmaped)
__munmap ((caddr_t) locale->filedata, locale->filesize);
else
-#endif
free ((void *) locale->filedata);
free (locale);
diff --git a/locale/locale.h b/locale/locale.h
index 41cb669bbe..1429328533 100644
--- a/locale/locale.h
+++ b/locale/locale.h
@@ -32,13 +32,19 @@ __BEGIN_DECLS
/* These are the possibilities for the first argument to setlocale.
The code assumes that LC_ALL is the highest value, and zero the lowest. */
-#define LC_CTYPE 0
-#define LC_NUMERIC 1
-#define LC_TIME 2
-#define LC_COLLATE 3
-#define LC_MONETARY 4
-#define LC_MESSAGES 5
-#define LC_ALL 6
+#define LC_CTYPE 0
+#define LC_NUMERIC 1
+#define LC_TIME 2
+#define LC_COLLATE 3
+#define LC_MONETARY 4
+#define LC_MESSAGES 5
+#define LC_ALL 6
+#define LC_PAPER 7
+#define LC_NAME 8
+#define LC_ADDRESS 9
+#define LC_TELEPHONE 10
+#define LC_MEASUREMENT 11
+#define LC_IDENTIFICATION 12
/* Structure giving information about numeric and monetary notation. */
diff --git a/locale/localeinfo.h b/locale/localeinfo.h
index 2c1ce65557..773143dd16 100644
--- a/locale/localeinfo.h
+++ b/locale/localeinfo.h
@@ -1,5 +1,5 @@
-/* localeinfo.h -- declarations for internal libc locale interfaces
- Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+/* Declarations for internal libc locale interfaces
+ Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@@ -24,17 +24,21 @@
#include <langinfo.h>
#include <limits.h>
#include <time.h>
+#include <stdint.h>
#include <sys/types.h>
-#include "../intl/loadinfo.h" /* For loaded_l10nfile definition. */
+/* This has to be changed whenever a new locale is defined. */
+#define __LC_LAST 13
+
+#include <intl/loadinfo.h> /* For loaded_l10nfile definition. */
/* Magic number at the beginning of a locale data file for CATEGORY. */
-#define LIMAGIC(category) (0x960617de ^ (category))
+#define LIMAGIC(category) (0x980505 ^ (category))
/* Two special weight constants for the collation data. */
-#define FORWARD_CHAR ((wchar_t) 0xfffffffd)
-#define ELLIPSIS_CHAR ((wchar_t) 0xfffffffe)
-#define IGNORE_CHAR ((wchar_t) 0xffffffff)
+#define FORWARD_CHAR ((uint32_t) 0xfffffffd)
+#define ELLIPSIS_CHAR ((uint32_t) 0xfffffffe)
+#define IGNORE_CHAR ((uint32_t) 0xffffffff)
/* We use a special value for the usage counter in `locale_data' to
signal that this data must never be removed anymore. */
@@ -54,7 +58,7 @@ struct locale_data
unsigned int nstrings; /* Number of strings below. */
union locale_data_value
{
- const wchar_t *wstr;
+ const uint32_t *wstr;
const char *string;
unsigned int word;
}
@@ -83,14 +87,15 @@ enum value_type
byte,
bytearray,
word,
- stringlist
+ stringlist,
+ wordarray
};
/* Structure to access `era' information from LC_TIME. */
struct era_entry
{
- u_int32_t direction; /* Contains '+' or '-'. */
+ uint32_t direction; /* Contains '+' or '-'. */
int32_t offset;
int32_t start_date[3];
int32_t stop_date[3];
@@ -99,27 +104,26 @@ struct era_entry
/* For each category declare the variable for the current locale data. */
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
extern struct locale_data *_nl_current_##category;
#include "categories.def"
#undef DEFINE_CATEGORY
-extern const char _nl_category_names[LC_ALL + 1][16];
-extern const size_t _nl_category_name_sizes[LC_ALL + 1];
-extern struct locale_data * *const _nl_current[LC_ALL + 1];
+extern const char *const _nl_category_names[__LC_LAST];
+extern const size_t _nl_category_name_sizes[__LC_LAST];
+extern struct locale_data * *const _nl_current[__LC_LAST];
/* Name of the standard locales. */
extern const char _nl_C_name[];
extern const char _nl_POSIX_name[];
-/* XXX Temporily until the locale data has everything. */
-extern struct locale_data _nl_C_LC_TIME;
-
/* Extract the current CATEGORY locale's string for ITEM. */
#define _NL_CURRENT(category, item) \
- ((item) < _NL_WABDAY_1 || (item) > _NL_WALT_DIGITS \
- ? (_nl_current_##category->values[_NL_ITEM_INDEX (item)].string) \
- : _nl_C_LC_TIME.values[_NL_ITEM_INDEX (item)].string)
+ (_nl_current_##category->values[_NL_ITEM_INDEX (item)].string)
+
+/* Extract the current CATEGORY locale's string for ITEM. */
+#define _NL_CURRENT_WSTR(category, item) \
+ ((wchar_t *) (_nl_current_##category->values[_NL_ITEM_INDEX (item)].wstr))
/* Extract the current CATEGORY locale's word for ITEM. */
#define _NL_CURRENT_WORD(category, item) \
@@ -154,15 +158,18 @@ extern struct era_entry *_nl_get_era_entry (const struct tm *tp);
/* Return `alt_digit' which corresponds to NUMBER. Used in strftime. */
extern const char *_nl_get_alt_digit (unsigned int number);
+/* Similar, but now for wide characters. */
+extern const wchar_t *_nl_get_walt_digit (unsigned int number);
+
/* Global variables for LC_COLLATE category data. */
-extern const u_int32_t *__collate_table;
-extern const u_int32_t *__collate_extra;
-extern const u_int32_t *__collate_element_hash;
+extern const uint32_t *__collate_tablewc;
+extern const uint32_t *__collate_extrawc;
+extern const uint32_t *__collate_element_hash;
extern const char *__collate_element_strings;
-extern const wchar_t *__collate_element_values;
-extern const u_int32_t *__collate_symbol_hash;
+extern const uint32_t *__collate_element_values;
+extern const uint32_t *__collate_symbol_hash;
extern const char *__collate_symbol_strings;
-extern const u_int32_t *__collate_symbol_classes;
+extern const uint32_t *__collate_symbol_classes;
#endif /* localeinfo.h */
diff --git a/locale/newlocale.c b/locale/newlocale.c
index c54d1c82c6..61a72c4aeb 100644
--- a/locale/newlocale.c
+++ b/locale/newlocale.c
@@ -1,5 +1,5 @@
/* Return a reference to locale information record.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -41,7 +41,7 @@ __locale_t
__newlocale (int category_mask, const char *locale, __locale_t base)
{
/* Intermediate memory for result. */
- const char *newnames[LC_ALL];
+ const char *newnames[__LC_LAST];
struct __locale_struct result;
__locale_t result_ptr;
char *locale_path;
@@ -51,10 +51,10 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
/* We treat LC_ALL in the same way as if all bits were set. */
if (category_mask == LC_ALL)
- category_mask = (1 << LC_ALL) - 1;
+ category_mask = (1 << __LC_LAST) - 1 - (1 << LC_ALL);
/* Sanity check for CATEGORY argument. */
- if ((category_mask & ~((1 << LC_ALL) - 1)) != 0)
+ if ((category_mask & ~((1 << LC_ALL) - 1 - (1 << LC_ALL))) != 0)
ERROR_RETURN;
/* `newlocale' does not support asking for the locale name. */
@@ -72,8 +72,9 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
else
{
/* Fill with pointers to C locale data to . */
- for (cnt = 0; cnt < LC_ALL; ++cnt)
- result.__locales[cnt] = _nl_C[cnt];
+ for (cnt = 0; cnt < __LC_LAST; ++cnt)
+ if (cnt != LC_ALL)
+ result.__locales[cnt] = _nl_C[cnt];
/* If no category is to be set we return BASE if available or a
dataset using the C locale data. */
@@ -105,8 +106,9 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
/* Get the names for the locales we are interested in. We either
allow a composite name or a single name. */
- for (cnt = 0; cnt < LC_ALL; ++cnt)
- newnames[cnt] = locale;
+ for (cnt = 0; cnt < __LC_LAST; ++cnt)
+ if (cnt != LC_ALL)
+ newnames[cnt] = locale;
if (strchr (locale, ';') != NULL)
{
/* This is a composite name. Make a copy and split it up. */
@@ -115,12 +117,13 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
while ((cp = strchr (np, '=')) != NULL)
{
- for (cnt = 0; cnt < LC_ALL; ++cnt)
- if ((size_t) (cp - np) == _nl_category_name_sizes[cnt]
+ for (cnt = 0; cnt < __LC_LAST; ++cnt)
+ if (cnt != LC_ALL
+ && (size_t) (cp - np) == _nl_category_name_sizes[cnt]
&& memcmp (np, _nl_category_names[cnt], cp - np) == 0)
break;
- if (cnt == LC_ALL)
+ if (cnt == __LC_LAST)
/* Bogus category name. */
ERROR_RETURN;
@@ -138,15 +141,16 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
break;
}
- for (cnt = 0; cnt < LC_ALL; ++cnt)
- if ((category_mask & 1 << cnt) != 0 && newnames[cnt] == locale)
+ for (cnt = 0; cnt < __LC_LAST; ++cnt)
+ if (cnt != LC_ALL
+ && (category_mask & 1 << cnt) != 0 && newnames[cnt] == locale)
/* The composite name did not specify the category we need. */
ERROR_RETURN;
}
/* Now process all categories we are interested in. */
- for (cnt = 0; cnt < LC_ALL; ++cnt)
- if ((category_mask & 1 << cnt) != 0)
+ for (cnt = 0; cnt < __LC_LAST; ++cnt)
+ if (cnt != LC_ALL && (category_mask & 1 << cnt) != 0)
{
result.__locales[cnt] = _nl_find_locale (locale_path, locale_path_len,
cnt, &newnames[cnt]);
diff --git a/locale/programs/charmap-kw.gperf b/locale/programs/charmap-kw.gperf
index 1fb9c38b04..34241041a6 100644
--- a/locale/programs/charmap-kw.gperf
+++ b/locale/programs/charmap-kw.gperf
@@ -1,7 +1,7 @@
%{
-/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
+ Contributed by Ulrich Drepper, <drepper@gnu.org>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -33,6 +33,9 @@ g0esc, tok_g0esc, 1
g1esc, tok_g1esc, 1
g2esc, tok_g2esc, 1
g3esc, tok_g3esc, 1
+escseq, tok_escseq, 1
+addset, tok_addset, 1
+include, tok_include, 1
CHARMAP, tok_charmap, 0
END, tok_end, 0
WIDTH, tok_width, 0
diff --git a/locale/programs/charmap-kw.h b/locale/programs/charmap-kw.h
index 3bfcd14612..4b402165ef 100644
--- a/locale/programs/charmap-kw.h
+++ b/locale/programs/charmap-kw.h
@@ -1,8 +1,8 @@
-/* C code produced by gperf version 2.5 (GNU C++ version) */
-/* Command-line: gperf -acCgopt -k1,2,5,$ -N charmap_hash programs/charmap-kw.gperf */
-/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+/* ANSI-C code produced by gperf version 2.7.1 (19981006 egcs) */
+/* Command-line: gperf -acCgopt -k1,2,5,9,$ -L ANSI-C -N charmap_hash programs/charmap-kw.gperf */
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
+ Contributed by Ulrich Drepper, <drepper@gnu.org>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -24,81 +24,103 @@
#include "locfile-token.h"
struct keyword_t ;
-#define TOTAL_KEYWORDS 14
+#define TOTAL_KEYWORDS 17
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 14
#define MIN_HASH_VALUE 3
-#define MAX_HASH_VALUE 25
-/* maximum key range = 23, duplicates = 0 */
+#define MAX_HASH_VALUE 35
+/* maximum key range = 33, duplicates = 0 */
#ifdef __GNUC__
-inline
+__inline
#endif
static unsigned int
-hash (register const char *str, register int len)
+hash (register const char *str, register unsigned int len)
{
static const unsigned char asso_values[] =
{
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 14, 10,
- 15, 4, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 0, 0, 0,
- 26, 26, 0, 0, 26, 26, 26, 0, 0, 26,
- 0, 26, 26, 26, 5, 26, 26, 0, 26, 26,
- 26, 26, 26, 26, 26, 0, 26, 26, 0, 0,
- 26, 0, 26, 0, 26, 26, 26, 26, 26, 0,
- 15, 0, 0, 26, 0, 0, 26, 0, 26, 26,
- 0, 26, 26, 26, 26, 26, 26, 26,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 25, 10,
+ 15, 20, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 10, 0, 0,
+ 5, 36, 0, 0, 36, 36, 36, 0, 0, 36,
+ 0, 36, 0, 36, 0, 36, 36, 0, 36, 36,
+ 36, 36, 36, 36, 36, 0, 36, 0, 0, 0,
+ 10, 0, 36, 0, 0, 0, 36, 36, 36, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 36, 36,
+ 25, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36
};
register int hval = len;
switch (hval)
{
default:
+ case 9:
+ hval += asso_values[(unsigned char)str[8]];
+ case 8:
+ case 7:
+ case 6:
case 5:
- hval += asso_values[str[4]];
+ hval += asso_values[(unsigned char)str[4]];
case 4:
case 3:
case 2:
- hval += asso_values[str[1]];
+ hval += asso_values[(unsigned char)str[1]];
case 1:
- hval += asso_values[str[0]];
+ hval += asso_values[(unsigned char)str[0]];
break;
}
- return hval + asso_values[str[len - 1]];
+ return hval + asso_values[(unsigned char)str[len - 1]];
}
#ifdef __GNUC__
-inline
+__inline
#endif
const struct keyword_t *
-charmap_hash (register const char *str, register int len)
+charmap_hash (register const char *str, register unsigned int len)
{
static const struct keyword_t wordlist[] =
{
- {"",}, {"",}, {"",},
- {"END", tok_end, 0},
- {"",},
- {"WIDTH", tok_width, 0},
- {"",},
- {"CHARMAP", tok_charmap, 0},
- {"",},
- {"g3esc", tok_g3esc, 1},
- {"mb_cur_max", tok_mb_cur_max, 1},
- {"escape_char", tok_escape_char, 1},
- {"comment_char", tok_comment_char, 1},
- {"code_set_name", tok_code_set_name, 1},
- {"WIDTH_VARIABLE", tok_width_variable, 0},
- {"g1esc", tok_g1esc, 1},
- {"",}, {"",},
- {"WIDTH_DEFAULT", tok_width_default, 0},
- {"g0esc", tok_g0esc, 1},
- {"g2esc", tok_g2esc, 1},
- {"",}, {"",}, {"",}, {"",},
- {"mb_cur_min", tok_mb_cur_min, 1},
+ {""}, {""}, {""},
+ {"END", tok_end, 0},
+ {""},
+ {"WIDTH", tok_width, 0},
+ {"escseq", tok_escseq, 1},
+ {"include", tok_include, 1},
+ {""}, {""},
+ {"mb_cur_min", tok_mb_cur_min, 1},
+ {"escape_char", tok_escape_char, 1},
+ {"comment_char", tok_comment_char, 1},
+ {"code_set_name", tok_code_set_name, 1},
+ {"WIDTH_VARIABLE", tok_width_variable, 0},
+ {"g1esc", tok_g1esc, 1},
+ {"addset", tok_addset, 1},
+ {"CHARMAP", tok_charmap, 0},
+ {"WIDTH_DEFAULT", tok_width_default, 0},
+ {""},
+ {"g2esc", tok_g2esc, 1},
+ {""}, {""}, {""}, {""},
+ {"g3esc", tok_g3esc, 1},
+ {""}, {""}, {""}, {""},
+ {"g0esc", tok_g0esc, 1},
+ {""}, {""}, {""}, {""},
+ {"mb_cur_max", tok_mb_cur_max, 1}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
@@ -109,7 +131,7 @@ charmap_hash (register const char *str, register int len)
{
register const char *s = wordlist[key].name;
- if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
return &wordlist[key];
}
}
diff --git a/locale/programs/charmap.c b/locale/programs/charmap.c
index fd9cc357e3..6db2b420a6 100644
--- a/locale/programs/charmap.c
+++ b/locale/programs/charmap.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -25,6 +25,7 @@
#include <dirent.h>
#include <errno.h>
#include <libintl.h>
+#include <limits.h>
#include <obstack.h>
#include <stdlib.h>
#include <string.h>
@@ -32,13 +33,10 @@
#include "error.h"
#include "linereader.h"
-#include "charset.h"
+#include "charmap.h"
#include "locfile.h"
#include "repertoire.h"
-
-/* Uncomment following line for production version. */
-/* define NDEBUG 1 */
#include <assert.h>
@@ -49,17 +47,20 @@
extern void *xmalloc (size_t __n);
/* Prototypes for local functions. */
-static struct charset_t *parse_charmap (const char *filename);
-static void new_width (struct linereader *cmfile, struct charset_t *result,
+static struct charmap_t *parse_charmap (const char *filename);
+static void new_width (struct linereader *cmfile, struct charmap_t *result,
const char *from, const char *to,
unsigned long int width);
+static void charmap_new_char (struct linereader *lr, struct charmap_t *cm,
+ int nbytes, char *bytes, const char *from,
+ const char *to, int decimal_ellipsis);
-struct charset_t *
+struct charmap_t *
charmap_read (const char *filename)
{
const char *pathnfile;
- struct charset_t *result = NULL;
+ struct charmap_t *result = NULL;
if (filename != NULL)
{
@@ -175,16 +176,17 @@ charmap_read (const char *filename)
}
-static struct charset_t *
+static struct charmap_t *
parse_charmap (const char *filename)
{
struct linereader *cmfile;
- struct charset_t *result;
+ struct charmap_t *result;
int state;
enum token_t expected_tok = tok_error;
const char *expected_str = NULL;
char *from_name = NULL;
char *to_name = NULL;
+ enum token_t ellipsis = 0;
/* Determine path. */
cmfile = lr_open (filename, charmap_hash);
@@ -206,9 +208,12 @@ parse_charmap (const char *filename)
return NULL;
}
+ /* We don't want symbolic names in string to be translated. */
+ cmfile->translate_strings = 0;
+
/* Allocate room for result. */
- result = (struct charset_t *) xmalloc (sizeof (struct charset_t));
- memset (result, '\0', sizeof (struct charset_t));
+ result = (struct charmap_t *) xmalloc (sizeof (struct charmap_t));
+ memset (result, '\0', sizeof (struct charmap_t));
/* The default DEFAULT_WIDTH is 1. */
result->width_default = 1;
@@ -216,7 +221,8 @@ parse_charmap (const char *filename)
#define obstack_chunk_free free
obstack_init (&result->mem_pool);
- if (init_hash (&result->char_table, 256))
+ if (init_hash (&result->char_table, 256)
+ || init_hash (&result->byte_table, 256))
{
free (result);
return NULL;
@@ -228,7 +234,7 @@ parse_charmap (const char *filename)
while (1)
{
/* What's on? */
- struct token *now = lr_token (cmfile, NULL);
+ struct token *now = lr_token (cmfile, NULL, NULL);
enum token_t nowtok = now->tok;
struct token *arg;
@@ -275,22 +281,24 @@ parse_charmap (const char *filename)
&& nowtok != tok_mb_cur_min && nowtok != tok_escape_char
&& nowtok != tok_comment_char && nowtok != tok_g0esc
&& nowtok != tok_g1esc && nowtok != tok_g2esc
- && nowtok != tok_g3esc)
+ && nowtok != tok_g3esc && nowtok != tok_repertoiremap
+ && nowtok != tok_include)
{
lr_error (cmfile, _("syntax error in prolog: %s"),
- _("illegal definition"));
+ _("invalid definition"));
lr_ignore_rest (cmfile, 0);
continue;
}
/* We know that we need an argument. */
- arg = lr_token (cmfile, NULL);
+ arg = lr_token (cmfile, NULL, NULL);
switch (nowtok)
{
case tok_code_set_name:
- if (arg->tok != tok_ident && arg->tok != tok_string)
+ case tok_repertoiremap:
+ if (arg->tok != tok_ident)
{
badarg:
lr_error (cmfile, _("syntax error in prolog: %s"),
@@ -300,9 +308,14 @@ parse_charmap (const char *filename)
continue;
}
- result->code_set_name = obstack_copy0 (&result->mem_pool,
- arg->val.str.start,
- arg->val.str.len);
+ if (nowtok == tok_code_set_name)
+ result->code_set_name = obstack_copy0 (&result->mem_pool,
+ arg->val.str.startmb,
+ arg->val.str.lenmb);
+ else
+ result->repertoiremap = obstack_copy0 (&result->mem_pool,
+ arg->val.str.startmb,
+ arg->val.str.lenmb);
lr_ignore_rest (cmfile, 1);
continue;
@@ -312,12 +325,21 @@ parse_charmap (const char *filename)
if (arg->tok != tok_number)
goto badarg;
- if (arg->val.num < 1 || arg->val.num > 4)
+ if (verbose
+ && ((nowtok == tok_mb_cur_max
+ && result->mb_cur_max != 0)
+ || (nowtok == tok_mb_cur_max
+ && result->mb_cur_max != 0)))
+ lr_error (cmfile, _("duplicate definition of <%s>"),
+ nowtok == tok_mb_cur_min
+ ? "mb_cur_min" : "mb_cur_max");
+
+ if (arg->val.num < 1)
{
lr_error (cmfile,
- _("value for <%s> must lie between 1 and 4"),
- nowtok == tok_mb_cur_min ? "mb_cur_min"
- : "mb_cur_max");
+ _("value for <%s> must be 1 or greater"),
+ nowtok == tok_mb_cur_min
+ ? "mb_cur_min" : "mb_cur_max");
lr_ignore_rest (cmfile, 0);
continue;
@@ -328,7 +350,8 @@ parse_charmap (const char *filename)
&& (int) arg->val.num > result->mb_cur_max))
{
lr_error (cmfile, _("\
-value of <mb_cur_max> must be greater than the value of <mb_cur_min>"));
+value of <%s> must be greater or equal than the value of <%s>"),
+ "mb_cur_max", "mb_cur_min");
lr_ignore_rest (cmfile, 0);
continue;
@@ -347,7 +370,7 @@ value of <mb_cur_max> must be greater than the value of <mb_cur_min>"));
if (arg->tok != tok_ident)
goto badarg;
- if (arg->val.str.len != 1)
+ if (arg->val.str.lenmb != 1)
{
lr_error (cmfile, _("\
argument to <%s> must be a single character"),
@@ -359,9 +382,9 @@ argument to <%s> must be a single character"),
}
if (nowtok == tok_escape_char)
- cmfile->escape_char = *arg->val.str.start;
+ cmfile->escape_char = *arg->val.str.startmb;
else
- cmfile->comment_char = *arg->val.str.start;
+ cmfile->comment_char = *arg->val.str.startmb;
lr_ignore_rest (cmfile, 1);
continue;
@@ -370,9 +393,15 @@ argument to <%s> must be a single character"),
case tok_g1esc:
case tok_g2esc:
case tok_g3esc:
+ case tok_escseq:
lr_ignore_rest (cmfile, 0); /* XXX */
continue;
+ case tok_include:
+ lr_error (cmfile, _("\
+character sets with locking states are not supported"));
+ exit (4);
+
default:
/* Cannot happen. */
assert (! "Should not happen");
@@ -409,8 +438,8 @@ argument to <%s> must be a single character"),
obstack_free (&result->mem_pool, from_name);
from_name = (char *) obstack_copy0 (&result->mem_pool,
- now->val.str.start,
- now->val.str.len);
+ now->val.str.startmb,
+ now->val.str.lenmb);
to_name = NULL;
state = 3;
@@ -419,19 +448,20 @@ argument to <%s> must be a single character"),
case 3:
/* We have two possibilities: We can see an ellipsis or an
encoding value. */
- if (nowtok == tok_ellipsis)
+ if (nowtok == tok_ellipsis3 || nowtok == tok_ellipsis4
+ || nowtok == tok_ellipsis2)
{
+ ellipsis = nowtok;
state = 4;
continue;
}
/* FALLTHROUGH */
case 5:
- if (nowtok != tok_charcode && nowtok != tok_ucs2
- && nowtok != tok_ucs4)
+ if (nowtok != tok_charcode)
{
lr_error (cmfile, _("syntax error in %s definition: %s"),
- "CHARMAP", _("illegal encoding given"));
+ "CHARMAP", _("invalid encoding given"));
lr_ignore_rest (cmfile, 0);
@@ -444,9 +474,9 @@ argument to <%s> must be a single character"),
else if (now->val.charcode.nbytes > result->mb_cur_max)
lr_error (cmfile, _("too many bytes in character encoding"));
else
- charset_new_char (cmfile, &result->char_table,
- now->val.charcode.nbytes,
- now->val.charcode.val, from_name, to_name);
+ charmap_new_char (cmfile, result, now->val.charcode.nbytes,
+ now->val.charcode.bytes, from_name, to_name,
+ ellipsis != tok_ellipsis2);
/* Ignore trailing comment silently. */
lr_ignore_rest (cmfile, 0);
@@ -470,8 +500,8 @@ argument to <%s> must be a single character"),
/* Copy the to-name in a safe place. */
to_name = (char *) obstack_copy0 (&result->mem_pool,
- cmfile->token.val.str.start,
- cmfile->token.val.str.len);
+ cmfile->token.val.str.startmb,
+ cmfile->token.val.str.lenmb);
state = 5;
continue;
@@ -557,15 +587,15 @@ only WIDTH definitions are allowed to follow the CHARMAP definition"));
obstack_free (&result->mem_pool, from_name);
from_name = (char *) obstack_copy0 (&result->mem_pool,
- now->val.str.start,
- now->val.str.len);
+ now->val.str.startmb,
+ now->val.str.lenmb);
to_name = NULL;
state = 94;
continue;
case 94:
- if (nowtok == tok_ellipsis)
+ if (nowtok == tok_ellipsis3)
{
state = 95;
continue;
@@ -602,8 +632,8 @@ only WIDTH definitions are allowed to follow the CHARMAP definition"));
}
to_name = (char *) obstack_copy0 (&result->mem_pool,
- now->val.str.start,
- now->val.str.len);
+ now->val.str.startmb,
+ now->val.str.lenmb);
state = 96;
continue;
@@ -637,15 +667,15 @@ only WIDTH definitions are allowed to follow the CHARMAP definition"));
obstack_free (&result->mem_pool, from_name);
from_name = (char *) obstack_copy0 (&result->mem_pool,
- now->val.str.start,
- now->val.str.len);
+ now->val.str.startmb,
+ now->val.str.lenmb);
to_name = NULL;
state = 99;
continue;
case 99:
- if (nowtok == tok_ellipsis)
+ if (nowtok == tok_ellipsis3)
state = 100;
/* Store info. */
@@ -663,8 +693,8 @@ only WIDTH definitions are allowed to follow the CHARMAP definition"));
else
{
to_name = (char *) obstack_copy0 (&result->mem_pool,
- now->val.str.start,
- now->val.str.len);
+ now->val.str.startmb,
+ now->val.str.lenmb);
/* XXX Enter value into table. */
}
@@ -690,13 +720,14 @@ only WIDTH definitions are allowed to follow the CHARMAP definition"));
static void
-new_width (struct linereader *cmfile, struct charset_t *result,
+new_width (struct linereader *cmfile, struct charmap_t *result,
const char *from, const char *to, unsigned long int width)
{
- unsigned int from_val, to_val;
+ struct charseq *from_val;
+ struct charseq *to_val;
- from_val = charset_find_value (&result->char_table, from, strlen (from));
- if ((wchar_t) from_val == ILLEGAL_CHAR_VALUE)
+ from_val = charmap_find_value (result, from, strlen (from));
+ if (from_val == NULL)
{
lr_error (cmfile, _("unknown character `%s'"), from);
return;
@@ -706,8 +737,8 @@ new_width (struct linereader *cmfile, struct charset_t *result,
to_val = from_val;
else
{
- to_val = charset_find_value (&result->char_table, to, strlen (to));
- if ((wchar_t) to_val == ILLEGAL_CHAR_VALUE)
+ to_val = charmap_find_value (result, to, strlen (to));
+ if (to_val == NULL)
{
lr_error (cmfile, _("unknown character `%s'"), to);
return;
@@ -734,3 +765,140 @@ new_width (struct linereader *cmfile, struct charset_t *result,
result->width_rules[result->nwidth_rules].width = (unsigned int) width;
++result->nwidth_rules;
}
+
+
+struct charseq *
+charmap_find_value (const struct charmap_t *cm, const char *name, size_t len)
+{
+ void *result;
+
+ return (find_entry ((hash_table *) &cm->char_table, name, len, &result)
+ < 0 ? NULL : (struct charseq *) result);
+}
+
+
+static void
+charmap_new_char (struct linereader *lr, struct charmap_t *cm,
+ int nbytes, char *bytes, const char *from, const char *to,
+ int decimal_ellipsis)
+{
+ hash_table *ht = &cm->char_table;
+ hash_table *bt = &cm->byte_table;
+ struct obstack *ob = &cm->mem_pool;
+ char *from_end;
+ char *to_end;
+ const char *cp;
+ int prefix_len, len1, len2;
+ unsigned int from_nr, to_nr, cnt;
+ struct charseq *newp;
+
+ len1 = strlen (from);
+
+ if (to == NULL)
+ {
+ newp = (struct charseq *) obstack_alloc (ob, sizeof (*newp) + nbytes);
+ newp->nbytes = nbytes;
+ memcpy (newp->bytes, bytes, nbytes);
+ newp->name = obstack_copy (ob, from, len1 + 1);
+ newp->ucs4 = UNINITIALIZED_CHAR_VALUE;
+
+ insert_entry (ht, from, len1, newp);
+ insert_entry (bt, newp->bytes, nbytes, newp);
+ /* Please note that it isn't a bug if a symbol is defined more
+ than once. All later definitions are simply discarded. */
+ return;
+ }
+
+ /* We have a range: the names must have names with equal prefixes
+ and an equal number of digits, where the second number is greater
+ or equal than the first. */
+ len2 = strlen (to);
+
+ if (len1 != len2)
+ {
+ illegal_range:
+ lr_error (lr, _("invalid names for character range"));
+ return;
+ }
+
+ cp = &from[len1 - 1];
+ if (decimal_ellipsis)
+ while (isdigit (*cp) && cp >= from)
+ --cp;
+ else
+ while (isxdigit (*cp) && cp >= from)
+ {
+ if (!isdigit (*cp) && !isupper (*cp))
+ lr_error (lr, _("\
+hexadecimal range format should use only capital characters"));
+ --cp;
+ }
+
+ prefix_len = (cp - from) + 1;
+
+ if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
+ goto illegal_range;
+
+ errno = 0;
+ from_nr = strtoul (&from[prefix_len], &from_end, decimal_ellipsis ? 10 : 16);
+ if (*from_end != '\0' || (from_nr == ULONG_MAX && errno == ERANGE)
+ || ((to_nr = strtoul (&to[prefix_len], &to_end,
+ decimal_ellipsis ? 10 : 16)) == ULONG_MAX
+ && errno == ERANGE)
+ || *to_end != '\0')
+ {
+ lr_error (lr, _("<%s> and <%s> are illegal names for range"));
+ return;
+ }
+
+ if (from_nr > to_nr)
+ {
+ lr_error (lr, _("upper limit in range is not higher then lower limit"));
+ return;
+ }
+
+ for (cnt = from_nr; cnt <= to_nr; ++cnt)
+ {
+ char *name_end;
+ obstack_printf (ob, decimal_ellipsis ? "%.*s%0*d" : "%.*s%0*X",
+ prefix_len, from, len1 - prefix_len, cnt);
+ name_end = obstack_finish (ob);
+
+ newp = (struct charseq *) obstack_alloc (ob, sizeof (*newp) + nbytes);
+ newp->nbytes = nbytes;
+ memcpy (newp->bytes, bytes, nbytes);
+ newp->name = name_end;
+ newp->ucs4 = UNINITIALIZED_CHAR_VALUE;
+
+ insert_entry (ht, name_end, len1, newp);
+ insert_entry (bt, newp->bytes, nbytes, newp);
+ /* Please note we don't examine the return value since it is no error
+ if we have two definitions for a symbol. */
+
+ /* Increment the value in the byte sequence. */
+ if (++bytes[nbytes - 1] == '\0')
+ {
+ int b = nbytes - 2;
+
+ do
+ if (b < 0)
+ {
+ lr_error (lr,
+ _("resulting bytes for range not representable."));
+ return;
+ }
+ while (++bytes[b--] == 0);
+ }
+ }
+}
+
+
+struct charseq *
+charmap_find_symbol (const struct charmap_t *cm, const char *bytes,
+ size_t nbytes)
+{
+ void *result;
+
+ return (find_entry ((hash_table *) &cm->byte_table, bytes, nbytes, &result)
+ < 0 ? NULL : (struct charseq *) result);
+}
diff --git a/locale/programs/charset.h b/locale/programs/charmap.h
index 8f066b115b..88fd078ed9 100644
--- a/locale/programs/charset.h
+++ b/locale/programs/charmap.h
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -17,27 +17,27 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#ifndef _CHARSET_H
-#define _CHARSET_H
+#ifndef _CHARMAP_H
+#define _CHARMAP_H
#include <obstack.h>
#include "repertoire.h"
#include "simple-hash.h"
-#include "linereader.h"
struct width_rule
{
- unsigned int from;
- unsigned int to;
+ struct charseq *from;
+ struct charseq *to;
unsigned int width;
};
-struct charset_t
+struct charmap_t
{
const char *code_set_name;
+ const char *repertoiremap;
int mb_cur_min;
int mb_cur_max;
@@ -48,27 +48,31 @@ struct charset_t
struct obstack mem_pool;
hash_table char_table;
+ hash_table byte_table;
+ hash_table ucs4_table;
};
-/* We need one value to mark the error case. Let's use 0xffffffff.
- I.e., it is placed in the last page of ISO 10646. For now only the
- first is used and we have plenty of room. */
-#define ILLEGAL_CHAR_VALUE ((wchar_t) 0xffffffffu)
-
+/* This is the structure used for entries in the hash table. It represents
+ the sequence of bytes used for the coded character. */
+struct charseq
+{
+ const char *name;
+ uint32_t ucs4;
+ int nbytes;
+ unsigned char bytes[0];
+};
-/* Declared in localedef.c. */
-extern int be_quiet;
/* Prototypes for charmap handling functions. */
-struct charset_t *charmap_read (const char *filename);
-
-/* Prototypes for function to insert new character. */
-void charset_new_char (struct linereader *lr, hash_table *ht, int bytes,
- unsigned int value, const char *from, const char *to);
+extern struct charmap_t *charmap_read (const char *filename);
/* Return the value stored under the given key in the hashing table. */
-unsigned int charset_find_value (const hash_table *ht,
- const char *name, size_t len);
+extern struct charseq *charmap_find_value (const struct charmap_t *charmap,
+ const char *name, size_t len);
+
+/* Return symbol for given multibyte sequence. */
+extern struct charseq *charmap_find_symbol (const struct charmap_t *charmap,
+ const char *name, size_t len);
-#endif /* charset.h */
+#endif /* charmap.h */
diff --git a/locale/programs/config.h b/locale/programs/config.h
index 9775572849..a293da3b09 100644
--- a/locale/programs/config.h
+++ b/locale/programs/config.h
@@ -1,5 +1,25 @@
+/* Configuration for localedef program.
+ Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
#ifndef _LD_CONFIG_H
-#define _LD_CONFIG_H
+#define _LD_CONFIG_H 1
/* Use the internal textdomain used for libc messages. */
#define PACKAGE _libc_intl_domainname
@@ -18,12 +38,8 @@
# endif
#endif
-
-
-#define HAVE_VPRINTF 1
-#define HAVE_STRING_H 1
-
+/* This must be one higer than the last used LC_xxx category value. */
+#define __LC_LAST 13
#include_next <config.h>
-
#endif
diff --git a/locale/programs/ld-address.c b/locale/programs/ld-address.c
new file mode 100644
index 0000000000..805330cfaf
--- /dev/null
+++ b/locale/programs/ld-address.c
@@ -0,0 +1,514 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <byteswap.h>
+#include <error.h>
+#include <langinfo.h>
+#include <string.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+
+#include "localeinfo.h"
+#include "locfile.h"
+
+
+static struct
+{
+ const char ab2[2];
+ const char ab3[3];
+ uint32_t num;
+} iso3166[] =
+{
+#define DEFINE_COUNTRY_CODE(Name, Ab2, Ab3, Num) \
+ { #Ab2, #Ab3, Num },
+#include "iso-3166.def"
+};
+
+
+static struct
+{
+ const char ab[2];
+ const char term[3];
+ const char lib[3];
+} iso639[] =
+{
+#define DEFINE_LANGUAGE_CODE(Name, Ab, Term, Lib) \
+ { #Ab, #Term, #Lib },
+#include "iso-639.def"
+};
+
+
+/* The real definition of the struct for the LC_ADDRESS locale. */
+struct locale_address_t
+{
+ const char *postal_fmt;
+ const char *country_name;
+ const char *country_post;
+ const char *country_ab2;
+ const char *country_ab3;
+ uint32_t country_num;
+ uint32_t country_num_ob;
+ const char *country_car;
+ const char *country_isbn;
+ const char *lang_name;
+ const char *lang_ab;
+ const char *lang_term;
+ const char *lang_lib;
+};
+
+
+static void
+address_startup (struct linereader *lr, struct localedef_t *locale,
+ int ignore_content)
+{
+ if (!ignore_content)
+ locale->categories[LC_ADDRESS].address =
+ (struct locale_address_t *) xcalloc (1,
+ sizeof (struct locale_address_t));
+
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
+}
+
+
+void
+address_finish (struct localedef_t *locale, struct charmap_t *charmap)
+{
+ struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
+ size_t cnt;
+ int helper;
+
+ if (address->postal_fmt == NULL)
+ {
+ error (0, 0, _("%s: field `%s' not defined"),
+ "LC_ADDRESS", "postal_fmt");
+ /* Use as the default value the value of the i18n locale. */
+ address->postal_fmt = "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N";
+ }
+ else
+ {
+ /* We must check whether the format string contains only the
+ allowed escape sequences. */
+ const char *cp = address->postal_fmt;
+
+ if (*cp == '\0')
+ error (0, 0, _("%s: field `%s' must not be empty"),
+ "LC_ADDRESS", "postal_fmt");
+ else
+ while (*cp != '\0')
+ {
+ if (*cp == '%')
+ {
+ if (*++cp == 'R')
+ /* Romanize-flag. */
+ ++cp;
+ if (strchr ("afdbshNtreCzTc%", *cp) == NULL)
+ {
+ error (0, 0, _("\
+%s: invalid escape `%%%c' sequence in field `%s'"),
+ "LC_ADDRESS", *cp, "postal_fmt");
+ break;
+ }
+ }
+ ++cp;
+ }
+ }
+
+#define TEST_ELEM(cat) \
+ if (address->cat == NULL) \
+ { \
+ if (verbose) \
+ error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS", #cat); \
+ address->cat = ""; \
+ }
+
+ TEST_ELEM (country_name);
+ /* XXX Test against list of defined codes. */
+ TEST_ELEM (country_post);
+ /* XXX Test against list of defined codes. */
+ TEST_ELEM (country_car);
+ /* XXX Test against list of defined codes. */
+ TEST_ELEM (country_isbn);
+ TEST_ELEM (lang_name);
+
+ helper = 1;
+ if (address->lang_term == NULL)
+ {
+ if (verbose)
+ error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS",
+ "lang_term");
+ address->lang_term = "";
+ cnt = sizeof (iso639) / sizeof (iso639[0]);
+ }
+ else if (address->lang_term[0] == '\0')
+ {
+ if (verbose)
+ error (0, 0, _("%s: field `%s' must not be empty"),
+ "LC_ADDRESS", "lang_term");
+ cnt = sizeof (iso639) / sizeof (iso639[0]);
+ }
+ else
+ {
+ /* Look for this language in the table. */
+ for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
+ if (strcmp (address->lang_term, iso639[cnt].term) == 0)
+ break;
+ if (cnt == sizeof (iso639) / sizeof (iso639[0]))
+ error (0, 0, _("\
+%s: terminology language code `%s' not defined"),
+ "LC_ADDRESS", address->lang_term);
+ }
+
+ if (address->lang_ab == NULL)
+ {
+ if (verbose)
+ error (0, 0, _("%s: field `%s' not defined"), "LC_ADDRESS", "lang_ab");
+ address->lang_ab = "";
+ }
+ else if (address->lang_ab[0] == '\0')
+ {
+ if (verbose)
+ error (0, 0, _("%s: field `%s' must not be empty"),
+ "LC_ADDRESS", "lang_ab");
+ }
+ else
+ {
+ if (cnt == sizeof (iso639) / sizeof (iso639[0]))
+ {
+ helper = 2;
+ for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
+ if (strcmp (address->lang_ab, iso639[cnt].ab) == 0)
+ break;
+ if (cnt == sizeof (iso639) / sizeof (iso639[0]))
+ error (0, 0, _("\
+%s: language abbreviation `%s' not defined"),
+ "LC_ADDRESS", address->lang_ab);
+ }
+ else
+ if (strcmp (iso639[cnt].ab, address->lang_ab) != 0)
+ error (0, 0, _("\
+%s: `%s' value does not match `%s' value"),
+ "LC_ADDRESS", "lang_ab", "lang_term");
+ }
+
+ if (address->lang_lib == NULL)
+ /* This is no error. */
+ address->lang_lib = address->lang_term;
+ else if (address->lang_lib[0] == '\0')
+ {
+ if (verbose)
+ error (0, 0, _("%s: field `%s' must not be empty"),
+ "LC_ADDRESS", "lang_lib");
+ }
+ else
+ {
+ if (cnt == sizeof (iso639) / sizeof (iso639[0]))
+ {
+ for (cnt = 0; cnt < sizeof (iso639) / sizeof (iso639[0]); ++cnt)
+ if (strcmp (address->lang_lib, iso639[cnt].lib) == 0)
+ break;
+ if (cnt == sizeof (iso639) / sizeof (iso639[0]))
+ error (0, 0, _("\
+%s: language abbreviation `%s' not defined"),
+ "LC_ADDRESS", address->lang_lib);
+ }
+ else
+ if (strcmp (iso639[cnt].ab, address->lang_ab) != 0)
+ error (0, 0, _("\
+%s: `%s' value does not match `%s' value"), "LC_ADDRESS", "lang_lib",
+ helper == 1 ? "lang_term" : "lang_ab");
+ }
+
+ if (address->country_num == 0)
+ {
+ if (verbose)
+ error (0, 0, _("%s: field `%s' not defined"),
+ "LC_ADDRESS", "country_num");
+ cnt = sizeof (iso3166) / sizeof (iso3166[0]);
+ }
+ else
+ {
+ for (cnt = 0; cnt < sizeof (iso3166) / sizeof (iso3166[0]); ++cnt)
+ if (address->country_num == iso3166[cnt].num)
+ break;
+
+ if (cnt == sizeof (iso3166) / sizeof (iso3166[0]))
+ error (0, 0, _("\
+%s: numeric country code `%d' not valid"),
+ "LC_ADDRESS", address->country_num);
+ }
+ address->country_num_ob = bswap_32 (address->country_num);
+
+ if (address->country_ab2 == NULL)
+ {
+ if (verbose)
+ error (0, 0, _("%s: field `%s' not defined"),
+ "LC_ADDRESS", "country_ab2");
+ address->country_ab2 = " ";
+ }
+ else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
+ && strcmp (address->country_ab2, iso3166[cnt].ab2) != 0)
+ error (0, 0, _("%s: `%s' value does not match `%s' value"),
+ "LC_ADDRESS", "country_ab2", "country_num");
+
+ if (address->country_ab3 == NULL)
+ {
+ if (verbose)
+ error (0, 0, _("%s: field `%s' not defined"),
+ "LC_ADDRESS", "country_ab3");
+ address->country_ab3 = " ";
+ }
+ else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
+ && strcmp (address->country_ab3, iso3166[cnt].ab3) != 0)
+ error (0, 0, _("%s: `%s' value does not match `%s' value"),
+ "LC_ADDRESS", "country_ab3", "country_num");
+}
+
+
+void
+address_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
+{
+ struct locale_address_t *address = locale->categories[LC_ADDRESS].address;
+ struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
+ struct locale_file data;
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS)];
+ size_t cnt = 0;
+
+ data.magic = LIMAGIC (LC_ADDRESS);
+ data.n = _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS);
+ iov[cnt].iov_base = (void *) &data;
+ iov[cnt].iov_len = sizeof (data);
+ ++cnt;
+
+ iov[cnt].iov_base = (void *) idx;
+ iov[cnt].iov_len = sizeof (idx);
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = (void *) address->postal_fmt;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->country_name;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->country_post;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->country_ab2;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->country_ab3;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->country_car;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define country_num_eb country_num_ob
+# define country_num_el country_num
+#else
+# define country_num_eb country_num
+# define country_num_el country_num_ob
+#endif
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->country_num_eb;
+ iov[cnt].iov_len = sizeof (uint32_t);
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->country_num_el;
+ iov[cnt].iov_len = sizeof (uint32_t);
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->country_isbn;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->lang_name;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->lang_ab;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->lang_term;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) address->lang_lib;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS));
+
+ write_locale_data (output_path, "LC_ADDRESS",
+ 2 + _NL_ITEM_INDEX (_NL_NUM_LC_ADDRESS), iov);
+}
+
+
+/* The parser for the LC_ADDRESS section of the locale definition. */
+void
+address_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
+{
+ struct repertoire_t *repertoire = NULL;
+ struct locale_address_t *address;
+ struct token *now;
+ struct token *arg;
+ enum token_t nowtok;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_ADDRESS' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_address, LC_ADDRESS,
+ "LC_ADDRESS", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ address_startup (ldfile, result, ignore_content);
+ address = result->categories[LC_ADDRESS].address;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+
+ switch (nowtok)
+ {
+#define STR_ELEM(cat) \
+ case tok_##cat: \
+ arg = lr_token (ldfile, charmap, NULL); \
+ if (arg->tok != tok_string) \
+ goto err_label; \
+ if (address->cat != NULL) \
+ lr_error (ldfile, _("\
+%s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \
+ else if (!ignore_content && arg->val.str.startmb == NULL) \
+ { \
+ lr_error (ldfile, _("\
+%s: unknown character in field `%s'"), "LC_ADDRESS", #cat); \
+ address->cat = ""; \
+ } \
+ else if (!ignore_content) \
+ address->cat = arg->val.str.startmb; \
+ break
+
+ STR_ELEM (postal_fmt);
+ STR_ELEM (country_name);
+ STR_ELEM (country_post);
+ STR_ELEM (country_ab2);
+ STR_ELEM (country_ab3);
+ STR_ELEM (country_car);
+ STR_ELEM (country_isbn);
+ STR_ELEM (lang_name);
+ STR_ELEM (lang_ab);
+ STR_ELEM (lang_term);
+ STR_ELEM (lang_lib);
+
+#define INT_ELEM(cat) \
+ case tok_##cat: \
+ arg = lr_token (ldfile, charmap, NULL); \
+ if (arg->tok != tok_number) \
+ goto err_label; \
+ else if (address->cat != 0) \
+ lr_error (ldfile, _("\
+%s: field `%s' declared more than once"), "LC_ADDRESS", #cat); \
+ else if (!ignore_content) \
+ address->cat = arg->val.num; \
+ break
+
+ INT_ELEM (country_num);
+
+ case tok_end:
+ /* Next we assume `LC_ADDRESS'. */
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok == tok_eof)
+ break;
+ if (arg->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"),
+ "LC_ADDRESS");
+ else if (arg->tok != tok_lc_address)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_ADDRESS");
+ lr_ignore_rest (ldfile, arg->tok == tok_lc_address);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_ADDRESS");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_ADDRESS");
+}
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index 265bfd0af1..3c1267420c 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -1,6 +1,6 @@
/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -21,32 +21,1034 @@
# include <config.h>
#endif
-#include <endian.h>
-#include <errno.h>
-#include <limits.h>
-#include <locale.h>
-#include <obstack.h>
+#include <error.h>
#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-#include <libintl.h>
+#include "charmap.h"
#include "localeinfo.h"
-#include "locales.h"
-#include "simple-hash.h"
-#include "stringtrans.h"
-#include "strlen-hash.h"
+#include "linereader.h"
+#include "locfile.h"
+#include "localedef.h"
/* Uncomment the following line in the production version. */
/* #define NDEBUG 1 */
#include <assert.h>
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+/* Forward declaration. */
+struct element_t;
+
+/* Data type for list of strings. */
+struct section_list
+{
+ struct section_list *next;
+ /* Name of the section. */
+ const char *name;
+ /* First element of this section. */
+ struct element_t *first;
+ /* Last element of this section. */
+ struct element_t *last;
+ /* These are the rules for this section. */
+ enum coll_sort_rule *rules;
+};
+
+/* Data type for collating element. */
+struct element_t
+{
+ const char *mbs;
+ const uint32_t *wcs;
+ int order;
+
+ struct element_t **weights;
+
+ /* Where does the definition come from. */
+ const char *file;
+ size_t line;
+
+ /* Which section does this belong to. */
+ struct section_list *section;
+
+ /* Predecessor and successor in the order list. */
+ struct element_t *last;
+ struct element_t *next;
+};
+
+/* Data type for collating symbol. */
+struct symbol_t
+{
+ /* Point to place in the order list. */
+ struct element_t *order;
+
+ /* Where does the definition come from. */
+ const char *file;
+ size_t line;
+};
+
+
+/* The real definition of the struct for the LC_COLLATE locale. */
+struct locale_collate_t
+{
+ int col_weight_max;
+ int cur_weight_max;
+
+ /* List of known scripts. */
+ struct section_list *sections;
+ /* Current section using definition. */
+ struct section_list *current_section;
+ /* There always can be an unnamed section. */
+ struct section_list unnamed_section;
+ /* To make handling of errors easier we have another section. */
+ struct section_list error_section;
+
+ /* Number of sorting rules given in order_start line. */
+ uint32_t nrules;
+
+ /* Start of the order list. */
+ struct element_t *start;
+
+ /* The undefined element. */
+ struct element_t undefined;
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
+ /* This is the cursor for `reorder_after' insertions. */
+ struct element_t *cursor;
-#define SWAPU32(w) \
- (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24))
+ /* Remember whether last weight was an ellipsis. */
+ int was_ellipsis;
+
+ /* Known collating elements. */
+ hash_table elem_table;
+
+ /* Known collating symbols. */
+ hash_table sym_table;
+
+ /* Known collation sequences. */
+ hash_table seq_table;
+
+ struct obstack mempool;
+
+ /* The LC_COLLATE category is a bit special as it is sometimes possible
+ that the definitions from more than one input file contains information.
+ Therefore we keep all relevant input in a list. */
+ struct locale_collate_t *next;
+};
+
+
+/* We have a few global variables which are used for reading all
+ LC_COLLATE category descriptions in all files. */
+static int nrules;
+
+
+static struct section_list *
+make_seclist_elem (struct locale_collate_t *collate, const char *string,
+ struct section_list *next)
+{
+ struct section_list *newp;
+
+ newp = (struct section_list *) obstack_alloc (&collate->mempool,
+ sizeof (*newp));
+ newp->next = next;
+ newp->name = string;
+ newp->first = NULL;
+
+ return newp;
+}
+
+
+static struct element_t *
+new_element (struct locale_collate_t *collate, const char *mbs,
+ const uint32_t *wcs)
+{
+ struct element_t *newp;
+
+ newp = (struct element_t *) obstack_alloc (&collate->mempool,
+ sizeof (*newp));
+ newp->mbs = mbs;
+ newp->wcs = wcs;
+ newp->order = 0;
+
+ newp->file = NULL;
+ newp->line = 0;
+
+ newp->section = NULL;
+
+ newp->last = NULL;
+ newp->next = NULL;
+
+ return newp;
+}
+
+
+static struct symbol_t *
+new_symbol (struct locale_collate_t *collate)
+{
+ struct symbol_t *newp;
+ newp = (struct symbol_t *) obstack_alloc (&collate->mempool, sizeof (*newp));
+
+ newp->order = NULL;
+
+ newp->file = NULL;
+ newp->line = 0;
+
+ return newp;
+}
+
+
+/* Test whether this name is already defined somewhere. */
+static int
+check_duplicate (struct linereader *ldfile, struct locale_collate_t *collate,
+ struct charmap_t *charmap, struct repertoire_t *repertoire,
+ const char *symbol, size_t symbol_len)
+{
+ void *ignore = NULL;
+
+ if (find_entry (&charmap->char_table, symbol, symbol_len, &ignore) == 0)
+ {
+ lr_error (ldfile, _("`%s' already defined in charmap"), symbol);
+ return 1;
+ }
+
+ if (find_entry (&repertoire->char_table, symbol, symbol_len, &ignore) == 0)
+ {
+ lr_error (ldfile, _("`%s' already defined in repertoire"), symbol);
+ return 1;
+ }
+
+ if (find_entry (&collate->sym_table, symbol, symbol_len, &ignore) == 0)
+ {
+ lr_error (ldfile, _("`%s' already defined as collating symbol"), symbol);
+ return 1;
+ }
+
+ if (find_entry (&collate->elem_table, symbol, symbol_len, &ignore) == 0)
+ {
+ lr_error (ldfile, _("`%s' already defined as collating element"),
+ symbol);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Read the direction specification. */
+static void
+read_directions (struct linereader *ldfile, struct token *arg,
+ struct charmap_t *charmap, struct repertoire_t *repertoire,
+ struct locale_collate_t *collate)
+{
+ int cnt = 0;
+ int max = nrules ?: 10;
+ enum coll_sort_rule *rules = calloc (max, sizeof (*rules));
+ int warned = 0;
+
+ while (1)
+ {
+ int valid = 0;
+
+ if (arg->tok == tok_forward)
+ {
+ if (rules[cnt] & sort_backward)
+ {
+ if (! warned)
+ {
+ lr_error (ldfile, _("\
+%s: `forward' and `backward' are mutually excluding each other"),
+ "LC_COLLATE");
+ warned = 1;
+ }
+ }
+ else if (rules[cnt] & sort_forward)
+ {
+ if (! warned)
+ {
+ lr_error (ldfile, _("\
+%s: `%s' mentioned twice in definition of weight %d"),
+ "LC_COLLATE", "forward", cnt + 1);
+ }
+ }
+ else
+ rules[cnt] |= sort_forward;
+
+ valid = 1;
+ }
+ else if (arg->tok == tok_backward)
+ {
+ if (rules[cnt] & sort_forward)
+ {
+ if (! warned)
+ {
+ lr_error (ldfile, _("\
+%s: `forward' and `backward' are mutually excluding each other"),
+ "LC_COLLATE");
+ warned = 1;
+ }
+ }
+ else if (rules[cnt] & sort_backward)
+ {
+ if (! warned)
+ {
+ lr_error (ldfile, _("\
+%s: `%s' mentioned twice in definition of weight %d"),
+ "LC_COLLATE", "backward", cnt + 1);
+ }
+ }
+ else
+ rules[cnt] |= sort_backward;
+
+ valid = 1;
+ }
+ else if (arg->tok == tok_position)
+ {
+ if (rules[cnt] & sort_position)
+ {
+ if (! warned)
+ {
+ lr_error (ldfile, _("\
+%s: `%s' mentioned twice in definition of weight %d in category `%s'"),
+ "LC_COLLATE", "position", cnt + 1);
+ }
+ }
+ else
+ rules[cnt] |= sort_position;
+
+ valid = 1;
+ }
+
+ if (arg->tok == tok_eof || arg->tok == tok_eol || arg->tok == tok_comma
+ || arg->tok == tok_semicolon)
+ {
+ if (! valid && ! warned)
+ {
+ lr_error (ldfile, _("%s: syntax error"), "LC_COLLATE");
+ warned = 1;
+ }
+
+ /* See whether we have to increment the counter. */
+ if (arg->tok != tok_comma && rules[cnt] != 0)
+ ++cnt;
+
+ if (arg->tok == tok_eof || arg->tok == tok_eol)
+ /* End of line or file, so we exit the loop. */
+ break;
+
+ if (nrules == 0)
+ {
+ /* See whether we have enough room in the array. */
+ if (cnt == max)
+ {
+ max += 10;
+ rules = (enum coll_sort_rule *) xrealloc (rules,
+ max
+ * sizeof (*rules));
+ memset (&rules[cnt], '\0', (max - cnt) * sizeof (*rules));
+ }
+ }
+ else
+ {
+ if (cnt == nrules)
+ {
+ /* There must not be any more rule. */
+ if (! warned)
+ {
+ lr_error (ldfile, _("\
+%s: too many rules; first entry only had %d"),
+ "LC_COLLATE", nrules);
+ warned = 1;
+ }
+
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (! warned)
+ {
+ lr_error (ldfile, _("%s: syntax error"), "LC_COLLATE");
+ warned = 1;
+ }
+ }
+
+ arg = lr_token (ldfile, charmap, repertoire);
+ }
+
+ if (nrules == 0)
+ {
+ /* Now we know how many rules we have. */
+ nrules = cnt;
+ rules = (enum coll_sort_rule *) xrealloc (rules,
+ nrules * sizeof (*rules));
+ }
+ else
+ {
+ if (cnt < nrules)
+ {
+ /* Not enough rules in this specification. */
+ if (! warned)
+ lr_error (ldfile, _("%s: not enough sorting rules"), "LC_COLLATE");
+
+ do
+ rules[cnt] = sort_forward;
+ while (++cnt < nrules);
+ }
+ }
+
+ collate->current_section->rules = rules;
+}
+
+
+static void
+insert_value (struct linereader *ldfile, struct token *arg,
+ struct charmap_t *charmap, struct repertoire_t *repertoire,
+ struct locale_collate_t *collate)
+{
+ /* First find out what kind of symbol this is. */
+ struct charseq *seq;
+ uint32_t wc;
+ struct element_t *elem = NULL;
+ int weight_cnt;
+
+ /* First determine the wide character. There must be such a value,
+ otherwise we ignore it (if it is no collatio symbol or element). */
+ wc = repertoire_find_value (repertoire, arg->val.str.startmb,
+ arg->val.str.lenmb);
+
+ /* Try to find the character in the charmap. */
+ seq = charmap_find_value (charmap, arg->val.str.startmb, arg->val.str.lenmb);
+
+ if (wc == ILLEGAL_CHAR_VALUE)
+ {
+ /* It's no character, so look through the collation elements and
+ symbol list. */
+ void *result;
+
+ if (find_entry (&collate->sym_table, arg->val.str.startmb,
+ arg->val.str.lenmb, &result) == 0)
+ {
+ /* It's a collation symbol. */
+ struct symbol_t *sym = (struct symbol_t *) result;
+ elem = sym->order;
+ }
+ else if (find_entry (&collate->elem_table, arg->val.str.startmb,
+ arg->val.str.lenmb, &result) != 0)
+ /* It's also no collation element. Therefore ignore it. */
+ return;
+ }
+
+ /* XXX elem must be defined. */
+
+ /* Test whether this element is not already in the list. */
+ if (elem->next != NULL)
+ {
+ lr_error (ldfile, _("order for `%.*s' already defined at %s:%Z"),
+ arg->val.str.startmb, arg->val.str.lenmb,
+ elem->file, elem->line);
+ return;
+ }
+
+ /* Initialize all the fields. */
+ elem->file = ldfile->fname;
+ elem->line = ldfile->lineno;
+ elem->last = collate->cursor;
+ elem->next = collate->cursor ? collate->cursor->next : NULL;
+ elem->weights = (struct element_t **)
+ obstack_alloc (&collate->mempool, nrules * sizeof (struct element_t *));
+ memset (elem->weights, '\0', nrules * sizeof (struct element_t *));
+
+ if (collate->current_section->first == NULL)
+ collate->current_section->first = elem;
+ if (collate->current_section->last == collate->cursor)
+ collate->current_section->last = elem;
+
+ collate->cursor = elem;
+
+ /* Now read the rest of the line. */
+ ldfile->return_widestr = 1;
+
+ weight_cnt = 0;
+ do
+ {
+ arg = lr_token (ldfile, charmap, repertoire);
+
+ if (arg->tok == tok_eof || arg->tok == tok_eol)
+ {
+ /* This means the rest of the line uses the current element
+ as the weight. */
+ do
+ elem->weights[weight_cnt] = elem;
+ while (++weight_cnt < nrules);
+
+ return;
+ }
+
+ if (arg->tok == tok_ignore)
+ {
+ /* The weight for this level has to be ignored. We use the
+ null pointer to indicate this. */
+ }
+ else if (arg->tok == tok_bsymbol)
+ {
+
+ }
+ }
+ while (++weight_cnt < nrules);
+
+ lr_ignore_rest (ldfile, weight_cnt == nrules);
+}
+
+
+static void
+collate_startup (struct linereader *ldfile, struct localedef_t *locale,
+ int ignore_content)
+{
+ if (!ignore_content)
+ {
+ struct locale_collate_t *collate;
+
+ collate = locale->categories[LC_COLLATE].collate =
+ (struct locale_collate_t *) xcalloc (1,
+ sizeof (struct locale_collate_t));
+
+ /* Init the various data structures. */
+ init_hash (&collate->elem_table, 100);
+ init_hash (&collate->sym_table, 100);
+ init_hash (&collate->seq_table, 500);
+ obstack_init (&collate->mempool);
+
+ collate->col_weight_max = -1;
+ }
+
+ ldfile->translate_strings = 1;
+ ldfile->return_widestr = 0;
+}
+
+
+void
+collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
+{
+}
+
+
+void
+collate_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
+{
+}
+
+
+void
+collate_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
+{
+ struct repertoire_t *repertoire = NULL;
+ struct locale_collate_t *collate;
+ struct token *now;
+ struct token *arg;
+ enum token_t nowtok;
+ int state = 0;
+ int was_ellipsis = 0;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_COLLATE' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ if (nowtok == tok_copy)
+ {
+ state = 2;
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_string)
+ goto err_label;
+ /* XXX Use the name */
+ lr_ignore_rest (ldfile, 1);
+
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* Prepare the data structures. */
+ collate_startup (ldfile, result, ignore_content);
+ collate = result->categories[LC_COLLATE].collate;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+
+ switch (nowtok)
+ {
+ case tok_coll_weight_max:
+ if (state != 0)
+ goto err_label;
+
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok != tok_number)
+ goto err_label;
+ if (collate->col_weight_max != -1)
+ lr_error (ldfile, _("%s: duplicate definition of `%s'"),
+ "LC_COLLATE", "col_weight_max");
+ else
+ collate->col_weight_max = arg->val.num;
+ lr_ignore_rest (ldfile, 1);
+ break;
+
+ case tok_section_symbol:
+ if (state != 0)
+ goto err_label;
+
+ arg = lr_token (ldfile, charmap, repertoire);
+ if (arg->tok != tok_bsymbol)
+ goto err_label;
+ else if (!ignore_content)
+ {
+ /* Check whether this section is already known. */
+ struct section_list *known = collate->sections;
+ while (known != NULL)
+ if (strcmp (known->name, arg->val.str.startmb) == 0)
+ break;
+
+ if (known != NULL)
+ {
+ lr_error (ldfile,
+ _("%s: duplicate declaration of section `%s'"),
+ "LC_COLLATE", arg->val.str.startmb);
+ free (arg->val.str.startmb);
+ }
+ else
+ collate->sections = make_seclist_elem (collate,
+ arg->val.str.startmb,
+ collate->sections);
+
+ lr_ignore_rest (ldfile, known == NULL);
+ }
+ else
+ {
+ free (arg->val.str.startmb);
+ lr_ignore_rest (ldfile, 1);
+ }
+ break;
+
+ case tok_collating_element:
+ if (state != 0)
+ goto err_label;
+
+ arg = lr_token (ldfile, charmap, repertoire);
+ if (arg->tok != tok_bsymbol)
+ goto err_label;
+ else
+ {
+ const char *symbol = arg->val.str.startmb;
+ size_t symbol_len = arg->val.str.lenmb;
+
+ /* Next the `from' keyword. */
+ arg = lr_token (ldfile, charmap, repertoire);
+ if (arg->tok != tok_from)
+ {
+ free ((char *) symbol);
+ goto err_label;
+ }
+
+ ldfile->return_widestr = 1;
+
+ /* Finally the string with the replacement. */
+ arg = lr_token (ldfile, charmap, repertoire);
+ ldfile->return_widestr = 0;
+ if (arg->tok != tok_string)
+ goto err_label;
+
+ if (!ignore_content)
+ {
+ if (symbol == NULL)
+ lr_error (ldfile, _("\
+%s: unknown character in collating element name"),
+ "LC_COLLATE");
+ if (arg->val.str.startmb == NULL)
+ lr_error (ldfile, _("\
+%s: unknown character in collating element definition"),
+ "LC_COLLATE");
+ if (arg->val.str.startwc == NULL)
+ lr_error (ldfile, _("\
+%s: unknown wide character in collating element definition"),
+ "LC_COLLATE");
+ else if (arg->val.str.lenwc < 2)
+ lr_error (ldfile, _("\
+%s: substitution string in collating element definition must have at least two characters"),
+ "LC_COLLATE");
+
+ if (symbol != NULL)
+ {
+ /* The name is already defined. */
+ if (check_duplicate (ldfile, collate, charmap,
+ repertoire, symbol, symbol_len))
+ goto col_elem_free;
+
+ if (insert_entry (&collate->elem_table,
+ symbol, symbol_len,
+ new_element (collate,
+ arg->val.str.startmb,
+ arg->val.str.startwc))
+ < 0)
+ lr_error (ldfile, _("\
+error while adding collating element"));
+ }
+ else
+ goto col_elem_free;
+ }
+ else
+ {
+ col_elem_free:
+ if (symbol != NULL)
+ free ((char *) symbol);
+ if (arg->val.str.startmb != NULL)
+ free (arg->val.str.startmb);
+ if (arg->val.str.startwc != NULL)
+ free (arg->val.str.startwc);
+ }
+ lr_ignore_rest (ldfile, 1);
+ }
+ break;
+
+ case tok_collating_symbol:
+ if (state != 0)
+ goto err_label;
+
+ arg = lr_token (ldfile, charmap, repertoire);
+ if (arg->tok != tok_bsymbol)
+ goto err_label;
+ else
+ {
+ const char *symbol = arg->val.str.startmb;
+ size_t symbol_len = arg->val.str.lenmb;
+
+ if (!ignore_content)
+ {
+ if (symbol == NULL)
+ lr_error (ldfile, _("\
+%s: unknown character in collating symbol name"),
+ "LC_COLLATE");
+ else
+ {
+ /* The name is already defined. */
+ if (check_duplicate (ldfile, collate, charmap,
+ repertoire, symbol, symbol_len))
+ goto col_sym_free;
+
+ if (insert_entry (&collate->sym_table,
+ symbol, symbol_len,
+ new_symbol (collate)) < 0)
+ lr_error (ldfile, _("\
+error while adding collating symbol"));
+ }
+ }
+ else
+ {
+ col_sym_free:
+ if (symbol != NULL)
+ free ((char *) symbol);
+ }
+ lr_ignore_rest (ldfile, 1);
+ }
+ break;
+
+ case tok_symbol_equivalence:
+ if (state != 0)
+ goto err_label;
+
+ arg = lr_token (ldfile, charmap, repertoire);
+ if (arg->tok != tok_bsymbol)
+ goto err_label;
+ else
+ {
+ const char *newname = arg->val.str.startmb;
+ size_t newname_len = arg->val.str.lenmb;
+ const char *symname;
+ size_t symname_len;
+ struct symbol_t *symval;
+
+ arg = lr_token (ldfile, charmap, repertoire);
+ if (arg->tok != tok_bsymbol)
+ {
+ if (newname != NULL)
+ free ((char *) newname);
+ goto err_label;
+ }
+
+ symname = arg->val.str.startmb;
+ symname_len = arg->val.str.lenmb;
+
+ if (!ignore_content)
+ {
+ if (newname == NULL)
+ {
+ lr_error (ldfile, _("\
+%s: unknown character in equivalent definition name"),
+ "LC_COLLATE");
+ goto sym_equiv_free;
+ }
+ if (symname == NULL)
+ {
+ lr_error (ldfile, _("\
+%s: unknown character in equivalent definition value"),
+ "LC_COLLATE");
+ goto sym_equiv_free;
+ }
+ /* The name is already defined. */
+ if (check_duplicate (ldfile, collate, charmap,
+ repertoire, symname, symname_len))
+ goto col_sym_free;
+
+ /* See whether the symbol name is already defined. */
+ if (find_entry (&collate->sym_table, symname, symname_len,
+ (void **) &symval) != 0)
+ {
+ lr_error (ldfile, _("\
+%s: unknown symbol `%s' in equivalent definition"),
+ "LC_COLLATE", symname);
+ goto col_sym_free;
+ }
+
+ if (insert_entry (&collate->sym_table,
+ newname, newname_len, symval) < 0)
+ {
+ lr_error (ldfile, _("\
+error while adding equivalent collating symbol"));
+ goto sym_equiv_free;
+ }
+
+ free ((char *) symname);
+ }
+ else
+ {
+ sym_equiv_free:
+ if (newname != NULL)
+ free ((char *) newname);
+ if (symname != NULL)
+ free ((char *) symname);
+ }
+ lr_ignore_rest (ldfile, 1);
+ }
+ break;
+
+ case tok_order_start:
+ if (state != 0 && state != 1)
+ goto err_label;
+ state = 1;
+
+ /* The 14652 draft does not specify whether all `order_start' lines
+ must contain the same number of sort-rules, but 14651 does. So
+ we require this here as well. */
+ arg = lr_token (ldfile, charmap, repertoire);
+ if (arg->tok == tok_bsymbol)
+ {
+ /* This better should be a section name. */
+ struct section_list *sp = collate->sections;
+ while (sp != NULL
+ && strcmp (sp->name, arg->val.str.startmb) != 0)
+ sp = sp->next;
+
+ if (sp == NULL)
+ {
+ lr_error (ldfile, _("\
+%s: unknown section name `%s'"),
+ "LC_COLLATE", arg->val.str.startmb);
+ /* We use the error section. */
+ collate->current_section = &collate->error_section;
+ }
+ else
+ {
+ /* Remember this section. */
+ collate->current_section = sp;
+
+ /* One should not be allowed to open the same
+ section twice. */
+ if (sp->first != NULL)
+ lr_error (ldfile, _("\
+%s: multiple order definitions for section `%s'"),
+ "LC_COLLATE", sp->name);
+
+ /* Next should come the end of the line or a semicolon. */
+ arg = lr_token (ldfile, charmap, repertoire);
+ if (arg->tok == tok_eol)
+ {
+ uint32_t cnt;
+
+ /* This means we have exactly one rule: `forward'. */
+ if (collate->nrules > 1)
+ lr_error (ldfile, _("\
+%s: invalid number of sorting rules"),
+ "LC_COLLATE");
+ else
+ collate->nrules = 1;
+ sp->rules = obstack_alloc (&collate->mempool,
+ (sizeof (enum coll_sort_rule)
+ * collate->nrules));
+ for (cnt = 0; cnt < collate->nrules; ++cnt)
+ sp->rules[cnt] = sort_forward;
+
+ /* Next line. */
+ break;
+ }
+
+ /* Get the next token. */
+ arg = lr_token (ldfile, charmap, repertoire);
+ }
+ }
+ else
+ {
+ /* There is no section symbol. Therefore we use the unnamed
+ section. */
+ collate->current_section = &collate->unnamed_section;
+
+ if (collate->unnamed_section.first != NULL)
+ lr_error (ldfile, _("\
+%s: multiple order definitions for unnamed section"),
+ "LC_COLLATE");
+ }
+
+ /* Now read the direction names. */
+ read_directions (ldfile, arg, charmap, repertoire, collate);
+ break;
+
+ case tok_order_end:
+ if (state != 1)
+ goto err_label;
+ state = 2;
+ lr_ignore_rest (ldfile, 1);
+ break;
+
+ case tok_reorder_after:
+ if (state != 2 && state != 3)
+ goto err_label;
+ state = 3;
+ /* XXX get symbol */
+ break;
+
+ case tok_reorder_end:
+ if (state != 3)
+ goto err_label;
+ state = 4;
+ lr_ignore_rest (ldfile, 1);
+ break;
+
+ case tok_bsymbol:
+ if (state != 1 && state != 3)
+ goto err_label;
+
+ if (state == 3)
+ {
+ /* It is possible that we already have this collation sequence.
+ In this case we move the entry. */
+ struct element_t *seqp;
+
+ if (find_entry (&collate->seq_table, arg->val.str.startmb,
+ arg->val.str.lenmb, (void **) &seqp) == 0)
+ {
+ /* Remove the entry from the old position. */
+ if (seqp->last == NULL)
+ collate->start = seqp->next;
+ else
+ seqp->last->next = seqp->next;
+ if (seqp->next != NULL)
+ seqp->next->last = seqp->last;
+
+ /* We also have to check whether this entry is the
+ first or last of a section. */
+ if (seqp->section->first == seqp)
+ {
+ if (seqp->section->first == seqp->section->last)
+ /* This setion has no content anymore. */
+ seqp->section->first = seqp->section->last = NULL;
+ else
+ seqp->section->first = seqp->next;
+ }
+ else if (seqp->section->last == seqp)
+ seqp->section->last = seqp->last;
+
+ seqp->last = seqp->next = NULL;
+ }
+ }
+
+ /* Now insert in the new place. */
+ insert_value (ldfile, arg, charmap, repertoire, collate);
+ break;
+
+ case tok_undefined:
+ if (state != 1)
+ goto err_label;
+ /* XXX handle UNDEFINED weight */
+ break;
+
+ case tok_ellipsis3:
+ if (state != 1 && state != 3)
+ goto err_label;
+
+ was_ellipsis = 1;
+ /* XXX Read the remainder of the line and remember what are
+ the weights. */
+ break;
+
+ case tok_end:
+ /* Next we assume `LC_COLLATE'. */
+ if (state == 0)
+ /* We must either see a copy statement or have ordering values. */
+ lr_error (ldfile, _("%s: empty category description not allowed"),
+ "LC_COLLATE");
+ else if (state == 1)
+ lr_error (ldfile, _("%s: missing `order_end' keyword"),
+ "LC_COLLATE");
+ else if (state == 3)
+ error (0, 0, _("%s: missing `reorder-end' keyword"),
+ "LC_COLLATE");
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok == tok_eof)
+ break;
+ if (arg->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"), "LC_COLLATE");
+ else if (arg->tok != tok_lc_collate)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_COLLATE");
+ lr_ignore_rest (ldfile, arg->tok == tok_lc_collate);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_COLLATE");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_COLLATE");
+}
+
+
+#if 0
/* What kind of symbols get defined? */
enum coll_symbol
@@ -75,7 +1077,8 @@ typedef struct patch_t
typedef struct element_t
{
- const wchar_t *name;
+ const char *namemb;
+ const uint32_t *namewc;
unsigned int this_weight;
struct element_t *next;
@@ -95,12 +1098,12 @@ struct locale_collate_t
hash_table elements;
struct obstack element_mem;
- /* The result table. */
- hash_table result;
+ /* The result tables. */
+ hash_table resultmb;
+ hash_table resultwc;
/* Sorting rules given in order_start line. */
- u_int32_t nrules;
- u_int32_t nrules_max;
+ uint32_t nrules;
enum coll_sort_rule *rules;
/* Used while recognizing symbol composed of multiple tokens
@@ -114,20 +1117,12 @@ struct locale_collate_t
/* Was lastline ellipsis? */
int was_ellipsis;
/* Value of last entry if was character. */
- wchar_t last_char;
+ uint32_t last_char;
/* Current element. */
element_t *current_element;
/* What kind of symbol is current element. */
enum coll_symbol kind;
- /* While collecting the weights we need some temporary space. */
- unsigned int current_order;
- int *weight_cnt;
- unsigned int weight_idx;
- unsigned int *weight;
- size_t nweight;
- size_t nweight_max;
-
/* Patch lists. */
patch_t *current_patch;
patch_t *all_patches;
@@ -135,6 +1130,10 @@ struct locale_collate_t
/* Room for the UNDEFINED information. */
element_t undefined;
unsigned int undefined_len;
+
+ /* Script information. */
+ const char **scripts;
+ unsigned int nscripts;
};
@@ -142,25 +1141,22 @@ struct locale_collate_t
extern int verbose;
-void *xmalloc (size_t __n);
-void *xrealloc (void *__p, size_t __n);
-
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
-void
-collate_startup (struct linereader *lr, struct localedef_t *locale,
- struct charset_t *charset)
-{
- struct locale_collate_t *collate;
+/* Prototypes for local functions. */
+static void collate_startup (struct linereader *ldfile,
+ struct localedef_t *locale,
+ struct charmap_t *charmap, int ignore_content);
- /* We have a definition for LC_COLLATE. */
- copy_posix.mask &= ~(1 << LC_COLLATE);
- /* It is important that we always use UCS4 encoding for strings now. */
- encoding_method = ENC_UCS4;
+static void
+collate_startup (struct linereader *ldfile, struct localedef_t *locale,
+ struct charmap_t *charset, int ignore_content)
+{
+ struct locale_collate_t *collate;
/* Allocate the needed room. */
locale->categories[LC_COLLATE].collate = collate =
@@ -196,12 +1192,14 @@ collate_startup (struct linereader *lr, struct localedef_t *locale,
/* This tells us no UNDEFINED entry was found until now. */
memset (&collate->undefined, '\0', sizeof (collate->undefined));
- lr->translate_strings = 0;
+ ldfile->translate_strings = 0;
+ ldfile->return_widestr = 0;
}
void
-collate_finish (struct localedef_t *locale, struct charset_t *charset)
+collate_finish (struct localedef_t *locale, struct charset_t *charset,
+ struct repertoire_t *repertoire)
{
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
patch_t *patch;
@@ -211,7 +1209,7 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset)
correctly filled. */
for (patch = collate->all_patches; patch != NULL; patch = patch->next)
{
- wchar_t wch;
+ uint32_t wch;
size_t toklen = strlen (patch->token);
void *ptmp;
unsigned int value = 0;
@@ -221,7 +1219,7 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset)
{
element_t *runp;
- if (find_entry (&collate->result, &wch, sizeof (wchar_t),
+ if (find_entry (&collate->result, &wch, sizeof (uint32_t),
(void *) &runp) < 0)
runp = NULL;
for (; runp != NULL; runp = runp->next)
@@ -262,9 +1260,9 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset)
|* XXX We should test whether really an unspecified character *|
|* exists before giving the message. *|
\**************************************************************/
- u_int32_t weight;
+ uint32_t weight;
- if (/* XXX Remove the 0 & */ 0 && !be_quiet)
+ if (!be_quiet)
error (0, 0, _("no definition of `UNDEFINED'"));
collate->undefined.ordering_len = collate->nrules;
@@ -272,7 +1270,7 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset)
for (cnt = 0; cnt < collate->nrules; ++cnt)
{
- u_int32_t one = 1;
+ uint32_t one = 1;
obstack_grow (&collate->element_mem, &one, sizeof (one));
}
@@ -282,7 +1280,7 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset)
collate->undefined.ordering = obstack_finish (&collate->element_mem);
}
- collate->undefined_len = 2; /* For the name: 1 x wchar_t + L'\0'. */
+ collate->undefined_len = 2; /* For the name: 1 x uint32_t + L'\0'. */
for (cnt = 0; cnt < collate->nrules; ++cnt)
collate->undefined_len += 1 + collate->undefined.ordering[cnt];
}
@@ -291,40 +1289,40 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset)
void
collate_output (struct localedef_t *locale, struct charset_t *charset,
- const char *output_path)
+ struct repertoire_t *repertoire, const char *output_path)
{
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
- u_int32_t table_size, table_best, level_best, sum_best;
+ uint32_t table_size, table_best, level_best, sum_best;
void *last;
element_t *pelem;
- wchar_t *name;
+ uint32_t *name;
size_t len;
const size_t nelems = _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE);
struct iovec iov[2 + nelems];
struct locale_file data;
- u_int32_t idx[nelems];
+ uint32_t idx[nelems];
struct obstack non_simple;
struct obstack string_pool;
size_t cnt, entry_size;
- u_int32_t undefined_offset = UINT_MAX;
- u_int32_t *table, *extra, *table2, *extra2;
+ uint32_t undefined_offset = UINT_MAX;
+ uint32_t *table, *extra, *table2, *extra2;
size_t extra_len;
- u_int32_t element_hash_tab_size;
- u_int32_t *element_hash_tab;
- u_int32_t *element_hash_tab_ob;
- u_int32_t element_string_pool_size;
+ uint32_t element_hash_tab_size;
+ uint32_t *element_hash_tab;
+ uint32_t *element_hash_tab_ob;
+ uint32_t element_string_pool_size;
char *element_string_pool;
- u_int32_t element_value_size;
- wchar_t *element_value;
- wchar_t *element_value_ob;
- u_int32_t symbols_hash_tab_size;
- u_int32_t *symbols_hash_tab;
- u_int32_t *symbols_hash_tab_ob;
- u_int32_t symbols_string_pool_size;
+ uint32_t element_value_size;
+ uint32_t *element_value;
+ uint32_t *element_value_ob;
+ uint32_t symbols_hash_tab_size;
+ uint32_t *symbols_hash_tab;
+ uint32_t *symbols_hash_tab_ob;
+ uint32_t symbols_string_pool_size;
char *symbols_string_pool;
- u_int32_t symbols_class_size;
- u_int32_t *symbols_class;
- u_int32_t *symbols_class_ob;
+ uint32_t symbols_class_size;
+ uint32_t *symbols_class;
+ uint32_t *symbols_class_ob;
hash_table *hash_tab;
unsigned int dummy_weights[collate->nrules + 1];
@@ -382,29 +1380,29 @@ Computing table size for collation information might take a while..."),
iov[1].iov_len = sizeof (idx);
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_NRULES)].iov_base = &collate->nrules;
- iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_NRULES)].iov_len = sizeof (u_int32_t);
+ iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_NRULES)].iov_len = sizeof (uint32_t);
- table = (u_int32_t *) alloca (collate->nrules * sizeof (u_int32_t));
+ table = (uint32_t *) alloca (collate->nrules * sizeof (uint32_t));
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_RULES)].iov_base = table;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_RULES)].iov_len
- = collate->nrules * sizeof (u_int32_t);
+ = collate->nrules * sizeof (uint32_t);
/* Another trick here. Describing the collation method needs only a
few bits (3, to be exact). But the binary file should be
accessible by machines with both endianesses and so we store both
forms in the same word. */
for (cnt = 0; cnt < collate->nrules; ++cnt)
- table[cnt] = collate->rules[cnt] | SWAPU32 (collate->rules[cnt]);
+ table[cnt] = collate->rules[cnt] | bswap_32 (collate->rules[cnt]);
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_SIZE)].iov_base = &table_best;
- iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_SIZE)].iov_len = sizeof (u_int32_t);
+ iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_SIZE)].iov_len = sizeof (uint32_t);
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_LAYERS)].iov_base = &level_best;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_HASH_LAYERS)].iov_len
- = sizeof (u_int32_t);
+ = sizeof (uint32_t);
entry_size = 1 + MAX (collate->nrules, 2);
- table = (u_int32_t *) alloca (table_best * level_best * entry_size
+ table = (uint32_t *) alloca (table_best * level_best * entry_size
* sizeof (table[0]));
memset (table, '\0', table_best * level_best * entry_size
* sizeof (table[0]));
@@ -413,7 +1411,7 @@ Computing table size for collation information might take a while..."),
/* Macros for inserting in output table. */
#define ADD_VALUE(expr) \
do { \
- u_int32_t to_write = (u_int32_t) expr; \
+ uint32_t to_write = (uint32_t) expr; \
obstack_grow (&non_simple, &to_write, sizeof (to_write)); \
} while (0)
@@ -424,7 +1422,7 @@ Computing table size for collation information might take a while..."),
ADD_VALUE (len); \
\
wlen = wcslen (pelem->name); \
- obstack_grow (&non_simple, pelem->name, (wlen + 1) * sizeof (u_int32_t)); \
+ obstack_grow (&non_simple, pelem->name, (wlen + 1) * sizeof (uint32_t)); \
\
idx = collate->nrules; \
for (cnt = 0; cnt < collate->nrules; ++cnt) \
@@ -448,14 +1446,14 @@ Computing table size for collation information might take a while..."),
table[(level * table_best + slot) * entry_size + 1] \
= FORWARD_CHAR; \
table[(level * table_best + slot) * entry_size + 2] \
- = obstack_object_size (&non_simple) / sizeof (u_int32_t); \
+ = obstack_object_size (&non_simple) / sizeof (uint32_t); \
\
/* Here we have to construct the non-simple table entry. First \
compute the total length of this entry. */ \
for (runp = (pelem); runp != NULL; runp = runp->next) \
if (runp->ordering != NULL) \
{ \
- u_int32_t value; \
+ uint32_t value; \
size_t cnt; \
\
value = 1 + wcslen (runp->name) + 1; \
@@ -491,7 +1489,7 @@ Computing table size for collation information might take a while..."),
ADD_VALUE (collate->undefined.ordering[cnt]); \
for (disp = 0; disp < collate->undefined.ordering[cnt]; ++disp) \
{ \
- if ((wchar_t) collate->undefined.ordering[idx] \
+ if ((uint32_t) collate->undefined.ordering[idx] \
== ELLIPSIS_CHAR) \
ADD_VALUE ((pelem)->name[0]); \
else \
@@ -543,14 +1541,15 @@ Computing table size for collation information might take a while..."),
{
/* We have to fill in the information from the UNDEFINED
entry. */
- table[cnt * entry_size] = (u_int32_t) cnt;
+ table[cnt * entry_size] = (uint32_t) cnt;
if (collate->undefined.ordering_len == collate->nrules)
{
size_t inner;
for (inner = 0; inner < collate->nrules; ++inner)
- if ((wchar_t)collate->undefined.ordering[collate->nrules + inner]
+ if ((uint32_t)collate->undefined.ordering[collate->nrules
+ + inner]
== ELLIPSIS_CHAR)
table[cnt * entry_size + 1 + inner] = cnt;
else
@@ -609,8 +1608,6 @@ Computing table size for collation information might take a while..."),
size_t idx, cnt;
undefined_offset = obstack_object_size (&non_simple);
- assert (undefined_offset % sizeof (u_int32_t) == 0);
- undefined_offset /= sizeof (u_int32_t);
idx = collate->nrules;
for (cnt = 0; cnt < collate->nrules; ++cnt)
@@ -625,19 +1622,19 @@ Computing table size for collation information might take a while..."),
/* Finish the extra block. */
extra_len = obstack_object_size (&non_simple);
- extra = (u_int32_t *) obstack_finish (&non_simple);
- assert ((extra_len % sizeof (u_int32_t)) == 0);
+ extra = (uint32_t *) obstack_finish (&non_simple);
+ assert ((extra_len % sizeof (uint32_t)) == 0);
/* Now we have to build the two array for the other byte ordering. */
- table2 = (u_int32_t *) alloca (table_best * level_best * entry_size
+ table2 = (uint32_t *) alloca (table_best * level_best * entry_size
* sizeof (table[0]));
- extra2 = (u_int32_t *) alloca (extra_len);
+ extra2 = (uint32_t *) alloca (extra_len);
for (cnt = 0; cnt < table_best * level_best * entry_size; ++cnt)
- table2[cnt] = SWAPU32 (table[cnt]);
+ table2[cnt] = bswap_32 (table[cnt]);
- for (cnt = 0; cnt < extra_len / sizeof (u_int32_t); ++cnt)
- extra2[cnt] = SWAPU32 (extra[cnt]);
+ for (cnt = 0; cnt < extra_len / sizeof (uint32_t); ++cnt)
+ extra2[cnt] = bswap_32 (extra2[cnt]);
/* We need a simple hashing table to get a collation-element->chars
mapping. We again use internal hashing using a secondary hashing
@@ -687,9 +1684,9 @@ Computing table size for collation information might take a while..."),
element_hash_tab_size = 7;
element_hash_tab = obstack_alloc (&non_simple, (2 * element_hash_tab_size
- * sizeof (u_int32_t)));
+ * sizeof (uint32_t)));
memset (element_hash_tab, '\377', (2 * element_hash_tab_size
- * sizeof (u_int32_t)));
+ * sizeof (uint32_t)));
ptr = NULL;
while (iterate_table (&collate->elements, &ptr, (const void **) &key,
@@ -698,7 +1695,7 @@ Computing table size for collation information might take a while..."),
size_t hash_val = hash_string (key, keylen);
size_t idx = hash_val % element_hash_tab_size;
- if (element_hash_tab[2 * idx] != (~((u_int32_t) 0)))
+ if (element_hash_tab[2 * idx] != (~((uint32_t) 0)))
{
/* We need the second hashing function. */
size_t c = 1 + (hash_val % (element_hash_tab_size - 2));
@@ -708,16 +1705,16 @@ Computing table size for collation information might take a while..."),
idx -= element_hash_tab_size - c;
else
idx += c;
- while (element_hash_tab[2 * idx] != (~((u_int32_t) 0)));
+ while (element_hash_tab[2 * idx] != (~((uint32_t) 0)));
}
element_hash_tab[2 * idx] = obstack_object_size (&non_simple);
element_hash_tab[2 * idx + 1] = (obstack_object_size (&string_pool)
- / sizeof (wchar_t));
+ / sizeof (uint32_t));
obstack_grow0 (&non_simple, key, keylen);
obstack_grow (&string_pool, data->name,
- (wcslen (data->name) + 1) * sizeof (wchar_t));
+ (wcslen (data->name) + 1) * sizeof (uint32_t));
}
if (obstack_object_size (&non_simple) % 4 != 0)
@@ -732,18 +1729,13 @@ Computing table size for collation information might take a while..."),
/* Create the tables for the other byte order. */
element_hash_tab_ob = obstack_alloc (&non_simple,
(2 * element_hash_tab_size
- * sizeof (u_int32_t)));
+ * sizeof (uint32_t)));
for (cnt = 0; cnt < 2 * element_hash_tab_size; ++cnt)
- element_hash_tab_ob[cnt] = SWAPU32 (element_hash_tab[cnt]);
+ element_hash_tab_ob[cnt] = bswap_U32 (element_hash_tab[cnt]);
element_value_ob = obstack_alloc (&string_pool, element_value_size);
- if (sizeof (wchar_t) != 4)
- {
- fputs ("sizeof (wchar_t) != 4 currently not handled", stderr);
- abort ();
- }
for (cnt = 0; cnt < element_value_size / 4; ++cnt)
- element_value_ob[cnt] = SWAPU32 (element_value[cnt]);
+ element_value_ob[cnt] = bswap_32 (element_value[cnt]);
}
/* Store collation elements as map to collation class. There are
@@ -757,9 +1749,9 @@ Computing table size for collation information might take a while..."),
+ collate->elements.filled
+ collate->symbols.filled)) / 3);
symbols_hash_tab = obstack_alloc (&non_simple, (2 * symbols_hash_tab_size
- * sizeof (u_int32_t)));
+ * sizeof (uint32_t)));
memset (symbols_hash_tab, '\377', (2 * symbols_hash_tab_size
- * sizeof (u_int32_t)));
+ * sizeof (uint32_t)));
/* Now fill the array. First the symbols from the character set,
then the collation elements and last the collation symbols. */
@@ -777,29 +1769,29 @@ Computing table size for collation information might take a while..."),
{
size_t hash_val;
size_t idx;
- u_int32_t word;
+ uint32_t word;
unsigned int *weights;
if (hash_tab == &charset->char_table
|| hash_tab == &collate->elements)
{
element_t *lastp, *firstp;
- wchar_t dummy_name[2];
- const wchar_t *name;
+ uint32_t dummy_name[2];
+ const uint32_t *name;
size_t name_len;
if (hash_tab == &charset->char_table)
{
- dummy_name[0] = (wchar_t) ((unsigned long int) data);
+ dummy_name[0] = (uint32_t) ((unsigned long int) data);
dummy_name[1] = L'\0';
name = dummy_name;
- name_len = sizeof (wchar_t);
+ name_len = sizeof (uint32_t);
}
else
{
element_t *elemp = (element_t *) data;
name = elemp->name;
- name_len = wcslen (name) * sizeof (wchar_t);
+ name_len = wcslen (name) * sizeof (uint32_t);
}
/* First check whether this character is used at all. */
@@ -815,8 +1807,6 @@ Computing table size for collation information might take a while..."),
lastp = firstp;
while (lastp->next != NULL && wcscmp (name, lastp->name))
lastp = lastp->next;
- if (lastp->ordering == NULL)
- lastp = &collate->undefined;
}
weights = lastp->ordering;
@@ -835,7 +1825,7 @@ Computing table size for collation information might take a while..."),
hash_val = hash_string (key, keylen);
idx = hash_val % symbols_hash_tab_size;
- if (symbols_hash_tab[2 * idx] != (~((u_int32_t) 0)))
+ if (symbols_hash_tab[2 * idx] != (~((uint32_t) 0)))
{
/* We need the second hashing function. */
size_t c = 1 + (hash_val % (symbols_hash_tab_size - 2));
@@ -845,23 +1835,23 @@ Computing table size for collation information might take a while..."),
idx -= symbols_hash_tab_size - c;
else
idx += c;
- while (symbols_hash_tab[2 * idx] != (~((u_int32_t) 0)));
+ while (symbols_hash_tab[2 * idx] != (~((uint32_t) 0)));
}
symbols_hash_tab[2 * idx] = obstack_object_size (&string_pool);
symbols_hash_tab[2 * idx + 1] = (obstack_object_size (&non_simple)
- / sizeof (u_int32_t));
+ / sizeof (uint32_t));
obstack_grow0 (&string_pool, key, keylen);
/* Adding the first weight looks complicated. We have to deal
with the kind it is stored and with the fact that original
- form uses `unsigned int's while we need `u_int32_t' here. */
+ form uses `unsigned int's while we need `uint32_t' here. */
word = weights[0];
- obstack_grow (&non_simple, &word, sizeof (u_int32_t));
+ obstack_grow (&non_simple, &word, sizeof (uint32_t));
for (cnt = 0; cnt < weights[0]; ++cnt)
{
word = weights[collate->nrules + cnt];
- obstack_grow (&non_simple, &word, sizeof (u_int32_t));
+ obstack_grow (&non_simple, &word, sizeof (uint32_t));
}
}
@@ -884,13 +1874,13 @@ Computing table size for collation information might take a while..."),
/* Generate tables with other byte order. */
symbols_hash_tab_ob = obstack_alloc (&non_simple, (2 * symbols_hash_tab_size
- * sizeof (u_int32_t)));
+ * sizeof (uint32_t)));
for (cnt = 0; cnt < 2 * symbols_hash_tab_size; ++cnt)
- symbols_hash_tab_ob[cnt] = SWAPU32 (symbols_hash_tab[cnt]);
+ symbols_hash_tab_ob[cnt] = bswap_32 (symbols_hash_tab[cnt]);
symbols_class_ob = obstack_alloc (&non_simple, symbols_class_size);
for (cnt = 0; cnt < symbols_class_size / 4; ++cnt)
- symbols_class_ob[cnt] = SWAPU32 (symbols_class[cnt]);
+ symbols_class_ob[cnt] = bswap_32 (symbols_class[cnt]);
/* Store table addresses and lengths. */
@@ -925,34 +1915,34 @@ Computing table size for collation information might take a while..."),
#endif
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].iov_base = &undefined_offset;
- iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].iov_len = sizeof (u_int32_t);
+ iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].iov_len = sizeof (uint32_t);
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_SIZE)].iov_base
= &element_hash_tab_size;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_SIZE)].iov_len
- = sizeof (u_int32_t);
+ = sizeof (uint32_t);
#if __BYTE_ORDER == __BIG_ENDIAN
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EB)].iov_base
= element_hash_tab;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EB)].iov_len
- = 2 * element_hash_tab_size * sizeof (u_int32_t);
+ = 2 * element_hash_tab_size * sizeof (uint32_t);
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EL)].iov_base
= element_hash_tab_ob;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EL)].iov_len
- = 2 * element_hash_tab_size * sizeof (u_int32_t);
+ = 2 * element_hash_tab_size * sizeof (uint32_t);
#else
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EL)].iov_base
= element_hash_tab;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EL)].iov_len
- = 2 * element_hash_tab_size * sizeof (u_int32_t);
+ = 2 * element_hash_tab_size * sizeof (uint32_t);
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EB)].iov_base
= element_hash_tab_ob;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EB)].iov_len
- = 2 * element_hash_tab_size * sizeof (u_int32_t);
+ = 2 * element_hash_tab_size * sizeof (uint32_t);
#endif
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_STR_POOL)].iov_base
@@ -985,28 +1975,28 @@ Computing table size for collation information might take a while..."),
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZE)].iov_base
= &symbols_hash_tab_size;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZE)].iov_len
- = sizeof (u_int32_t);
+ = sizeof (uint32_t);
#if __BYTE_ORDER == __BIG_ENDIAN
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EB)].iov_base
= symbols_hash_tab;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EB)].iov_len
- = 2 * symbols_hash_tab_size * sizeof (u_int32_t);
+ = 2 * symbols_hash_tab_size * sizeof (uint32_t);
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EL)].iov_base
= symbols_hash_tab_ob;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EL)].iov_len
- = 2 * symbols_hash_tab_size * sizeof (u_int32_t);
+ = 2 * symbols_hash_tab_size * sizeof (uint32_t);
#else
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EL)].iov_base
= symbols_hash_tab;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EL)].iov_len
- = 2 * symbols_hash_tab_size * sizeof (u_int32_t);
+ = 2 * symbols_hash_tab_size * sizeof (uint32_t);
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EB)].iov_base
= symbols_hash_tab_ob;
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EB)].iov_len
- = 2 * symbols_hash_tab_size * sizeof (u_int32_t);
+ = 2 * symbols_hash_tab_size * sizeof (uint32_t);
#endif
iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_STR_POOL)].iov_base
@@ -1048,58 +2038,64 @@ Computing table size for collation information might take a while..."),
}
-void
-collate_element_to (struct linereader *lr, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
+static int
+collate_element_to (struct linereader *ldfile,
+ struct locale_collate_t *collate,
+ struct token *code, struct charmap_t *charmap,
+ struct repertoire_t *repertoire)
{
- struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
- unsigned int value;
+ struct charseq *seq;
+ uint32_t value;
void *not_used;
- if (collate->combine_token != NULL)
+ seq = charmap_find_value (charmap, code->val.str.start, code->val.str.len);
+ if (seq != NULL)
{
- free ((void *) collate->combine_token);
- collate->combine_token = NULL;
+ lr_error (ldfile, _("symbol for multicharacter collating element "
+ "`%.*s' duplicates symbolic name in charmap"),
+ (int) code->val.str.len, code->val.str.start);
+ return 1;
}
- value = charset_find_value (&charset->char_table, code->val.str.start,
- code->val.str.len);
- if ((wchar_t) value != ILLEGAL_CHAR_VALUE)
+ value = repertoire_find_value (repertoire, code->val.str.start,
+ code->val.str.len);
+ if (value != ILLEGAL_CHAR_VALUE)
{
- lr_error (lr, _("symbol for multicharacter collating element "
- "`%.*s' duplicates symbolic name in charset"),
+ lr_error (ldfile, _("symbol for multicharacter collating element "
+ "`%.*s' duplicates symbolic name in repertoire"),
(int) code->val.str.len, code->val.str.start);
- return;
+ return 1;
}
if (find_entry (&collate->elements, code->val.str.start, code->val.str.len,
&not_used) >= 0)
{
- lr_error (lr, _("symbol for multicharacter collating element "
- "`%.*s' duplicates element definition"),
+ lr_error (ldfile, _("symbol for multicharacter collating element "
+ "`%.*s' duplicates other element definition"),
(int) code->val.str.len, code->val.str.start);
- return;
+ return 1;
}
if (find_entry (&collate->elements, code->val.str.start, code->val.str.len,
&not_used) >= 0)
{
- lr_error (lr, _("symbol for multicharacter collating element "
+ lr_error (ldfile, _("symbol for multicharacter collating element "
"`%.*s' duplicates symbol definition"),
(int) code->val.str.len, code->val.str.start);
- return;
+ return 1;
}
- collate->combine_token = code->val.str.start;
- collate->combine_token_len = code->val.str.len;
+ return 0;
}
-void
-collate_element_from (struct linereader *lr, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
+static void
+collate_element_from (struct linereader *ldfile,
+ struct locale_collate_t *collate,
+ const char *to_str, struct token *code,
+ struct charmap_t *charmap,
+ struct repertoire_t *repertoire)
{
- struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
element_t *elemp, *runp;
/* CODE is a string. */
@@ -1108,33 +2104,26 @@ collate_element_from (struct linereader *lr, struct localedef_t *locale,
/* We have to translate the string. It may contain <...> character
names. */
- elemp->name = (wchar_t *) translate_string (code->val.str.start, charset);
+ elemp->namemb = code->val.str.startmb;
+ elemp->namewc = code->val.str.startwc;
elemp->this_weight = 0;
elemp->ordering = NULL;
elemp->ordering_len = 0;
- free (code->val.str.start);
-
- if (elemp->name == NULL)
+ if (elemp->namemb == NULL && elemp->namewc == NULL)
{
- /* At least one character in the string is not defined. We simply
- do nothing. */
+ /* The string contains characters which are not in the charmap nor
+ in the repertoire. Ignore the string. */
if (verbose)
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
`from' string in collation element declaration contains unknown character"));
return;
}
- if (elemp->name[0] == L'\0' || elemp->name[1] == L'\0')
- {
- lr_error (lr, _("illegal collation element"));
- return;
- }
-
/* The entries in the linked lists of RESULT are sorting in
descending order. The order is important for the `strcoll' and
`wcscoll' functions. */
- if (find_entry (&collate->result, elemp->name, sizeof (wchar_t),
+ if (find_entry (&collate->resultwc, elemp->namewc, sizeof (uint32_t),
(void *) &runp) >= 0)
{
/* We already have an entry with this key. Check whether it is
@@ -1144,7 +2133,49 @@ collate_element_from (struct linereader *lr, struct localedef_t *locale,
do
{
- cmpres = wcscmp (elemp->name, runp->name);
+ cmpres = wcscmp (elemp->namewc, runp->namewc);
+ if (cmpres <= 0)
+ break;
+ prevp = runp;
+ }
+ while ((runp = runp->next) != NULL);
+
+ if (cmpres == 0)
+ lr_error (ldfile, _("\
+duplicate collating element definition (repertoire)"));
+ else
+ {
+ elemp->next = runp;
+ if (prevp == NULL)
+ {
+ if (set_entry (&collate->resultwc, elemp->namewc,
+ sizeof (uint32_t), elemp) < 0)
+ error (EXIT_FAILURE, 0, _("\
+error while inserting collation element into hash table"));
+ }
+ else
+ prevp->next = elemp;
+ }
+ }
+ else
+ {
+ elemp->next = NULL;
+ if (insert_entry (&collate->resultwc, elemp->namewc, sizeof (uint32_t),
+ elemp) < 0)
+ error (EXIT_FAILURE, errno, _("error while inserting to hash table"));
+ }
+
+ /* Now also insert the element definition in the multibyte table. */
+ if (find_entry (&collate->resultmb, elemp->namemb, 1, (void *) &runp) >= 0)
+ {
+ /* We already have an entry with this key. Check whether it is
+ identical. */
+ element_t *prevp = NULL;
+ int cmpres;
+
+ do
+ {
+ cmpres = strcmp (elemp->namemb, runp->namemb);
if (cmpres <= 0)
break;
prevp = runp;
@@ -1152,14 +2183,14 @@ collate_element_from (struct linereader *lr, struct localedef_t *locale,
while ((runp = runp->next) != NULL);
if (cmpres == 0)
- lr_error (lr, _("duplicate collating element definition"));
+ lr_error (ldfile, _("\
+duplicate collating element definition (charmap)"));
else
{
elemp->next = runp;
if (prevp == NULL)
{
- if (set_entry (&collate->result, elemp->name, sizeof (wchar_t),
- elemp) < 0)
+ if (set_entry (&collate->resultmb, elemp->namemb, 1, elemp) < 0)
error (EXIT_FAILURE, 0, _("\
error while inserting collation element into hash table"));
}
@@ -1170,32 +2201,41 @@ error while inserting collation element into hash table"));
else
{
elemp->next = NULL;
- if (insert_entry (&collate->result, elemp->name, sizeof (wchar_t), elemp)
- < 0)
+ if (insert_entry (&collate->resultmb, elemp->namemb, 1, elemp) < 0)
error (EXIT_FAILURE, errno, _("error while inserting to hash table"));
}
- if (insert_entry (&collate->elements, collate->combine_token,
- collate->combine_token_len, (void *) elemp) < 0)
- lr_error (lr, _("cannot insert new collating symbol definition: %s"),
+ /* Finally install the mapping from the `to'-name to the `from'-name. */
+ if (insert_entry (&collate->elements, to_str, strlen (to_str),
+ (void *) elemp) < 0)
+ lr_error (ldfile, _("cannot insert new collating symbol definition: %s"),
strerror (errno));
}
-void
-collate_symbol (struct linereader *lr, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
+static void
+collate_symbol (struct linereader *ldfile, struct locale_collate_t *collate,
+ struct token *code, struct charmap_t *charmap,
+ struct repertoire_t *repertoire)
{
- struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
- wchar_t value;
+ uint32_t value;
+ struct charseq *seq;
void *not_used;
- value = charset_find_value (&charset->char_table, code->val.str.start,
- code->val.str.len);
+ seq = charset_find_value (charmap, code->val.str.start, code->val.str.len);
+ if (seq != NULL)
+ {
+ lr_error (ldfile, _("symbol for multicharacter collating element "
+ "`%.*s' duplicates symbolic name in charmap"),
+ (int) code->val.str.len, code->val.str.start);
+ return;
+ }
+
+ value = repertoire (repertoire, code->val.str.start, code->val.str.len);
if (value != ILLEGAL_CHAR_VALUE)
{
- lr_error (lr, _("symbol for multicharacter collating element "
- "`%.*s' duplicates symbolic name in charset"),
+ lr_error (ldfile, _("symbol for multicharacter collating element "
+ "`%.*s' duplicates symbolic name in repertoire"),
(int) code->val.str.len, code->val.str.start);
return;
}
@@ -1203,7 +2243,7 @@ collate_symbol (struct linereader *lr, struct localedef_t *locale,
if (find_entry (&collate->elements, code->val.str.start, code->val.str.len,
&not_used) >= 0)
{
- lr_error (lr, _("symbol for multicharacter collating element "
+ lr_error (ldfile, _("symbol for multicharacter collating element "
"`%.*s' duplicates element definition"),
(int) code->val.str.len, code->val.str.start);
return;
@@ -1212,7 +2252,7 @@ collate_symbol (struct linereader *lr, struct localedef_t *locale,
if (find_entry (&collate->symbols, code->val.str.start, code->val.str.len,
&not_used) >= 0)
{
- lr_error (lr, _("symbol for multicharacter collating element "
+ lr_error (ldfile, _("symbol for multicharacter collating element "
"`%.*s' duplicates other symbol definition"),
(int) code->val.str.len, code->val.str.start);
return;
@@ -1220,13 +2260,13 @@ collate_symbol (struct linereader *lr, struct localedef_t *locale,
if (insert_entry (&collate->symbols, code->val.str.start, code->val.str.len,
(void *) 0) < 0)
- lr_error (lr, _("cannot insert new collating symbol definition: %s"),
+ lr_error (ldfile, _("cannot insert new collating symbol definition: %s"),
strerror (errno));
}
void
-collate_new_order (struct linereader *lr, struct localedef_t *locale,
+collate_new_order (struct linereader *ldfile, struct localedef_t *locale,
enum coll_sort_rule sort_rule)
{
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
@@ -1245,7 +2285,7 @@ collate_new_order (struct linereader *lr, struct localedef_t *locale,
void
-collate_build_arrays (struct linereader *lr, struct localedef_t *locale)
+collate_build_arrays (struct linereader *ldfile, struct localedef_t *locale)
{
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
@@ -1264,13 +2304,13 @@ collate_build_arrays (struct linereader *lr, struct localedef_t *locale)
int
-collate_order_elem (struct linereader *lr, struct localedef_t *locale,
+collate_order_elem (struct linereader *ldfile, struct localedef_t *locale,
struct token *code, struct charset_t *charset)
{
- const wchar_t zero = L'\0';
+ const uint32_t zero = L'\0';
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
int result = 0;
- wchar_t value;
+ uint32_t value;
void *tmp;
unsigned int i;
@@ -1286,7 +2326,7 @@ collate_order_elem (struct linereader *lr, struct localedef_t *locale,
collate->kind = character;
- if (find_entry (&collate->result, &value, sizeof (wchar_t),
+ if (find_entry (&collate->result, &value, sizeof (uint32_t),
(void *) &firstp) < 0)
firstp = lastp = NULL;
else
@@ -1299,9 +2339,10 @@ collate_order_elem (struct linereader *lr, struct localedef_t *locale,
if (lastp->name[0] == value && lastp->name[1] == L'\0')
{
- lr_error (lr, _("duplicate definition for character `%.*s'"),
+ lr_error (ldfile,
+ _("duplicate definition for character `%.*s'"),
(int) code->val.str.len, code->val.str.start);
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
result = -1;
break;
}
@@ -1315,7 +2356,7 @@ collate_order_elem (struct linereader *lr, struct localedef_t *locale,
obstack_grow (&collate->element_mem, &zero, sizeof (zero));
collate->current_element->name =
- (const wchar_t *) obstack_finish (&collate->element_mem);
+ (const uint32_t *) obstack_finish (&collate->element_mem);
collate->current_element->this_weight = ++collate->order_cnt;
@@ -1323,10 +2364,10 @@ collate_order_elem (struct linereader *lr, struct localedef_t *locale,
if (firstp == NULL)
{
- if (insert_entry (&collate->result, &value, sizeof (wchar_t),
+ if (insert_entry (&collate->result, &value, sizeof (uint32_t),
(void *) collate->current_element) < 0)
{
- lr_error (lr, _("cannot insert collation element `%.*s'"),
+ lr_error (ldfile, _("cannot insert collation element `%.*s'"),
(int) code->val.str.len, code->val.str.start);
exit (4);
}
@@ -1341,10 +2382,10 @@ collate_order_elem (struct linereader *lr, struct localedef_t *locale,
if (collate->current_element->this_weight != 0)
{
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
collation element `%.*s' appears more than once: ignore line"),
(int) code->val.str.len, code->val.str.start);
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
result = -1;
break;
}
@@ -1359,10 +2400,10 @@ collation element `%.*s' appears more than once: ignore line"),
if ((unsigned long int) tmp != 0ul)
{
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
collation symbol `%.*s' appears more than once: ignore line"),
(int) code->val.str.len, code->val.str.start);
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
result = -1;
break;
}
@@ -1372,16 +2413,16 @@ collation symbol `%.*s' appears more than once: ignore line"),
if (set_entry (&collate->symbols, code->val.str.start,
code->val.str.len, (void *) order) < 0)
{
- lr_error (lr, _("cannot process order specification"));
+ lr_error (ldfile, _("cannot process order specification"));
exit (4);
}
}
else
{
if (verbose)
- lr_error (lr, _("unknown symbol `%.*s': line ignored"),
+ lr_error (ldfile, _("unknown symbol `%.*s': line ignored"),
(int) code->val.str.len, code->val.str.start);
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
result = -1;
}
@@ -1395,7 +2436,7 @@ collation symbol `%.*s' appears more than once: ignore line"),
case tok_ellipsis:
if (collate->was_ellipsis)
{
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
two lines in a row containing `...' are not allowed"));
result = -1;
}
@@ -1403,9 +2444,9 @@ two lines in a row containing `...' are not allowed"));
{
/* An ellipsis requires the previous line to be an
character definition. */
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
line before ellipsis does not contain definition for character constant"));
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
result = -1;
}
else
@@ -1424,21 +2465,21 @@ line before ellipsis does not contain definition for character constant"));
{
if (collate->kind != character)
{
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
line after ellipsis must contain character definition"));
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
result = -1;
}
else if (collate->last_char > value)
{
- lr_error (lr, _("end point of ellipsis range is bigger then start"));
- lr_ignore_rest (lr, 0);
+ lr_error (ldfile, _("end point of ellipsis range is bigger then start"));
+ lr_ignore_rest (ldfile, 0);
result = -1;
}
else
{
/* We can fill the arrays with the information we need. */
- wchar_t name[2];
+ uint32_t name[2];
unsigned int *data;
size_t *ptr;
size_t cnt;
@@ -1450,9 +2491,6 @@ line after ellipsis must contain character definition"));
* sizeof (unsigned int));
ptr = (size_t *) alloca (collate->nrules * sizeof (size_t));
- if (data == NULL || ptr == NULL)
- error (4, 0, _("memory exhausted"));
-
/* Prepare data. Because the characters covered by an
ellipsis all have equal values we prepare the data once
and only change the variable number (if there are any).
@@ -1470,7 +2508,7 @@ line after ellipsis must contain character definition"));
data[collate->nrules + cnt] = collate->weight[cnt];
for (cnt = 0; cnt < collate->nrules; ++cnt)
- if ((wchar_t) data[ptr[cnt]] != ELLIPSIS_CHAR)
+ if ((uint32_t) data[ptr[cnt]] != ELLIPSIS_CHAR)
ptr[cnt] = 0;
while (name[0] <= value)
@@ -1479,12 +2517,9 @@ line after ellipsis must contain character definition"));
pelem = (element_t *) obstack_alloc (&collate->element_mem,
sizeof (element_t));
- if (pelem == NULL)
- error (4, 0, _("memory exhausted"));
-
pelem->name
- = (const wchar_t *) obstack_copy (&collate->element_mem,
- name, 2 * sizeof (wchar_t));
+ = (const uint32_t *) obstack_copy (&collate->element_mem,
+ name, 2 * sizeof (uint32_t));
pelem->this_weight = ++collate->order_cnt;
pelem->ordering_len = collate->nweight;
@@ -1500,17 +2535,17 @@ line after ellipsis must contain character definition"));
pelem->ordering[ptr[cnt]] = pelem->this_weight;
/* Insert new entry into result table. */
- if (find_entry (&collate->result, name, sizeof (wchar_t),
+ if (find_entry (&collate->result, name, sizeof (uint32_t),
(void *) &pelem->next) >= 0)
{
- if (set_entry (&collate->result, name, sizeof (wchar_t),
+ if (set_entry (&collate->result, name, sizeof (uint32_t),
(void *) pelem) < 0)
error (4, 0, _("cannot insert into result table"));
}
else
{
pelem->next = NULL;
- if (insert_entry (&collate->result, name, sizeof (wchar_t),
+ if (insert_entry (&collate->result, name, sizeof (uint32_t),
(void *) pelem) < 0)
error (4, 0, _("cannot insert into result table"));
}
@@ -1533,12 +2568,12 @@ line after ellipsis must contain character definition"));
int
-collate_weight_bsymbol (struct linereader *lr, struct localedef_t *locale,
+collate_weight_bsymbol (struct linereader *ldfile, struct localedef_t *locale,
struct token *code, struct charset_t *charset)
{
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
unsigned int here_weight;
- wchar_t value;
+ uint32_t value;
void *tmp;
assert (code->tok == tok_bsymbol);
@@ -1549,7 +2584,7 @@ collate_weight_bsymbol (struct linereader *lr, struct localedef_t *locale,
{
element_t *runp;
- if (find_entry (&collate->result, &value, sizeof (wchar_t),
+ if (find_entry (&collate->result, &value, sizeof (uint32_t),
(void *)&runp) < 0)
runp = NULL;
@@ -1574,9 +2609,9 @@ collate_weight_bsymbol (struct linereader *lr, struct localedef_t *locale,
else
{
if (verbose)
- lr_error (lr, _("unknown symbol `%.*s': line ignored"),
+ lr_error (ldfile, _("unknown symbol `%.*s': line ignored"),
(int) code->val.str.len, code->val.str.start);
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
return -1;
}
@@ -1584,9 +2619,9 @@ collate_weight_bsymbol (struct linereader *lr, struct localedef_t *locale,
weight. */
if (collate->kind == symbol)
{
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
specification of sorting weight for collation symbol does not make sense"));
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
return -1;
}
@@ -1606,8 +2641,8 @@ specification of sorting weight for collation symbol does not make sense"));
newp = (patch_t *) obstack_alloc (&collate->element_mem,
sizeof (patch_t));
- newp->fname = lr->fname;
- newp->lineno = lr->lineno;
+ newp->fname = ldfile->fname;
+ newp->lineno = ldfile->lineno;
newp->token = (const char *) obstack_copy0 (&collate->element_mem,
code->val.str.start,
code->val.str.len);
@@ -1624,23 +2659,23 @@ specification of sorting weight for collation symbol does not make sense"));
int
-collate_next_weight (struct linereader *lr, struct localedef_t *locale)
+collate_next_weight (struct linereader *ldfile, struct localedef_t *locale)
{
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
if (collate->kind == symbol)
{
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
specification of sorting weight for collation symbol does not make sense"));
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
return -1;
}
++collate->weight_idx;
if (collate->weight_idx >= collate->nrules)
{
- lr_error (lr, _("too many weights"));
- lr_ignore_rest (lr, 0);
+ lr_error (ldfile, _("too many weights"));
+ lr_ignore_rest (ldfile, 0);
return -1;
}
@@ -1649,7 +2684,7 @@ specification of sorting weight for collation symbol does not make sense"));
int
-collate_simple_weight (struct linereader *lr, struct localedef_t *locale,
+collate_simple_weight (struct linereader *ldfile, struct localedef_t *locale,
struct token *code, struct charset_t *charset)
{
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
@@ -1668,9 +2703,9 @@ collate_simple_weight (struct linereader *lr, struct localedef_t *locale,
entry. */
if (collate->kind != ellipsis && collate->kind != undefined)
{
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
`...' must only be used in `...' and `UNDEFINED' entries"));
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
return -1;
}
value = ELLIPSIS_CHAR;
@@ -1691,18 +2726,18 @@ collate_simple_weight (struct linereader *lr, struct localedef_t *locale,
{
char *startp = (char *) runp;
char *putp = (char *) runp;
- wchar_t wch;
+ uint32_t wch;
/* Lookup weight for char and store it. */
if (*runp == '<')
{
while (*++runp != '\0' && *runp != '>')
{
- if (*runp == lr->escape_char)
+ if (*runp == ldfile->escape_char)
if (*++runp == '\0')
{
- lr_error (lr, _("unterminated weight name"));
- lr_ignore_rest (lr, 0);
+ lr_error (ldfile, _("unterminated weight name"));
+ lr_ignore_rest (ldfile, 0);
return -1;
}
*putp++ = *runp;
@@ -1712,8 +2747,8 @@ collate_simple_weight (struct linereader *lr, struct localedef_t *locale,
if (putp == startp)
{
- lr_error (lr, _("empty weight name: line ignored"));
- lr_ignore_rest (lr, 0);
+ lr_error (ldfile, _("empty weight name: line ignored"));
+ lr_ignore_rest (ldfile, 0);
return -1;
}
@@ -1723,7 +2758,7 @@ collate_simple_weight (struct linereader *lr, struct localedef_t *locale,
{
element_t *pelem;
- if (find_entry (&collate->result, &wch, sizeof (wchar_t),
+ if (find_entry (&collate->result, &wch, sizeof (uint32_t),
(void *)&pelem) < 0)
pelem = NULL;
@@ -1749,30 +2784,30 @@ collate_simple_weight (struct linereader *lr, struct localedef_t *locale,
else
{
if (verbose)
- lr_error (lr, _("unknown symbol `%.*s': line ignored"),
+ lr_error (ldfile, _("unknown symbol `%.*s': line ignored"),
(int) (putp - startp), startp);
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
return -1;
}
}
else
{
element_t *wp;
- wchar_t wch;
+ uint32_t wch;
- if (*runp == lr->escape_char)
+ if (*runp == ldfile->escape_char)
{
static const char digits[] = "0123456789abcdef";
const char *dp;
int base;
++runp;
- if (_tolower (*runp) == 'x')
+ if (tolower (*runp) == 'x')
{
++runp;
base = 16;
}
- else if (_tolower (*runp) == 'd')
+ else if (tolower (*runp) == 'd')
{
++runp;
base = 10;
@@ -1780,19 +2815,19 @@ collate_simple_weight (struct linereader *lr, struct localedef_t *locale,
else
base = 8;
- dp = strchr (digits, _tolower (*runp));
+ dp = strchr (digits, tolower (*runp));
if (dp == NULL || (dp - digits) >= base)
{
illegal_char:
- lr_error (lr, _("\
+ lr_error (ldfile, _("\
illegal character constant in string"));
- lr_ignore_rest (lr, 0);
+ lr_ignore_rest (ldfile, 0);
return -1;
}
wch = dp - digits;
++runp;
- dp = strchr (digits, _tolower (*runp));
+ dp = strchr (digits, tolower (*runp));
if (dp == NULL || (dp - digits) >= base)
goto illegal_char;
wch *= base;
@@ -1801,7 +2836,7 @@ illegal character constant in string"));
if (base != 16)
{
- dp = strchr (digits, _tolower (*runp));
+ dp = strchr (digits, tolower (*runp));
if (dp != NULL && (dp - digits < base))
{
wch *= base;
@@ -1811,7 +2846,7 @@ illegal character constant in string"));
}
}
else
- wch = (wchar_t) *runp++;
+ wch = (uint32_t) *runp++;
/* Lookup the weight for WCH. */
if (find_entry (&collate->result, &wch, sizeof (wch),
@@ -1849,8 +2884,8 @@ illegal character constant in string"));
newp = (patch_t *) obstack_alloc (&collate->element_mem,
sizeof (patch_t));
- newp->fname = lr->fname;
- newp->lineno = lr->lineno;
+ newp->fname = ldfile->fname;
+ newp->lineno = ldfile->lineno;
newp->token
= (const char *) obstack_copy0 (&collate->element_mem,
startp, putp - startp);
@@ -1885,7 +2920,7 @@ illegal character constant in string"));
void
-collate_end_weight (struct linereader *lr, struct localedef_t *locale)
+collate_end_weight (struct linereader *ldfile, struct localedef_t *locale)
{
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
element_t *pelem = collate->current_element;
@@ -1951,3 +2986,239 @@ collate_end_weight (struct linereader *lr, struct localedef_t *locale)
if (collate->kind != undefined)
collate->last_char = pelem->name[0];
}
+
+
+/* The parser for the LC_CTYPE section of the locale definition. */
+void
+read_lc_collate (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, struct repertoire_t *repertoire,
+ int ignore_content)
+{
+ struct locale_collate_t *collate;
+ int did_copy = 0;
+ const char *save_str;
+
+ /* The rest of the line containing `LC_COLLATE' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, tok_lc_collate, LC_COLLATE, "LC_COLLATE",
+ ignore_content);
+ did_copy = 1;
+ }
+
+ /* Prepare the data structures. */
+ collate_startup (ldfile, result, charmap, ignore_content);
+ collate = result->categories[LC_COLLATE].collate;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+
+ switch (nowtok)
+ {
+ case tok_coll_weight_max:
+ if (did_copy)
+ goto err_label;
+ /* The rest of the line must be a single integer value. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_number)
+ goto err_label;
+ /* We simply forget about the value we just read, the implementation
+ has no fixed limits. */
+ lr_ignore_rest (ldfile, 1);
+ break;
+
+ case tok_script:
+ if (did_copy)
+ goto err_label;
+ /* We expect the name of the script in brackets. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_bsymbol && now->tok != tok_ucs4)
+ goto err_label;
+ if (now->tok != tok_bsymbol)
+ {
+ lr_error (ldfile, _("\
+script name `%s' must not duplicate any known name"),
+ tok->val.str.startmb);
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+ collate->scripts = xmalloc (collate->scripts,
+ (collate->nscripts
+ * sizeof (const char *)));
+ collate->scripts[collate->nscripts++] = tok->val.str.startmb;
+ lr_ignore_rest (ldfile, 1);
+ break;
+
+ case tok_collating_element:
+ if (did_copy)
+ goto err_label;
+ /* Get the first argument, a symbol in brackets. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_bsymbol)
+ goto err_label;
+ /* Test it. */
+ if (collate_element_to (ldfile, collate, now, charmap, repertoire))
+ {
+ /* An error occurred. */
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+ save_str = tok->val.str.startmb;
+ /* Next comes `from'. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_from)
+ goto err_label;
+ /* Now comes a string. */
+ now = lr_token (ldfile, charmap, repertoire);
+ if (now->tok != tok_string)
+ goto err_label;
+ collate_element_from (ldfile, collate, save_str, now, charmap,
+ repertoire);
+ /* The rest of the line should be empty. */
+ lr_ignore_rest (ldfile, 1);
+ break;
+
+ case tok_collating_symbol:
+ if (did_copy)
+ goto err_label;
+ /* Get the argument, a single symbol in brackets. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_bsymbol)
+ goto err_label;
+ collate_symbol (ldfile, collate, now, charmap, repertoire);
+ break;
+
+ case tok_order_start:
+ if (did_copy)
+ goto err_label;
+
+ /* We expect now a scripting symbol or start right away
+ with the order keywords. Or we have no argument at all
+ in which means `forward'. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_eol)
+ {
+ static enum coll_sort_rule default_rule = sort_forward;
+ /* Use a single `forward' rule. */
+ collate->nrules = 1;
+ collate->rules = &default_rule;
+ }
+ else
+ {
+ /* XXX We don't recognize the ISO 14651 extensions yet. */
+ uint32_t nrules = 0;
+ uint32_t nrules_max = 32;
+ enum coll_sort_rule *rules = alloca (nrules_max
+ * sizeof (*rules));
+ int saw_semicolon = 0;
+
+ memset (rules, '\0', nrules_max * sizeof (*rules));
+ do
+ {
+ if (now->tok != tok_forward && now->tok != tok_backward
+ && now->tok != tok_position)
+ goto err_label;
+
+ if (saw_semicolon)
+ {
+ if (nrules == nrules_max)
+ {
+ newp = alloca (nrules_max * 2 * sizeof (*rules));
+ rules = memcpy (newp, rules,
+ nrules_max * sizeof (*rules));
+ memset (&rules[nrules_max], '\0',
+ nrules_max * sizeof (*rules));
+ nrules_max *= 2;
+ }
+ ++nrules;
+ }
+
+ switch (now->tok)
+ {
+ case tok_forward:
+ if ((rules[nrules] & sort_backward) != 0)
+ {
+ lr_error (ldfile, _("\
+`forward' and `backward' order exclude each other"));
+ lr_ignore_rest (ldfile, 0);
+ goto error_sort;
+ }
+ rules[nrules] |= sort_forward;
+ break;
+ case tok_backward:
+ if ((rules[nrules] & sort_forward) != 0)
+ {
+ lr_error (ldfile, _("\
+`forward' and `backward' order exclude each other"));
+ lr_ignore_rest (ldfile, 0);
+ goto error_sort;
+ }
+ rules[nrules] |= sort_backward;
+ break;
+ case tok_position:
+ rules[nrules] |= tok_position;
+ break;
+ }
+
+ /* Get the next token. This is either the end of the line,
+ a comma or a semicolon. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_comma || now->tok == tok_semicolon)
+ {
+ saw_semicolon = now->tok == tok_semicolon;
+ now = lr_token (ldfile, charmap, NULL);
+ }
+ }
+ while (now->tok != tok_eol || now->tok != tok_eof);
+
+ error_sort:
+ collate->nrules = nrules;
+ collate->rules = memcpy (xmalloc (nrules * sizeof (*rules)),
+ rules, nrules * sizeof (*rules));
+ }
+
+ /* Now read the rules. */
+ read_rules (ldfile, collate, charmap, repertoire);
+ break;
+
+ case tok_reorder_after:
+ break;
+
+ case tok_reorder_script_after:
+ break;
+
+ default:
+ err_label:
+ if (now->tok != tok_eof)
+ SYNTAX_ERROR (_("syntax error in %s locale definition"),
+ "LC_COLLATE");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("premature end of file while reading category `%s'"),
+ "LC_COLLATE");
+}
+
+#endif
diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
index 714a71898b..6743c1837c 100644
--- a/locale/programs/ld-ctype.c
+++ b/locale/programs/ld-ctype.c
@@ -1,6 +1,6 @@
/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -22,183 +22,274 @@
#endif
#include <alloca.h>
+#include <byteswap.h>
#include <endian.h>
+#include <errno.h>
#include <limits.h>
+#include <obstack.h>
+#include <stdlib.h>
#include <string.h>
-#include <libintl.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <sys/uio.h>
-#include "locales.h"
+#include "charmap.h"
#include "localeinfo.h"
#include "langinfo.h"
+#include "linereader.h"
#include "locfile-token.h"
-#include "stringtrans.h"
+#include "locfile.h"
+#include "localedef.h"
-/* Uncomment the following line in the production version. */
-/* define NDEBUG 1 */
#include <assert.h>
-void *xmalloc (size_t __n);
-void *xcalloc (size_t __n, size_t __s);
-void *xrealloc (void *__ptr, size_t __n);
+/* These are the extra bits not in wctype.h since these are not preallocated
+ classes. */
+#define _ISwspecial1 (1 << 29)
+#define _ISwspecial2 (1 << 30)
+#define _ISwspecial3 (1 << 31)
/* The bit used for representing a special class. */
#define BITPOS(class) ((class) - tok_upper)
-#define BIT(class) (1 << BITPOS (class))
+#define BIT(class) (_ISbit (BITPOS (class)))
+#define BITw(class) (_ISwbit (BITPOS (class)))
#define ELEM(ctype, collection, idx, value) \
*find_idx (ctype, &ctype->collection idx, &ctype->collection##_max idx, \
&ctype->collection##_act idx, value)
-#define SWAPU32(w) \
- (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24))
-
-#define SWAPU16(w) \
- ((((w) >> 8) & 0xff) | (((w) & 0xff) << 8))
-
/* To be compatible with former implementations we for now restrict
the number of bits for character classes to 16. When compatibility
is not necessary anymore increase the number to 32. */
-#define char_class_t u_int16_t
-#define CHAR_CLASS_TRANS SWAPU16
-#define char_class32_t u_int32_t
-#define CHAR_CLASS32_TRANS SWAPU32
+#define char_class_t uint16_t
+#define CHAR_CLASS_TRANS bswap_16
+#define char_class32_t uint32_t
+#define CHAR_CLASS32_TRANS bswap_32
+
+
+/* Type to describe a transliteration action. We have a possibly
+ multiple character from-string and a set of multiple character
+ to-strings. All are 32bit values since this is what is used in
+ the gconv functions. */
+struct translit_to_t
+{
+ uint32_t *str;
+
+ struct translit_to_t *next;
+};
+
+struct translit_t
+{
+ uint32_t *from;
+
+ struct translit_to_t *to;
+
+ struct translit_t *next;
+};
/* The real definition of the struct for the LC_CTYPE locale. */
struct locale_ctype_t
{
- unsigned int *charnames;
+ uint32_t *charnames;
size_t charnames_max;
size_t charnames_act;
- /* We will allow up to 8 * sizeof(u_int32_t) - 1 character classes. */
-#define MAX_NR_CHARCLASS (8 * sizeof (u_int32_t) - 1)
+ struct repertoire_t *repertoire;
+
+ /* We will allow up to 8 * sizeof (uint32_t) character classes. */
+#define MAX_NR_CHARCLASS (8 * sizeof (uint32_t))
size_t nr_charclass;
const char *classnames[MAX_NR_CHARCLASS];
- unsigned long int current_class_mask;
- unsigned int last_class_char;
- u_int32_t *class_collection;
+ uint32_t last_class_char;
+ uint32_t class256_collection[256];
+ uint32_t *class_collection;
size_t class_collection_max;
size_t class_collection_act;
- unsigned long int class_done;
+ uint32_t class_done;
+
+ struct charseq **mbdigits;
+ size_t mbdigits_act;
+ size_t mbdigits_max;
+ uint32_t *wcdigits;
+ size_t wcdigits_act;
+ size_t wcdigits_max;
+
+ struct charseq *mboutdigits[10];
+ uint32_t wcoutdigits[10];
+ size_t outdigits_act;
/* If the following number ever turns out to be too small simply
increase it. But I doubt it will. --drepper@gnu */
#define MAX_NR_CHARMAP 16
const char *mapnames[MAX_NR_CHARMAP];
- u_int32_t *map_collection[MAX_NR_CHARMAP];
+ uint32_t *map_collection[MAX_NR_CHARMAP];
+ uint32_t map256_collection[2][256];
size_t map_collection_max[MAX_NR_CHARMAP];
size_t map_collection_act[MAX_NR_CHARMAP];
size_t map_collection_nr;
size_t last_map_idx;
- unsigned int from_map_char;
- int toupper_done;
- int tolower_done;
+ int tomap_done[MAX_NR_CHARMAP];
+
+ /* Transliteration information. */
+ const char *translit_copy_locale;
+ const char *translit_copy_repertoire;
+ struct translit_t *translit;
/* The arrays for the binary representation. */
- u_int32_t plane_size;
- u_int32_t plane_cnt;
+ uint32_t plane_size;
+ uint32_t plane_cnt;
char_class_t *ctype_b;
char_class32_t *ctype32_b;
- u_int32_t *names_el;
- u_int32_t *names_eb;
- u_int32_t **map_eb;
- u_int32_t **map_el;
- u_int32_t *class_name_ptr;
- u_int32_t *map_name_ptr;
+ uint32_t *names_el;
+ uint32_t *names_eb;
+ uint32_t **map_eb;
+ uint32_t **map_el;
+ uint32_t *class_name_ptr;
+ uint32_t *map_name_ptr;
unsigned char *width;
- u_int32_t mb_cur_max;
+ uint32_t mb_cur_max;
const char *codeset_name;
+ uint32_t translit_hash_size_eb;
+ uint32_t translit_hash_size_el;
+ uint32_t translit_hash_layers_eb;
+ uint32_t translit_hash_layers_el;
+ uint32_t *translit_from_idx_eb;
+ uint32_t *translit_from_idx_el;
+ uint32_t *translit_from_tbl_eb;
+ uint32_t *translit_from_tbl_el;
+ uint32_t *translit_to_idx_eb;
+ uint32_t *translit_to_idx_el;
+ uint32_t *translit_to_tbl_eb;
+ uint32_t *translit_to_tbl_el;
+ size_t translit_idx_size;
+ size_t translit_from_tbl_size;
+ size_t translit_to_tbl_size;
+
+ struct obstack mem_pool;
};
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
+
/* Prototypes for local functions. */
-static void ctype_class_newP (struct linereader *lr,
- struct locale_ctype_t *ctype, const char *name);
-static void ctype_map_newP (struct linereader *lr,
- struct locale_ctype_t *ctype,
- const char *name, struct charset_t *charset);
-static u_int32_t *find_idx (struct locale_ctype_t *ctype, u_int32_t **table,
- size_t *max, size_t *act, unsigned int idx);
+static void ctype_startup (struct linereader *lr, struct localedef_t *locale,
+ struct charmap_t *charmap, int ignore_content);
+static void ctype_class_new (struct linereader *lr,
+ struct locale_ctype_t *ctype, const char *name);
+static void ctype_map_new (struct linereader *lr,
+ struct locale_ctype_t *ctype,
+ const char *name, struct charmap_t *charmap);
+static uint32_t *find_idx (struct locale_ctype_t *ctype, uint32_t **table,
+ size_t *max, size_t *act, unsigned int idx);
static void set_class_defaults (struct locale_ctype_t *ctype,
- struct charset_t *charset);
+ struct charmap_t *charmap,
+ struct repertoire_t *repertoire);
static void allocate_arrays (struct locale_ctype_t *ctype,
- struct charset_t *charset);
+ struct charmap_t *charmap,
+ struct repertoire_t *repertoire);
-void
+static const char *longnames[] =
+{
+ "zero", "one", "two", "three", "four",
+ "five", "six", "seven", "eight", "nine"
+};
+static const unsigned char digits[] = "0123456789";
+
+
+static void
ctype_startup (struct linereader *lr, struct localedef_t *locale,
- struct charset_t *charset)
+ struct charmap_t *charmap, int ignore_content)
{
unsigned int cnt;
struct locale_ctype_t *ctype;
- /* We have a definition for LC_CTYPE. */
- copy_posix.mask &= ~(1 << LC_CTYPE);
-
- /* It is important that we always use UCS1 encoding for strings now. */
- encoding_method = ENC_UCS1;
-
- /* Allocate the needed room. */
- locale->categories[LC_CTYPE].ctype = ctype =
- (struct locale_ctype_t *) xmalloc (sizeof (struct locale_ctype_t));
-
- /* We have no names seen yet. */
- ctype->charnames_max = charset->mb_cur_max == 1 ? 256 : 512;
- ctype->charnames =
- (unsigned int *) xmalloc (ctype->charnames_max * sizeof (unsigned int));
- for (cnt = 0; cnt < 256; ++cnt)
- ctype->charnames[cnt] = cnt;
- ctype->charnames_act = 256;
-
- /* Fill character class information. */
- ctype->nr_charclass = 0;
- ctype->current_class_mask = 0;
- ctype->last_class_char = ILLEGAL_CHAR_VALUE;
- /* The order of the following instructions determines the bit
- positions! */
- ctype_class_newP (lr, ctype, "upper");
- ctype_class_newP (lr, ctype, "lower");
- ctype_class_newP (lr, ctype, "alpha");
- ctype_class_newP (lr, ctype, "digit");
- ctype_class_newP (lr, ctype, "xdigit");
- ctype_class_newP (lr, ctype, "space");
- ctype_class_newP (lr, ctype, "print");
- ctype_class_newP (lr, ctype, "graph");
- ctype_class_newP (lr, ctype, "blank");
- ctype_class_newP (lr, ctype, "cntrl");
- ctype_class_newP (lr, ctype, "punct");
- ctype_class_newP (lr, ctype, "alnum");
-
- ctype->class_collection_max = charset->mb_cur_max == 1 ? 256 : 512;
- ctype->class_collection
- = (u_int32_t *) xmalloc (sizeof (unsigned long int)
- * ctype->class_collection_max);
- memset (ctype->class_collection, '\0',
- sizeof (unsigned long int) * ctype->class_collection_max);
- ctype->class_collection_act = 256;
-
- /* Fill character map information. */
- ctype->map_collection_nr = 0;
- ctype->last_map_idx = MAX_NR_CHARMAP;
- ctype->from_map_char = ILLEGAL_CHAR_VALUE;
- ctype_map_newP (lr, ctype, "toupper", charset);
- ctype_map_newP (lr, ctype, "tolower", charset);
-
- /* Fill first 256 entries in `toupper' and `tolower' arrays. */
- for (cnt = 0; cnt < 256; ++cnt)
+ if (!ignore_content)
{
- ctype->map_collection[0][cnt] = cnt;
- ctype->map_collection[1][cnt] = cnt;
+ /* Allocate the needed room. */
+ locale->categories[LC_CTYPE].ctype = ctype =
+ (struct locale_ctype_t *) xcalloc (1, sizeof (struct locale_ctype_t));
+
+ /* We have seen no names yet. */
+ ctype->charnames_max = charmap->mb_cur_max == 1 ? 256 : 512;
+ ctype->charnames =
+ (unsigned int *) xmalloc (ctype->charnames_max
+ * sizeof (unsigned int));
+ for (cnt = 0; cnt < 256; ++cnt)
+ ctype->charnames[cnt] = cnt;
+ ctype->charnames_act = 256;
+
+ /* Fill character class information. */
+ ctype->last_class_char = ILLEGAL_CHAR_VALUE;
+ /* The order of the following instructions determines the bit
+ positions! */
+ ctype_class_new (lr, ctype, "upper");
+ ctype_class_new (lr, ctype, "lower");
+ ctype_class_new (lr, ctype, "alpha");
+ ctype_class_new (lr, ctype, "digit");
+ ctype_class_new (lr, ctype, "xdigit");
+ ctype_class_new (lr, ctype, "space");
+ ctype_class_new (lr, ctype, "print");
+ ctype_class_new (lr, ctype, "graph");
+ ctype_class_new (lr, ctype, "blank");
+ ctype_class_new (lr, ctype, "cntrl");
+ ctype_class_new (lr, ctype, "punct");
+ ctype_class_new (lr, ctype, "alnum");
+ /* The following are extensions from ISO 14652. */
+ ctype_class_new (lr, ctype, "left_to_right");
+ ctype_class_new (lr, ctype, "right_to_left");
+ ctype_class_new (lr, ctype, "num_terminator");
+ ctype_class_new (lr, ctype, "num_separator");
+ ctype_class_new (lr, ctype, "segment_separator");
+ ctype_class_new (lr, ctype, "block_separator");
+ ctype_class_new (lr, ctype, "direction_control");
+ ctype_class_new (lr, ctype, "sym_swap_layout");
+ ctype_class_new (lr, ctype, "char_shape_selector");
+ ctype_class_new (lr, ctype, "num_shape_selector");
+ ctype_class_new (lr, ctype, "non_spacing");
+ ctype_class_new (lr, ctype, "non_spacing_level3");
+ ctype_class_new (lr, ctype, "normal_connect");
+ ctype_class_new (lr, ctype, "r_connect");
+ ctype_class_new (lr, ctype, "no_connect");
+ ctype_class_new (lr, ctype, "no_connect-space");
+ ctype_class_new (lr, ctype, "vowel_connect");
+
+ ctype->class_collection_max = charmap->mb_cur_max == 1 ? 256 : 512;
+ ctype->class_collection
+ = (uint32_t *) xcalloc (sizeof (unsigned long int),
+ ctype->class_collection_max);
+ ctype->class_collection_act = 256;
+
+ /* Fill character map information. */
+ ctype->map_collection_nr = 0;
+ ctype->last_map_idx = MAX_NR_CHARMAP;
+ ctype_map_new (lr, ctype, "toupper", charmap);
+ ctype_map_new (lr, ctype, "tolower", charmap);
+ ctype_map_new (lr, ctype, "tosymmetric", charmap);
+
+ /* Fill first 256 entries in `toXXX' arrays. */
+ for (cnt = 0; cnt < 256; ++cnt)
+ {
+ ctype->map_collection[0][cnt] = cnt;
+ ctype->map_collection[1][cnt] = cnt;
+ ctype->map_collection[2][cnt] = cnt;
+ ctype->map256_collection[0][cnt] = cnt;
+ ctype->map256_collection[1][cnt] = cnt;
+ }
+
+ obstack_init (&ctype->mem_pool);
}
}
void
-ctype_finish (struct localedef_t *locale, struct charset_t *charset)
+ctype_finish (struct localedef_t *locale, struct charmap_t *charmap)
{
/* See POSIX.2, table 2-6 for the meaning of the following table. */
#define NCLASS 12
@@ -226,106 +317,138 @@ ctype_finish (struct localedef_t *locale, struct charset_t *charset)
};
size_t cnt;
int cls1, cls2;
- unsigned int space_value;
+ uint32_t space_value;
+ struct charseq *space_seq;
struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
+ int warned;
/* Set default value for classes not specified. */
- set_class_defaults (ctype, charset);
+ set_class_defaults (ctype, charmap, ctype->repertoire);
/* Check according to table. */
for (cnt = 0; cnt < ctype->class_collection_max; ++cnt)
{
- unsigned long int tmp;
+ uint32_t tmp = ctype->class_collection[cnt];
- tmp = ctype->class_collection[cnt];
- if (tmp == 0)
- continue;
-
- for (cls1 = 0; cls1 < NCLASS; ++cls1)
- if ((tmp & (1 << cls1)) != 0)
- for (cls2 = 0; cls2 < NCLASS; ++cls2)
- if (valid_table[cls1].allow[cls2] != '-')
- {
- int eq = (tmp & (1 << cls2)) != 0;
- switch (valid_table[cls1].allow[cls2])
+ if (tmp != 0)
+ {
+ for (cls1 = 0; cls1 < NCLASS; ++cls1)
+ if ((tmp & _ISwbit (cls1)) != 0)
+ for (cls2 = 0; cls2 < NCLASS; ++cls2)
+ if (valid_table[cls1].allow[cls2] != '-')
{
- case 'M':
- if (!eq)
+ int eq = (tmp & _ISwbit (cls2)) != 0;
+ switch (valid_table[cls1].allow[cls2])
{
- char buf[17];
- char *cp = buf;
- unsigned int value;
-
- value = ctype->charnames[cnt];
-
- if ((value & 0xff000000) != 0)
- cp += sprintf (cp, "\\%o", (value >> 24) & 0xff);
- if ((value & 0xffff0000) != 0)
- cp += sprintf (cp, "\\%o", (value >> 16) & 0xff);
- if ((value & 0xffffff00) != 0)
- cp += sprintf (cp, "\\%o", (value >> 8) & 0xff);
- sprintf (cp, "\\%o", value & 0xff);
-
- if (!be_quiet)
- error (0, 0, _("\
-character %s'%s' in class `%s' must be in class `%s'"), value > 256 ? "L" : "",
- buf, valid_table[cls1].name,
- valid_table[cls2].name);
+ case 'M':
+ if (!eq)
+ {
+ uint32_t value = ctype->charnames[cnt];
+
+ if (!be_quiet)
+ error (0, 0, _("\
+character L'\\u%0*x' in class `%s' must be in class `%s'"),
+ value > 0xffff ? 8 : 4, value,
+ valid_table[cls1].name,
+ valid_table[cls2].name);
+ }
+ break;
+
+ case 'X':
+ if (eq)
+ {
+ uint32_t value = ctype->charnames[cnt];
+
+ if (!be_quiet)
+ error (0, 0, _("\
+character L'\\u%0*x' in class `%s' must not be in class `%s'"),
+ value > 0xffff ? 8 : 4, value,
+ valid_table[cls1].name,
+ valid_table[cls2].name);
+ }
+ break;
+
+ case 'D':
+ ctype->class_collection[cnt] |= _ISwbit (cls2);
+ break;
+
+ default:
+ error (5, 0, _("internal error in %s, line %u"),
+ __FUNCTION__, __LINE__);
}
- break;
+ }
+ }
+ }
+
+ for (cnt = 0; cnt < 256; ++cnt)
+ {
+ uint32_t tmp = ctype->class256_collection[cnt];
- case 'X':
- if (eq)
+ if (tmp != 0)
+ {
+ for (cls1 = 0; cls1 < NCLASS; ++cls1)
+ if ((tmp & _ISbit (cls1)) != 0)
+ for (cls2 = 0; cls2 < NCLASS; ++cls2)
+ if (valid_table[cls1].allow[cls2] != '-')
+ {
+ int eq = (tmp & _ISbit (cls2)) != 0;
+ switch (valid_table[cls1].allow[cls2])
{
- char buf[17];
- char *cp = buf;
- unsigned int value;
-
- value = ctype->charnames[cnt];
-
- if ((value & 0xff000000) != 0)
- cp += sprintf (cp, "\\%o", value >> 24);
- if ((value & 0xffff0000) != 0)
- cp += sprintf (cp, "\\%o", (value >> 16) & 0xff);
- if ((value & 0xffffff00) != 0)
- cp += sprintf (cp, "\\%o", (value >> 8) & 0xff);
- sprintf (cp, "\\%o", value & 0xff);
-
- if (!be_quiet)
- error (0, 0, _("\
-character %s'%s' in class `%s' must not be in class `%s'"),
- value > 256 ? "L" : "", buf,
- valid_table[cls1].name,
- valid_table[cls2].name);
+ case 'M':
+ if (!eq)
+ {
+ char buf[17];
+
+ sprintf (buf, "\\%o", cnt);
+
+ if (!be_quiet)
+ error (0, 0, _("\
+character '%s' in class `%s' must be in class `%s'"),
+ buf, valid_table[cls1].name,
+ valid_table[cls2].name);
+ }
+ break;
+
+ case 'X':
+ if (eq)
+ {
+ char buf[17];
+
+ sprintf (buf, "\\%o", cnt);
+
+ if (!be_quiet)
+ error (0, 0, _("\
+character '%s' in class `%s' must not be in class `%s'"),
+ buf, valid_table[cls1].name,
+ valid_table[cls2].name);
+ }
+ break;
+
+ case 'D':
+ ctype->class256_collection[cnt] |= _ISbit (cls2);
+ break;
+
+ default:
+ error (5, 0, _("internal error in %s, line %u"),
+ __FUNCTION__, __LINE__);
}
- break;
-
- case 'D':
- ctype->class_collection[cnt] |= 1 << cls2;
- break;
-
- default:
- error (5, 0, _("internal error in %s, line %u"),
- __FUNCTION__, __LINE__);
- }
- }
+ }
+ }
}
/* ... and now test <SP> as a special case. */
- space_value = charset_find_value (&charset->char_table, "SP", 2);
- if ((wchar_t) space_value == ILLEGAL_CHAR_VALUE)
- space_value = charset_find_value (&charset->char_table, "space", 5);
- if ((wchar_t) space_value == ILLEGAL_CHAR_VALUE)
+ space_value = repertoire_find_value (ctype->repertoire, "SP", 2);
+ if (space_value == ILLEGAL_CHAR_VALUE)
{
if (!be_quiet)
error (0, 0, _("character <SP> not defined in character map"));
}
else if (((cnt = BITPOS (tok_space),
(ELEM (ctype, class_collection, , space_value)
- & BIT (tok_space)) == 0)
+ & BITw (tok_space)) == 0)
|| (cnt = BITPOS (tok_blank),
(ELEM (ctype, class_collection, , space_value)
- & BIT (tok_blank)) == 0)))
+ & BITw (tok_blank)) == 0)))
{
if (!be_quiet)
error (0, 0, _("<SP> character not in class `%s'"),
@@ -333,10 +456,10 @@ character %s'%s' in class `%s' must not be in class `%s'"),
}
else if (((cnt = BITPOS (tok_punct),
(ELEM (ctype, class_collection, , space_value)
- & BIT (tok_punct)) != 0)
+ & BITw (tok_punct)) != 0)
|| (cnt = BITPOS (tok_graph),
(ELEM (ctype, class_collection, , space_value)
- & BIT (tok_graph))
+ & BITw (tok_graph))
!= 0)))
{
if (!be_quiet)
@@ -344,24 +467,205 @@ character %s'%s' in class `%s' must not be in class `%s'"),
valid_table[cnt].name);
}
else
- ELEM (ctype, class_collection, , space_value) |= BIT (tok_print);
+ ELEM (ctype, class_collection, , space_value) |= BITw (tok_print);
+
+ space_seq = charmap_find_value (charmap, "SP", 2);
+ if (space_seq == NULL || space_seq->nbytes != 1)
+ {
+ if (!be_quiet)
+ error (0, 0, _("character <SP> not defined in character map"));
+ }
+ else if (((cnt = BITPOS (tok_space),
+ (ctype->class256_collection[space_seq->bytes[0]]
+ & BIT (tok_space)) == 0)
+ || (cnt = BITPOS (tok_blank),
+ (ctype->class256_collection[space_seq->bytes[0]]
+ & BIT (tok_blank)) == 0)))
+ {
+ if (!be_quiet)
+ error (0, 0, _("<SP> character not in class `%s'"),
+ valid_table[cnt].name);
+ }
+ else if (((cnt = BITPOS (tok_punct),
+ (ctype->class256_collection[space_seq->bytes[0]]
+ & BIT (tok_punct)) != 0)
+ || (cnt = BITPOS (tok_graph),
+ (ctype->class256_collection[space_seq->bytes[0]]
+ & BIT (tok_graph)) != 0)))
+ {
+ if (!be_quiet)
+ error (0, 0, _("<SP> character must not be in class `%s'"),
+ valid_table[cnt].name);
+ }
+ else
+ ctype->class256_collection[space_seq->bytes[0]] |= BIT (tok_print);
/* Now that the tests are done make sure the name array contains all
characters which are handled in the WIDTH section of the
character set definition file. */
- if (charset->width_rules != NULL)
- for (cnt = 0; cnt < charset->nwidth_rules; ++cnt)
+ if (charmap->width_rules != NULL)
+ for (cnt = 0; cnt < charmap->nwidth_rules; ++cnt)
{
+#if 0
size_t inner;
- for (inner = charset->width_rules[cnt].from;
- inner <= charset->width_rules[cnt].to; ++inner)
+ for (inner = charmap->width_rules[cnt].from;
+ inner <= charmap->width_rules[cnt].to; ++inner)
(void) find_idx (ctype, NULL, NULL, NULL, inner);
+#else
+ /* XXX Handle width. We must convert from the charseq to the
+ repertoire value */
+ abort ();
+#endif
+ }
+
+ /* There must be a multiple of 10 digits. */
+ if (ctype->mbdigits_act % 10 != 0)
+ {
+ assert (ctype->mbdigits_act == ctype->wcdigits_act);
+ ctype->wcdigits_act -= ctype->mbdigits_act % 10;
+ ctype->mbdigits_act -= ctype->mbdigits_act % 10;
+ error (0, 0, _("`digit' category has not entries in groups of ten"));
+ }
+
+ /* Check the input digits. There must be a multiple of ten available.
+ In each group I could be that one or the other character is missing.
+ In this case the whole group must be removed. */
+ cnt = 0;
+ while (cnt < ctype->mbdigits_act)
+ {
+ size_t inner;
+ for (inner = 0; inner < 10; ++inner)
+ if (ctype->mbdigits[cnt + inner] == NULL)
+ break;
+
+ if (inner == 10)
+ cnt += 10;
+ else
+ {
+ /* Remove the group. */
+ memmove (&ctype->mbdigits[cnt], &ctype->mbdigits[cnt + 10],
+ ((ctype->wcdigits_act - cnt - 10)
+ * sizeof (ctype->mbdigits[0])));
+ ctype->mbdigits_act -= 10;
+ }
+ }
+
+ /* If no input digits are given use the default. */
+ if (ctype->mbdigits_act == 0)
+ {
+ if (ctype->mbdigits_max == 0)
+ {
+ ctype->mbdigits = obstack_alloc (&charmap->mem_pool,
+ 10 * sizeof (struct charseq *));
+ ctype->mbdigits_max = 10;
+ }
+
+ for (cnt = 0; cnt < 10; ++cnt)
+ {
+ ctype->mbdigits[cnt] = charmap_find_symbol (charmap,
+ digits + cnt, 1);
+ if (ctype->mbdigits[cnt] == NULL)
+ {
+ ctype->mbdigits[cnt] = charmap_find_symbol (charmap,
+ longnames[cnt],
+ strlen (longnames[cnt]));
+ if (ctype->mbdigits[cnt] == NULL)
+ {
+ /* Hum, this ain't good. */
+ error (0, 0, _("\
+no input digits defined and none of the standard names in the charmap"));
+
+ ctype->mbdigits[cnt] = obstack_alloc (&charmap->mem_pool,
+ sizeof (struct charseq) + 1);
+
+ /* This is better than nothing. */
+ ctype->mbdigits[cnt]->bytes[0] = digits[cnt];
+ ctype->mbdigits[cnt]->nbytes = 1;
+ }
+ }
+ }
+
+ ctype->mbdigits_act = 10;
+ }
+
+ /* Check the wide character input digits. There must be a multiple
+ of ten available. In each group I could be that one or the other
+ character is missing. In this case the whole group must be
+ removed. */
+ cnt = 0;
+ while (cnt < ctype->wcdigits_act)
+ {
+ size_t inner;
+ for (inner = 0; inner < 10; ++inner)
+ if (ctype->wcdigits[cnt + inner] == ILLEGAL_CHAR_VALUE)
+ break;
+
+ if (inner == 10)
+ cnt += 10;
+ else
+ {
+ /* Remove the group. */
+ memmove (&ctype->wcdigits[cnt], &ctype->wcdigits[cnt + 10],
+ ((ctype->wcdigits_act - cnt - 10)
+ * sizeof (ctype->wcdigits[0])));
+ ctype->wcdigits_act -= 10;
+ }
+ }
+
+ /* If no input digits are given use the default. */
+ if (ctype->wcdigits_act == 0)
+ {
+ if (ctype->wcdigits_max == 0)
+ {
+ ctype->wcdigits = obstack_alloc (&charmap->mem_pool,
+ 10 * sizeof (uint32_t));
+ ctype->wcdigits_max = 10;
+ }
+
+ for (cnt = 0; cnt < 10; ++cnt)
+ ctype->wcdigits[cnt] = L'0' + cnt;
+
+ ctype->mbdigits_act = 10;
+ }
+
+ /* Check the outdigits. */
+ warned = 0;
+ for (cnt = 0; cnt < 10; ++cnt)
+ if (ctype->mboutdigits[cnt] == NULL)
+ {
+ static struct charseq replace[2];
+
+ if (!warned)
+ {
+ error (0, 0, _("\
+not all characters used in `outdigit' are available in the charmap"));
+ warned = 1;
+ }
+
+ replace[0].nbytes = 1;
+ replace[0].bytes[0] = '?';
+ replace[0].bytes[1] = '\0';
+ ctype->mboutdigits[cnt] = &replace[0];
+ }
+
+ warned = 0;
+ for (cnt = 0; cnt < 10; ++cnt)
+ if (ctype->wcoutdigits[cnt] == 0)
+ {
+ if (!warned)
+ {
+ error (0, 0, _("\
+not all characters used in `outdigit' are available in the repertoire"));
+ warned = 1;
+ }
+
+ ctype->wcoutdigits[cnt] = L'?';
}
}
void
-ctype_output (struct localedef_t *locale, struct charset_t *charset,
+ctype_output (struct localedef_t *locale, struct charmap_t *charmap,
const char *output_path)
{
struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
@@ -370,23 +674,12 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
struct iovec iov[2 + nelems + ctype->nr_charclass
+ ctype->map_collection_nr];
struct locale_file data;
- u_int32_t idx[nelems];
+ uint32_t idx[nelems + 1];
size_t elem, cnt, offset, total;
-
-
- if ((locale->binary & (1 << LC_CTYPE)) != 0)
- {
- iov[0].iov_base = ctype;
- iov[0].iov_len = locale->len[LC_CTYPE];
-
- write_locale_data (output_path, "LC_CTYPE", 1, iov);
-
- return;
- }
-
+ char *cp;
/* Now prepare the output: Find the sizes of the table we can use. */
- allocate_arrays (ctype, charset);
+ allocate_arrays (ctype, charmap, ctype->repertoire);
data.magic = LIMAGIC (LC_CTYPE);
data.n = nelems;
@@ -419,20 +712,20 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
CTYPE_DATA (_NL_CTYPE_TOUPPER_EB,
ctype->map_eb[0],
(ctype->plane_size * ctype->plane_cnt + 128)
- * sizeof (u_int32_t));
+ * sizeof (uint32_t));
CTYPE_DATA (_NL_CTYPE_TOLOWER_EB,
ctype->map_eb[1],
(ctype->plane_size * ctype->plane_cnt + 128)
- * sizeof (u_int32_t));
+ * sizeof (uint32_t));
CTYPE_DATA (_NL_CTYPE_TOUPPER_EL,
ctype->map_el[0],
(ctype->plane_size * ctype->plane_cnt + 128)
- * sizeof (u_int32_t));
+ * sizeof (uint32_t));
CTYPE_DATA (_NL_CTYPE_TOLOWER_EL,
ctype->map_el[1],
(ctype->plane_size * ctype->plane_cnt + 128)
- * sizeof (u_int32_t));
+ * sizeof (uint32_t));
CTYPE_DATA (_NL_CTYPE_CLASS32,
ctype->ctype32_b,
@@ -441,15 +734,88 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
CTYPE_DATA (_NL_CTYPE_NAMES_EB,
ctype->names_eb, (ctype->plane_size * ctype->plane_cnt
- * sizeof (u_int32_t)));
+ * sizeof (uint32_t)));
CTYPE_DATA (_NL_CTYPE_NAMES_EL,
ctype->names_el, (ctype->plane_size * ctype->plane_cnt
- * sizeof (u_int32_t)));
-
- CTYPE_DATA (_NL_CTYPE_HASH_SIZE,
- &ctype->plane_size, sizeof (u_int32_t));
- CTYPE_DATA (_NL_CTYPE_HASH_LAYERS,
- &ctype->plane_cnt, sizeof (u_int32_t));
+ * sizeof (uint32_t)));
+
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_HASH_SIZE_EB,
+ &ctype->translit_hash_size_eb, sizeof (uint32_t));
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_HASH_SIZE_EL,
+ &ctype->translit_hash_size_el, sizeof (uint32_t));
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_HASH_LAYERS_EB,
+ &ctype->translit_hash_layers_eb, sizeof (uint32_t));
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_HASH_LAYERS_EL,
+ &ctype->translit_hash_layers_el, sizeof (uint32_t));
+
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_FROM_IDX_EB,
+ ctype->translit_from_idx_eb,
+ ctype->translit_idx_size);
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_FROM_IDX_EL,
+ ctype->translit_from_idx_el,
+ ctype->translit_idx_size);
+
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_FROM_TBL_EB,
+ ctype->translit_from_tbl_eb,
+ ctype->translit_from_tbl_size);
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_FROM_TBL_EL,
+ ctype->translit_from_tbl_el,
+ ctype->translit_from_tbl_size);
+
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_TO_IDX_EB,
+ ctype->translit_to_idx_eb,
+ ctype->translit_idx_size);
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_TO_IDX_EL,
+ ctype->translit_to_idx_el,
+ ctype->translit_idx_size);
+
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_TO_TBL_EB,
+ ctype->translit_to_tbl_eb, ctype->translit_to_tbl_size);
+ CTYPE_DATA (_NL_CTYPE_TRANSLIT_TO_TBL_EL,
+ ctype->translit_to_tbl_el, ctype->translit_to_tbl_size);
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+ CTYPE_DATA (_NL_CTYPE_HASH_SIZE_EB,
+ &ctype->plane_size, sizeof (uint32_t));
+ CTYPE_DATA (_NL_CTYPE_HASH_LAYERS_EB,
+ &ctype->plane_cnt, sizeof (uint32_t));
+#else
+ case _NL_ITEM_INDEX (_NL_CTYPE_HASH_SIZE_EB):
+ iov[2 + elem + offset].iov_base =
+ (uint32_t *) alloca (sizeof (uint32_t));
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ bswap_32 (ctype->plane_size);
+ iov[2 + elem + offset].iov_len = sizeof (uint32_t);
+ break;
+ case _NL_ITEM_INDEX (_NL_CTYPE_HASH_LAYERS_EB):
+ iov[2 + elem + offset].iov_base =
+ (uint32_t *) alloca (sizeof (uint32_t));
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ bswap_32 (ctype->plane_cnt);
+ iov[2 + elem + offset].iov_len = sizeof (uint32_t);
+ break;
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+ CTYPE_DATA (_NL_CTYPE_HASH_SIZE_EL,
+ &ctype->plane_size, sizeof (uint32_t));
+ CTYPE_DATA (_NL_CTYPE_HASH_LAYERS_EL,
+ &ctype->plane_cnt, sizeof (uint32_t));
+#else
+ case _NL_ITEM_INDEX (_NL_CTYPE_HASH_SIZE_EL):
+ iov[2 + elem + offset].iov_base =
+ (uint32_t *) alloca (sizeof (uint32_t));
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ bswap_32 (ctype->plane_size);
+ iov[2 + elem + offset].iov_len = sizeof (uint32_t);
+ break;
+ case _NL_ITEM_INDEX (_NL_CTYPE_HASH_LAYERS_EL):
+ iov[2 + elem + offset].iov_base =
+ (uint32_t *) alloca (sizeof (uint32_t));
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ bswap_32 (ctype->plane_cnt);
+ iov[2 + elem + offset].iov_len = sizeof (uint32_t);
+ break;
+#endif
case _NL_ITEM_INDEX (_NL_CTYPE_CLASS_NAMES):
/* The class name array. */
@@ -466,8 +832,7 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
iov[2 + elem + offset].iov_len = 1 + (4 - ((total + 1) % 4));
total += 1 + (4 - ((total + 1) % 4));
- if (elem + 1 < nelems)
- idx[elem + 1] = idx[elem] + total;
+ idx[elem + 1] = idx[elem] + total;
break;
case _NL_ITEM_INDEX (_NL_CTYPE_MAP_NAMES):
@@ -485,15 +850,14 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
iov[2 + elem + offset].iov_len = 1 + (4 - ((total + 1) % 4));
total += 1 + (4 - ((total + 1) % 4));
- if (elem + 1 < nelems)
- idx[elem + 1] = idx[elem] + total;
+ idx[elem + 1] = idx[elem] + total;
break;
CTYPE_DATA (_NL_CTYPE_WIDTH,
ctype->width, ctype->plane_size * ctype->plane_cnt);
CTYPE_DATA (_NL_CTYPE_MB_CUR_MAX,
- &ctype->mb_cur_max, sizeof (u_int32_t));
+ &ctype->mb_cur_max, sizeof (uint32_t));
case _NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME):
total = strlen (ctype->codeset_name) + 1;
@@ -508,8 +872,127 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
total = (total + 3) & ~3;
}
iov[2 + elem + offset].iov_len = total;
- if (elem + 1 < nelems)
- idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+ idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+ break;
+
+ case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN_EB):
+ case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN_EL):
+ iov[2 + elem + offset].iov_base = alloca (sizeof (uint32_t));
+ iov[2 + elem + offset].iov_len = sizeof (uint32_t);
+ if ((elem == _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN_EB)
+ && __BYTE_ORDER == __BIG_ENDIAN)
+ || (elem == _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN_EL)
+ && __BYTE_ORDER == __LITTLE_ENDIAN))
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ ctype->mbdigits_act / 10;
+ else
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ bswap_32 (ctype->mbdigits_act / 10);
+ break;
+
+ case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_WC_LEN_EB):
+ case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_WC_LEN_EL):
+ iov[2 + elem + offset].iov_base = alloca (sizeof (uint32_t));
+ iov[2 + elem + offset].iov_len = sizeof (uint32_t);
+ if ((elem == _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_WC_LEN_EB)
+ && __BYTE_ORDER == __BIG_ENDIAN)
+ || (elem == _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_WC_LEN_EL)
+ && __BYTE_ORDER == __LITTLE_ENDIAN))
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ ctype->wcdigits_act / 10;
+ else
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ bswap_32 (ctype->wcdigits_act / 10);
+ break;
+
+ case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS0_MB) ... _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS9_MB):
+ /* Compute the length of all possible characters. For INDIGITS
+ there might be more than one. We simply concatenate all of
+ them with a NUL byte following. The NUL byte wouldn't be
+ necessary but it makes it easier for the user. */
+ total = 0;
+ for (cnt = elem - _NL_CTYPE_INDIGITS0_MB;
+ cnt < ctype->mbdigits_act; cnt += 10)
+ total += ctype->mbdigits[cnt]->nbytes + 1;
+ iov[2 + elem + offset].iov_base = (char *) alloca (total);
+ iov[2 + elem + offset].iov_len = total;
+
+ cp = iov[2 + elem + offset].iov_base;
+ for (cnt = elem - _NL_CTYPE_INDIGITS0_MB;
+ cnt < ctype->mbdigits_act; cnt += 10)
+ {
+ cp = mempcpy (cp, ctype->mbdigits[cnt]->bytes,
+ ctype->mbdigits[cnt]->nbytes);
+ *cp++ = '\0';
+ }
+ break;
+
+ case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_MB) ... _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT9_MB):
+ /* Compute the length of all possible characters. For INDIGITS
+ there might be more than one. We simply concatenate all of
+ them with a NUL byte following. The NUL byte wouldn't be
+ necessary but it makes it easier for the user. */
+ cnt = elem - _NL_CTYPE_OUTDIGIT0_MB;
+ total = ctype->mboutdigits[cnt]->nbytes + 1;
+ iov[2 + elem + offset].iov_base = (char *) alloca (total);
+ iov[2 + elem + offset].iov_len = total;
+
+ *(char *) mempcpy (iov[2 + elem + offset].iov_base,
+ ctype->mbdigits[cnt]->bytes,
+ ctype->mbdigits[cnt]->nbytes) = '\0';
+ break;
+
+ case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS0_WC_EB) ... _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS9_WC_EB):
+ total = ctype->wcdigits_act / 10;
+
+ iov[2 + elem + offset].iov_base =
+ (uint32_t *) alloca (total * sizeof (uint32_t));
+ iov[2 + elem + offset].iov_len = total * sizeof (uint32_t);
+
+ for (cnt = elem - _NL_CTYPE_INDIGITS0_WC_EB;
+ cnt < ctype->wcdigits_act; cnt += 10)
+ ((uint32_t *) iov[2 + elem + offset].iov_base)[cnt / 10]
+ = (__BYTE_ORDER == __LITTLE_ENDIAN
+ ? bswap_32 (ctype->wcdigits[cnt]) : ctype->wcdigits[cnt]);
+ break;
+
+ case _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS0_WC_EL) ... _NL_ITEM_INDEX (_NL_CTYPE_INDIGITS9_WC_EL):
+ total = ctype->wcdigits_act / 10;
+
+ iov[2 + elem + offset].iov_base =
+ (uint32_t *) alloca (total * sizeof (uint32_t));
+ iov[2 + elem + offset].iov_len = total * sizeof (uint32_t);
+
+ for (cnt = elem - _NL_CTYPE_INDIGITS0_WC_EL;
+ cnt < ctype->wcdigits_act; cnt += 10)
+ ((uint32_t *) iov[2 + elem + offset].iov_base)[cnt / 10]
+ = (__BYTE_ORDER == __BIG_ENDIAN
+ ? bswap_32 (ctype->wcdigits[cnt]) : ctype->wcdigits[cnt]);
+ break;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+ case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_WC_EB) ... _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT9_WC_EB):
+ cnt = elem - _NL_CTYPE_OUTDIGIT0_WC_EB;
+#else
+ case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_WC_EL) ... _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT9_WC_EL):
+ cnt = elem - _NL_CTYPE_OUTDIGIT0_WC_EL;
+#endif
+ iov[2 + elem + offset].iov_base = &ctype->wcoutdigits[cnt];
+ iov[2 + elem + offset].iov_len = sizeof (uint32_t);
+ break;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_WC_EB) ... _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT9_WC_EB):
+ cnt = elem - _NL_CTYPE_OUTDIGIT0_WC_EB;
+#else
+ case _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT0_WC_EL) ... _NL_ITEM_INDEX (_NL_CTYPE_OUTDIGIT9_WC_EL):
+ cnt = elem - _NL_CTYPE_OUTDIGIT0_WC_EL;
+#endif
+ iov[2 + elem + offset].iov_base =
+ (uint32_t *) alloca (sizeof (uint32_t));
+ *(uint32_t *) iov[2 + elem + offset].iov_base =
+ bswap_32 (ctype->wcoutdigits[cnt]);
+ iov[2 + elem + offset].iov_len = sizeof (uint32_t);
break;
default:
@@ -527,10 +1010,9 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
iov[2 + elem + offset].iov_len = ((ctype->plane_size
* ctype->plane_cnt + 128)
- * sizeof (u_int32_t));
+ * sizeof (uint32_t));
- if (elem + 1 < nelems)
- idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
+ idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
}
}
@@ -541,596 +1023,1575 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
}
-/* Character class handling. */
-void
-ctype_class_new (struct linereader *lr, struct localedef_t *locale,
- enum token_t tok, struct token *code,
- struct charset_t *charset)
+/* Local functions. */
+static void
+ctype_class_new (struct linereader *lr, struct locale_ctype_t *ctype,
+ const char *name)
{
- ctype_class_newP (lr, locale->categories[LC_CTYPE].ctype,
- code->val.str.start);
+ size_t cnt;
+
+ for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
+ if (strcmp (ctype->classnames[cnt], name) == 0)
+ break;
+
+ if (cnt < ctype->nr_charclass)
+ {
+ lr_error (lr, _("character class `%s' already defined"), name);
+ return;
+ }
+
+ if (ctype->nr_charclass == MAX_NR_CHARCLASS)
+ /* Exit code 2 is prescribed in P1003.2b. */
+ error (2, 0, _("\
+implementation limit: no more than %d character classes allowed"),
+ MAX_NR_CHARCLASS);
+
+ ctype->classnames[ctype->nr_charclass++] = name;
}
-int
-ctype_is_charclass (struct linereader *lr, struct localedef_t *locale,
- const char *name)
+static void
+ctype_map_new (struct linereader *lr, struct locale_ctype_t *ctype,
+ const char *name, struct charmap_t *charmap)
{
+ size_t max_chars = 0;
size_t cnt;
- for (cnt = 0; cnt < locale->categories[LC_CTYPE].ctype->nr_charclass; ++cnt)
- if (strcmp (name, locale->categories[LC_CTYPE].ctype->classnames[cnt])
- == 0)
- return 1;
+ for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
+ {
+ if (strcmp (ctype->mapnames[cnt], name) == 0)
+ break;
- return 0;
+ if (max_chars < ctype->map_collection_max[cnt])
+ max_chars = ctype->map_collection_max[cnt];
+ }
+
+ if (cnt < ctype->map_collection_nr)
+ {
+ lr_error (lr, _("character map `%s' already defined"), name);
+ return;
+ }
+
+ if (ctype->map_collection_nr == MAX_NR_CHARMAP)
+ /* Exit code 2 is prescribed in P1003.2b. */
+ error (2, 0, _("\
+implementation limit: no more than %d character maps allowed"),
+ MAX_NR_CHARMAP);
+
+ ctype->mapnames[cnt] = name;
+
+ if (max_chars == 0)
+ ctype->map_collection_max[cnt] = charmap->mb_cur_max == 1 ? 256 : 512;
+ else
+ ctype->map_collection_max[cnt] = max_chars;
+
+ ctype->map_collection[cnt] = (uint32_t *)
+ xmalloc (sizeof (uint32_t) * ctype->map_collection_max[cnt]);
+ memset (ctype->map_collection[cnt], '\0',
+ sizeof (uint32_t) * ctype->map_collection_max[cnt]);
+ ctype->map_collection_act[cnt] = 256;
+
+ ++ctype->map_collection_nr;
}
-void
-ctype_class_start (struct linereader *lr, struct localedef_t *locale,
- enum token_t tok, const char *str,
- struct charset_t *charset)
+/* We have to be prepared that TABLE, MAX, and ACT can be NULL. This
+ is possible if we only want ot extend the name array. */
+static uint32_t *
+find_idx (struct locale_ctype_t *ctype, uint32_t **table, size_t *max,
+ size_t *act, uint32_t idx)
{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
size_t cnt;
- switch (tok)
- {
- case tok_upper:
- str = "upper";
- break;
- case tok_lower:
- str = "lower";
- break;
- case tok_alpha:
- str = "alpha";
- break;
- case tok_digit:
- str = "digit";
- break;
- case tok_xdigit:
- str = "xdigit";
- break;
- case tok_space:
- str = "space";
- break;
- case tok_print:
- str = "print";
- break;
- case tok_graph:
- str = "graph";
- break;
- case tok_blank:
- str = "blank";
- break;
- case tok_cntrl:
- str = "cntrl";
- break;
- case tok_punct:
- str = "punct";
- break;
- case tok_alnum:
- str = "alnum";
- break;
- case tok_ident:
+ if (idx < 256)
+ return table == NULL ? NULL : &(*table)[idx];
+
+ for (cnt = 256; cnt < ctype->charnames_act; ++cnt)
+ if (ctype->charnames[cnt] == idx)
break;
- default:
- assert (! "illegal token as class name: should not happen");
+
+ /* We have to distinguish two cases: the name is found or not. */
+ if (cnt == ctype->charnames_act)
+ {
+ /* Extend the name array. */
+ if (ctype->charnames_act == ctype->charnames_max)
+ {
+ ctype->charnames_max *= 2;
+ ctype->charnames = (unsigned int *)
+ xrealloc (ctype->charnames,
+ sizeof (unsigned int) * ctype->charnames_max);
+ }
+ ctype->charnames[ctype->charnames_act++] = idx;
}
- for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
- if (strcmp (str, ctype->classnames[cnt]) == 0)
- break;
+ if (table == NULL)
+ /* We have done everything we are asked to do. */
+ return NULL;
+
+ if (cnt >= *act)
+ {
+ if (cnt >= *max)
+ {
+ size_t old_max = *max;
+ do
+ *max *= 2;
+ while (*max <= cnt);
- if (cnt >= ctype->nr_charclass)
- assert (! "unknown class in class definition: should not happen");
+ *table =
+ (uint32_t *) xrealloc (*table, *max * sizeof (unsigned long int));
+ memset (&(*table)[old_max], '\0',
+ (*max - old_max) * sizeof (uint32_t));
+ }
- ctype->class_done |= BIT (tok);
+ *act = cnt;
+ }
- ctype->current_class_mask = 1 << cnt;
- ctype->last_class_char = ILLEGAL_CHAR_VALUE;
+ return &(*table)[cnt];
}
-void
-ctype_class_from (struct linereader *lr, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
+static int
+get_character (struct token *now, struct charmap_t *charmap,
+ struct repertoire_t *repertoire,
+ struct charseq **seqp, uint32_t *wchp)
{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
- unsigned int value;
+ if (now->tok == tok_bsymbol)
+ {
+ /* This will hopefully be the normal case. */
+ *wchp = repertoire_find_value (repertoire, now->val.str.startmb,
+ now->val.str.lenmb);
+ *seqp = charmap_find_value (charmap, now->val.str.startmb,
+ now->val.str.lenmb);
+ }
+ else if (now->tok == tok_ucs4)
+ {
+ *seqp = repertoire_find_seq (repertoire, now->val.ucs4);
- value = charset_find_value (&charset->char_table, code->val.str.start,
- code->val.str.len);
+ if (*seqp == NULL)
+ {
+ /* Compute the value in the charmap from the UCS value. */
+ const char *symbol = repertoire_find_symbol (repertoire,
+ now->val.ucs4);
- ctype->last_class_char = value;
+ if (symbol == NULL)
+ *seqp = NULL;
+ else
+ *seqp = charmap_find_value (charmap, symbol, strlen (symbol));
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
- /* In the LC_CTYPE category it is no error when a character is
- not found. This has to be ignored silently. */
- return;
+ if (*seqp == NULL)
+ {
+ /* Insert a negative entry. */
+ static const struct charseq negative
+ = { .ucs4 = ILLEGAL_CHAR_VALUE };
+ uint32_t *newp = obstack_alloc (&repertoire->mem_pool, 4);
+ *newp = now->val.ucs4;
+
+ insert_entry (&repertoire->seq_table, newp, 4,
+ (void *) &negative);
+ }
+ else
+ (*seqp)->ucs4 = now->val.ucs4;
+ }
+ else if ((*seqp)->ucs4 != now->val.ucs4)
+ *seqp = NULL;
+
+ *wchp = now->val.ucs4;
+ }
+ else if (now->tok == tok_charcode)
+ {
+ /* We must map from the byte code to UCS4. */
+ *seqp = charmap_find_symbol (charmap, now->val.str.startmb,
+ now->val.str.lenmb);
- *find_idx (ctype, &ctype->class_collection, &ctype->class_collection_max,
- &ctype->class_collection_act, value)
- |= ctype->current_class_mask;
+ if (*seqp == NULL)
+ *wchp = ILLEGAL_CHAR_VALUE;
+ else
+ {
+ if ((*seqp)->ucs4 == UNINITIALIZED_CHAR_VALUE)
+ (*seqp)->ucs4 = repertoire_find_value (repertoire, (*seqp)->name,
+ strlen ((*seqp)->name));
+ *wchp = (*seqp)->ucs4;
+ }
+ }
+ else
+ return 1;
+
+ return 0;
}
-void
-ctype_class_to (struct linereader *lr, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
+/* Ellipsis like in `<foo123>..<foo12a>' or `<j1234>....<j1245>'. */
+static void
+charclass_symbolic_ellipsis (struct linereader *ldfile,
+ struct locale_ctype_t *ctype,
+ struct charmap_t *charmap,
+ struct repertoire_t *repertoire,
+ struct token *now,
+ const char *last_str,
+ unsigned long int class256_bit,
+ unsigned long int class_bit, int base,
+ int ignore_content, int handle_digits)
{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
- unsigned int value, cnt;
+ const char *nowstr = now->val.str.startmb;
+ char tmp[now->val.str.lenmb + 1];
+ const char *cp;
+ char *endp;
+ unsigned long int from;
+ unsigned long int to;
- value = charset_find_value (&charset->char_table, code->val.str.start,
- code->val.str.len);
+ /* We have to compute the ellipsis values using the symbolic names. */
+ assert (last_str != NULL);
- /* In the LC_CTYPE category it is no error when a character is
- not found. This has to be ignored silently. */
- if ((wchar_t) ctype->last_class_char != ILLEGAL_CHAR_VALUE
- && (wchar_t) value != ILLEGAL_CHAR_VALUE)
- for (cnt = ctype->last_class_char + 1; cnt <= value; ++cnt)
- *find_idx (ctype, &ctype->class_collection, &ctype->class_collection_max,
- &ctype->class_collection_act, cnt)
- |= ctype->current_class_mask;
+ if (strlen (last_str) != now->val.str.lenmb)
+ {
+ invalid_range:
+ lr_error (ldfile,
+ _("`%s' and `%s' are no valid names for symbolic range"),
+ last_str, nowstr);
+ return;
+ }
- ctype->last_class_char = ILLEGAL_CHAR_VALUE;
-}
+ if (memcmp (last_str, nowstr, now->val.str.lenmb) == 0)
+ /* Nothing to do, the names are the same. */
+ return;
+ for (cp = last_str; *cp == *(nowstr + (cp - last_str)); ++cp)
+ ;
-void
-ctype_class_end (struct linereader *lr, struct localedef_t *locale)
-{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
+ errno = 0;
+ from = strtoul (cp, &endp, base);
+ if ((from == UINT_MAX && errno == ERANGE) || *endp != '\0')
+ goto invalid_range;
- /* We have no special actions to perform here. */
- ctype->current_class_mask = 0;
- ctype->last_class_char = ILLEGAL_CHAR_VALUE;
-}
+ to = strtoul (nowstr + (cp - last_str), &endp, base);
+ if ((to == UINT_MAX && errno == ERANGE) || *endp != '\0' || from >= to)
+ goto invalid_range;
+ /* OK, we have a range FROM - TO. Now we can create the symbolic names. */
+ if (!ignore_content)
+ {
+ now->val.str.startmb = tmp;
+ while (++from <= to)
+ {
+ struct charseq *seq;
+ uint32_t wch;
-/* Character map handling. */
-void
-ctype_map_new (struct linereader *lr, struct localedef_t *locale,
- enum token_t tok, struct token *code,
- struct charset_t *charset)
-{
- ctype_map_newP (lr, locale->categories[LC_CTYPE].ctype,
- code->val.str.start, charset);
-}
+ sprintf (tmp, (base == 10 ? "%.*s%0*d" : "%.*s%0*X"), cp - last_str,
+ last_str, now->val.str.lenmb - (cp - last_str), from);
+ get_character (now, charmap, repertoire, &seq, &wch);
-int
-ctype_is_charconv (struct linereader *lr, struct localedef_t *locale,
- const char *name)
-{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
- size_t cnt;
+ if (seq != NULL && seq->nbytes == 1)
+ /* Yep, we can store information about this byte sequence. */
+ ctype->class256_collection[seq->bytes[0]] |= class256_bit;
- for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
- if (strcmp (name, ctype->mapnames[cnt]) == 0)
- return 1;
+ if (wch != ILLEGAL_CHAR_VALUE && class_bit != 0)
+ /* We have the UCS4 position. */
+ *find_idx (ctype, &ctype->class_collection,
+ &ctype->class_collection_max,
+ &ctype->class_collection_act, wch) |= class_bit;
- return 0;
+ if (handle_digits == 1)
+ {
+ /* We must store the digit values. */
+ if (ctype->mbdigits_act == ctype->mbdigits_max)
+ {
+ ctype->mbdigits_max *= 2;
+ ctype->mbdigits = xrealloc (ctype->mbdigits,
+ (ctype->mbdigits_max
+ * sizeof (char *)));
+ ctype->wcdigits_max *= 2;
+ ctype->wcdigits = xrealloc (ctype->wcdigits,
+ (ctype->wcdigits_max
+ * sizeof (uint32_t)));
+ }
+
+ ctype->mbdigits[ctype->mbdigits_act++] = seq;
+ ctype->wcdigits[ctype->wcdigits_act++] = wch;
+ }
+ else if (handle_digits == 2)
+ {
+ /* We must store the digit values. */
+ if (ctype->outdigits_act >= 10)
+ {
+ lr_error (ldfile, _("\
+%s: field `%s' does not contain exactly ten entries"),
+ "LC_CTYPE", "outdigit");
+ return;
+ }
+
+ ctype->mboutdigits[ctype->outdigits_act] = seq;
+ ctype->wcoutdigits[ctype->outdigits_act] = wch;
+ ++ctype->outdigits_act;
+ }
+ }
+ }
}
-void
-ctype_map_start (struct linereader *lr, struct localedef_t *locale,
- enum token_t tok, const char *name, struct charset_t *charset)
+/* Ellipsis like in `<U1234>..<U2345>'. */
+static void
+charclass_ucs4_ellipsis (struct linereader *ldfile,
+ struct locale_ctype_t *ctype,
+ struct charmap_t *charmap,
+ struct repertoire_t *repertoire,
+ struct token *now, uint32_t last_wch,
+ unsigned long int class256_bit,
+ unsigned long int class_bit, int ignore_content,
+ int handle_digits)
{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
- size_t cnt;
-
- switch (tok)
+ if (last_wch > now->val.ucs4)
{
- case tok_toupper:
- ctype->toupper_done = 1;
- name = "toupper";
- break;
- case tok_tolower:
- ctype->tolower_done = 1;
- name = "tolower";
- break;
- case tok_ident:
- break;
- default:
- assert (! "unknown token in category `LC_CTYPE' should not happen");
+ lr_error (ldfile, _("\
+to-value <U%0*X> of range is smaller than from-value <U%0*X>"),
+ (now->val.ucs4 | last_wch) < 65536 ? 4 : 8, now->val.ucs4,
+ (now->val.ucs4 | last_wch) < 65536 ? 4 : 8, last_wch);
+ return;
}
- for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
- if (strcmp (name, ctype->mapnames[cnt]) == 0)
- break;
+ if (!ignore_content)
+ while (++last_wch <= now->val.ucs4)
+ {
+ /* We have to find out whether there is a byte sequence corresponding
+ to this UCS4 value. */
+ struct charseq *seq = repertoire_find_seq (repertoire, last_wch);
- if (cnt == ctype->map_collection_nr)
- assert (! "unknown token in category `LC_CTYPE' should not happen");
+ /* If this is the first time we look for this sequence create a new
+ entry. */
+ if (seq == NULL)
+ {
+ /* Find the symbolic name for this UCS4 value. */
+ const char *symbol = repertoire_find_symbol (repertoire, last_wch);
+ uint32_t *newp = obstack_alloc (&repertoire->mem_pool, 4);
+ *newp = last_wch;
- ctype->last_map_idx = cnt;
- ctype->from_map_char = ILLEGAL_CHAR_VALUE;
-}
+ if (symbol != NULL)
+ /* We have a name, now search the multibyte value. */
+ seq = charmap_find_value (charmap, symbol, strlen (symbol));
+ if (seq == NULL)
+ {
+ /* We have to create a fake entry. */
+ static const struct charseq negative
+ = { .ucs4 = ILLEGAL_CHAR_VALUE };
+ seq = (struct charseq *) &negative;
+ }
+ else
+ seq->ucs4 = last_wch;
-void
-ctype_map_from (struct linereader *lr, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
-{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
- unsigned int value;
+ insert_entry (&repertoire->seq_table, newp, 4, seq);
+ }
- value = charset_find_value (&charset->char_table, code->val.str.start,
- code->val.str.len);
+ /* We have a name, now search the multibyte value. */
+ if (seq->ucs4 == last_wch && seq->nbytes == 1)
+ /* Yep, we can store information about this byte sequence. */
+ ctype->class256_collection[(size_t) seq->bytes[0]]
+ |= class256_bit;
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
- /* In the LC_CTYPE category it is no error when a character is
- not found. This has to be ignored silently. */
- return;
+ /* And of course we have the UCS4 position. */
+ if (class_bit != 0 && class_bit != 0)
+ *find_idx (ctype, &ctype->class_collection,
+ &ctype->class_collection_max,
+ &ctype->class_collection_act, last_wch) |= class_bit;
- assert (ctype->last_map_idx < ctype->map_collection_nr);
+ if (handle_digits == 1)
+ {
+ /* We must store the digit values. */
+ if (ctype->mbdigits_act == ctype->mbdigits_max)
+ {
+ ctype->mbdigits_max *= 2;
+ ctype->mbdigits = xrealloc (ctype->mbdigits,
+ (ctype->mbdigits_max
+ * sizeof (char *)));
+ ctype->wcdigits_max *= 2;
+ ctype->wcdigits = xrealloc (ctype->wcdigits,
+ (ctype->wcdigits_max
+ * sizeof (uint32_t)));
+ }
+
+ ctype->mbdigits[ctype->mbdigits_act++] = (seq->ucs4 == last_wch
+ ? seq : NULL);
+ ctype->wcdigits[ctype->wcdigits_act++] = last_wch;
+ }
+ else if (handle_digits == 2)
+ {
+ /* We must store the digit values. */
+ if (ctype->outdigits_act >= 10)
+ {
+ lr_error (ldfile, _("\
+%s: field `%s' does not contain exactly ten entries"),
+ "LC_CTYPE", "outdigit");
+ return;
+ }
- ctype->from_map_char = value;
+ ctype->mboutdigits[ctype->outdigits_act] = (seq->ucs4 == last_wch
+ ? seq : NULL);
+ ctype->wcoutdigits[ctype->outdigits_act] = last_wch;
+ ++ctype->outdigits_act;
+ }
+ }
}
-void
-ctype_map_to (struct linereader *lr, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
+/* Ellipsis as in `/xea/x12.../xea/x34'. */
+static void
+charclass_charcode_ellipsis (struct linereader *ldfile,
+ struct locale_ctype_t *ctype,
+ struct charmap_t *charmap,
+ struct repertoire_t *repertoire,
+ struct token *now, char *last_charcode,
+ uint32_t last_charcode_len,
+ unsigned long int class256_bit,
+ unsigned long int class_bit, int ignore_content,
+ int handle_digits)
{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
- unsigned int value;
-
- value = charset_find_value (&charset->char_table, code->val.str.start,
- code->val.str.len);
+ /* First check whether the to-value is larger. */
+ if (now->val.charcode.nbytes != last_charcode_len)
+ {
+ lr_error (ldfile, _("\
+start end end character sequence of range must have the same length"));
+ return;
+ }
- if ((wchar_t) ctype->from_map_char == ILLEGAL_CHAR_VALUE
- || (wchar_t) value == ILLEGAL_CHAR_VALUE)
+ if (memcmp (last_charcode, now->val.charcode.bytes, last_charcode_len) > 0)
{
- /* In the LC_CTYPE category it is no error when a character is
- not found. This has to be ignored silently. */
- ctype->from_map_char = ILLEGAL_CHAR_VALUE;
+ lr_error (ldfile, _("\
+to-value character sequence is smaller than from-value sequence"));
return;
}
- *find_idx (ctype, &ctype->map_collection[ctype->last_map_idx],
- &ctype->map_collection_max[ctype->last_map_idx],
- &ctype->map_collection_act[ctype->last_map_idx],
- ctype->from_map_char) = value;
+ if (!ignore_content)
+ {
+ do
+ {
+ /* Increment the byte sequence value. */
+ struct charseq *seq;
+ uint32_t wch;
+ int i;
+
+ for (i = last_charcode_len - 1; i >= 0; --i)
+ if (++last_charcode[i] != 0)
+ break;
+
+ if (last_charcode_len == 1)
+ /* Of course we have the charcode value. */
+ ctype->class256_collection[(size_t) last_charcode[0]]
+ |= class256_bit;
+
+ /* Find the symbolic name. */
+ seq = charmap_find_symbol (charmap, last_charcode,
+ last_charcode_len);
+ if (seq != NULL)
+ {
+ if (seq->ucs4 == UNINITIALIZED_CHAR_VALUE)
+ seq->ucs4 = repertoire_find_value (repertoire, seq->name,
+ strlen (seq->name));
+ wch = seq->ucs4;
+
+ if (wch != ILLEGAL_CHAR_VALUE && class_bit != 0)
+ *find_idx (ctype, &ctype->class_collection,
+ &ctype->class_collection_max,
+ &ctype->class_collection_act, wch) |= class_bit;
+ }
+ else
+ wch = ILLEGAL_CHAR_VALUE;
- ctype->from_map_char = ILLEGAL_CHAR_VALUE;
+ if (handle_digits == 1)
+ {
+ /* We must store the digit values. */
+ if (ctype->mbdigits_act == ctype->mbdigits_max)
+ {
+ ctype->mbdigits_max *= 2;
+ ctype->mbdigits = xrealloc (ctype->mbdigits,
+ (ctype->mbdigits_max
+ * sizeof (char *)));
+ ctype->wcdigits_max *= 2;
+ ctype->wcdigits = xrealloc (ctype->wcdigits,
+ (ctype->wcdigits_max
+ * sizeof (uint32_t)));
+ }
+
+ seq = xmalloc (sizeof (struct charseq) + last_charcode_len);
+ memcpy ((char *) (seq + 1), last_charcode, last_charcode_len);
+ seq->nbytes = last_charcode_len;
+
+ ctype->mbdigits[ctype->mbdigits_act++] = seq;
+ ctype->wcdigits[ctype->wcdigits_act++] = wch;
+ }
+ else if (handle_digits == 2)
+ {
+ struct charseq *seq;
+ /* We must store the digit values. */
+ if (ctype->outdigits_act >= 10)
+ {
+ lr_error (ldfile, _("\
+%s: field `%s' does not contain exactly ten entries"),
+ "LC_CTYPE", "outdigit");
+ return;
+ }
+
+ seq = xmalloc (sizeof (struct charseq) + last_charcode_len);
+ memcpy ((char *) (seq + 1), last_charcode, last_charcode_len);
+ seq->nbytes = last_charcode_len;
+
+ ctype->mboutdigits[ctype->outdigits_act] = seq;
+ ctype->wcoutdigits[ctype->outdigits_act] = wch;
+ ++ctype->outdigits_act;
+ }
+ }
+ while (memcmp (last_charcode, now->val.charcode.bytes,
+ last_charcode_len) != 0);
+ }
}
-void
-ctype_map_end (struct linereader *lr, struct localedef_t *locale)
+/* Read one transliteration entry. */
+static uint32_t *
+read_widestring (struct linereader *ldfile, struct token *now,
+ struct charmap_t *charmap, struct repertoire_t *repertoire)
{
- struct locale_ctype_t *ctype = locale->categories[LC_CTYPE].ctype;
+ uint32_t *wstr;
+
+ if (now->tok == tok_default_missing)
+ /* The special name "" will denote this case. */
+ wstr = (uint32_t *) L"";
+ else if (now->tok == tok_bsymbol)
+ {
+ /* Get the value from the repertoire. */
+ wstr = xmalloc (2 * sizeof (uint32_t));
+ wstr[0] = repertoire_find_value (repertoire, now->val.str.startmb,
+ now->val.str.lenmb);
+ if (wstr[0] == ILLEGAL_CHAR_VALUE)
+ /* We cannot proceed, we don't know the UCS4 value. */
+ return NULL;
+
+ wstr[1] = 0;
+ }
+ else if (now->tok == tok_ucs4)
+ {
+ wstr = xmalloc (2 * sizeof (uint32_t));
+ wstr[0] = now->val.ucs4;
+ wstr[1] = 0;
+ }
+ else if (now->tok == tok_charcode)
+ {
+ /* Argh, we have to convert to the symbol name first and then to the
+ UCS4 value. */
+ struct charseq *seq = charmap_find_symbol (charmap,
+ now->val.str.startmb,
+ now->val.str.lenmb);
+ if (seq == NULL)
+ /* Cannot find the UCS4 value. */
+ return NULL;
+
+ if (seq->ucs4 == UNINITIALIZED_CHAR_VALUE)
+ seq->ucs4 = repertoire_find_value (repertoire, seq->name,
+ strlen (seq->name));
+ if (seq->ucs4 == ILLEGAL_CHAR_VALUE)
+ /* We cannot proceed, we don't know the UCS4 value. */
+ return NULL;
+
+ wstr = xmalloc (2 * sizeof (uint32_t));
+ wstr[0] = seq->ucs4;
+ wstr[1] = 0;
+ }
+ else if (now->tok == tok_string)
+ {
+ wstr = now->val.str.startwc;
+ if (wstr[0] == 0)
+ return NULL;
+ }
+ else
+ {
+ if (now->tok != tok_eol && now->tok != tok_eof)
+ lr_ignore_rest (ldfile, 0);
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_CTYPE");
+ return (uint32_t *) -1l;
+ }
- ctype->last_map_idx = MAX_NR_CHARMAP;
- ctype->from_map_char = ILLEGAL_CHAR_VALUE;
+ return wstr;
}
-/* Local functions. */
static void
-ctype_class_newP (struct linereader *lr, struct locale_ctype_t *ctype,
- const char *name)
+read_translit_entry (struct linereader *ldfile, struct locale_ctype_t *ctype,
+ struct token *now, struct charmap_t *charmap,
+ struct repertoire_t *repertoire)
{
- size_t cnt;
+ uint32_t *from_wstr = read_widestring (ldfile, now, charmap, repertoire);
+ struct translit_t *result;
+ struct translit_to_t **top;
+ struct obstack *ob = &ctype->mem_pool;
+ int first;
+ int ignore;
+
+ if (from_wstr == NULL)
+ /* There is no valid from string. */
+ return;
- for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
- if (strcmp (ctype->classnames[cnt], name) == 0)
- break;
+ result = (struct translit_t *) obstack_alloc (ob,
+ sizeof (struct translit_t));
+ result->from = from_wstr;
+ result->next = NULL;
+ result->to = NULL;
+ top = &result->to;
+ first = 1;
+ ignore = 0;
- if (cnt < ctype->nr_charclass)
+ while (1)
{
- lr_error (lr, _("character class `%s' already defined"), name);
- return;
- }
+ uint32_t *to_wstr;
- if (ctype->nr_charclass == MAX_NR_CHARCLASS)
- /* Exit code 2 is prescribed in P1003.2b. */
- error (2, 0, _("\
-implementation limit: no more than %d character classes allowed"),
- MAX_NR_CHARCLASS);
+ /* Next we have one or more transliterations. They are
+ separated by semicolons. */
+ now = lr_token (ldfile, charmap, repertoire);
- ctype->classnames[ctype->nr_charclass++] = name;
+ if (!first && (now->tok == tok_semicolon || now->tok == tok_eol))
+ {
+ /* One string read. */
+ const uint32_t zero = 0;
+
+ if (!ignore)
+ {
+ obstack_grow (ob, &zero, 4);
+ to_wstr = obstack_finish (ob);
+
+ *top = obstack_alloc (ob, sizeof (struct translit_to_t));
+ (*top)->str = to_wstr;
+ (*top)->next = NULL;
+ }
+
+ if (now->tok == tok_eol)
+ {
+ result->next = ctype->translit;
+ ctype->translit = result;
+ return;
+ }
+
+ if (!ignore)
+ top = &(*top)->next;
+ ignore = 0;
+ }
+ else
+ {
+ to_wstr = read_widestring (ldfile, now, charmap, repertoire);
+ if (to_wstr == (uint32_t *) -1l)
+ {
+ /* An error occurred. */
+ obstack_free (ob, result);
+ return;
+ }
+
+ if (to_wstr == NULL)
+ ignore = 1;
+ else
+ /* This value is usable. */
+ obstack_grow (ob, to_wstr, wcslen ((wchar_t *) to_wstr) * 4);
+
+ first = 0;
+ }
+ }
}
-static void
-ctype_map_newP (struct linereader *lr, struct locale_ctype_t *ctype,
- const char *name, struct charset_t *charset)
+/* The parser for the LC_CTYPE section of the locale definition. */
+void
+ctype_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
{
- size_t max_chars = 0;
+ struct repertoire_t *repertoire = NULL;
+ struct locale_ctype_t *ctype;
+ struct token *now;
+ enum token_t nowtok;
size_t cnt;
+ struct charseq *last_seq;
+ uint32_t last_wch = 0;
+ enum token_t last_token;
+ enum token_t ellipsis_token;
+ char last_charcode[16];
+ size_t last_charcode_len = 0;
+ const char *last_str = NULL;
+ int mapidx;
- for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
- {
- if (strcmp (ctype->mapnames[cnt], name) == 0)
- break;
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
- if (max_chars < ctype->map_collection_max[cnt])
- max_chars = ctype->map_collection_max[cnt];
+ /* The rest of the line containing `LC_CTYPE' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
}
+ while (nowtok == tok_eol);
- if (cnt < ctype->map_collection_nr)
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
{
- lr_error (lr, _("character map `%s' already defined"), name);
+ handle_copy (ldfile, charmap, repertoire, tok_lc_ctype, LC_CTYPE,
+ "LC_CTYPE", ignore_content);
return;
}
- if (ctype->map_collection_nr == MAX_NR_CHARMAP)
- /* Exit code 2 is prescribed in P1003.2b. */
- error (2, 0, _("\
-implementation limit: no more than %d character maps allowed"),
- MAX_NR_CHARMAP);
+ /* Prepare the data structures. */
+ ctype_startup (ldfile, result, charmap, ignore_content);
+ ctype = result->categories[LC_CTYPE].ctype;
- ctype->mapnames[cnt] = name;
+ /* Remember the repertoire we use. */
+ if (!ignore_content)
+ ctype->repertoire = repertoire;
- if (max_chars == 0)
- ctype->map_collection_max[cnt] = charset->mb_cur_max == 1 ? 256 : 512;
- else
- ctype->map_collection_max[cnt] = max_chars;
+ while (1)
+ {
+ unsigned long int class_bit = 0;
+ unsigned long int class256_bit = 0;
+ int handle_digits = 0;
- ctype->map_collection[cnt] = (u_int32_t *)
- xmalloc (sizeof (u_int32_t) * ctype->map_collection_max[cnt]);
- memset (ctype->map_collection[cnt], '\0',
- sizeof (u_int32_t) * ctype->map_collection_max[cnt]);
- ctype->map_collection_act[cnt] = 256;
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
- ++ctype->map_collection_nr;
-}
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+ switch (nowtok)
+ {
+ case tok_class:
+ /* We simply forget the `class' keyword and use the following
+ operand to determine the bit. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_ident || now->tok == tok_string)
+ {
+ /* Must be one of the predefined class names. */
+ for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
+ if (strcmp (ctype->classnames[cnt], now->val.str.startmb) == 0)
+ break;
+ if (cnt >= ctype->nr_charclass)
+ {
+ if (now->val.str.lenmb == 8
+ && memcmp ("special1", now->val.str.startmb, 8) == 0)
+ class_bit = _ISwspecial1;
+ else if (now->val.str.lenmb == 8
+ && memcmp ("special2", now->val.str.startmb, 8) == 0)
+ class_bit = _ISwspecial2;
+ else if (now->val.str.lenmb == 8
+ && memcmp ("special3", now->val.str.startmb, 8) == 0)
+ class_bit = _ISwspecial3;
+ else
+ {
+ lr_error (ldfile, _("\
+unknown character class `%s' in category `LC_CTYPE'"),
+ now->val.str.startmb);
+ free (now->val.str.startmb);
+
+ lr_ignore_rest (ldfile, 0);
+ continue;
+ }
+ }
+ else
+ class_bit = _ISwbit (cnt);
+
+ free (now->val.str.startmb);
+ }
+ else if (now->tok == tok_digit)
+ goto handle_tok_digit;
+ else if (now->tok < tok_upper || now->tok > tok_blank)
+ goto err_label;
+ else
+ {
+ class_bit = BITw (now->tok);
+ class256_bit = BIT (now->tok);
+ }
-/* We have to be prepared that TABLE, MAX, and ACT can be NULL. This
- is possible if we only want to extend the name array. */
-static u_int32_t *
-find_idx (struct locale_ctype_t *ctype, u_int32_t **table, size_t *max,
- size_t *act, unsigned int idx)
-{
- size_t cnt;
+ /* The next character must be a semicolon. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_semicolon)
+ goto err_label;
+ goto read_charclass;
+
+ case tok_upper:
+ case tok_lower:
+ case tok_alpha:
+ case tok_alnum:
+ case tok_space:
+ case tok_cntrl:
+ case tok_punct:
+ case tok_graph:
+ case tok_print:
+ case tok_xdigit:
+ case tok_blank:
+ class_bit = BITw (now->tok);
+ class256_bit = BIT (now->tok);
+ handle_digits = 0;
+ read_charclass:
+ ctype->class_done |= class_bit;
+ last_token = tok_none;
+ ellipsis_token = tok_none;
+ now = lr_token (ldfile, charmap, NULL);
+ while (now->tok != tok_eol && now->tok != tok_eof)
+ {
+ uint32_t wch;
+ struct charseq *seq;
+
+ if (ellipsis_token == tok_none)
+ {
+ if (get_character (now, charmap, repertoire, &seq, &wch))
+ goto err_label;
+
+ if (!ignore_content && seq != NULL && seq->nbytes == 1)
+ /* Yep, we can store information about this byte
+ sequence. */
+ ctype->class256_collection[seq->bytes[0]] |= class256_bit;
+
+ if (!ignore_content && wch != ILLEGAL_CHAR_VALUE
+ && class_bit != 0)
+ /* We have the UCS4 position. */
+ *find_idx (ctype, &ctype->class_collection,
+ &ctype->class_collection_max,
+ &ctype->class_collection_act, wch) |= class_bit;
+
+ last_token = now->tok;
+ last_str = now->val.str.startmb;
+ last_seq = seq;
+ last_wch = wch;
+ memcpy (last_charcode, now->val.charcode.bytes, 16);
+ last_charcode_len = now->val.charcode.nbytes;
+
+ if (!ignore_content && handle_digits == 1)
+ {
+ /* We must store the digit values. */
+ if (ctype->mbdigits_act == ctype->mbdigits_max)
+ {
+ ctype->mbdigits_max *= 2;
+ ctype->mbdigits = xrealloc (ctype->mbdigits,
+ (ctype->mbdigits_max
+ * sizeof (char *)));
+ ctype->wcdigits_max *= 2;
+ ctype->wcdigits = xrealloc (ctype->wcdigits,
+ (ctype->wcdigits_max
+ * sizeof (uint32_t)));
+ }
+
+ ctype->mbdigits[ctype->mbdigits_act++] = seq;
+ ctype->wcdigits[ctype->wcdigits_act++] = wch;
+ }
+ else if (!ignore_content && handle_digits == 2)
+ {
+ /* We must store the digit values. */
+ if (ctype->outdigits_act >= 10)
+ {
+ lr_error (ldfile, _("\
+%s: field `%s' does not contain exactly ten entries"),
+ "LC_CTYPE", "outdigit");
+ goto err_label;
+ }
+
+ ctype->mboutdigits[ctype->outdigits_act] = seq;
+ ctype->wcoutdigits[ctype->outdigits_act] = wch;
+ ++ctype->outdigits_act;
+ }
+ }
+ else
+ {
+ /* Now it gets complicated. We have to resolve the
+ ellipsis problem. First we must distinguish between
+ the different kind of ellipsis and this must match the
+ tokens we have seen. */
+ assert (last_token != tok_none);
+
+ if (last_token != now->tok)
+ {
+ lr_error (ldfile, _("\
+ellipsis range must be marked by two operands of same type"));
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+
+ if (last_token == tok_bsymbol)
+ {
+ if (ellipsis_token == tok_ellipsis3)
+ lr_error (ldfile, _("with symbolic name range values \
+the absolute ellipsis `...' must not be used"));
+
+ charclass_symbolic_ellipsis (ldfile, ctype, charmap,
+ repertoire, now, last_str,
+ class256_bit, class_bit,
+ (ellipsis_token
+ == tok_ellipsis4
+ ? 10 : 16),
+ ignore_content,
+ handle_digits);
+ }
+ else if (last_token == tok_ucs4)
+ {
+ if (ellipsis_token != tok_ellipsis2)
+ lr_error (ldfile, _("\
+with UCS range values one must use the hexadecimal symbolic ellipsis `..'"));
+
+ charclass_ucs4_ellipsis (ldfile, ctype, charmap,
+ repertoire, now, last_wch,
+ class256_bit, class_bit,
+ ignore_content, handle_digits);
+ }
+ else
+ {
+ assert (last_token == tok_charcode);
+
+ if (ellipsis_token != tok_ellipsis3)
+ lr_error (ldfile, _("\
+with character code range values one must use the absolute ellipsis `...'"));
+
+ charclass_charcode_ellipsis (ldfile, ctype, charmap,
+ repertoire, now,
+ last_charcode,
+ last_charcode_len,
+ class256_bit, class_bit,
+ ignore_content,
+ handle_digits);
+ }
+
+ /* Now we have used the last value. */
+ last_token = tok_none;
+ }
+
+ /* Next we expect a semicolon or the end of the line. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_eol || now->tok == tok_eof)
+ break;
+
+ if (last_token != tok_none
+ && now->tok >= tok_ellipsis2 && now->tok <= tok_ellipsis4)
+ {
+ ellipsis_token = now->tok;
+ now = lr_token (ldfile, charmap, NULL);
+ continue;
+ }
+
+ if (now->tok != tok_semicolon)
+ goto err_label;
+
+ /* And get the next character. */
+ now = lr_token (ldfile, charmap, NULL);
+
+ ellipsis_token = tok_none;
+ }
+ break;
+
+ case tok_digit:
+ handle_tok_digit:
+ class_bit = _ISwdigit;
+ class256_bit = _ISdigit;
+ handle_digits = 1;
+ goto read_charclass;
+
+ case tok_outdigit:
+ if (ctype->outdigits_act != 0)
+ lr_error (ldfile, _("\
+%s: field `%s' declared more than once"),
+ "LC_CTYPE", "outdigit");
+ class_bit = 0;
+ class256_bit = 0;
+ handle_digits = 2;
+ goto read_charclass;
+
+ case tok_toupper:
+ mapidx = 0;
+ goto read_mapping;
+
+ case tok_tolower:
+ mapidx = 1;
+ goto read_mapping;
+
+ case tok_map:
+ /* We simply forget the `map' keyword and use the following
+ operand to determine the mapping. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_ident || now->tok == tok_string)
+ {
+ size_t cnt;
- if (idx < 256)
- return table == NULL ? NULL : &(*table)[idx];
+ for (cnt = 2; cnt < ctype->map_collection_nr; ++cnt)
+ if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
+ break;
- for (cnt = 256; cnt < ctype->charnames_act; ++cnt)
- if (ctype->charnames[cnt] == idx)
- break;
+ if (cnt < ctype->map_collection_nr)
+ mapidx = cnt;
+ else
+ {
+ lr_error (ldfile, _("unknown map `%s'"),
+ now->val.str.startmb);
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+ }
+ else if (now->tok < tok_toupper || now->tok > tok_tolower)
+ goto err_label;
+ else
+ mapidx = now->tok - tok_toupper;
- /* We have to distinguish two cases: the name is found or not. */
- if (cnt == ctype->charnames_act)
- {
- /* Extend the name array. */
- if (ctype->charnames_act == ctype->charnames_max)
- {
- ctype->charnames_max *= 2;
- ctype->charnames = (unsigned int *)
- xrealloc (ctype->charnames,
- sizeof (unsigned int) * ctype->charnames_max);
- }
- ctype->charnames[ctype->charnames_act++] = idx;
- }
+ now = lr_token (ldfile, charmap, NULL);
+ /* This better should be a semicolon. */
+ if (now->tok != tok_semicolon)
+ goto err_label;
- if (table == NULL)
- /* We have done everything we are asked to do. */
- return NULL;
+ read_mapping:
+ /* Test whether this mapping was already defined. */
+ if (ctype->tomap_done[mapidx])
+ {
+ lr_error (ldfile, _("duplicated definition for mapping `%s'"),
+ ctype->mapnames[mapidx]);
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+ ctype->tomap_done[mapidx] = 1;
- if (cnt >= *act)
- {
- if (cnt >= *max)
- {
- size_t old_max = *max;
- do
- *max *= 2;
- while (*max <= cnt);
+ now = lr_token (ldfile, charmap, NULL);
+ while (now->tok != tok_eol && now->tok != tok_eof)
+ {
+ struct charseq *from_seq;
+ uint32_t from_wch;
+ struct charseq *to_seq;
+ uint32_t to_wch;
+
+ /* Every pair starts with an opening brace. */
+ if (now->tok != tok_open_brace)
+ goto err_label;
+
+ /* Next comes the from-value. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (get_character (now, charmap, repertoire, &from_seq,
+ &from_wch) != 0)
+ goto err_label;
+
+ /* The next is a comma. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_comma)
+ goto err_label;
+
+ /* And the other value. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (get_character (now, charmap, repertoire, &to_seq,
+ &to_wch) != 0)
+ goto err_label;
+
+ /* And the last thing is the closing brace. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_close_brace)
+ goto err_label;
+
+ if (!ignore_content)
+ {
+ if (mapidx < 2 && from_seq != NULL && to_seq != NULL
+ && from_seq->nbytes == 1 && to_seq->nbytes == 1)
+ /* We can use this value. */
+ ctype->map256_collection[mapidx][from_seq->bytes[0]]
+ = to_seq->bytes[0];
+
+ if (from_wch != ILLEGAL_CHAR_VALUE
+ && to_wch != ILLEGAL_CHAR_VALUE)
+ /* Both correct values. */
+ *find_idx (ctype, &ctype->map_collection[mapidx],
+ &ctype->map_collection_max[mapidx],
+ &ctype->map_collection_act[mapidx],
+ from_wch) = to_wch;
+ }
+
+ /* Now comes a semicolon or the end of the line/file. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_semicolon)
+ now = lr_token (ldfile, charmap, NULL);
+ }
+ break;
- *table =
- (u_int32_t *) xrealloc (*table, *max * sizeof (unsigned long int));
- memset (&(*table)[old_max], '\0',
- (*max - old_max) * sizeof (u_int32_t));
+ case tok_translit_start:
+ /* The rest of the line better should be empty. */
+ lr_ignore_rest (ldfile, 1);
+
+ /* We count here the number of allocated entries in the `translit'
+ array. */
+ cnt = 0;
+
+ /* We proceed until we see the `translit_end' token. */
+ while (now = lr_token (ldfile, charmap, repertoire),
+ now->tok != tok_translit_end && now->tok != tok_eof)
+ {
+ if (now->tok == tok_eol)
+ /* Ignore empty lines. */
+ continue;
+
+ if (now->tok == tok_translit_end)
+ {
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+
+ if (now->tok == tok_include)
+ {
+ /* We have to include locale. */
+ const char *locale_name;
+ const char *repertoire_name;
+
+ now = lr_token (ldfile, charmap, NULL);
+ /* This should be a string or an identifier. In any
+ case something to name a locale. */
+ if (now->tok != tok_string && now->tok != tok_ident)
+ {
+ translit_syntax:
+ lr_error (ldfile, _("%s: syntax error"), "LC_CTYPE");
+ lr_ignore_rest (ldfile, 0);
+ continue;
+ }
+ locale_name = now->val.str.startmb;
+
+ /* Next should be a semicolon. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_semicolon)
+ goto translit_syntax;
+
+ /* Now the repertoire name. */
+ now = lr_token (ldfile, charmap, NULL);
+ if ((now->tok != tok_string && now->tok != tok_ident)
+ || now->val.str.startmb == NULL)
+ goto translit_syntax;
+ repertoire_name = now->val.str.startmb;
+
+ /* We must not have more than one `include'. */
+ if (ctype->translit_copy_locale != NULL)
+ {
+ lr_error (ldfile, _("\
+%s: only one `include' instruction allowed"), "LC_CTYPE");
+ lr_ignore_rest (ldfile, 0);
+ continue;
+ }
+
+ ctype->translit_copy_locale = locale_name;
+ ctype->translit_copy_repertoire = repertoire_name;
+
+ /* The rest of the line must be empty. */
+ lr_ignore_rest (ldfile, 1);
+ continue;
+ }
+
+ read_translit_entry (ldfile, ctype, now, charmap, repertoire);
+ }
+ break;
+
+ case tok_ident:
+ /* This could mean one of several things. First test whether
+ it's a character class name. */
+ for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
+ if (strcmp (now->val.str.startmb, ctype->classnames[cnt]) == 0)
+ break;
+ if (cnt < ctype->nr_charclass)
+ {
+ class_bit = _ISwbit (cnt);
+ class256_bit = cnt <= 11 ? _ISbit (cnt) : 0;
+ free (now->val.str.startmb);
+ goto read_charclass;
+ }
+ if (strcmp (now->val.str.startmb, "special1") == 0)
+ {
+ class_bit = _ISwspecial1;
+ free (now->val.str.startmb);
+ goto read_charclass;
+ }
+ if (strcmp (now->val.str.startmb, "special2") == 0)
+ {
+ class_bit = _ISwspecial2;
+ free (now->val.str.startmb);
+ goto read_charclass;
+ }
+ if (strcmp (now->val.str.startmb, "special3") == 0)
+ {
+ class_bit = _ISwspecial3;
+ free (now->val.str.startmb);
+ goto read_charclass;
+ }
+ if (strcmp (now->val.str.startmb, "tosymmetric") == 0)
+ {
+ mapidx = 2;
+ goto read_mapping;
+ }
+ break;
+
+ case tok_end:
+ /* Next we assume `LC_CTYPE'. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_eof)
+ break;
+ if (now->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"),
+ "LC_CTYPE");
+ else if (now->tok != tok_lc_ctype)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_CTYPE");
+ lr_ignore_rest (ldfile, now->tok == tok_lc_ctype);
+ return;
+
+ default:
+ err_label:
+ if (now->tok != tok_eof)
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_CTYPE");
}
- (*table)[cnt] = 0;
- *act = cnt;
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
}
- return &(*table)[cnt];
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_CTYPE");
}
static void
-set_class_defaults (struct locale_ctype_t *ctype, struct charset_t *charset)
+set_class_defaults (struct locale_ctype_t *ctype, struct charmap_t *charmap,
+ struct repertoire_t *repertoire)
{
+ size_t cnt;
+
/* These function defines the default values for the classes and conversions
according to POSIX.2 2.5.2.1.
It may seem that the order of these if-blocks is arbitrary but it is NOT.
Don't move them unless you know what you do! */
- void set_default (int bit, int from, int to)
+ void set_default (int bitpos, int from, int to)
{
char tmp[2];
int ch;
+ int bit = _ISbit (bitpos);
+ int bitw = _ISwbit (bitpos);
/* Define string. */
strcpy (tmp, "?");
for (ch = from; ch <= to; ++ch)
{
- unsigned int value;
+ uint32_t value;
+ struct charseq *seq;
tmp[0] = ch;
- value = charset_find_value (&charset->char_table, tmp, 1);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ value = repertoire_find_value (repertoire, tmp, 1);
+ if (value == ILLEGAL_CHAR_VALUE)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- tmp);
- continue;
+%s: character `%s' not defined in repertoire while needed as default value"),
+ "LC_CTYPE", tmp);
}
else
- ELEM (ctype, class_collection, , value) |= bit;
+ ELEM (ctype, class_collection, , value) |= bitw;
+
+ seq = charmap_find_value (charmap, tmp, 1);
+ if (seq == NULL)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined in charmap while needed as default value"),
+ "LC_CTYPE", tmp);
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", tmp);
+ else
+ ctype->class256_collection[seq->bytes[0]] |= bit;
}
}
/* Set default values if keyword was not present. */
- if ((ctype->class_done & BIT (tok_upper)) == 0)
+ if ((ctype->class_done & BITw (tok_upper)) == 0)
/* "If this keyword [lower] is not specified, the lowercase letters
`A' through `Z', ..., shall automatically belong to this class,
with implementation defined character values." [P1003.2, 2.5.2.1] */
- set_default (BIT (tok_upper), 'A', 'Z');
+ set_default (BITPOS (tok_upper), 'A', 'Z');
- if ((ctype->class_done & BIT (tok_lower)) == 0)
+ if ((ctype->class_done & BITw (tok_lower)) == 0)
/* "If this keyword [lower] is not specified, the lowercase letters
`a' through `z', ..., shall automatically belong to this class,
with implementation defined character values." [P1003.2, 2.5.2.1] */
- set_default (BIT (tok_lower), 'a', 'z');
+ set_default (BITPOS (tok_lower), 'a', 'z');
- if ((ctype->class_done & BIT (tok_alpha)) == 0)
+ if ((ctype->class_done & BITw (tok_alpha)) == 0)
{
/* Table 2-6 in P1003.2 says that characters in class `upper' or
class `lower' *must* be in class `alpha'. */
unsigned long int mask = BIT (tok_upper) | BIT (tok_lower);
- size_t cnt;
for (cnt = 0; cnt < ctype->class_collection_act; ++cnt)
if ((ctype->class_collection[cnt] & mask) != 0)
ctype->class_collection[cnt] |= BIT (tok_alpha);
}
- if ((ctype->class_done & BIT (tok_digit)) == 0)
+ if ((ctype->class_done & BITw (tok_digit)) == 0)
/* "If this keyword [digit] is not specified, the digits `0' through
`9', ..., shall automatically belong to this class, with
implementation-defined character values." [P1003.2, 2.5.2.1] */
- set_default (BIT (tok_digit), '0', '9');
+ set_default (BITPOS (tok_digit), '0', '9');
/* "Only characters specified for the `alpha' and `digit' keyword
shall be specified. Characters specified for the keyword `alpha'
and `digit' are automatically included in this class. */
{
unsigned long int mask = BIT (tok_alpha) | BIT (tok_digit);
- size_t cnt;
for (cnt = 0; cnt < ctype->class_collection_act; ++cnt)
if ((ctype->class_collection[cnt] & mask) != 0)
ctype->class_collection[cnt] |= BIT (tok_alnum);
}
- if ((ctype->class_done & BIT (tok_space)) == 0)
+ if ((ctype->class_done & BITw (tok_space)) == 0)
/* "If this keyword [space] is not specified, the characters <space>,
<form-feed>, <newline>, <carriage-return>, <tab>, and
<vertical-tab>, ..., shall automatically belong to this class,
with implementation-defined character values." [P1003.2, 2.5.2.1] */
{
- unsigned int value;
+ uint32_t value;
+ struct charseq *seq;
- value = charset_find_value (&charset->char_table, "space", 5);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ value = repertoire_find_value (repertoire, "space", 5);
+ if (value == ILLEGAL_CHAR_VALUE)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- "<space>");
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<space>");
}
else
ELEM (ctype, class_collection, , value) |= BIT (tok_space);
- value = charset_find_value (&charset->char_table, "form-feed", 9);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ seq = charmap_find_value (charmap, "space", 5);
+ if (seq == NULL)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- "<form-feed>");
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<space>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<space>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
+
+
+ value = repertoire_find_value (repertoire, "form-feed", 9);
+ if (value == ILLEGAL_CHAR_VALUE)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<form-feed>");
}
else
ELEM (ctype, class_collection, , value) |= BIT (tok_space);
- value = charset_find_value (&charset->char_table, "newline", 7);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ seq = charmap_find_value (charmap, "form-feed", 9);
+ if (seq == NULL)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- "<newline>");
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<form-feed>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<form-feed>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
+
+
+ value = repertoire_find_value (repertoire, "newline", 7);
+ if (value == ILLEGAL_CHAR_VALUE)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<newline>");
}
else
ELEM (ctype, class_collection, , value) |= BIT (tok_space);
- value = charset_find_value (&charset->char_table, "carriage-return", 15);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ seq = charmap_find_value (charmap, "newline", 7);
+ if (seq == NULL)
{
if (!be_quiet)
error (0, 0, _("\
character `%s' not defined while needed as default value"),
- "<carriage-return>");
+ "<newline>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<newline>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
+
+
+ value = repertoire_find_value (repertoire, "carriage-return", 15);
+ if (value == ILLEGAL_CHAR_VALUE)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<carriage-return>");
}
else
ELEM (ctype, class_collection, , value) |= BIT (tok_space);
- value = charset_find_value (&charset->char_table, "tab", 3);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ seq = charmap_find_value (charmap, "carriage-return", 15);
+ if (seq == NULL)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- "<tab>");
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<carriage-return>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<carriage-return>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
+
+
+ value = repertoire_find_value (repertoire, "tab", 3);
+ if (value == ILLEGAL_CHAR_VALUE)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<tab>");
}
else
ELEM (ctype, class_collection, , value) |= BIT (tok_space);
- value = charset_find_value (&charset->char_table, "vertical-tab", 12);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ seq = charmap_find_value (charmap, "tab", 3);
+ if (seq == NULL)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- "<vertical-tab>");
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<tab>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<tab>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
+
+
+ value = repertoire_find_value (repertoire, "vertical-tab", 12);
+ if (value == ILLEGAL_CHAR_VALUE)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<vertical-tab>");
}
else
ELEM (ctype, class_collection, , value) |= BIT (tok_space);
+
+ seq = charmap_find_value (charmap, "vertical-tab", 12);
+ if (seq == NULL)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<vertical-tab>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<vertical-tab>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
}
- if ((ctype->class_done & BIT (tok_xdigit)) == 0)
+ if ((ctype->class_done & BITw (tok_xdigit)) == 0)
/* "If this keyword is not specified, the digits `0' to `9', the
uppercase letters `A' through `F', and the lowercase letters `a'
through `f', ..., shell automatically belong to this class, with
implementation defined character values." [P1003.2, 2.5.2.1] */
{
- set_default (BIT (tok_xdigit), '0', '9');
- set_default (BIT (tok_xdigit), 'A', 'F');
- set_default (BIT (tok_xdigit), 'a', 'f');
+ set_default (BITPOS (tok_xdigit), '0', '9');
+ set_default (BITPOS (tok_xdigit), 'A', 'F');
+ set_default (BITPOS (tok_xdigit), 'a', 'f');
}
- if ((ctype->class_done & BIT (tok_blank)) == 0)
+ if ((ctype->class_done & BITw (tok_blank)) == 0)
/* "If this keyword [blank] is unspecified, the characters <space> and
<tab> shall belong to this character class." [P1003.2, 2.5.2.1] */
{
- unsigned int value;
+ uint32_t value;
+ struct charseq *seq;
- value = charset_find_value (&charset->char_table, "space", 5);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ value = repertoire_find_value (repertoire, "space", 5);
+ if (value == ILLEGAL_CHAR_VALUE)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- "<space>");
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<space>");
}
else
ELEM (ctype, class_collection, , value) |= BIT (tok_blank);
- value = charset_find_value (&charset->char_table, "tab", 3);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+ seq = charmap_find_value (charmap, "space", 5);
+ if (seq == NULL)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- "<tab>");
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<space>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<space>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_blank);
+
+
+ value = repertoire_find_value (repertoire, "tab", 3);
+ if (value == ILLEGAL_CHAR_VALUE)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<tab>");
}
else
ELEM (ctype, class_collection, , value) |= BIT (tok_blank);
+
+ seq = charmap_find_value (charmap, "tab", 3);
+ if (seq == NULL)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<tab>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<tab>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_blank);
}
- if ((ctype->class_done & BIT (tok_graph)) == 0)
+ if ((ctype->class_done & BITw (tok_graph)) == 0)
/* "If this keyword [graph] is not specified, characters specified for
the keywords `upper', `lower', `alpha', `digit', `xdigit' and `punct',
shall belong to this character class." [P1003.2, 2.5.2.1] */
@@ -1142,9 +2603,13 @@ character `%s' not defined while needed as default value"),
for (cnt = 0; cnt < ctype->class_collection_act; ++cnt)
if ((ctype->class_collection[cnt] & mask) != 0)
ctype->class_collection[cnt] |= BIT (tok_graph);
+
+ for (cnt = 0; cnt < 256; ++cnt)
+ if ((ctype->class256_collection[cnt] & mask) != 0)
+ ctype->class256_collection[cnt] |= BIT (tok_graph);
}
- if ((ctype->class_done & BIT (tok_print)) == 0)
+ if ((ctype->class_done & BITw (tok_print)) == 0)
/* "If this keyword [print] is not provided, characters specified for
the keywords `upper', `lower', `alpha', `digit', `xdigit', `punct',
and the <space> character shall belong to this character class."
@@ -1153,25 +2618,46 @@ character `%s' not defined while needed as default value"),
unsigned long int mask = BIT (tok_upper) | BIT (tok_lower) |
BIT (tok_alpha) | BIT (tok_digit) | BIT (tok_xdigit) | BIT (tok_punct);
size_t cnt;
- wchar_t space;
+ uint32_t space;
+ struct charseq *seq;
for (cnt = 0; cnt < ctype->class_collection_act; ++cnt)
if ((ctype->class_collection[cnt] & mask) != 0)
ctype->class_collection[cnt] |= BIT (tok_print);
- space = charset_find_value (&charset->char_table, "space", 5);
+ for (cnt = 0; cnt < 256; ++cnt)
+ if ((ctype->class256_collection[cnt] & mask) != 0)
+ ctype->class256_collection[cnt] |= BIT (tok_print);
+
+
+ space = repertoire_find_value (repertoire, "space", 5);
if (space == ILLEGAL_CHAR_VALUE)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- "<space>");
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<space>");
}
else
ELEM (ctype, class_collection, , space) |= BIT (tok_print);
+
+ seq = charmap_find_value (charmap, "space", 5);
+ if (seq == NULL)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", "<space>");
+ }
+ else if (seq->nbytes != 1)
+ error (0, 0, _("\
+%s: character `%s' in charmap not representable with one byte"),
+ "LC_CTYPE", "<space>");
+ else
+ ctype->class256_collection[seq->bytes[0]] |= BIT (tok_print);
}
- if (ctype->toupper_done == 0)
+ if (ctype->tomap_done[0] == 0)
/* "If this keyword [toupper] is not specified, the lowercase letters
`a' through `z', and their corresponding uppercase letters `A' to
`Z', ..., shall automatically be included, with implementation-
@@ -1184,55 +2670,133 @@ character `%s' not defined while needed as default value"),
for (ch = 'a'; ch <= 'z'; ++ch)
{
- unsigned int value_from, value_to;
+ uint32_t value_from, value_to;
+ struct charseq *seq_from, *seq_to;
tmp[1] = (char) ch;
- value_from = charset_find_value (&charset->char_table, &tmp[1], 1);
- if ((wchar_t) value_from == ILLEGAL_CHAR_VALUE)
+ value_from = repertoire_find_value (repertoire, &tmp[1], 1);
+ if (value_from == ILLEGAL_CHAR_VALUE)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- tmp);
- continue;
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", tmp);
+ }
+ else
+ {
+ /* This conversion is implementation defined. */
+ tmp[1] = (char) (ch + ('A' - 'a'));
+ value_to = repertoire_find_value (repertoire, &tmp[1], 1);
+ if (value_to == ILLEGAL_CHAR_VALUE)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", tmp);
+ }
+ else
+ /* The index [0] is determined by the order of the
+ `ctype_map_newP' calls in `ctype_startup'. */
+ ELEM (ctype, map_collection, [0], value_from) = value_to;
}
- /* This conversion is implementation defined. */
- tmp[1] = (char) (ch + ('A' - 'a'));
- value_to = charset_find_value (&charset->char_table, &tmp[1], 1);
- if ((wchar_t) value_to == ILLEGAL_CHAR_VALUE)
+ seq_from = charmap_find_value (charmap, &tmp[1], 1);
+ if (seq_from == NULL)
{
if (!be_quiet)
error (0, 0, _("\
-character `%s' not defined while needed as default value"),
- tmp);
- continue;
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", tmp);
+ }
+ else if (seq_from->nbytes != 1)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' needed as default value not representable with one byte"),
+ "LC_CTYPE", tmp);
+ }
+ else
+ {
+ /* This conversion is implementation defined. */
+ tmp[1] = (char) (ch + ('A' - 'a'));
+ seq_to = charmap_find_value (charmap, &tmp[1], 1);
+ if (seq_to == NULL)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' not defined while needed as default value"),
+ "LC_CTYPE", tmp);
+ }
+ else if (seq_to->nbytes != 1)
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: character `%s' needed as default value not representable with one byte"),
+ "LC_CTYPE", tmp);
+ }
+ else
+ /* The index [0] is determined by the order of the
+ `ctype_map_newP' calls in `ctype_startup'. */
+ ctype->map256_collection[0][seq_from->bytes[0]]
+ = seq_to->bytes[0];
}
-
- /* The index [0] is determined by the order of the
- `ctype_map_newP' calls in `ctype_startup'. */
- ELEM (ctype, map_collection, [0], value_from) = value_to;
}
}
- if (ctype->tolower_done == 0)
+ if (ctype->tomap_done[1] == 0)
/* "If this keyword [tolower] is not specified, the mapping shall be
the reverse mapping of the one specified to `toupper'." [P1003.2] */
{
- size_t cnt;
-
for (cnt = 0; cnt < ctype->map_collection_act[0]; ++cnt)
if (ctype->map_collection[0][cnt] != 0)
ELEM (ctype, map_collection, [1],
ctype->map_collection[0][cnt])
= ctype->charnames[cnt];
+
+ for (cnt = 0; cnt < 256; ++cnt)
+ if (ctype->map256_collection[0][cnt] != 0)
+ ctype->map_collection[1][ctype->map_collection[0][cnt]]
+ = ctype->charnames[cnt];
+ }
+
+ if (ctype->outdigits_act == 0)
+ {
+ for (cnt = 0; cnt < 10; ++cnt)
+ {
+ ctype->mboutdigits[cnt] = charmap_find_symbol (charmap,
+ digits + cnt, 1);
+
+ if (ctype->mboutdigits[cnt] == NULL)
+ {
+ ctype->mboutdigits[cnt] = charmap_find_symbol (charmap,
+ longnames[cnt],
+ strlen (longnames[cnt]));
+
+ if (ctype->mboutdigits[cnt] == NULL)
+ {
+ /* Provide a replacement. */
+ error (0, 0, _("\
+no output digits defined and none of the standard names in the charmap"));
+
+ ctype->mboutdigits[cnt] = obstack_alloc (&charmap->mem_pool,
+ sizeof (struct charseq) + 1);
+
+ /* This is better than nothing. */
+ ctype->mboutdigits[cnt]->bytes[0] = digits[cnt];
+ ctype->mboutdigits[cnt]->nbytes = 1;
+ }
+ }
+ }
+
+ ctype->outdigits_act = 10;
}
}
static void
-allocate_arrays (struct locale_ctype_t *ctype, struct charset_t *charset)
+allocate_arrays (struct locale_ctype_t *ctype, struct charmap_t *charmap,
+ struct repertoire_t *repertoire)
{
size_t idx;
@@ -1300,12 +2864,12 @@ Computing table size for character classes might take a while..."),
# define NAMES_B2 ctype->names_el
#endif
- ctype->names_eb = (u_int32_t *) xcalloc (ctype->plane_size
- * ctype->plane_cnt,
- sizeof (u_int32_t));
- ctype->names_el = (u_int32_t *) xcalloc (ctype->plane_size
- * ctype->plane_cnt,
- sizeof (u_int32_t));
+ ctype->names_eb = (uint32_t *) xcalloc (ctype->plane_size
+ * ctype->plane_cnt,
+ sizeof (uint32_t));
+ ctype->names_el = (uint32_t *) xcalloc (ctype->plane_size
+ * ctype->plane_cnt,
+ sizeof (uint32_t));
for (idx = 1; idx < 256; ++idx)
NAMES_B1[idx] = idx;
@@ -1330,7 +2894,7 @@ Computing table size for character classes might take a while..."),
NAMES_B1[0] = 0;
for (idx = 0; idx < ctype->plane_size * ctype->plane_cnt; ++idx)
- NAMES_B2[idx] = SWAPU32 (NAMES_B1[idx]);
+ NAMES_B2[idx] = bswap_32 (NAMES_B1[idx]);
/* You wonder about this amount of memory? This is only because some
@@ -1353,10 +2917,9 @@ Computing table size for character classes might take a while..."),
# define TRANS32(w) (w)
#endif
- for (idx = 0; idx < ctype->class_collection_act; ++idx)
- if (ctype->charnames[idx] < 256)
- ctype->ctype_b[128 + ctype->charnames[idx]]
- = TRANS (ctype->class_collection[idx]);
+ /* This is the array accessed usig the multibyte string elements. */
+ for (idx = 0; idx < 256; ++idx)
+ ctype->ctype_b[128 + idx] = TRANS (ctype->class256_collection[idx]);
/* Mirror first 127 entries. We must take care that entry -1 is not
mirrored because EOF == -1. */
@@ -1369,10 +2932,10 @@ Computing table size for character classes might take a while..."),
= TRANS32 (ctype->class_collection[idx]);
/* Room for table of mappings. */
- ctype->map_eb = (u_int32_t **) xmalloc (ctype->map_collection_nr
- * sizeof (u_int32_t *));
- ctype->map_el = (u_int32_t **) xmalloc (ctype->map_collection_nr
- * sizeof (u_int32_t *));
+ ctype->map_eb = (uint32_t **) xmalloc (ctype->map_collection_nr
+ * sizeof (uint32_t *));
+ ctype->map_el = (uint32_t **) xmalloc (ctype->map_collection_nr
+ * sizeof (uint32_t *));
/* Fill in all mappings. */
for (idx = 0; idx < ctype->map_collection_nr; ++idx)
@@ -1380,12 +2943,12 @@ Computing table size for character classes might take a while..."),
unsigned int idx2;
/* Allocate table. */
- ctype->map_eb[idx] = (u_int32_t *) xmalloc ((ctype->plane_size
- * ctype->plane_cnt + 128)
- * sizeof (u_int32_t));
- ctype->map_el[idx] = (u_int32_t *) xmalloc ((ctype->plane_size
- * ctype->plane_cnt + 128)
- * sizeof (u_int32_t));
+ ctype->map_eb[idx] = (uint32_t *) xmalloc ((ctype->plane_size
+ * ctype->plane_cnt + 128)
+ * sizeof (uint32_t));
+ ctype->map_el[idx] = (uint32_t *) xmalloc ((ctype->plane_size
+ * ctype->plane_cnt + 128)
+ * sizeof (uint32_t));
#if __BYTE_ORDER == __LITTLE_ENDIAN
# define MAP_B1 ctype->map_el
@@ -1397,13 +2960,11 @@ Computing table size for character classes might take a while..."),
/* Copy default value (identity mapping). */
memcpy (&MAP_B1[idx][128], NAMES_B1,
- ctype->plane_size * ctype->plane_cnt * sizeof (u_int32_t));
+ ctype->plane_size * ctype->plane_cnt * sizeof (uint32_t));
/* Copy values from collection. */
- for (idx2 = 0; idx2 < ctype->map_collection_act[idx]; ++idx2)
- if (ctype->map_collection[idx][idx2] != 0)
- MAP_B1[idx][128 + ctype->charnames[idx2]] =
- ctype->map_collection[idx][idx2];
+ for (idx2 = 0; idx2 < 256; ++idx2)
+ MAP_B1[idx][128 + idx2] = ctype->map256_collection[idx][idx2];
/* Mirror first 127 entries. We must take care not to map entry
-1 because EOF == -1. */
@@ -1415,14 +2976,14 @@ Computing table size for character classes might take a while..."),
/* And now the other byte order. */
for (idx2 = 0; idx2 < ctype->plane_size * ctype->plane_cnt + 128; ++idx2)
- MAP_B2[idx][idx2] = SWAPU32 (MAP_B1[idx][idx2]);
+ MAP_B2[idx][idx2] = bswap_32 (MAP_B1[idx][idx2]);
}
/* Extra array for class and map names. */
- ctype->class_name_ptr = (u_int32_t *) xmalloc (ctype->nr_charclass
- * sizeof (u_int32_t));
- ctype->map_name_ptr = (u_int32_t *) xmalloc (ctype->map_collection_nr
- * sizeof (u_int32_t));
+ ctype->class_name_ptr = (uint32_t *) xmalloc (ctype->nr_charclass
+ * sizeof (uint32_t));
+ ctype->map_name_ptr = (uint32_t *) xmalloc (ctype->map_collection_nr
+ * sizeof (uint32_t));
/* Array for width information. Because the expected width are very
small we use only one single byte. This save space and we need
@@ -1430,16 +2991,17 @@ Computing table size for character classes might take a while..."),
ctype->width = (unsigned char *) xmalloc (ctype->plane_size
* ctype->plane_cnt);
/* Initialize with default width value. */
- memset (ctype->width, charset->width_default,
+ memset (ctype->width, charmap->width_default,
ctype->plane_size * ctype->plane_cnt);
- if (charset->width_rules != NULL)
+ if (charmap->width_rules != NULL)
{
+#if 0
size_t cnt;
- for (cnt = 0; cnt < charset->nwidth_rules; ++cnt)
- if (charset->width_rules[cnt].width != charset->width_default)
- for (idx = charset->width_rules[cnt].from;
- idx <= charset->width_rules[cnt].to; ++idx)
+ for (cnt = 0; cnt < charmap->nwidth_rules; ++cnt)
+ if (charmap->width_rules[cnt].width != charmap->width_default)
+ for (idx = charmap->width_rules[cnt].from;
+ idx <= charmap->width_rules[cnt].to; ++idx)
{
size_t nr = idx % ctype->plane_size;
size_t depth = 0;
@@ -1449,15 +3011,229 @@ Computing table size for character classes might take a while..."),
assert (depth < ctype->plane_cnt);
ctype->width[nr + depth * ctype->plane_size]
- = charset->width_rules[cnt].width;
+ = charmap->width_rules[cnt].width;
}
+#else
+ abort ();
+#endif
}
- /* Compute MB_CUR_MAX. */
- ctype->mb_cur_max = charset->mb_cur_max;
+ /* Set MB_CUR_MAX. */
+ ctype->mb_cur_max = charmap->mb_cur_max;
/* We need the name of the currently used 8-bit character set to
make correct conversion between this 8-bit representation and the
ISO 10646 character set used internally for wide characters. */
- ctype->codeset_name = charset->code_set_name ? : "";
+ ctype->codeset_name = charmap->code_set_name;
+
+ /* Now determine the table for the transliteration information.
+
+ XXX It is not yet clear to me whether it is worth implementing a
+ complicated algorithm which uses a hash table to locate the entries.
+ For now I'll use a simple array which can be searching using binary
+ search. */
+ if (ctype->translit_copy_locale != NULL)
+ {
+ /* Fold in the transliteration information from the locale mentioned
+ in the `include' statement. */
+ struct locale_ctype_t *here = ctype;
+
+ do
+ {
+ struct localedef_t *other = find_locale (LC_CTYPE,
+ here->translit_copy_locale,
+ repertoire->name, charmap);
+
+ if (other == NULL)
+ {
+ error (0, 0, _("\
+%s: transliteration data from locale `%s' not available"),
+ "LC_CTYPE", here->translit_copy_locale);
+ break;
+ }
+
+ here = other->categories[LC_CTYPE].ctype;
+
+ /* Enqueue the information if necessary. */
+ if (here->translit != NULL)
+ {
+ struct translit_t *endp = here->translit;
+ while (endp->next != NULL)
+ endp = endp->next;
+
+ endp->next = ctype->translit;
+ ctype->translit = here->translit;
+ }
+ }
+ while (here->translit_copy_locale != NULL);
+ }
+
+ if (ctype->translit != NULL)
+ {
+ /* First count how many entries we have. This is the upper limit
+ since some entries from the included files might be overwritten. */
+ size_t number = 0;
+ size_t cnt;
+ struct translit_t *runp = ctype->translit;
+ struct translit_t **sorted;
+ size_t from_len, to_len;
+
+ while (runp != NULL)
+ {
+ ++number;
+ runp = runp->next;
+ }
+
+ /* Next we allocate an array large enough and fill in the values. */
+ sorted = alloca (number * sizeof (struct translit_t **));
+ runp = ctype->translit;
+ number = 0;
+ do
+ {
+ /* Search for the place where to insert this string.
+ XXX Better use a real sorting algorithm later. */
+ size_t idx = 0;
+ int replace = 0;
+
+ while (idx < number)
+ {
+ int res = wcscmp ((const wchar_t *) sorted[idx]->from,
+ (const wchar_t *) runp->from);
+ if (res == 0)
+ {
+ replace = 1;
+ break;
+ }
+ if (res > 0)
+ break;
+ ++idx;
+ }
+
+ if (replace)
+ sorted[idx] = runp;
+ else
+ {
+ memmove (&sorted[idx + 1], &sorted[idx],
+ (number - idx) * sizeof (struct translit_t *));
+ sorted[idx] = runp;
+ ++number;
+ }
+
+ runp = runp->next;
+ }
+ while (runp != NULL);
+
+ /* The next step is putting all the possible transliteration
+ strings in one memory block so that we can write it out.
+ We need several different blocks:
+ - index to the tfromstring array
+ - from-string array
+ - index to the to-string array
+ - to-string array.
+ And this all must be available for both endianes variants.
+ */
+ from_len = to_len = 0;
+ for (cnt = 0; cnt < number; ++cnt)
+ {
+ struct translit_to_t *srunp;
+ from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
+ srunp = sorted[cnt]->to;
+ while (srunp != NULL)
+ {
+ to_len += wcslen ((const wchar_t *) srunp->str) + 1;
+ srunp = srunp->next;
+ }
+ /* Plus one for the extra NUL character marking the end of
+ the list for the current entry. */
+ ++to_len;
+ }
+
+ /* We can allocate the arrays for the results. */
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define from_idx translit_from_idx_el
+# define from_tbl translit_from_tbl_el
+# define to_idx translit_to_idx_el
+# define to_tbl translit_to_tbl_el
+# define from_idx_ob translit_from_idx_eb
+# define from_tbl_ob translit_from_tbl_eb
+# define to_idx_ob translit_to_idx_eb
+# define to_tbl_ob translit_to_tbl_eb
+#else
+# define from_idx translit_from_idx_eb
+# define from_tbl translit_from_tbl_eb
+# define to_idx translit_to_idx_eb
+# define to_tbl translit_to_tbl_eb
+# define from_idx_ob translit_from_idx_el
+# define from_tbl_ob translit_from_tbl_el
+# define to_idx_ob translit_to_idx_el
+# define to_tbl_ob translit_to_tbl_el
+#endif
+ ctype->from_idx = xmalloc (number * sizeof (uint32_t));
+ ctype->from_idx_ob = xmalloc (number * sizeof (uint32_t));
+ ctype->from_tbl = xmalloc (from_len * sizeof (uint32_t));
+ ctype->from_tbl_ob = xmalloc (from_len * sizeof (uint32_t));
+ ctype->to_idx = xmalloc (number * sizeof (uint32_t));
+ ctype->to_idx_ob = xmalloc (number * sizeof (uint32_t));
+ ctype->to_tbl = xmalloc (to_len * sizeof (uint32_t));
+ ctype->to_tbl_ob = xmalloc (to_len * sizeof (uint32_t));
+
+ from_len = 0;
+ to_len = 0;
+ for (cnt = 0; cnt < number; ++cnt)
+ {
+ size_t len;
+ struct translit_to_t *srunp;
+
+ ctype->from_idx[cnt] = from_len;
+ ctype->to_idx[cnt] = to_len;
+
+ len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1;
+ wmemcpy ((wchar_t *) &ctype->from_tbl[from_len],
+ (const wchar_t *) sorted[cnt]->from, len);
+ from_len += len;
+
+ ctype->to_idx[cnt] = to_len;
+ srunp = sorted[cnt]->to;
+ while (srunp != NULL)
+ {
+ len = wcslen ((const wchar_t *) srunp->str) + 1;
+ wmemcpy ((wchar_t *) &ctype->to_tbl[to_len],
+ (const wchar_t *) srunp->str, len);
+ to_len += len;
+ srunp = srunp->next;
+ }
+ ctype->to_tbl[to_len++] = L'\0';
+ }
+
+ /* Now create the tables for the other endianess. */
+ for (cnt = 0; cnt < number; ++cnt)
+ {
+ ctype->from_idx_ob[cnt] = bswap_32 (ctype->from_idx[cnt]);
+ ctype->to_idx_ob[cnt] = bswap_32 (ctype->to_idx[cnt]);
+ }
+ for (cnt = 0; cnt < from_len; ++cnt)
+ ctype->from_tbl[cnt] = bswap_32 (ctype->from_tbl_ob[cnt]);
+ for (cnt = 0; cnt < to_len; ++cnt)
+ ctype->to_tbl[cnt] = bswap_32 (ctype->to_tbl_ob[cnt]);
+
+ /* Store the information about the length. */
+ ctype->translit_idx_size = number * sizeof (uint32_t);
+ ctype->translit_from_tbl_size = from_len * sizeof (uint32_t);
+ ctype->translit_to_tbl_size = to_len * sizeof (uint32_t);
+ }
+ else
+ {
+ /* Provide some dummy pointers since we have nothing to write out. */
+ static uint32_t no_str = { 0 };
+
+ ctype->translit_from_idx_el = &no_str;
+ ctype->translit_from_idx_eb = &no_str;
+ ctype->translit_from_tbl_el = &no_str;
+ ctype->translit_from_tbl_eb = &no_str;
+ ctype->translit_to_tbl_el = &no_str;
+ ctype->translit_to_tbl_eb = &no_str;
+ ctype->translit_idx_size = 0;
+ ctype->translit_from_tbl_size = 0;
+ ctype->translit_to_tbl_size = 0;
+ }
}
diff --git a/locale/programs/ld-identification.c b/locale/programs/ld-identification.c
new file mode 100644
index 0000000000..79bcd44328
--- /dev/null
+++ b/locale/programs/ld-identification.c
@@ -0,0 +1,376 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <error.h>
+#include <langinfo.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+
+#include "localeinfo.h"
+#include "locfile.h"
+
+
+/* The real definition of the struct for the LC_IDENTIFICATION locale. */
+struct locale_identification_t
+{
+ const char *title;
+ const char *source;
+ const char *address;
+ const char *contact;
+ const char *email;
+ const char *tel;
+ const char *fax;
+ const char *language;
+ const char *territory;
+ const char *audience;
+ const char *application;
+ const char *abbreviation;
+ const char *revision;
+ const char *date;
+ const char *category[__LC_LAST];
+};
+
+
+static void
+identification_startup (struct linereader *lr, struct localedef_t *locale,
+ int ignore_content)
+{
+ if (!ignore_content)
+ {
+ locale->categories[LC_IDENTIFICATION].identification =
+ (struct locale_identification_t *)
+ xcalloc (1, sizeof (struct locale_identification_t));
+
+ locale->categories[LC_IDENTIFICATION].identification->category[LC_ALL] =
+ "";
+ }
+
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
+}
+
+
+void
+identification_finish (struct localedef_t *locale, struct charmap_t *charmap)
+{
+ struct locale_identification_t *identification
+ = locale->categories[LC_IDENTIFICATION].identification;
+
+#define TEST_ELEM(cat) \
+ if (identification->cat == NULL) \
+ { \
+ if (verbose) \
+ error (0, 0, _("%s: field `%s' not defined"), \
+ "LC_IDENTIFICATION", #cat); \
+ identification->cat = ""; \
+ }
+
+ TEST_ELEM (title);
+ TEST_ELEM (source);
+ TEST_ELEM (address);
+ TEST_ELEM (contact);
+ TEST_ELEM (email);
+ TEST_ELEM (tel);
+ TEST_ELEM (fax);
+ TEST_ELEM (language);
+ TEST_ELEM (territory);
+ TEST_ELEM (audience);
+ TEST_ELEM (application);
+ TEST_ELEM (abbreviation);
+ TEST_ELEM (revision);
+ TEST_ELEM (date);
+}
+
+
+void
+identification_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
+{
+ struct locale_identification_t *identification
+ = locale->categories[LC_IDENTIFICATION].identification;
+ struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)
+ + (__LC_LAST - 1)];
+ struct locale_file data;
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)];
+ size_t cnt = 0;
+ size_t num;
+
+ data.magic = LIMAGIC (LC_IDENTIFICATION);
+ data.n = _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION);
+ iov[cnt].iov_base = (void *) &data;
+ iov[cnt].iov_len = sizeof (data);
+ ++cnt;
+
+ iov[cnt].iov_base = (void *) idx;
+ iov[cnt].iov_len = sizeof (idx);
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = (void *) identification->title;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->source;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->address;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->contact;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->email;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->tel;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->fax;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->language;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->territory;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->audience;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->application;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->abbreviation;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->revision;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) identification->date;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ for (num = 0; num < __LC_LAST; ++num)
+ {
+ iov[cnt].iov_base = (void *) identification->category[num];
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+ }
+
+ assert (cnt == (2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION)
+ + (__LC_LAST - 1)));
+
+ write_locale_data (output_path, "LC_IDENTIFICATION",
+ 2 + _NL_ITEM_INDEX (_NL_NUM_LC_IDENTIFICATION), iov);
+}
+
+
+/* The parser for the LC_IDENTIFICATION section of the locale definition. */
+void
+identification_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
+{
+ struct repertoire_t *repertoire = NULL;
+ struct locale_identification_t *identification;
+ struct token *now;
+ struct token *arg;
+ struct token *cattok;
+ int category;
+ enum token_t nowtok;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_IDENTIFICATION' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_identification,
+ LC_IDENTIFICATION, "LC_IDENTIFICATION", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ identification_startup (ldfile, result, ignore_content);
+ identification = result->categories[LC_IDENTIFICATION].identification;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+
+ switch (nowtok)
+ {
+#define STR_ELEM(cat) \
+ case tok_##cat: \
+ arg = lr_token (ldfile, charmap, NULL); \
+ if (arg->tok != tok_string) \
+ goto err_label; \
+ if (identification->cat != NULL) \
+ lr_error (ldfile, _("\
+%s: field `%s' declared more than once"), "LC_IDENTIFICATION", #cat); \
+ else if (!ignore_content && arg->val.str.startmb == NULL) \
+ { \
+ lr_error (ldfile, _("\
+%s: unknown character in field `%s'"), "LC_IDENTIFICATION", #cat); \
+ identification->cat = ""; \
+ } \
+ else if (!ignore_content) \
+ identification->cat = arg->val.str.startmb; \
+ break
+
+ STR_ELEM (title);
+ STR_ELEM (source);
+ STR_ELEM (address);
+ STR_ELEM (contact);
+ STR_ELEM (email);
+ STR_ELEM (tel);
+ STR_ELEM (fax);
+ STR_ELEM (language);
+ STR_ELEM (territory);
+ STR_ELEM (audience);
+ STR_ELEM (application);
+ STR_ELEM (abbreviation);
+ STR_ELEM (revision);
+ STR_ELEM (date);
+
+ case tok_category:
+ /* We expect two operands. */
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok != tok_string && arg->tok != tok_ident)
+ goto err_label;
+ /* Next is a semicolon. */
+ cattok = lr_token (ldfile, charmap, NULL);
+ if (cattok->tok != tok_semicolon)
+ goto err_label;
+ /* Now a LC_xxx identifier. */
+ cattok = lr_token (ldfile, charmap, NULL);
+ switch (cattok->tok)
+ {
+#define CATEGORY(lname, uname) \
+ case tok_lc_##lname: \
+ category = LC_##uname; \
+ break
+
+ CATEGORY (identification, IDENTIFICATION);
+ CATEGORY (ctype, CTYPE);
+ CATEGORY (collate, COLLATE);
+ CATEGORY (time, TIME);
+ CATEGORY (numeric, NUMERIC);
+ CATEGORY (monetary, MONETARY);
+ CATEGORY (messages, MESSAGES);
+ CATEGORY (paper, PAPER);
+ CATEGORY (name, NAME);
+ CATEGORY (address, ADDRESS);
+ CATEGORY (telephone, TELEPHONE);
+ CATEGORY (measurement, MEASUREMENT);
+
+ default:
+ goto err_label;
+ }
+ if (identification->category[category] != NULL)
+ {
+ lr_error (ldfile, _("\
+%s: duplicate category version definition"), "LC_IDENTIFICATION");
+ free (arg->val.str.startmb);
+ }
+ else
+ identification->category[category] = arg->val.str.startmb;
+ break;
+
+ case tok_end:
+ /* Next we assume `LC_IDENTIFICATION'. */
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok == tok_eof)
+ break;
+ if (arg->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"),
+ "LC_IDENTIFICATION");
+ else if (arg->tok != tok_lc_identification)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_IDENTIFICATION");
+ lr_ignore_rest (ldfile, arg->tok == tok_lc_identification);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_IDENTIFICATION");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_IDENTIFICATION");
+}
diff --git a/locale/programs/ld-measurement.c b/locale/programs/ld-measurement.c
new file mode 100644
index 0000000000..38a6160b26
--- /dev/null
+++ b/locale/programs/ld-measurement.c
@@ -0,0 +1,206 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <error.h>
+#include <langinfo.h>
+#include <string.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+
+#include "localeinfo.h"
+#include "locfile.h"
+
+
+/* The real definition of the struct for the LC_MEASUREMENT locale. */
+struct locale_measurement_t
+{
+ unsigned char measurement;
+};
+
+
+static void
+measurement_startup (struct linereader *lr, struct localedef_t *locale,
+ int ignore_content)
+{
+ if (!ignore_content)
+ locale->categories[LC_MEASUREMENT].measurement =
+ (struct locale_measurement_t *)
+ xcalloc (1, sizeof (struct locale_measurement_t));
+
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
+}
+
+
+void
+measurement_finish (struct localedef_t *locale, struct charmap_t *charmap)
+{
+ struct locale_measurement_t *measurement =
+ locale->categories[LC_MEASUREMENT].measurement;
+
+ if (measurement->measurement == 0)
+ {
+ error (0, 0, _("%s: field `%s' not defined"),
+ "LC_MEASUREMENT", "measurement");
+ /* Use as the default value the value of the i18n locale. */
+ measurement->measurement = 1;
+ }
+ else
+ {
+ if (measurement->measurement > 3)
+ error (0, 0, _("%s: invalid value for field `%s'"),
+ "LC_MEASUREMENT", "meassurement");
+ }
+}
+
+
+void
+measurement_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
+{
+ struct locale_measurement_t *measurement =
+ locale->categories[LC_MEASUREMENT].measurement;
+ struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT)];
+ struct locale_file data;
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT)];
+ size_t cnt = 0;
+
+ data.magic = LIMAGIC (LC_MEASUREMENT);
+ data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT);
+ iov[cnt].iov_base = (void *) &data;
+ iov[cnt].iov_len = sizeof (data);
+ ++cnt;
+
+ iov[cnt].iov_base = (void *) idx;
+ iov[cnt].iov_len = sizeof (idx);
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = &measurement->measurement;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT));
+
+ write_locale_data (output_path, "LC_MEASUREMENT",
+ 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MEASUREMENT), iov);
+}
+
+
+/* The parser for the LC_MEASUREMENT section of the locale definition. */
+void
+measurement_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
+{
+ struct repertoire_t *repertoire = NULL;
+ struct locale_measurement_t *measurement;
+ struct token *now;
+ struct token *arg;
+ enum token_t nowtok;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_MEASUREMENT' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_measurement,
+ LC_MEASUREMENT, "LC_MEASUREMENT", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ measurement_startup (ldfile, result, ignore_content);
+ measurement = result->categories[LC_MEASUREMENT].measurement;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+
+ switch (nowtok)
+ {
+#define INT_ELEM(cat) \
+ case tok_##cat: \
+ arg = lr_token (ldfile, charmap, NULL); \
+ if (arg->tok != tok_number) \
+ goto err_label; \
+ else if (measurement->cat != 0) \
+ lr_error (ldfile, _("%s: field `%s' declared more than once"), \
+ "LC_MEASUREMENT", #cat); \
+ else if (!ignore_content) \
+ measurement->cat = arg->val.num; \
+ break
+
+ INT_ELEM (measurement);
+
+ case tok_end:
+ /* Next we assume `LC_MEASUREMENT'. */
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok == tok_eof)
+ break;
+ if (arg->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"),
+ "LC_MEASUREMENT");
+ else if (arg->tok != tok_lc_measurement)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_MEASUREMENT");
+ lr_ignore_rest (ldfile, arg->tok == tok_lc_measurement);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_MEASUREMENT");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"),
+ "LC_MEASUREMENT");
+}
diff --git a/locale/programs/ld-messages.c b/locale/programs/ld-messages.c
index 69e411c8d6..33b7735b7d 100644
--- a/locale/programs/ld-messages.c
+++ b/locale/programs/ld-messages.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -21,28 +21,18 @@
# include <config.h>
#endif
-#include <alloca.h>
#include <langinfo.h>
+#include <sys/types.h>
+#include <regex.h>
#include <string.h>
-#include <libintl.h>
#include <sys/uio.h>
-#ifdef HAVE_REGEX
-# include <regex.h>
-#else
-# include <rx.h>
-#endif
-
-/* Undefine following line in production version. */
-/* #define NDEBUG 1 */
#include <assert.h>
-#include "locales.h"
-#include "stringtrans.h"
+#include "linereader.h"
+#include "localedef.h"
#include "localeinfo.h"
-
-
-extern void *xmalloc (size_t __n);
+#include "locfile.h"
/* The real definition of the struct for the LC_MESSAGES locale. */
@@ -55,44 +45,51 @@ struct locale_messages_t
};
-void
+static void
messages_startup (struct linereader *lr, struct localedef_t *locale,
- struct charset_t *charset)
+ int ignore_content)
{
- struct locale_messages_t *messages;
+ if (!ignore_content)
+ locale->categories[LC_MESSAGES].messages =
+ (struct locale_messages_t *) xcalloc (1,
+ sizeof (struct locale_messages_t));
- /* We have a definition for LC_MESSAGES. */
- copy_posix.mask &= ~(1 << LC_MESSAGES);
-
- /* It is important that we always use UCS1 encoding for strings now. */
- encoding_method = ENC_UCS1;
-
- locale->categories[LC_MESSAGES].messages = messages =
- (struct locale_messages_t *) xmalloc (sizeof (struct locale_messages_t));
-
- memset (messages, '\0', sizeof (struct locale_messages_t));
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
}
void
-messages_finish (struct localedef_t *locale)
+messages_finish (struct localedef_t *locale, struct charmap_t *charmap)
{
struct locale_messages_t *messages
= locale->categories[LC_MESSAGES].messages;
/* The fields YESSTR and NOSTR are optional. */
+ if (messages->yesstr == NULL)
+ messages->yesstr = "";
+ if (messages->nostr == NULL)
+ messages->nostr = "";
+
if (messages->yesexpr == NULL)
{
if (!be_quiet)
- error (0, 0, _("field `%s' in category `%s' undefined"),
- "yesexpr", "LC_MESSAGES");
+ error (0, 0, _("%s: field `%s' undefined"), "LC_MESSAGES", "yesexpr");
+ messages->yesexpr = "";
+ }
+ else if (messages->yesexpr[0] == '\0')
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: value for field `%s' must not be an empty string"),
+ "LC_MESSAGES", "yesexpr");
}
else
{
int result;
regex_t re;
- /* Test whether it is a correct regular expression. */
+ /* Test whether it are correct regular expressions. */
result = regcomp (&re, messages->yesexpr, REG_EXTENDED);
if (result != 0 && !be_quiet)
{
@@ -100,23 +97,32 @@ messages_finish (struct localedef_t *locale)
(void) regerror (result, &re, errbuf, BUFSIZ);
error (0, 0, _("\
-no correct regular expression for field `%s' in category `%s': %s"),
- "yesexpr", "LC_MESSAGES", errbuf);
+%s: no correct regular expression for field `%s': %s"),
+ "LC_MESSAGES", "yesexpr", errbuf);
}
+ else if (result != 0)
+ regfree (&re);
}
if (messages->noexpr == NULL)
{
if (!be_quiet)
- error (0, 0, _("field `%s' in category `%s' undefined"),
- "noexpr", "LC_MESSAGES");
+ error (0, 0, _("%s: field `%s' undefined"), "LC_MESSAGES", "noexpr");
+ messages->noexpr = "";
+ }
+ else if (messages->noexpr[0] == '\0')
+ {
+ if (!be_quiet)
+ error (0, 0, _("\
+%s: value for field `%s' must not be an empty string"),
+ "LC_MESSAGES", "noexpr");
}
else
{
int result;
regex_t re;
- /* Test whether it is a correct regular expression. */
+ /* Test whether it are correct regular expressions. */
result = regcomp (&re, messages->noexpr, REG_EXTENDED);
if (result != 0 && !be_quiet)
{
@@ -124,33 +130,26 @@ no correct regular expression for field `%s' in category `%s': %s"),
(void) regerror (result, &re, errbuf, BUFSIZ);
error (0, 0, _("\
-no correct regular expression for field `%s' in category `%s': %s"),
- "noexpr", "LC_MESSAGES", errbuf);
+%s: no correct regular expression for field `%s': %s"),
+ "LC_MESSAGES", "noexpr", errbuf);
}
+ else if (result != 0)
+ regfree (&re);
}
}
void
-messages_output (struct localedef_t *locale, const char *output_path)
+messages_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
{
struct locale_messages_t *messages
= locale->categories[LC_MESSAGES].messages;
struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)];
struct locale_file data;
- u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)];
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)];
size_t cnt = 0;
- if ((locale->binary & (1 << LC_MESSAGES)) != 0)
- {
- iov[0].iov_base = messages;
- iov[0].iov_len = locale->len[LC_MESSAGES];
-
- write_locale_data (output_path, "LC_MESSAGES", 1, iov);
-
- return;
- }
-
data.magic = LIMAGIC (LC_MESSAGES);
data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES);
iov[cnt].iov_base = (void *) &data;
@@ -162,22 +161,22 @@ messages_output (struct localedef_t *locale, const char *output_path)
++cnt;
idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
- iov[cnt].iov_base = (void *) (messages->yesexpr ?: "");
+ iov[cnt].iov_base = (char *) messages->yesexpr;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) (messages->noexpr ?: "");
+ iov[cnt].iov_base = (char *) messages->noexpr;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) (messages->yesstr ?: "");
+ iov[cnt].iov_base = (char *) messages->yesstr;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) (messages->nostr ?: "");
+ iov[cnt].iov_base = (char *) messages->nostr;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES));
@@ -187,61 +186,112 @@ messages_output (struct localedef_t *locale, const char *output_path)
}
+/* The parser for the LC_MESSAGES section of the locale definition. */
void
-messages_add (struct linereader *lr, struct localedef_t *locale,
- enum token_t tok, struct token *code,
- struct charset_t *charset)
+messages_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
{
- struct locale_messages_t *messages
- = locale->categories[LC_MESSAGES].messages;
+ struct repertoire_t *repertoire = NULL;
+ struct locale_messages_t *messages;
+ struct token *now;
+ enum token_t nowtok;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
- switch (tok)
+ /* The rest of the line containing `LC_MESSAGES' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+
+ do
{
- case tok_yesexpr:
- if (code->val.str.start == NULL)
- {
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),
- "yesexpr", "LC_MESSAGES");
- messages->yesexpr = "";
- }
- else
- messages->yesexpr = code->val.str.start;
- break;
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
- case tok_noexpr:
- if (code->val.str.start == NULL)
- {
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),
- "noexpr", "LC_MESSAGES");
- messages->noexpr = "";
- }
- else
- messages->noexpr = code->val.str.start;
- break;
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_messages, LC_MESSAGES,
+ "LC_MESSAGES", ignore_content);
+ return;
+ }
- case tok_yesstr:
- if (code->val.str.start == NULL)
+ /* Prepare the data structures. */
+ messages_startup (ldfile, result, ignore_content);
+ messages = result->categories[LC_MESSAGES].messages;
+
+ while (1)
+ {
+ struct token *arg;
+
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
{
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),
- "yesstr", "LC_MESSAGES");
- messages->yesstr = "";
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
}
- else
- messages->yesstr = code->val.str.start;
- break;
- case tok_nostr:
- if (code->val.str.start == NULL)
+ switch (nowtok)
{
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),
- "nostr", "LC_MESSAGES");
- messages->nostr = "";
+#define STR_ELEM(cat) \
+ case tok_##cat: \
+ if (messages->cat != NULL) \
+ { \
+ lr_error (ldfile, _("\
+%s: field `%s' declared more than once"), "LC_MESSAGES", #cat); \
+ lr_ignore_rest (ldfile, 0); \
+ break; \
+ } \
+ now = lr_token (ldfile, charmap, repertoire); \
+ if (now->tok != tok_string) \
+ goto syntax_error; \
+ else if (!ignore_content && now->val.str.startmb == NULL) \
+ { \
+ lr_error (ldfile, _("\
+%s: unknown character in field `%s'"), "LC_MESSAGES", #cat); \
+ messages->cat = ""; \
+ } \
+ else if (!ignore_content) \
+ messages->cat = now->val.str.startmb; \
+ break
+
+ STR_ELEM (yesexpr);
+ STR_ELEM (noexpr);
+ STR_ELEM (yesstr);
+ STR_ELEM (nostr);
+
+ case tok_end:
+ /* Next we assume `LC_MESSAGES'. */
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok == tok_eof)
+ break;
+ if (arg->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"), "LC_MESSAGES");
+ else if (arg->tok != tok_lc_messages)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_MESSAGES");
+ lr_ignore_rest (ldfile, arg->tok == tok_lc_messages);
+ return;
+
+ default:
+ syntax_error:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_MESSAGES");
}
- else
- messages->nostr = code->val.str.start;
- break;
- default:
- assert (! "unknown token in category `LC_MESSAGES': should not happen");
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
}
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_MESSAGES");
}
diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c
index b903d630aa..61f9f8dc6c 100644
--- a/locale/programs/ld-monetary.c
+++ b/locale/programs/ld-monetary.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -21,26 +21,22 @@
# include <config.h>
#endif
+#include <byteswap.h>
#include <langinfo.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include <libintl.h>
+#include <sys/uio.h>
-
-/* Undefine following line in production version. */
-/* #define NDEBUG 1 */
#include <assert.h>
-#include "locales.h"
+#include "linereader.h"
+#include "localedef.h"
#include "localeinfo.h"
-#include "stringtrans.h"
-
-extern void *xmalloc (size_t __n);
-extern void *xrealloc (void *__ptr, size_t __n);
+#include "locfile.h"
-/* The real definition of the struct for the LC_NUMERIC locale. */
+/* The real definition of the struct for the LC_MONETARY locale. */
struct locale_monetary_t
{
const char *int_curr_symbol;
@@ -48,8 +44,7 @@ struct locale_monetary_t
const char *mon_decimal_point;
const char *mon_thousands_sep;
char *mon_grouping;
- size_t mon_grouping_max;
- size_t mon_grouping_act;
+ size_t mon_grouping_len;
const char *positive_sign;
const char *negative_sign;
signed char int_frac_digits;
@@ -60,10 +55,38 @@ struct locale_monetary_t
signed char n_sep_by_space;
signed char p_sign_posn;
signed char n_sign_posn;
+ signed char int_p_cs_precedes;
+ signed char int_p_sep_by_space;
+ signed char int_n_cs_precedes;
+ signed char int_n_sep_by_space;
+ signed char int_p_sign_posn;
+ signed char int_n_sign_posn;
+ const char *duo_int_curr_symbol;
+ const char *duo_currency_symbol;
+ signed char duo_int_frac_digits;
+ signed char duo_frac_digits;
+ signed char duo_p_cs_precedes;
+ signed char duo_p_sep_by_space;
+ signed char duo_n_cs_precedes;
+ signed char duo_n_sep_by_space;
+ signed char duo_p_sign_posn;
+ signed char duo_n_sign_posn;
+ signed char duo_int_p_cs_precedes;
+ signed char duo_int_p_sep_by_space;
+ signed char duo_int_n_cs_precedes;
+ signed char duo_int_n_sep_by_space;
+ signed char duo_int_p_sign_posn;
+ signed char duo_int_n_sign_posn;
+ uint32_t uno_valid_from;
+ uint32_t uno_valid_to;
+ uint32_t duo_valid_from;
+ uint32_t duo_valid_to;
+ uint32_t conversion_rate[2];
+ uint32_t conversion_rate_ob[2];
};
-/* The contents of the field int_curr_symbol have to be taken from
+/* The content iof the field int_curr_symbol has to be taken from
ISO-4217. We test for correct values. */
#define DEFINE_INT_CURR(str) str,
static const char *const valid_int_curr[] =
@@ -76,52 +99,73 @@ static const char *const valid_int_curr[] =
/* Prototypes for local functions. */
-static int curr_strcmp(const char *s1, const char **s2);
+static int curr_strcmp (const char *s1, const char **s2);
-void
+static void
monetary_startup (struct linereader *lr, struct localedef_t *locale,
- struct charset_t *charset)
+ int ignore_content)
{
- struct locale_monetary_t *monetary;
-
- /* We have a definition for LC_MONETARY. */
- copy_posix.mask &= ~(1 << LC_MONETARY);
-
- /* It is important that we always use UCS1 encoding for strings now. */
- encoding_method = ENC_UCS1;
-
- locale->categories[LC_MONETARY].monetary = monetary =
- (struct locale_monetary_t *) xmalloc (sizeof (struct locale_monetary_t));
-
- memset (monetary, '\0', sizeof (struct locale_monetary_t));
-
- monetary->mon_grouping_max = 80;
- monetary->mon_grouping =
- (char *) xmalloc (monetary->mon_grouping_max);
- monetary->mon_grouping_act = 0;
+ if (!ignore_content)
+ {
+ struct locale_monetary_t *monetary;
+
+ locale->categories[LC_MONETARY].monetary = monetary =
+ (struct locale_monetary_t *) xmalloc (sizeof (*monetary));
+
+ memset (monetary, '\0', sizeof (struct locale_monetary_t));
+
+ monetary->mon_grouping = NULL;
+ monetary->mon_grouping_len = 0;
+
+ monetary->int_frac_digits = -2;
+ monetary->frac_digits = -2;
+ monetary->p_cs_precedes = -2;
+ monetary->p_sep_by_space = -2;
+ monetary->n_cs_precedes = -2;
+ monetary->n_sep_by_space = -2;
+ monetary->p_sign_posn = -2;
+ monetary->n_sign_posn = -2;
+ monetary->int_p_cs_precedes = -2;
+ monetary->int_p_sep_by_space = -2;
+ monetary->int_n_cs_precedes = -2;
+ monetary->int_n_sep_by_space = -2;
+ monetary->int_p_sign_posn = -2;
+ monetary->int_n_sign_posn = -2;
+ monetary->duo_int_frac_digits = -2;
+ monetary->duo_frac_digits = -2;
+ monetary->duo_p_cs_precedes = -2;
+ monetary->duo_p_sep_by_space = -2;
+ monetary->duo_n_cs_precedes = -2;
+ monetary->duo_n_sep_by_space = -2;
+ monetary->duo_p_sign_posn = -2;
+ monetary->duo_n_sign_posn = -2;
+ monetary->duo_int_p_cs_precedes = -2;
+ monetary->duo_int_p_sep_by_space = -2;
+ monetary->duo_int_n_cs_precedes = -2;
+ monetary->duo_int_n_sep_by_space = -2;
+ monetary->duo_int_p_sign_posn = -2;
+ monetary->duo_int_n_sign_posn = -2;
+ }
- monetary->int_frac_digits = -2;
- monetary->frac_digits = -2;
- monetary->p_cs_precedes = -2;
- monetary->p_sep_by_space = -2;
- monetary->n_cs_precedes = -2;
- monetary->n_sep_by_space = -2;
- monetary->p_sign_posn = -2;
- monetary->n_sign_posn = -2;
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
}
void
-monetary_finish (struct localedef_t *locale)
+monetary_finish (struct localedef_t *locale, struct charmap_t *charmap)
{
struct locale_monetary_t *monetary
= locale->categories[LC_MONETARY].monetary;
-#define TEST_ELEM(cat) \
+#define TEST_ELEM(cat) \
if (monetary->cat == NULL && !be_quiet) \
- error (0, 0, _("field `%s' in category `%s' undefined"), \
- #cat, "LC_MONETARY")
+ { \
+ error (0, 0, _("%s: field `%s' not defined"), \
+ "LC_MONETARY", #cat); \
+ monetary->cat = ""; \
+ }
TEST_ELEM (int_curr_symbol);
TEST_ELEM (currency_symbol);
@@ -133,21 +177,21 @@ monetary_finish (struct localedef_t *locale)
/* The international currency symbol must come from ISO 4217. */
if (monetary->int_curr_symbol != NULL)
{
- if (strlen (monetary->int_curr_symbol) != 4
- && monetary->int_curr_symbol[0] != '\0')
+ if (strlen (monetary->int_curr_symbol) != 4)
{
if (!be_quiet)
error (0, 0, _("\
-value of field `int_curr_symbol' in category `LC_MONETARY' has wrong length"));
+%s: value of field `int_curr_symbol' has wrong length"),
+ "LC_MONETARY");
}
- else if (monetary->int_curr_symbol[0] != '\0'
- && bsearch (monetary->int_curr_symbol, valid_int_curr,
- NR_VALID_INT_CURR, sizeof (const char *),
- (comparison_fn_t) curr_strcmp) == NULL
+ else if (bsearch (monetary->int_curr_symbol, valid_int_curr,
+ NR_VALID_INT_CURR, sizeof (const char *),
+ (comparison_fn_t) curr_strcmp) == NULL
&& !be_quiet)
error (0, 0, _("\
-value of field `int_curr_symbol' in category `LC_MONETARY' does \
-not correspond to a valid name in ISO 4217"));
+%s: value of field `int_curr_symbol' does \
+not correspond to a valid name in ISO 4217"),
+ "LC_MONETARY");
}
/* The decimal point must not be empty. This is not said explicitly
@@ -156,27 +200,27 @@ not correspond to a valid name in ISO 4217"));
if (monetary->mon_decimal_point[0] == '\0' && !be_quiet)
{
error (0, 0, _("\
-value for field `%s' in category `%s' must not be the empty string"),
- "mon_decimal_point", "LC_MONETARY");
+%s: value for field `%s' must not be the empty string"),
+ "LC_MONETARY", "mon_decimal_point");
}
- if (monetary->mon_grouping_act == 0 && !be_quiet)
- error (0, 0, _("field `%s' in category `%s' undefined"),
- "mon_grouping", "LC_MONETARY");
+ if (monetary->mon_grouping_len == 0 && !be_quiet)
+ error (0, 0, _("%s: field `%s' not defined"),
+ "LC_MONETARY", "mon_grouping");
#undef TEST_ELEM
-#define TEST_ELEM(cat, min, max) \
+#define TEST_ELEM(cat, min, max) \
if (monetary->cat == -2 && !be_quiet) \
- error (0, 0, _("field `%s' in category `%s' undefined"), \
- #cat, "LC_MONETARY"); \
+ error (0, 0, _("%s: field `%s' not defined"), \
+ "LC_MONETARY", #cat); \
else if ((monetary->cat < min || monetary->cat > max) && !be_quiet) \
error (0, 0, _("\
-value for field `%s' in category `%s' must be in range %d...%d"), \
- #cat, "LC_MONETARY", min, max)
+%s: value for field `%s' must be in range %d...%d"), \
+ "LC_MONETARY", #cat, min, max)
#if 0
- /* The following two tests are not really necessary because all values
- the variable could have are valid. */
+/* The following two test are not really necessary because all values
+ the variable could have are valid. */
TEST_ELEM (int_frac_digits, -128, 127); /* No range check. */
TEST_ELEM (frac_digits, -128, 127); /* No range check. */
#endif
@@ -186,29 +230,78 @@ value for field `%s' in category `%s' must be in range %d...%d"), \
TEST_ELEM (n_sep_by_space, -1, 2);
TEST_ELEM (p_sign_posn, -1, 4);
TEST_ELEM (n_sign_posn, -1, 4);
+
+ /* The non-POSIX.2 extensions are optional. */
+ if (monetary->duo_int_curr_symbol == NULL)
+ monetary->duo_int_curr_symbol = monetary->int_curr_symbol;
+ if (monetary->duo_currency_symbol == NULL)
+ monetary->duo_currency_symbol = monetary->currency_symbol;
+
+ if (monetary->duo_int_frac_digits == -2)
+ monetary->duo_int_frac_digits = monetary->int_frac_digits;
+ if (monetary->duo_frac_digits == -2)
+ monetary->duo_frac_digits = monetary->frac_digits;
+
+#undef TEST_ELEM
+#define TEST_ELEM(cat, alt, min, max) \
+ if (monetary->cat == -2 && !be_quiet) \
+ monetary->cat = monetary->alt; \
+ else if ((monetary->cat < min || monetary->cat > max) && !be_quiet) \
+ error (0, 0, _("\
+%s: value for field `%s' must be in range %d...%d"), \
+ "LC_MONETARY", #cat, min, max)
+
+ TEST_ELEM (int_p_cs_precedes, p_cs_precedes, -1, 1);
+ TEST_ELEM (int_p_sep_by_space, p_sep_by_space, -1, 2);
+ TEST_ELEM (int_n_cs_precedes, n_cs_precedes, -1, 1);
+ TEST_ELEM (int_n_sep_by_space, n_sep_by_space, -1, 2);
+ TEST_ELEM (int_p_sign_posn, p_sign_posn, -1, 4);
+ TEST_ELEM (int_n_sign_posn, n_sign_posn, -1, 4);
+
+ TEST_ELEM (duo_p_cs_precedes, p_cs_precedes, -1, 1);
+ TEST_ELEM (duo_p_sep_by_space, p_sep_by_space, -1, 2);
+ TEST_ELEM (duo_n_cs_precedes, n_cs_precedes, -1, 1);
+ TEST_ELEM (duo_n_sep_by_space, n_sep_by_space, -1, 2);
+ TEST_ELEM (duo_int_p_cs_precedes, int_p_cs_precedes, -1, 1);
+ TEST_ELEM (duo_int_p_sep_by_space, int_p_sep_by_space, -1, 2);
+ TEST_ELEM (duo_int_n_cs_precedes, int_n_cs_precedes, -1, 1);
+ TEST_ELEM (duo_int_n_sep_by_space, int_n_sep_by_space, -1, 2);
+ TEST_ELEM (duo_p_sign_posn, p_sign_posn, -1, 4);
+ TEST_ELEM (duo_n_sign_posn, n_sign_posn, -1, 4);
+ TEST_ELEM (duo_int_p_sign_posn, int_p_sign_posn, -1, 4);
+ TEST_ELEM (duo_int_n_sign_posn, int_n_sign_posn, -1, 4);
+
+ if (monetary->uno_valid_from == 0)
+ monetary->uno_valid_from = 10101;
+ if (monetary->uno_valid_to == 0)
+ monetary->uno_valid_to = 99991231;
+ if (monetary->duo_valid_from == 0)
+ monetary->duo_valid_from = 10101;
+ if (monetary->duo_valid_to == 0)
+ monetary->duo_valid_to = 99991231;
+
+ if (monetary->conversion_rate[0] == 0)
+ {
+ monetary->conversion_rate[0] = 1;
+ monetary->conversion_rate[1] = 1;
+ }
+
+ monetary->conversion_rate_ob[0] = bswap_32 (monetary->conversion_rate[0]);
+ monetary->conversion_rate_ob[1] = bswap_32 (monetary->conversion_rate[1]);
}
void
-monetary_output (struct localedef_t *locale, const char *output_path)
+monetary_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
{
struct locale_monetary_t *monetary
= locale->categories[LC_MONETARY].monetary;
struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
struct locale_file data;
- u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
size_t cnt = 0;
- if ((locale->binary & (1 << LC_MONETARY)) != 0)
- {
- iov[0].iov_base = monetary;
- iov[0].iov_len = locale->len[LC_MONETARY];
-
- write_locale_data (output_path, "LC_MONETARY", 1, iov);
-
- return;
- }
-
data.magic = LIMAGIC (LC_MONETARY);
data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY);
iov[cnt].iov_base = (void *) &data;
@@ -220,40 +313,37 @@ monetary_output (struct localedef_t *locale, const char *output_path)
++cnt;
idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
- iov[cnt].iov_base = (void *) (monetary->int_curr_symbol ?: "");
+ iov[cnt].iov_base = (void *) monetary->int_curr_symbol;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) (monetary->currency_symbol ?: "");
+ iov[cnt].iov_base = (void *) monetary->currency_symbol;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) (monetary->mon_decimal_point ?: "");
+ iov[cnt].iov_base = (void *) monetary->mon_decimal_point;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) (monetary->mon_thousands_sep ?: "");
+ iov[cnt].iov_base = (void *) monetary->mon_thousands_sep;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = alloca (monetary->mon_grouping_act + 1);
- iov[cnt].iov_len = monetary->mon_grouping_act + 1;
- memcpy (iov[cnt].iov_base, monetary->mon_grouping,
- monetary->mon_grouping_act);
- ((char *) iov[cnt].iov_base)[monetary->mon_grouping_act] = '\0';
+ iov[cnt].iov_base = monetary->mon_grouping;
+ iov[cnt].iov_len = monetary->mon_grouping_len;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) (monetary->positive_sign ?: "");
+ iov[cnt].iov_base = (void *) monetary->positive_sign;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = (void *) (monetary->negative_sign ?: "");
+ iov[cnt].iov_base = (void *) monetary->negative_sign;
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
@@ -295,109 +385,422 @@ monetary_output (struct localedef_t *locale, const char *output_path)
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->n_sign_posn;
iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->int_p_cs_precedes;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->int_p_sep_by_space;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->int_n_cs_precedes;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->int_n_sep_by_space;
+ iov[cnt].iov_len = 1;
+ ++cnt;
- assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->int_p_sign_posn;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->int_n_sign_posn;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = (void *) monetary->duo_int_curr_symbol;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) monetary->duo_currency_symbol;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_int_frac_digits;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_frac_digits;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_p_cs_precedes;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_p_sep_by_space;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_n_cs_precedes;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_n_sep_by_space;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_int_p_cs_precedes;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_int_p_sep_by_space;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_int_n_cs_precedes;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_int_n_sep_by_space;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_p_sign_posn;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_n_sign_posn;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_int_p_sign_posn;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_int_n_sign_posn;
+ iov[cnt].iov_len = 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->uno_valid_from;
+ iov[cnt].iov_len = 4;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->uno_valid_to;
+ iov[cnt].iov_len = 4;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_valid_from;
+ iov[cnt].iov_len = 4;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->duo_valid_to;
+ iov[cnt].iov_len = 4;
+ ++cnt;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define conversion_rate_el conversion_rate
+# define conversion_rate_eb conversion_rate_ob
+#else
+# define conversion_rate_el conversion_rate_ob
+# define conversion_rate_eb conversion_rate
+#endif
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->conversion_rate_el;
+ iov[cnt].iov_len = 8;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) &monetary->conversion_rate_eb;
+ iov[cnt].iov_len = 8;
+ ++cnt;
+
+ assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
write_locale_data (output_path, "LC_MONETARY",
2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY), iov);
}
+static int
+curr_strcmp (const char *s1, const char **s2)
+{
+ return strcmp (s1, *s2);
+}
+
+
+/* The parser for the LC_MONETARY section of the locale definition. */
void
-monetary_add (struct linereader *lr, struct localedef_t *locale,
- enum token_t tok, struct token *code,
- struct charset_t *charset)
+monetary_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
{
- struct locale_monetary_t *monetary
- = locale->categories[LC_MONETARY].monetary;
+ struct repertoire_t *repertoire = NULL;
+ struct locale_monetary_t *monetary;
+ struct token *now;
+ enum token_t nowtok;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_MONETARY' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_monetary, LC_MONETARY,
+ "LC_MONETARY", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ monetary_startup (ldfile, result, ignore_content);
+ monetary = result->categories[LC_MONETARY].monetary;
- switch (tok)
+ while (1)
{
-#define STR_ELEM(cat) \
- case tok_##cat: \
- if (monetary->cat != NULL) \
- lr_error (lr, _("\
-field `%s' in category `%s' declared more than once"), \
- #cat, "LC_MONETARY"); \
- else if (code->val.str.start == NULL) \
- { \
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
- #cat, "LC_MONETARY"); \
- monetary->cat = ""; \
- } \
- else \
- monetary->cat = code->val.str.start; \
- break
-
- STR_ELEM (int_curr_symbol);
- STR_ELEM (currency_symbol);
- STR_ELEM (mon_decimal_point);
- STR_ELEM (mon_thousands_sep);
- STR_ELEM (positive_sign);
- STR_ELEM (negative_sign);
-
-#define INT_ELEM(cat) \
- case tok_##cat: \
- if (monetary->cat != -2) \
- lr_error (lr, _("\
-field `%s' in category `%s' declared more than once"), \
- #cat, "LC_MONETARY"); \
- else if (code->tok == tok_minus1) \
- monetary->cat = -1; \
- else \
- monetary->cat = code->val.num; \
- break
-
- INT_ELEM (int_frac_digits);
- INT_ELEM (frac_digits);
- INT_ELEM (p_cs_precedes);
- INT_ELEM (p_sep_by_space);
- INT_ELEM (n_cs_precedes);
- INT_ELEM (n_sep_by_space);
- INT_ELEM (p_sign_posn);
- INT_ELEM (n_sign_posn);
-
- case tok_mon_grouping:
- if (monetary->mon_grouping_act == monetary->mon_grouping_max)
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
{
- monetary->mon_grouping_max *= 2;
- monetary->mon_grouping =
- (char *) xrealloc (monetary->mon_grouping,
- monetary->mon_grouping_max);
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
}
- if (monetary->mon_grouping[monetary->mon_grouping_act - 1]
- == '\177')
- lr_error (lr, _("\
-`-1' must be last entry in `%s' field in `%s' category"),
- "mon_grouping", "LC_MONETARY");
- else
+
+ switch (nowtok)
{
- if (code->tok == tok_minus1)
- monetary->mon_grouping[monetary->mon_grouping_act++] = '\177';
- else if (code->val.num == 0)
- /* A value of 0 disables grouping from here on but we must
- not store a NUL character since this terminates the
- string. Use something different which must not be used
- otherwise. */
- monetary->mon_grouping[monetary->mon_grouping_act++] = '\377';
- else if (code->val.num > 126)
- lr_error (lr, _("\
-values for field `%s' in category `%s' must be smaller than 127"),
- "mon_grouping", "LC_MONETARY");
+#define STR_ELEM(cat) \
+ case tok_##cat: \
+ now = lr_token (ldfile, charmap, NULL); \
+ if (now->tok != tok_string) \
+ goto err_label; \
+ else if (monetary->cat != NULL) \
+ lr_error (ldfile, _("%s: field `%s' declared more than once"), \
+ "LC_MONETARY", #cat); \
+ else if (!ignore_content && now->val.str.startmb == NULL) \
+ { \
+ lr_error (ldfile, _("\
+%s: unknown character in field `%s'"), "LC_MONETARY", #cat); \
+ monetary->cat = ""; \
+ } \
+ else if (!ignore_content) \
+ monetary->cat = now->val.str.startmb; \
+ lr_ignore_rest (ldfile, 1); \
+ break
+
+ STR_ELEM (int_curr_symbol);
+ STR_ELEM (currency_symbol);
+ STR_ELEM (mon_decimal_point);
+ STR_ELEM (mon_thousands_sep);
+ STR_ELEM (positive_sign);
+ STR_ELEM (negative_sign);
+ STR_ELEM (duo_int_curr_symbol);
+ STR_ELEM (duo_currency_symbol);
+
+#define INT_ELEM(cat) \
+ case tok_##cat: \
+ now = lr_token (ldfile, charmap, NULL); \
+ if (now->tok != tok_minus1 && now->tok != tok_number) \
+ goto err_label; \
+ else if (monetary->cat != -2) \
+ lr_error (ldfile, _("%s: field `%s' declared more than once"), \
+ "LC_MONETARY", #cat); \
+ else if (!ignore_content) \
+ monetary->cat = now->tok == tok_minus1 ? -1 : now->val.num; \
+ break
+
+ INT_ELEM (int_frac_digits);
+ INT_ELEM (frac_digits);
+ INT_ELEM (p_cs_precedes);
+ INT_ELEM (p_sep_by_space);
+ INT_ELEM (n_cs_precedes);
+ INT_ELEM (n_sep_by_space);
+ INT_ELEM (p_sign_posn);
+ INT_ELEM (n_sign_posn);
+ INT_ELEM (int_p_cs_precedes);
+ INT_ELEM (int_p_sep_by_space);
+ INT_ELEM (int_n_cs_precedes);
+ INT_ELEM (int_n_sep_by_space);
+ INT_ELEM (int_p_sign_posn);
+ INT_ELEM (int_n_sign_posn);
+ INT_ELEM (duo_int_frac_digits);
+ INT_ELEM (duo_frac_digits);
+ INT_ELEM (duo_p_cs_precedes);
+ INT_ELEM (duo_p_sep_by_space);
+ INT_ELEM (duo_n_cs_precedes);
+ INT_ELEM (duo_n_sep_by_space);
+ INT_ELEM (duo_p_sign_posn);
+ INT_ELEM (duo_n_sign_posn);
+ INT_ELEM (duo_int_p_cs_precedes);
+ INT_ELEM (duo_int_p_sep_by_space);
+ INT_ELEM (duo_int_n_cs_precedes);
+ INT_ELEM (duo_int_n_sep_by_space);
+ INT_ELEM (duo_int_p_sign_posn);
+ INT_ELEM (duo_int_n_sign_posn);
+ INT_ELEM (uno_valid_from);
+ INT_ELEM (uno_valid_to);
+ INT_ELEM (duo_valid_from);
+ INT_ELEM (duo_valid_to);
+
+ case tok_mon_grouping:
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_minus1 && now->tok != tok_number)
+ goto err_label;
else
- monetary->mon_grouping[monetary->mon_grouping_act++]
- = code->val.num;
+ {
+ size_t act = 0;
+ size_t max = 10;
+ char *grouping = ignore_content ? NULL : xmalloc (max);
+
+ do
+ {
+ if (act + 1 >= max)
+ {
+ max *= 2;
+ grouping = xrealloc (grouping, max);
+ }
+
+ if (act > 0 && grouping[act - 1] == '\177')
+ {
+ lr_error (ldfile, _("\
+%s: `-1' must be last entry in `%s' field"),
+ "LC_MONETARY", "mon_grouping");
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+
+ if (now->tok == tok_minus1)
+ {
+ if (!ignore_content)
+ grouping[act++] = '\177';
+ }
+ else if (now->val.num == 0)
+ {
+ /* A value of 0 disables grouping from here on but
+ we must not store a NUL character since this
+ terminates the string. Use something different
+ which must not be used otherwise. */
+ if (!ignore_content)
+ grouping[act++] = '\377';
+ }
+ else if (now->val.num > 126)
+ lr_error (ldfile, _("\
+%s: values for field `%s' must be smaller than 127"),
+ "LC_MONETARY", "mon_grouping");
+ else if (!ignore_content)
+ grouping[act++] = now->val.num;
+
+ /* Next must be semicolon. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_semicolon)
+ break;
+
+ now = lr_token (ldfile, charmap, NULL);
+ }
+ while (now->tok == tok_minus1 || now->tok == tok_number);
+
+ if (now->tok != tok_eol)
+ goto err_label;
+
+ if (!ignore_content)
+ {
+ grouping[act++] = '\0';
+
+ monetary->mon_grouping = xrealloc (grouping, act);
+ monetary->mon_grouping_len = act;
+ }
+ }
+ break;
+
+ case tok_conversion_rate:
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_number)
+ goto err_label;
+ if (now->val.num == 0)
+ {
+ invalid_conversion_rate:
+ lr_error (ldfile, _("conversion rate valze cannot be zero"));
+ if (!ignore_content)
+ {
+ monetary->conversion_rate[0] = 1;
+ monetary->conversion_rate[1] = 1;
+ }
+ break;
+ }
+ if (!ignore_content)
+ monetary->conversion_rate[0] = now->val.num;
+ /* Next must be a semicolon. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_semicolon)
+ goto err_label;
+ /* And another number. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_number)
+ goto err_label;
+ if (now->val.num == 0)
+ goto invalid_conversion_rate;
+ if (!ignore_content)
+ monetary->conversion_rate[1] = now->val.num;
+ /* The rest of the line must be empty. */
+ lr_ignore_rest (ldfile, 1);
+ break;
+
+ case tok_end:
+ /* Next we assume `LC_MONETARY'. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_eof)
+ break;
+ if (now->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"), "LC_MONETARY");
+ else if (now->tok != tok_lc_monetary)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_MONETARY");
+ lr_ignore_rest (ldfile, now->tok == tok_lc_monetary);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_MONETARY");
}
- break;
- default:
- assert (! "unknown token in category `LC_MONETARY': should not happen");
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
}
-}
-
-static int
-curr_strcmp(const char *s1, const char **s2)
-{
- return strcmp (s1, *s2);
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_MONETARY");
}
diff --git a/locale/programs/ld-name.c b/locale/programs/ld-name.c
new file mode 100644
index 0000000000..85acb413ec
--- /dev/null
+++ b/locale/programs/ld-name.c
@@ -0,0 +1,276 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <langinfo.h>
+#include <string.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+
+#include "localeinfo.h"
+#include "locfile.h"
+
+
+/* The real definition of the struct for the LC_NAME locale. */
+struct locale_name_t
+{
+ const char *name_fmt;
+ const char *name_gen;
+ const char *name_mr;
+ const char *name_mrs;
+ const char *name_miss;
+ const char *name_ms;
+};
+
+
+static void
+name_startup (struct linereader *lr, struct localedef_t *locale,
+ int ignore_content)
+{
+ if (!ignore_content)
+ locale->categories[LC_NAME].name =
+ (struct locale_name_t *) xcalloc (1, sizeof (struct locale_name_t));
+
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
+}
+
+
+void
+name_finish (struct localedef_t *locale, struct charmap_t *charmap)
+{
+ struct locale_name_t *name = locale->categories[LC_NAME].name;
+
+ if (name->name_fmt == NULL)
+ {
+ error (0, 0, _("%s: field `%s' not defined"), "LC_NAME", "name_fmt");
+ /* Use as the default value the value of the i18n locale. */
+ name->name_fmt = "%p%t%g%t%m%t%f";
+ }
+ else
+ {
+ /* We must check whether the format string contains only the
+ allowed escape sequences. */
+ const char *cp = name->name_fmt;
+
+ if (*cp == '\0')
+ error (0, 0, _("%s: field `%s' must not be empty"),
+ "LC_NAME", "name_fmt");
+ else
+ while (*cp != '\0')
+ {
+ if (*cp == '%')
+ {
+ if (*++cp == 'R')
+ /* Romanize-flag. */
+ ++cp;
+ if (strchr ("fFgGlomMpsSt", *cp) == NULL)
+ {
+ error (0, 0, _("\
+%s: invalid escape sequence in field `%s'"),
+ "LC_NAME", "name_fmt");
+ break;
+ }
+ }
+ ++cp;
+ }
+ }
+
+#define TEST_ELEM(cat) \
+ if (name->cat == NULL) \
+ { \
+ if (verbose) \
+ error (0, 0, _("%s: field `%s' not defined"), "LC_NAME", #cat); \
+ name->cat = ""; \
+ }
+
+ TEST_ELEM (name_gen);
+ TEST_ELEM (name_mr);
+ TEST_ELEM (name_mrs);
+ TEST_ELEM (name_miss);
+ TEST_ELEM (name_ms);
+}
+
+
+void
+name_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
+{
+ struct locale_name_t *name = locale->categories[LC_NAME].name;
+ struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_NAME)];
+ struct locale_file data;
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_NAME)];
+ size_t cnt = 0;
+
+ data.magic = LIMAGIC (LC_NAME);
+ data.n = _NL_ITEM_INDEX (_NL_NUM_LC_NAME);
+ iov[cnt].iov_base = (void *) &data;
+ iov[cnt].iov_len = sizeof (data);
+ ++cnt;
+
+ iov[cnt].iov_base = (void *) idx;
+ iov[cnt].iov_len = sizeof (idx);
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = (void *) name->name_fmt;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) name->name_gen;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) name->name_mr;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) name->name_mrs;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) name->name_miss;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) name->name_ms;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NAME));
+
+ write_locale_data (output_path, "LC_NAME",
+ 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NAME), iov);
+}
+
+
+/* The parser for the LC_NAME section of the locale definition. */
+void
+name_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
+{
+ struct repertoire_t *repertoire = NULL;
+ struct locale_name_t *name;
+ struct token *now;
+ struct token *arg;
+ enum token_t nowtok;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_NAME' must be empty. */
+ lr_ignore_rest (ldfile, 1);
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_name, LC_NAME,
+ "LC_NAME", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ name_startup (ldfile, result, ignore_content);
+ name = result->categories[LC_NAME].name;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+
+ switch (nowtok)
+ {
+#define STR_ELEM(cat) \
+ case tok_##cat: \
+ arg = lr_token (ldfile, charmap, NULL); \
+ if (arg->tok != tok_string) \
+ goto err_label; \
+ if (name->cat != NULL) \
+ lr_error (ldfile, _("%s: field `%s' declared more than once"), \
+ "LC_NAME", #cat); \
+ else if (!ignore_content && arg->val.str.startmb == NULL) \
+ { \
+ lr_error (ldfile, _("%s: unknown character in field `%s'"), \
+ "LC_NAME", #cat); \
+ name->cat = ""; \
+ } \
+ else if (!ignore_content) \
+ name->cat = arg->val.str.startmb; \
+ break
+
+ STR_ELEM (name_fmt);
+ STR_ELEM (name_gen);
+ STR_ELEM (name_mr);
+ STR_ELEM (name_mrs);
+ STR_ELEM (name_miss);
+ STR_ELEM (name_ms);
+
+ case tok_end:
+ /* Next we assume `LC_NAME'. */
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok == tok_eof)
+ break;
+ if (arg->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"), "LC_NAME");
+ else if (arg->tok != tok_lc_name)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_NAME");
+ lr_ignore_rest (ldfile, arg->tok == tok_lc_name);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_NAME");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_NAME");
+}
diff --git a/locale/programs/ld-numeric.c b/locale/programs/ld-numeric.c
index 0e61481c73..3e51aba7e2 100644
--- a/locale/programs/ld-numeric.c
+++ b/locale/programs/ld-numeric.c
@@ -1,6 +1,6 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -21,21 +21,16 @@
# include <config.h>
#endif
-#include <alloca.h>
#include <langinfo.h>
#include <string.h>
-#include <libintl.h>
+#include <sys/uio.h>
-/* Undefine following line in production version. */
-/* #define NDEBUG 1 */
#include <assert.h>
-#include "locales.h"
+#include "linereader.h"
+#include "localedef.h"
#include "localeinfo.h"
-#include "stringtrans.h"
-
-void *xmalloc (size_t __n);
-void *xrealloc (void *__ptr, size_t __n);
+#include "locfile.h"
/* The real definition of the struct for the LC_NUMERIC locale. */
@@ -44,43 +39,38 @@ struct locale_numeric_t
const char *decimal_point;
const char *thousands_sep;
char *grouping;
- size_t grouping_max;
- size_t grouping_act;
+ size_t grouping_len;
};
-void
+static void
numeric_startup (struct linereader *lr, struct localedef_t *locale,
- struct charset_t *charset)
+ int ignore_content)
{
- struct locale_numeric_t *numeric;
-
- /* We have a definition for LC_NUMERIC. */
- copy_posix.mask &= ~(1 << LC_NUMERIC);
-
- /* It is important that we always use UCS1 encoding for strings now. */
- encoding_method = ENC_UCS1;
+ if (!ignore_content)
+ {
+ struct locale_numeric_t *numeric;
- locale->categories[LC_NUMERIC].numeric = numeric =
- (struct locale_numeric_t *) xmalloc (sizeof (struct locale_numeric_t));
+ locale->categories[LC_NUMERIC].numeric = numeric =
+ (struct locale_numeric_t *) xcalloc (1, sizeof (*numeric));
- memset (numeric, '\0', sizeof (struct locale_numeric_t));
+ numeric->grouping = NULL;
+ numeric->grouping_len = 0;
+ }
- numeric->grouping_max = 80;
- numeric->grouping = (char *) xmalloc (numeric->grouping_max);
- numeric->grouping_act = 0;
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
}
void
-numeric_finish (struct localedef_t *locale)
+numeric_finish (struct localedef_t *locale, struct charmap_t *charmap)
{
struct locale_numeric_t *numeric = locale->categories[LC_NUMERIC].numeric;
#define TEST_ELEM(cat) \
if (numeric->cat == NULL && !be_quiet) \
- error (0, 0, _("field `%s' in category `%s' undefined"), \
- #cat, "LC_NUMERIC")
+ error (0, 0, _("%s: field `%s' not defined"), "LC_NUMERIC", #cat)
TEST_ELEM (decimal_point);
TEST_ELEM (thousands_sep);
@@ -91,35 +81,25 @@ numeric_finish (struct localedef_t *locale)
if (numeric->decimal_point[0] == '\0' && !be_quiet)
{
error (0, 0, _("\
-value for field `%s' in category `%s' must not be the empty string"),
- "decimal_point", "LC_NUMERIC");
+%s: value for field `%s' must not be the empty string"),
+ "LC_NUMERIC", "decimal_point");
}
- if (numeric->grouping_act == 0 && !be_quiet)
- error (0, 0, _("field `%s' in category `%s' undefined"),
- "grouping", "LC_NUMERIC");
+ if (numeric->grouping_len == 0 && !be_quiet)
+ error (0, 0, _("%s: field `%s' not defined"), "LC_NUMERIC", "grouping");
}
void
-numeric_output (struct localedef_t *locale, const char *output_path)
+numeric_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
{
struct locale_numeric_t *numeric = locale->categories[LC_NUMERIC].numeric;
struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)];
struct locale_file data;
- u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)];
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)];
size_t cnt = 0;
- if ((locale->binary & (1 << LC_NUMERIC)) != 0)
- {
- iov[0].iov_base = numeric;
- iov[0].iov_len = locale->len[LC_NUMERIC];
-
- write_locale_data (output_path, "LC_NUMERIC", 1, iov);
-
- return;
- }
-
data.magic = LIMAGIC (LC_NUMERIC);
data.n = _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC);
iov[cnt].iov_base = (void *) &data;
@@ -141,10 +121,8 @@ numeric_output (struct localedef_t *locale, const char *output_path)
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
- iov[cnt].iov_base = alloca (numeric->grouping_act + 1);
- iov[cnt].iov_len = numeric->grouping_act + 1;
- memcpy (iov[cnt].iov_base, numeric->grouping, numeric->grouping_act);
- ((char *) iov[cnt].iov_base)[numeric->grouping_act] = '\0';
+ iov[cnt].iov_base = numeric->grouping;
+ iov[cnt].iov_len = numeric->grouping_len;
assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC));
@@ -153,66 +131,173 @@ numeric_output (struct localedef_t *locale, const char *output_path)
}
+/* The parser for the LC_NUMERIC section of the locale definition. */
void
-numeric_add (struct linereader *lr, struct localedef_t *locale,
- enum token_t tok, struct token *code,
- struct charset_t *charset)
+numeric_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
{
- struct locale_numeric_t *numeric = locale->categories[LC_NUMERIC].numeric;
+ struct repertoire_t *repertoire = NULL;
+ struct locale_numeric_t *numeric;
+ struct token *now;
+ enum token_t nowtok;
- switch (tok)
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_NUMERIC' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_numeric, LC_NUMERIC,
+ "LC_NUMERIC", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ numeric_startup (ldfile, result, ignore_content);
+ numeric = result->categories[LC_NUMERIC].numeric;
+
+ while (1)
{
-#define STR_ELEM(cat) \
- case tok_##cat: \
- if (numeric->cat != NULL) \
- lr_error (lr, _("\
-field `%s' in category `%s' declared more than once"), \
- #cat, "LC_NUMERIC"); \
- else if (code->val.str.start == NULL) \
- { \
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
- #cat, "LC_NUMERIC"); \
- numeric->cat = ""; \
- } \
- else \
- numeric->cat = code->val.str.start; \
- break
-
- STR_ELEM (decimal_point);
- STR_ELEM (thousands_sep);
-
- case tok_grouping:
- if (numeric->grouping_act == numeric->grouping_max)
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
{
- numeric->grouping_max *= 2;
- numeric->grouping = (char *) xrealloc (numeric->grouping,
- numeric->grouping_max);
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
}
- if (numeric->grouping_act > 0
- && (numeric->grouping[numeric->grouping_act - 1] == '\177'))
+
+ switch (nowtok)
{
- lr_error (lr, _("\
-`-1' must be last entry in `%s' field in `%s' category"),
- "grouping", "LC_NUMERIC");
- --numeric->grouping_act;
+#define STR_ELEM(cat) \
+ case tok_##cat: \
+ now = lr_token (ldfile, charmap, NULL); \
+ if (now->tok != tok_string) \
+ goto err_label; \
+ if (numeric->cat != NULL) \
+ lr_error (ldfile, _("\
+%s: field `%s' declared more than once"), "LC_NUMERIC", #cat); \
+ else if (!ignore_content && now->val.str.startmb == NULL) \
+ { \
+ lr_error (ldfile, _("\
+%s: unknown character in field `%s'"), "LC_NUMERIC", #cat); \
+ numeric->cat = ""; \
+ } \
+ else if (!ignore_content) \
+ numeric->cat = now->val.str.startmb; \
+ break
+
+ STR_ELEM (decimal_point);
+ STR_ELEM (thousands_sep);
+
+ case tok_grouping:
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_minus1 && now->tok != tok_number)
+ goto err_label;
+ else
+ {
+ size_t act = 0;
+ size_t max = 10;
+ char *grouping = ignore_content ? NULL : xmalloc (max);
+
+ do
+ {
+ if (act + 1 >= max)
+ {
+ max *= 2;
+ grouping = xrealloc (grouping, max);
+ }
+
+ if (act > 0 && grouping[act - 1] == '\177')
+ {
+ lr_error (ldfile, _("\
+%s: `-1' must be last entry in `%s' field"), "LC_NUMERIC", "grouping");
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+
+ if (now->tok == tok_minus1)
+ {
+ if (!ignore_content)
+ grouping[act++] = '\177';
+ }
+ else if (now->val.num == 0)
+ {
+ /* A value of 0 disables grouping from here on but
+ we must not store a NUL character since this
+ terminates the string. Use something different
+ which must not be used otherwise. */
+ if (!ignore_content)
+ grouping[act++] = '\377';
+ }
+ else if (now->val.num > 126)
+ lr_error (ldfile, _("\
+%s: values for field `%s' must be smaller than 127"),
+ "LC_NUMERIC", "grouping");
+ else if (!ignore_content)
+ grouping[act++] = now->val.num;
+
+ /* Next must be semicolon. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_semicolon)
+ break;
+
+ now = lr_token (ldfile, charmap, NULL);
+ }
+ while (now->tok == tok_minus1 || now->tok == tok_number);
+
+ if (now->tok != tok_eol)
+ goto err_label;
+
+ if (!ignore_content)
+ {
+ grouping[act++] = '\0';
+
+ numeric->grouping = xrealloc (grouping, act);
+ numeric->grouping_len = act;
+ }
+ }
+ break;
+
+ case tok_end:
+ /* Next we assume `LC_NUMERIC'. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_eof)
+ break;
+ if (now->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"), "LC_NUMERIC");
+ else if (now->tok != tok_lc_numeric)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_NUMERIC");
+ lr_ignore_rest (ldfile, now->tok == tok_lc_numeric);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_NUMERIC");
}
- if (code->tok == tok_minus1)
- numeric->grouping[numeric->grouping_act++] = '\177';
- else if (code->val.num == 0)
- /* A value of 0 disables grouping from here on but we must
- not store a NUL character since this terminates the string.
- Use something different which must not be used otherwise. */
- numeric->grouping[numeric->grouping_act++] = '\377';
- else if (code->val.num > 126)
- lr_error (lr, _("\
-values for field `%s' in category `%s' must be smaller than 127"),
- "grouping", "LC_NUMERIC");
- else
- numeric->grouping[numeric->grouping_act++] = code->val.num;
- break;
-
- default:
- assert (! "unknown token in category `LC_NUMERIC': should not happen");
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
}
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_NUMERIC");
}
diff --git a/locale/programs/ld-paper.c b/locale/programs/ld-paper.c
new file mode 100644
index 0000000000..5d834eb1bd
--- /dev/null
+++ b/locale/programs/ld-paper.c
@@ -0,0 +1,235 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <byteswap.h>
+#include <error.h>
+#include <langinfo.h>
+#include <string.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+
+#include "localeinfo.h"
+#include "locfile.h"
+
+
+/* The real definition of the struct for the LC_PAPER locale. */
+struct locale_paper_t
+{
+ uint32_t height;
+ uint32_t height_ob;
+ uint32_t width;
+ uint32_t width_ob;
+};
+
+
+static void
+paper_startup (struct linereader *lr, struct localedef_t *locale,
+ int ignore_content)
+{
+ if (!ignore_content)
+ locale->categories[LC_PAPER].paper =
+ (struct locale_paper_t *) xcalloc (1, sizeof (struct locale_paper_t));
+
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
+}
+
+
+void
+paper_finish (struct localedef_t *locale, struct charmap_t *charmap)
+{
+ struct locale_paper_t *paper = locale->categories[LC_PAPER].paper;
+
+ if (paper->height == 0)
+ {
+ error (0, 0, _("%s: field `%s' not defined"), "LC_PAPER", "height");
+ /* Use as default values the values from the i18n locale. */
+ paper->height = 297;
+ }
+ paper->height_ob = bswap_32 (paper->height);
+
+ if (paper->width == 0)
+ {
+ error (0, 0, _("%s: field `%s' not defined"), "LC_PAPER", "width");
+ /* Use as default values the values from the i18n locale. */
+ paper->width = 210;
+ }
+ paper->width_ob = bswap_32 (paper->width);
+}
+
+
+void
+paper_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
+{
+ struct locale_paper_t *paper = locale->categories[LC_PAPER].paper;
+ struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_PAPER)];
+ struct locale_file data;
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_PAPER)];
+ size_t cnt = 0;
+
+ data.magic = LIMAGIC (LC_PAPER);
+ data.n = _NL_ITEM_INDEX (_NL_NUM_LC_PAPER);
+ iov[cnt].iov_base = (void *) &data;
+ iov[cnt].iov_len = sizeof (data);
+ ++cnt;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define height_eb height_ob
+# define height_el height
+# define width_eb width_ob
+# define width_el width
+#else
+# define height_eb height
+# define height_el height_ob
+# define width_eb width
+# define width_el width_ob
+#endif
+
+ iov[cnt].iov_base = (void *) idx;
+ iov[cnt].iov_len = sizeof (idx);
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = &paper->height_eb;
+ iov[cnt].iov_len = 4;
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = &paper->height_el;
+ iov[cnt].iov_len = 4;
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = &paper->width_eb;
+ iov[cnt].iov_len = 4;
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = &paper->width_el;
+ iov[cnt].iov_len = 4;
+ ++cnt;
+
+ assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_PAPER));
+
+ write_locale_data (output_path, "LC_PAPER",
+ 2 + _NL_ITEM_INDEX (_NL_NUM_LC_PAPER), iov);
+}
+
+
+/* The parser for the LC_PAPER section of the locale definition. */
+void
+paper_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
+{
+ struct repertoire_t *repertoire = NULL;
+ struct locale_paper_t *paper;
+ struct token *now;
+ struct token *arg;
+ enum token_t nowtok;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_PAPER' must be empty. */
+ lr_ignore_rest (ldfile, 1);
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_paper, LC_PAPER,
+ "LC_PAPER", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ paper_startup (ldfile, result, ignore_content);
+ paper = result->categories[LC_PAPER].paper;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+
+ switch (nowtok)
+ {
+#define INT_ELEM(cat) \
+ case tok_##cat: \
+ arg = lr_token (ldfile, charmap, NULL); \
+ if (arg->tok != tok_number) \
+ goto err_label; \
+ else if (paper->cat != 0) \
+ lr_error (ldfile, _("%s: field `%s' declared more than once"), \
+ "LC_PAPER", #cat); \
+ else if (!ignore_content) \
+ paper->cat = arg->val.num; \
+ break
+
+ INT_ELEM (height);
+ INT_ELEM (width);
+
+ case tok_end:
+ /* Next we assume `LC_PAPER'. */
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok == tok_eof)
+ break;
+ if (arg->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"), "LC_PAPER");
+ else if (arg->tok != tok_lc_paper)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_PAPER");
+ lr_ignore_rest (ldfile, arg->tok == tok_lc_paper);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_PAPER");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_PAPER");
+}
diff --git a/locale/programs/ld-telephone.c b/locale/programs/ld-telephone.c
new file mode 100644
index 0000000000..2d75fea6b6
--- /dev/null
+++ b/locale/programs/ld-telephone.c
@@ -0,0 +1,283 @@
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <error.h>
+#include <langinfo.h>
+#include <string.h>
+#include <sys/uio.h>
+
+#include <assert.h>
+
+#include "localeinfo.h"
+#include "locfile.h"
+
+
+/* The real definition of the struct for the LC_TELEPHONE locale. */
+struct locale_telephone_t
+{
+ const char *tel_int_fmt;
+ const char *tel_dom_fmt;
+ const char *int_select;
+ const char *int_prefix;
+};
+
+
+static void
+telephone_startup (struct linereader *lr, struct localedef_t *locale,
+ int ignore_content)
+{
+ if (!ignore_content)
+ locale->categories[LC_TELEPHONE].telephone = (struct locale_telephone_t *)
+ xcalloc (1, sizeof (struct locale_telephone_t));
+
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
+}
+
+
+void
+telephone_finish (struct localedef_t *locale, struct charmap_t *charmap)
+{
+ struct locale_telephone_t *telephone =
+ locale->categories[LC_TELEPHONE].telephone;
+
+ if (telephone->tel_int_fmt == NULL)
+ {
+ error (0, 0, _("%s: field `%s' not defined"),
+ "LC_TELEPHONE", "tel_int_fmt");
+ /* Use as the default value the value of the i18n locale. */
+ telephone->tel_int_fmt = "+%c %a %l";
+ }
+ else
+ {
+ /* We must check whether the format string contains only the
+ allowed escape sequences. */
+ const char *cp = telephone->tel_int_fmt;
+
+ if (*cp == '\0')
+ error (0, 0, _("%s: field `%s' must not be empty"),
+ "LC_TELEPHONE", "tel_int_fmt");
+ else
+ while (*cp != '\0')
+ {
+ if (*cp == '%')
+ {
+ if (strchr ("aAlc", *++cp) == NULL)
+ {
+ error (0, 0, _("\
+%s: invalid escape sequence in field `%s'"),
+ "LC_TELEPHONE", "tel_int_fmt");
+ break;
+ }
+ }
+ ++cp;
+ }
+ }
+
+ if (telephone->tel_dom_fmt == NULL)
+ telephone->tel_dom_fmt = "";
+ else if (telephone->tel_dom_fmt[0] != '\0')
+ {
+ /* We must check whether the format string contains only the
+ allowed escape sequences. */
+ const char *cp = telephone->tel_dom_fmt;
+
+ while (*cp != '\0')
+ {
+ if (*cp == '%')
+ {
+ if (strchr ("aAlc", *++cp) == NULL)
+ {
+ error (0, 0, _("%s: invalid escape sequence in field `%s'"),
+ "LC_TELEPHONE", "tel_dom_fmt");
+ break;
+ }
+ }
+ ++cp;
+ }
+ }
+
+#define TEST_ELEM(cat) \
+ if (telephone->cat == NULL) \
+ { \
+ if (verbose) \
+ error (0, 0, _("%s: field `%s' not defined"), "LC_TELEPHONE", #cat); \
+ telephone->cat = ""; \
+ }
+
+ TEST_ELEM (int_select);
+ TEST_ELEM (int_prefix);
+}
+
+
+void
+telephone_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
+{
+ struct locale_telephone_t *telephone =
+ locale->categories[LC_TELEPHONE].telephone;
+ struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)];
+ struct locale_file data;
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE)];
+ size_t cnt = 0;
+
+ data.magic = LIMAGIC (LC_TELEPHONE);
+ data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE);
+ iov[cnt].iov_base = (void *) &data;
+ iov[cnt].iov_len = sizeof (data);
+ ++cnt;
+
+ iov[cnt].iov_base = (void *) idx;
+ iov[cnt].iov_len = sizeof (idx);
+ ++cnt;
+
+ idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
+ iov[cnt].iov_base = (void *) telephone->tel_int_fmt;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) telephone->tel_dom_fmt;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) telephone->int_select;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
+ iov[cnt].iov_base = (void *) telephone->int_prefix;
+ iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
+ ++cnt;
+
+ assert (cnt == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE));
+
+ write_locale_data (output_path, "LC_TELEPHONE",
+ 2 + _NL_ITEM_INDEX (_NL_NUM_LC_TELEPHONE), iov);
+}
+
+
+/* The parser for the LC_TELEPHONE section of the locale definition. */
+void
+telephone_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
+{
+ struct repertoire_t *repertoire = NULL;
+ struct locale_telephone_t *telephone;
+ struct token *now;
+ struct token *arg;
+ enum token_t nowtok;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_TELEPHONE' must be free. */
+ lr_ignore_rest (ldfile, 1);
+
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_telephone, LC_TELEPHONE,
+ "LC_TELEPHONE", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ telephone_startup (ldfile, result, ignore_content);
+ telephone = result->categories[LC_TELEPHONE].telephone;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
+ }
+
+ switch (nowtok)
+ {
+#define STR_ELEM(cat) \
+ case tok_##cat: \
+ arg = lr_token (ldfile, charmap, NULL); \
+ if (arg->tok != tok_string) \
+ goto err_label; \
+ if (telephone->cat != NULL) \
+ lr_error (ldfile, _("%s: field `%s' declared more than once"), \
+ "LC_TELEPHONE", #cat); \
+ else if (!ignore_content && arg->val.str.startmb == NULL) \
+ { \
+ lr_error (ldfile, _("%s: unknown character in field `%s'"), \
+ "LC_TELEPHONE", #cat); \
+ telephone->cat = ""; \
+ } \
+ else if (!ignore_content) \
+ telephone->cat = arg->val.str.startmb; \
+ break
+
+ STR_ELEM (tel_int_fmt);
+ STR_ELEM (tel_dom_fmt);
+ STR_ELEM (int_select);
+ STR_ELEM (int_prefix);
+
+ case tok_end:
+ /* Next we assume `LC_TELEPHONE'. */
+ arg = lr_token (ldfile, charmap, NULL);
+ if (arg->tok == tok_eof)
+ break;
+ if (arg->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"), "LC_TELEPHONE");
+ else if (arg->tok != tok_lc_telephone)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_TELEPHONE");
+ lr_ignore_rest (ldfile, arg->tok == tok_lc_telephone);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_TELEPHONE");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_TELEPHONE");
+}
diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c
index c63d897f07..bae38fcaea 100644
--- a/locale/programs/ld-time.c
+++ b/locale/programs/ld-time.c
@@ -1,6 +1,6 @@
/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -21,25 +21,19 @@
# include <config.h>
#endif
+#include <byteswap.h>
#include <langinfo.h>
+#include <stdlib.h>
#include <string.h>
-#include <libintl.h>
+#include <wchar.h>
+#include <sys/uio.h>
-/* Undefine following line in production version. */
-/* #define NDEBUG 1 */
#include <assert.h>
-#include <stdlib.h>
-#include "locales.h"
+#include "linereader.h"
+#include "localedef.h"
#include "localeinfo.h"
-#include "stringtrans.h"
-
-#define SWAPU32(w) \
- (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24))
-
-
-extern void *xmalloc (size_t __n);
-extern void *xrealloc (void *__p, size_t __n);
+#include "locfile.h"
/* Entry describing an entry of the era specification. */
@@ -51,6 +45,8 @@ struct era_data
int32_t stop_date[3];
const char *name;
const char *format;
+ uint32_t *wname;
+ uint32_t *wformat;
};
@@ -58,75 +54,135 @@ struct era_data
struct locale_time_t
{
const char *abday[7];
- size_t cur_num_abday;
+ const uint32_t *wabday[7];
+ const uint32_t *wabday_ob[7];
+ int abday_defined;
const char *day[7];
- size_t cur_num_day;
+ const uint32_t *wday[7];
+ const uint32_t *wday_ob[7];
+ int day_defined;
const char *abmon[12];
- size_t cur_num_abmon;
+ const uint32_t *wabmon[12];
+ const uint32_t *wabmon_ob[12];
+ int abmon_defined;
const char *mon[12];
- size_t cur_num_mon;
+ const uint32_t *wmon[12];
+ const uint32_t *wmon_ob[12];
+ int mon_defined;
const char *am_pm[2];
- size_t cur_num_am_pm;
+ const uint32_t *wam_pm[2];
+ const uint32_t *wam_pm_ob[2];
+ int am_pm_defined;
const char *d_t_fmt;
+ const uint32_t *wd_t_fmt;
+ const uint32_t *wd_t_fmt_ob;
const char *d_fmt;
+ const uint32_t *wd_fmt;
+ const uint32_t *wd_fmt_ob;
const char *t_fmt;
+ const uint32_t *wt_fmt;
+ const uint32_t *wt_fmt_ob;
const char *t_fmt_ampm;
+ const uint32_t *wt_fmt_ampm;
+ const uint32_t *wt_fmt_ampm_ob;
const char **era;
- u_int32_t cur_num_era;
+ const uint32_t **wera;
+ const uint32_t **wera_ob;
+ uint32_t num_era;
const char *era_year;
+ const uint32_t *wera_year;
+ const uint32_t *wera_year_ob;
const char *era_d_t_fmt;
+ const uint32_t *wera_d_t_fmt;
+ const uint32_t *wera_d_t_fmt_ob;
const char *era_t_fmt;
+ const uint32_t *wera_t_fmt;
+ const uint32_t *wera_t_fmt_ob;
const char *era_d_fmt;
+ const uint32_t *wera_d_fmt;
+ const uint32_t *wera_d_fmt_ob;
const char *alt_digits[100];
- u_int32_t cur_num_alt_digits;
+ const uint32_t *walt_digits[100];
+ const uint32_t *walt_digits_ob[100];
+ int alt_digits_defined;
+ unsigned char week_ndays;
+ uint32_t week_1stday;
+ unsigned char week_1stweek;
+ unsigned char first_weekday;
+ unsigned char first_workday;
+ unsigned char cal_direction;
+ const char *timezone;
+ const uint32_t *wtimezone;
struct era_data *era_entries;
struct era_data *era_entries_ob;
};
-void
-time_startup (struct linereader *lr, struct localedef_t *locale,
- struct charset_t *charset)
-{
- struct locale_time_t *time;
-
- /* We have a definition for LC_TIME. */
- copy_posix.mask &= ~(1 << LC_TIME);
+/* This constant is used to represent an empty wide character string. */
+static const uint32_t empty_wstr[1] = { 0 };
- /* It is important that we always use UCS1 encoding for strings now. */
- encoding_method = ENC_UCS1;
- locale->categories[LC_TIME].time = time =
- (struct locale_time_t *) xmalloc (sizeof (struct locale_time_t));
+static void
+time_startup (struct linereader *lr, struct localedef_t *locale,
+ int ignore_content)
+{
+ if (!ignore_content)
+ locale->categories[LC_TIME].time =
+ (struct locale_time_t *) xcalloc (1, sizeof (struct locale_time_t));
- memset (time, '\0', sizeof (struct locale_time_t));
+ lr->translate_strings = 1;
+ lr->return_widestr = 0;
}
void
-time_finish (struct localedef_t *locale)
+time_finish (struct localedef_t *locale, struct charmap_t *charmap)
{
struct locale_time_t *time = locale->categories[LC_TIME].time;
+ size_t cnt;
+
+#define TESTARR_ELEM(cat) \
+ if (!time->cat##_defined && !be_quiet) \
+ error (0, 0, _("%s: field `%s' not defined"), "LC_TIME", #cat); \
+ else if (time->w##cat != NULL) \
+ { \
+ size_t n; \
+ for (n = 0; n < sizeof (time->w##cat) / sizeof (time->w##cat[0]); ++n) \
+ { \
+ size_t len = wcslen ((wchar_t *) time->w##cat[n]) + 1; \
+ uint32_t *wstr = (uint32_t *) xmalloc (len * sizeof (uint32_t)); \
+ do \
+ { \
+ --len; \
+ wstr[len] = bswap_32 (time->w##cat[n][len]); \
+ } \
+ while (len > 0); \
+ time->w##cat##_ob[n] = wstr; \
+ } \
+ }
+
+ TESTARR_ELEM (abday);
+ TESTARR_ELEM (day);
+ TESTARR_ELEM (abmon);
+ TESTARR_ELEM (mon);
+ TESTARR_ELEM (am_pm);
-#define TESTARR_ELEM(cat, max) \
- if (time->cur_num_##cat == 0 && !be_quiet) \
- error (0, 0, _("field `%s' in category `%s' undefined"), \
- #cat, "LC_TIME"); \
- else if (time->cur_num_##cat != max && !be_quiet) \
- error (0, 0, _("field `%s' in category `%s' has not enough values"), \
- #cat, "LC_TIME")
-
- TESTARR_ELEM (abday, 7);
- TESTARR_ELEM (day, 7);
- TESTARR_ELEM (abmon, 12);
- TESTARR_ELEM (mon, 12);
- TESTARR_ELEM (am_pm, 2);
-
-#define TEST_ELEM(cat) \
+#define TEST_ELEM(cat) \
if (time->cat == NULL && !be_quiet) \
- error (0, 0, _("field `%s' in category `%s' undefined"), \
- #cat, "LC_TIME")
+ error (0, 0, _("%s: field `%s' not defined"), "LC_TIME", #cat); \
+ else if (time->w##cat != NULL) \
+ { \
+ size_t len = wcslen ((wchar_t *) time->w##cat) + 1; \
+ uint32_t *wstr = (uint32_t *) xmalloc (len * sizeof (uint32_t)); \
+ do \
+ { \
+ --len; \
+ wstr[len] = bswap_32 (time->w##cat[len]); \
+ } \
+ while (len > 0); \
+ time->w##cat##_ob = wstr; \
+ }
TEST_ELEM (d_t_fmt);
TEST_ELEM (d_fmt);
@@ -135,21 +191,39 @@ time_finish (struct localedef_t *locale)
/* According to C.Y.Alexis Cheng <alexis@vnet.ibm.com> the T_FMT_AMPM
field is optional. */
if (time->t_fmt_ampm == NULL)
- /* Use the 24h format as default. */
- time->t_fmt_ampm = time->t_fmt;
+ {
+ /* Use the 24h format as default. */
+ time->t_fmt_ampm = time->t_fmt;
+ time->wt_fmt_ampm = time->wt_fmt;
+ time->wt_fmt_ampm_ob = time->wt_fmt_ob;
+ }
+ else
+ {
+ /* Convert the byte order. */
+ size_t len = wcslen ((wchar_t *) time->wt_fmt_ampm) + 1;
+ uint32_t *wstr = (uint32_t *) xmalloc (len * sizeof (uint32_t));
+ do
+ {
+ --len;
+ wstr[len] = bswap_32 (time->wt_fmt_ampm[len]);
+ }
+ while (len > 0);
+ time->wt_fmt_ampm_ob = wstr;
+ }
/* Now process the era entries. */
- if (time->cur_num_era != 0)
+ if (time->num_era != 0)
{
const int days_per_month[12] = { 31, 29, 31, 30, 31, 30,
31, 31, 30, 31 ,30, 31 };
size_t idx;
+ wchar_t *wstr;
time->era_entries =
- (struct era_data *) xmalloc (time->cur_num_era
+ (struct era_data *) xmalloc (time->num_era
* sizeof (struct era_data));
- for (idx = 0; idx < time->cur_num_era; ++idx)
+ for (idx = 0; idx < time->num_era; ++idx)
{
size_t era_len = strlen (time->era[idx]);
char *str = xmalloc ((era_len + 1 + 3) & ~3);
@@ -161,9 +235,9 @@ time_finish (struct localedef_t *locale)
if (*str != '+' && *str != '-')
{
if (!be_quiet)
- error (0, 0, _("direction flag in string %d in `era' field"
- " in category `%s' is not '+' nor '-'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: direction flag in string %d in `era' field"
+ " is not '+' nor '-'"),
+ "LC_TIME", idx + 1);
/* Default arbitrarily to '+'. */
time->era_entries[idx].direction = '+';
}
@@ -172,9 +246,9 @@ time_finish (struct localedef_t *locale)
if (*++str != ':')
{
if (!be_quiet)
- error (0, 0, _("direction flag in string %d in `era' field"
- " in category `%s' is not a single character"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: direction flag in string %d in `era' field"
+ " is not a single character"),
+ "LC_TIME", idx + 1);
(void) strsep (&str, ":");
}
else
@@ -185,17 +259,17 @@ time_finish (struct localedef_t *locale)
if (endp == str)
{
if (!be_quiet)
- error (0, 0, _("illegal number for offset in string %d in"
- " `era' field in category `%s'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: invalid number for offset in string %d in"
+ " `era' field"),
+ "LC_TIME", idx + 1);
(void) strsep (&str, ":");
}
else if (*endp != ':')
{
if (!be_quiet)
- error (0, 0, _("garbage at end of offset value in string %d in"
- " `era' field in category `%s'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: garbage at end of offset value in"
+ " string %d in `era' field"),
+ "LC_TIME", idx + 1);
(void) strsep (&str, ":");
}
else
@@ -241,19 +315,18 @@ time_finish (struct localedef_t *locale)
{
invalid_start_date:
if (!be_quiet)
- error (0, 0, _("illegal starting date in string %d in"
- " `era' field in category `%s'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: invalid starting date in string %d in"
+ " `era' field"),
+ "LC_TIME", idx + 1);
(void) strsep (&str, ":");
}
else if (*endp != ':')
{
garbage_start_date:
if (!be_quiet)
- error (0, 0, _("garbage at end of starting date "
- "in string %d in `era' field "
- "in category `%s'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: garbage at end of starting date "
+ "in string %d in `era' field "),
+ "LC_TIME", idx + 1);
(void) strsep (&str, ":");
}
else
@@ -270,10 +343,9 @@ time_finish (struct localedef_t *locale)
&& time->era_entries[idx].start_date[2] == 29
&& !__isleap (time->era_entries[idx].start_date[0])))
&& !be_quiet)
- error (0, 0, _("starting date is illegal in"
- " string %d in `era' field in"
- " category `%s'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: starting date is invalid in"
+ " string %d in `era' field"),
+ "LC_TIME", idx + 1);
}
}
@@ -317,19 +389,18 @@ time_finish (struct localedef_t *locale)
{
invalid_stop_date:
if (!be_quiet)
- error (0, 0, _("illegal stopping date in string %d in"
- " `era' field in category `%s'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: invalid stopping date in string %d in"
+ " `era' field"),
+ "LC_TIME", idx + 1);
(void) strsep (&str, ":");
}
else if (*endp != ':')
{
garbage_stop_date:
if (!be_quiet)
- error (0, 0, _("garbage at end of stopping date "
- "in string %d in `era' field "
- "in category `%s'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: garbage at end of stopping date "
+ "in string %d in `era' field"),
+ "LC_TIME", idx + 1);
(void) strsep (&str, ":");
}
else
@@ -346,23 +417,19 @@ time_finish (struct localedef_t *locale)
&& time->era_entries[idx].stop_date[2] == 29
&& !__isleap (time->era_entries[idx].stop_date[0])))
&& !be_quiet)
- error (0, 0, _("stopping date is illegal in"
- " string %d in `era' field in"
- " category `%s'"),
- idx + 1, "LC_TIME");
+ error (0, 0, _("%s: stopping date is invalid in"
+ " string %d in `era' field"),
+ "LC_TIME", idx + 1);
}
}
if (str == NULL || *str == '\0')
{
if (!be_quiet)
- error (0, 0, _("missing era name in string %d in `era' field"
- " in category `%s'"), idx + 1, "LC_TIME");
- /* Make sure that name and format are adjacent strings
- in memory. */
- time->era_entries[idx].name = "\0";
- time->era_entries[idx].format
- = time->era_entries[idx].name + 1;
+ error (0, 0, _("%s: missing era name in string %d in `era'"
+ " field"), "LC_TIME", idx + 1);
+ time->era_entries[idx].name =
+ time->era_entries[idx].format = "";
}
else
{
@@ -371,74 +438,149 @@ time_finish (struct localedef_t *locale)
if (str == NULL || *str == '\0')
{
if (!be_quiet)
- error (0, 0, _("missing era format in string %d in `era'"
- " field in category `%s'"),
- idx + 1, "LC_TIME");
- /* Make sure that name and format are adjacent strings
- in memory. */
- time->era_entries[idx].name = "\0";
- time->era_entries[idx].format
- = time->era_entries[idx].name + 1;
+ error (0, 0, _("%s: missing era format in string %d"
+ " in `era' field"),
+ "LC_TIME", idx + 1);
+ time->era_entries[idx].name =
+ time->era_entries[idx].format = "";
}
else
time->era_entries[idx].format = str;
}
+
+ /* Now generate the wide character name and format. */
+ wstr = wcschr ((wchar_t *) time->wera, L':'); /* end direction */
+ wstr = wstr ? wcschr (wstr, L':') : NULL; /* end offset */
+ wstr = wstr ? wcschr (wstr, L':') : NULL; /* end start */
+ wstr = wstr ? wcschr (wstr, L':') : NULL; /* end end */
+ time->era_entries[idx].wname = (uint32_t *) wstr;
+ wstr = wstr ? wcschr (wstr, L':') : NULL; /* end name */
+ time->era_entries[idx].wformat = (uint32_t *) wstr;
}
/* Construct the array for the other byte order. */
time->era_entries_ob =
- (struct era_data *) xmalloc (time->cur_num_era
- * sizeof (struct era_data));
+ (struct era_data *) xmalloc (time->num_era * sizeof (struct era_data));
- for (idx = 0; idx < time->cur_num_era; ++idx)
+ for (idx = 0; idx < time->num_era; ++idx)
{
time->era_entries_ob[idx].direction =
- SWAPU32 (time->era_entries[idx].direction);
+ bswap_32 (time->era_entries[idx].direction);
time->era_entries_ob[idx].offset =
- SWAPU32 (time->era_entries[idx].offset);
+ bswap_32 (time->era_entries[idx].offset);
time->era_entries_ob[idx].start_date[0] =
- SWAPU32 (time->era_entries[idx].start_date[0]);
+ bswap_32 (time->era_entries[idx].start_date[0]);
time->era_entries_ob[idx].start_date[1] =
- SWAPU32 (time->era_entries[idx].start_date[1]);
+ bswap_32 (time->era_entries[idx].start_date[1]);
time->era_entries_ob[idx].start_date[2] =
- SWAPU32 (time->era_entries[idx].stop_date[2]);
+ bswap_32 (time->era_entries[idx].stop_date[2]);
time->era_entries_ob[idx].stop_date[0] =
- SWAPU32 (time->era_entries[idx].stop_date[0]);
+ bswap_32 (time->era_entries[idx].stop_date[0]);
time->era_entries_ob[idx].stop_date[1] =
- SWAPU32 (time->era_entries[idx].stop_date[1]);
+ bswap_32 (time->era_entries[idx].stop_date[1]);
time->era_entries_ob[idx].stop_date[2] =
- SWAPU32 (time->era_entries[idx].stop_date[2]);
+ bswap_32 (time->era_entries[idx].stop_date[2]);
time->era_entries_ob[idx].name =
time->era_entries[idx].name;
time->era_entries_ob[idx].format =
time->era_entries[idx].format;
+ if (time->era_entries[idx].wname != NULL)
+ {
+ size_t inner = (wcslen ((wchar_t *) time->era_entries[idx].wname)
+ + 1);
+ time->era_entries_ob[idx].wname = xmalloc (inner
+ * sizeof (uint32_t));
+ do
+ time->era_entries_ob[idx].wname[inner - 1]
+ = bswap_32 (time->era_entries[idx].wname[inner - 1]);
+ while (inner-- > 0);
+ }
+ else
+ time->era_entries_ob[idx].wname = NULL;
+ if (time->era_entries[idx].wformat != NULL)
+ {
+ size_t inner
+ = wcslen ((wchar_t *) time->era_entries[idx].wformat) + 1;
+ time->era_entries_ob[idx].wformat = xmalloc (inner
+ * sizeof (uint32_t));
+ do
+ time->era_entries_ob[idx].wformat[inner - 1]
+ = bswap_32 (time->era_entries[idx].wformat[inner - 1]);
+ while (inner-- > 0);
+ }
+ else
+ time->era_entries_ob[idx].wformat = NULL;
}
}
+
+ if (time->week_ndays == 0)
+ time->week_ndays = 7;
+
+ if (time->week_1stday == 0)
+ time->week_1stday = 19971130;
+
+ if (time->week_1stweek > time->week_ndays)
+ error (0, 0, _("\
+%s: third operand for value of field `%s' must not be larger than %d"),
+ "LC_TIME", "week", 7);
+
+ if (time->first_weekday == '\0')
+ /* The definition does not specify this so the default is used. */
+ time->first_weekday = 1;
+ else if (time->first_weekday > time->week_ndays)
+ error (0, 0, _("\
+%s: values of field `%s' must not be larger than %d"),
+ "LC_TIME", "first_weekday", 7);
+
+ if (time->first_workday == '\0')
+ /* The definition does not specify this so the default is used. */
+ time->first_workday = 1;
+ else if (time->first_workday > time->week_ndays)
+ error (0, 0, _("\
+%s: values of field `%s' must not be larger than %d"),
+ "LC_TIME", "first_workday", 7);
+
+ if (time->cal_direction == '\0')
+ /* The definition does not specify this so the default is used. */
+ time->cal_direction = 1;
+ else if (time->cal_direction > 3)
+ error (0, 0, _("\
+%s: values for field `%s' must not be larger than 3"),
+ "LC_TIME", "cal_direction", 3);
+
+ /* XXX We don't perform any tests on the timezone value since this is
+ simply useless, stupid $&$!@... */
+ if (time->timezone == NULL)
+ time->timezone = "";
+
+ /* Generate alt digits in other byte order. */
+ for (cnt = 0; cnt < 100; ++cnt)
+ if (time->walt_digits[cnt] != NULL)
+ {
+ size_t len = wcslen ((wchar_t *) time->walt_digits[cnt]) + 1;
+ uint32_t *wstr = xmalloc (len * sizeof (uint32_t));
+ do
+ wstr[len - 1] = bswap_32 (time->walt_digits[cnt][len - 1]);
+ while (len-- > 0);
+ time->walt_digits_ob[cnt] = wstr;
+ }
}
void
-time_output (struct localedef_t *locale, const char *output_path)
+time_output (struct localedef_t *locale, struct charmap_t *charmap,
+ const char *output_path)
{
struct locale_time_t *time = locale->categories[LC_TIME].time;
struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME)
- + time->cur_num_era - 1
- + time->cur_num_alt_digits - 1
- + 1 + (time->cur_num_era * 9 - 1) * 2
- + (time->cur_num_era == 0)];
+ + time->num_era - 1
+ + 3 * 99
+ + 1 + (time->num_era * 10 - 1) * 2];
struct locale_file data;
- u_int32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)];
- size_t cnt, last_idx, num;
-
- if ((locale->binary & (1 << LC_TIME)) != 0)
- {
- iov[0].iov_base = time;
- iov[0].iov_len = locale->len[LC_TIME];
-
- write_locale_data (output_path, "LC_TIME", 1, iov);
-
- return;
- }
+ uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)];
+ size_t cnt, last_idx, num, n;
+ uint32_t num_era_eb;
+ uint32_t num_era_el;
data.magic = LIMAGIC (LC_TIME);
data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TIME);
@@ -516,7 +658,7 @@ time_output (struct localedef_t *locale, const char *output_path)
last_idx = ++cnt;
idx[1 + last_idx] = idx[last_idx];
- for (num = 0; num < time->cur_num_era; ++num, ++cnt)
+ for (num = 0; num < time->num_era; ++num, ++cnt)
{
iov[2 + cnt].iov_base = (void *) time->era[num];
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
@@ -537,7 +679,7 @@ time_output (struct localedef_t *locale, const char *output_path)
++last_idx;
idx[1 + last_idx] = idx[last_idx];
- for (num = 0; num < time->cur_num_alt_digits; ++num, ++cnt)
+ for (num = 0; num < 100; ++num, ++cnt)
{
iov[2 + cnt].iov_base = (void *) (time->alt_digits[num] ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
@@ -564,15 +706,23 @@ time_output (struct localedef_t *locale, const char *output_path)
idx[last_idx] = (idx[last_idx] + 3) & ~3;
++cnt;
- iov[2 + cnt].iov_base = (void *) &time->cur_num_alt_digits;
- iov[2 + cnt].iov_len = sizeof (u_int32_t);
+ /* The `era' data in usable form. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ num_era_eb = bswap_32 (time->num_era);
+ num_era_el = time->num_era;
+#else
+ num_era_eb = time->num_era;
+ num_era_el = bswap_32 (time->num_era);
+#endif
+
+ iov[2 + cnt].iov_base = (void *) &num_era_eb;
+ iov[2 + cnt].iov_len = sizeof (uint32_t);
idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
++cnt;
++last_idx;
- /* The `era' data in usable form. */
- iov[2 + cnt].iov_base = (void *) &time->cur_num_era;
- iov[2 + cnt].iov_len = sizeof (u_int32_t);
+ iov[2 + cnt].iov_base = (void *) &num_era_el;
+ iov[2 + cnt].iov_len = sizeof (uint32_t);
idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
++cnt;
++last_idx;
@@ -585,7 +735,7 @@ time_output (struct localedef_t *locale, const char *output_path)
# define ERA_B2 time->era_entries_ob
#endif
idx[1 + last_idx] = idx[last_idx];
- for (num = 0; num < time->cur_num_era; ++num)
+ for (num = 0; num < time->num_era; ++num)
{
size_t l;
@@ -596,10 +746,22 @@ time_output (struct localedef_t *locale, const char *output_path)
iov[2 + cnt].iov_len = sizeof (int32_t);
++cnt;
iov[2 + cnt].iov_base = (void *) &ERA_B1[num].start_date[0];
- iov[2 + cnt].iov_len = 3 * sizeof (int32_t);
+ iov[2 + cnt].iov_len = sizeof (int32_t);
+ ++cnt;
+ iov[2 + cnt].iov_base = (void *) &ERA_B1[num].start_date[1];
+ iov[2 + cnt].iov_len = sizeof (int32_t);
+ ++cnt;
+ iov[2 + cnt].iov_base = (void *) &ERA_B1[num].start_date[2];
+ iov[2 + cnt].iov_len = sizeof (int32_t);
++cnt;
iov[2 + cnt].iov_base = (void *) &ERA_B1[num].stop_date[0];
- iov[2 + cnt].iov_len = 3 * sizeof (int32_t);
+ iov[2 + cnt].iov_len = sizeof (int32_t);
+ ++cnt;
+ iov[2 + cnt].iov_base = (void *) &ERA_B1[num].stop_date[1];
+ iov[2 + cnt].iov_len = sizeof (int32_t);
+ ++cnt;
+ iov[2 + cnt].iov_base = (void *) &ERA_B1[num].stop_date[2];
+ iov[2 + cnt].iov_len = sizeof (int32_t);
++cnt;
l = (strchr (ERA_B1[num].format, '\0') - ERA_B1[num].name) + 1;
@@ -611,11 +773,19 @@ time_output (struct localedef_t *locale, const char *output_path)
idx[1 + last_idx] += 8 * sizeof (int32_t) + l;
assert (idx[1 + last_idx] % 4 == 0);
+
+ iov[2 + cnt].iov_base = (void *) ERA_B1[num].wname;
+ iov[2 + cnt].iov_len = ((wcschr ((wchar_t *) ERA_B1[cnt].wformat, L'\0')
+ - (wchar_t *) ERA_B1[num].wname + 1)
+ * sizeof (uint32_t));
+ ++cnt;
+
+ idx[1 + last_idx] += iov[2 + cnt].iov_len;
}
++last_idx;
- /* idx[1 + last_idx] = idx[last_idx]; */
- for (num = 0; num < time->cur_num_era; ++num)
+ idx[1 + last_idx] = idx[last_idx];
+ for (num = 0; num < time->num_era; ++num)
{
size_t l;
@@ -626,10 +796,22 @@ time_output (struct localedef_t *locale, const char *output_path)
iov[2 + cnt].iov_len = sizeof (int32_t);
++cnt;
iov[2 + cnt].iov_base = (void *) &ERA_B2[num].start_date[0];
- iov[2 + cnt].iov_len = 3 * sizeof (int32_t);
+ iov[2 + cnt].iov_len = sizeof (int32_t);
+ ++cnt;
+ iov[2 + cnt].iov_base = (void *) &ERA_B2[num].start_date[1];
+ iov[2 + cnt].iov_len = sizeof (int32_t);
+ ++cnt;
+ iov[2 + cnt].iov_base = (void *) &ERA_B2[num].start_date[2];
+ iov[2 + cnt].iov_len = sizeof (int32_t);
++cnt;
iov[2 + cnt].iov_base = (void *) &ERA_B2[num].stop_date[0];
- iov[2 + cnt].iov_len = 3 * sizeof (int32_t);
+ iov[2 + cnt].iov_len = sizeof (int32_t);
+ ++cnt;
+ iov[2 + cnt].iov_base = (void *) &ERA_B2[num].stop_date[1];
+ iov[2 + cnt].iov_len = sizeof (int32_t);
+ ++cnt;
+ iov[2 + cnt].iov_base = (void *) &ERA_B2[num].stop_date[2];
+ iov[2 + cnt].iov_len = sizeof (int32_t);
++cnt;
l = (strchr (ERA_B2[num].format, '\0') - ERA_B2[num].name) + 1;
@@ -638,103 +820,618 @@ time_output (struct localedef_t *locale, const char *output_path)
iov[2 + cnt].iov_len = l;
++cnt;
- /* idx[1 + last_idx] += 8 * sizeof (int32_t) + l; */
+ idx[1 + last_idx] += 8 * sizeof (int32_t) + l;
+
+ iov[2 + cnt].iov_base = (void *) ERA_B1[num].wname;
+ iov[2 + cnt].iov_len = ((wcschr ((wchar_t *) ERA_B1[cnt].wformat, L'\0')
+ - (wchar_t *) ERA_B1[num].wname + 1)
+ * sizeof (uint32_t));
+ ++cnt;
+
+ idx[1 + last_idx] += iov[2 + cnt].iov_len;
}
+ ++last_idx;
- /* We have a problem when no era data is present. In this case the
- data pointer for _NL_TIME_ERA_ENTRIES_EB and
- _NL_TIME_ERA_ENTRIES_EL point after the end of the file. So we
- introduce some dummy data here. */
- if (time->cur_num_era == 0)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define WABDAY_B1 wabday_ob
+# define WDAY_B1 wday_ob
+# define WABMON_B1 wabmon_ob
+# define WMON_B1 wmon_ob
+# define WAM_PM_B1 wam_pm_ob
+# define WD_T_FMT_B1 wd_t_fmt_ob
+# define WD_FMT_B1 wd_fmt_ob
+# define WT_FMT_B1 wt_fmt_ob
+# define WT_FMT_AMPM_B1 wt_fmt_ampm_ob
+# define WERA_YEAR_B1 wera_year_ob
+# define WERA_D_FMT_B1 wera_d_fmt_ob
+# define WALT_DIGITS_B1 walt_digits_ob
+# define WERA_D_T_FMT_B1 wera_d_t_fmt_ob
+# define WERA_T_FMT_B1 wera_t_fmt_ob
+# define WABDAY_B2 wabday
+# define WDAY_B2 wday
+# define WABMON_B2 wabmon
+# define WMON_B2 wmon
+# define WAM_PM_B2 wam_pm
+# define WD_T_FMT_B2 wd_t_fmt
+# define WD_FMT_B2 wd_fmt
+# define WT_FMT_B2 wt_fmt
+# define WT_FMT_AMPM_B2 wt_fmt_ampm
+# define WERA_YEAR_B2 wera_year
+# define WERA_D_FMT_B2 wera_d_fmt
+# define WALT_DIGITS_B2 walt_digits
+# define WERA_D_T_FMT_B2 wera_d_t_fmt
+# define WERA_T_FMT_B2 wera_t_fmt
+#else
+# define WABDAY_B1 wabday
+# define WDAY_B1 wday
+# define WABMON_B1 wabmon
+# define WMON_B1 wmon
+# define WAM_PM_B1 wam_pm
+# define WD_T_FMT_B1 wd_t_fmt
+# define WD_FMT_B1 wd_fmt
+# define WT_FMT_B1 wt_fmt
+# define WT_FMT_AMPM_B1 wt_fmt_ampm
+# define WERA_YEAR_B1 wera_year
+# define WERA_D_FMT_B1 wera_d_fmt
+# define WALT_DIGITS_B1 walt_digits
+# define WERA_D_T_FMT_B1 wera_d_t_fmt
+# define WERA_T_FMT_B1 wera_t_fmt
+# define WABDAY_B2 wabday_ob
+# define WDAY_B2 wday_ob
+# define WABMON_B2 wabmon_ob
+# define WMON_B2 wmon_ob
+# define WAM_PM_B2 wam_pm_ob
+# define WD_T_FMT_B2 wd_t_fmt_ob
+# define WD_FMT_B2 wd_fmt_ob
+# define WT_FMT_B2 wt_fmt_ob
+# define WT_FMT_AMPM_B2 wt_fmt_ampm_ob
+# define WERA_YEAR_B2 wera_year_ob
+# define WERA_D_FMT_B2 wera_d_fmt_ob
+# define WALT_DIGITS_B2 walt_digits_ob
+# define WERA_D_T_FMT_B2 wera_d_t_fmt_ob
+# define WERA_T_FMT_B2 wera_t_fmt_ob
+#endif
+
+ /* The wide character ab'days. */
+ for (n = 0; n < 7; ++n, ++cnt, ++last_idx)
{
- static u_int32_t dummy = 0;
- iov[2 + cnt].iov_base = (void *) &dummy;
- iov[2 + cnt].iov_len = 4;
- ++cnt;
+ iov[2 + cnt].iov_base =
+ (void *) (time->WABDAY_B1[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+ for (n = 0; n < 7; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WABDAY_B2[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+
+ /* The wide character days. */
+ for (n = 0; n < 7; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WDAY_B1[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+ for (n = 0; n < 7; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WDAY_B2[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+
+ /* The wide character ab'mons. */
+ for (n = 0; n < 12; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WABMON_B1[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+ for (n = 0; n < 12; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WABMON_B2[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+
+ /* The wide character mons. */
+ for (n = 0; n < 12; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WMON_B1[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+ for (n = 0; n < 12; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WMON_B2[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+
+ /* Wide character AM/PM. */
+ for (n = 0; n < 2; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WAM_PM_B1[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+ for (n = 0; n < 2; ++n, ++cnt, ++last_idx)
+ {
+ iov[2 + cnt].iov_base =
+ (void *) (time->WAM_PM_B2[n] ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ }
+
+ iov[2 + cnt].iov_base = (void *) (time->WD_T_FMT_B1 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WD_FMT_B1 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WT_FMT_B1 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WT_FMT_AMPM_B1 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WD_T_FMT_B2 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WD_FMT_B2 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WT_FMT_B2 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WT_FMT_AMPM_B2 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WERA_YEAR_B2 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WERA_D_FMT_B2 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ idx[1 + last_idx] = idx[last_idx];
+ for (num = 0; num < 100; ++num, ++cnt)
+ {
+ iov[2 + cnt].iov_base = (void *) (time->WALT_DIGITS_B2[num]
+ ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] += iov[2 + cnt].iov_len;
}
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WERA_D_T_FMT_B2 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WERA_T_FMT_B2 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WERA_YEAR_B1 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WERA_D_FMT_B1 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ idx[1 + last_idx] = idx[last_idx];
+ for (num = 0; num < 100; ++num, ++cnt)
+ {
+ iov[2 + cnt].iov_base = (void *) (time->WALT_DIGITS_B1[num]
+ ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] += iov[2 + cnt].iov_len;
+ }
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WERA_D_T_FMT_B1 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) (time->WERA_T_FMT_B1 ?: empty_wstr);
+ iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
+ * sizeof (uint32_t));
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) &time->week_ndays;
+ iov[2 + cnt].iov_len = 1;
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) &time->week_1stday;
+ iov[2 + cnt].iov_len = 1;
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) &time->week_1stweek;
+ iov[2 + cnt].iov_len = 1;
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) &time->first_weekday;
+ iov[2 + cnt].iov_len = 1;
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) &time->first_workday;
+ iov[2 + cnt].iov_len = 1;
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) &time->cal_direction;
+ iov[2 + cnt].iov_len = 1;
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
+
+ iov[2 + cnt].iov_base = (void *) time->timezone;
+ iov[2 + cnt].iov_len = strlen (time->timezone) + 1;
+ idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
+ ++cnt;
+ ++last_idx;
assert (cnt == (_NL_ITEM_INDEX (_NL_NUM_LC_TIME)
- + time->cur_num_era - 1
- + time->cur_num_alt_digits - 1
- + 1 + (time->cur_num_era * 9 - 1) * 2
- + (time->cur_num_era == 0))
- && last_idx + 1 == _NL_ITEM_INDEX (_NL_NUM_LC_TIME));
+ + time->num_era - 1
+ + 3 * 99
+ + 1 + (time->num_era * 10 - 1) * 2));
+ assert (last_idx == _NL_ITEM_INDEX (_NL_NUM_LC_TIME));
write_locale_data (output_path, "LC_TIME", 2 + cnt, iov);
}
+/* The parser for the LC_TIME section of the locale definition. */
void
-time_add (struct linereader *lr, struct localedef_t *locale,
- enum token_t tok, struct token *code,
- struct charset_t *charset)
+time_read (struct linereader *ldfile, struct localedef_t *result,
+ struct charmap_t *charmap, const char *repertoire_name,
+ int ignore_content)
{
- struct locale_time_t *time = locale->categories[LC_TIME].time;
+ struct repertoire_t *repertoire = NULL;
+ struct locale_time_t *time;
+ struct token *now;
+ enum token_t nowtok;
+ size_t cnt;
+
+ /* Get the repertoire we have to use. */
+ if (repertoire_name != NULL)
+ repertoire = repertoire_read (repertoire_name);
+
+ /* The rest of the line containing `LC_TIME' must be free. */
+ lr_ignore_rest (ldfile, 1);
- switch (tok)
+
+ do
{
-#define STRARR_ELEM(cat, max) \
- case tok_##cat: \
- if (time->cur_num_##cat >= max) \
- lr_error (lr, _("\
-too many values for field `%s' in category `%s'"), \
- #cat, "LC_TIME"); \
- else if (code->val.str.start == NULL) \
- { \
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
- #cat, "LC_TIME"); \
- time->cat[time->cur_num_##cat++] = ""; \
- } \
- else \
- time->cat[time->cur_num_##cat++] = code->val.str.start; \
- break
-
- STRARR_ELEM (abday, 7);
- STRARR_ELEM (day, 7);
- STRARR_ELEM (abmon, 12);
- STRARR_ELEM (mon, 12);
- STRARR_ELEM (am_pm, 2);
- STRARR_ELEM (alt_digits, 100);
-
- case tok_era:
- if (code->val.str.start == NULL)
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),
- "era", "LC_TIME");
- else
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ }
+ while (nowtok == tok_eol);
+
+ /* If we see `copy' now we are almost done. */
+ if (nowtok == tok_copy)
+ {
+ handle_copy (ldfile, charmap, repertoire, tok_lc_time, LC_TIME,
+ "LC_TIME", ignore_content);
+ return;
+ }
+
+ /* Prepare the data structures. */
+ time_startup (ldfile, result, ignore_content);
+ time = result->categories[LC_TIME].time;
+
+ while (1)
+ {
+ /* Of course we don't proceed beyond the end of file. */
+ if (nowtok == tok_eof)
+ break;
+
+ /* Ingore empty lines. */
+ if (nowtok == tok_eol)
{
- ++time->cur_num_era;
- time->era = xrealloc (time->era,
- time->cur_num_era * sizeof (char *));
- time->era[time->cur_num_era - 1] = code->val.str.start;
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
+ continue;
}
- break;
-
-#define STR_ELEM(cat) \
- case tok_##cat: \
- if (time->cat != NULL) \
- lr_error (lr, _("\
-field `%s' in category `%s' declared more than once"), \
- #cat, "LC_TIME"); \
- else if (code->val.str.start == NULL) \
- { \
- lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
- #cat, "LC_TIME"); \
- time->cat = ""; \
- } \
- else \
- time->cat = code->val.str.start; \
- break
-
- STR_ELEM (d_t_fmt);
- STR_ELEM (d_fmt);
- STR_ELEM (t_fmt);
- STR_ELEM (t_fmt_ampm);
- STR_ELEM (era_year);
- STR_ELEM (era_d_t_fmt);
- STR_ELEM (era_d_fmt);
- STR_ELEM (era_t_fmt);
-
- default:
- assert (! "unknown token in category `LC_TIME': should not happen");
+
+ switch (nowtok)
+ {
+#define STRARR_ELEM(cat, min, max) \
+ case tok_##cat: \
+ for (cnt = 0; cnt < max; ++cnt) \
+ { \
+ now = lr_token (ldfile, charmap, repertoire); \
+ if (now->tok == tok_eol) \
+ { \
+ if (cnt < min) \
+ lr_error (ldfile, _("%s: too few values for field `%s'"), \
+ "LC_TIME", #cat); \
+ if (!ignore_content) \
+ do \
+ { \
+ time->cat[cnt] = ""; \
+ time->w##cat[cnt] = empty_wstr; \
+ } \
+ while (++cnt < max); \
+ break; \
+ } \
+ else if (now->tok != tok_string) \
+ goto err_label; \
+ else if (!ignore_content && (now->val.str.startmb == NULL \
+ || now->val.str.startwc == NULL)) \
+ { \
+ lr_error (ldfile, _("%s: unknown character in field `%s'"), \
+ "LC_TIME", #cat); \
+ time->cat[cnt] = ""; \
+ time->w##cat[cnt] = empty_wstr; \
+ } \
+ else if (!ignore_content) \
+ { \
+ time->cat[cnt] = now->val.str.startmb; \
+ time->w##cat[cnt] = now->val.str.startwc; \
+ } \
+ \
+ /* Match the semicolon. */ \
+ now = lr_token (ldfile, charmap, NULL); \
+ if (now->tok != tok_semicolon && now->tok != tok_eol) \
+ break; \
+ } \
+ if (now->tok != tok_eol) \
+ { \
+ while (!ignore_content && cnt < min) \
+ { \
+ time->cat[cnt] = ""; \
+ time->w##cat[cnt++] = empty_wstr; \
+ } \
+ \
+ if (now->tok == tok_semicolon) \
+ { \
+ now = lr_token (ldfile, charmap, NULL); \
+ if (now->tok == tok_eol) \
+ lr_error (ldfile, _("extra trailing semicolon")); \
+ else if (now->tok == tok_string) \
+ { \
+ lr_error (ldfile, _("\
+%s: too many values for field `%s'"), \
+ "LC_TIME", #cat); \
+ lr_ignore_rest (ldfile, 0); \
+ } \
+ else \
+ goto err_label; \
+ } \
+ else \
+ goto err_label; \
+ } \
+ time->cat##_defined = 1; \
+ break
+
+ STRARR_ELEM (abday, 7, 7);
+ STRARR_ELEM (day, 7, 7);
+ STRARR_ELEM (abmon, 12, 12);
+ STRARR_ELEM (mon, 12, 12);
+ STRARR_ELEM (am_pm, 2, 2);
+ STRARR_ELEM (alt_digits, 0, 100);
+
+ case tok_era:
+ do
+ {
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_string)
+ goto err_label;
+ if (!ignore_content && (now->val.str.startmb == NULL
+ || now->val.str.startwc == NULL))
+ {
+ lr_error (ldfile, _("%s: unknown character in field `%s'"),
+ "LC_TIME", "era");
+ lr_ignore_rest (ldfile, 0);
+ break;
+ }
+
+ if (!ignore_content)
+ {
+ time->era = xrealloc (time->era,
+ (time->num_era + 1) * sizeof (char *));
+ time->era[time->num_era] = now->val.str.startmb;
+
+ time->wera = xrealloc (time->wera,
+ (time->num_era + 1)
+ * sizeof (char *));
+ time->wera[time->num_era++] = now->val.str.startwc;
+ }
+
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_eof && now->tok != tok_semicolon)
+ goto err_label;
+ }
+ while (now->tok == tok_semicolon);
+ break;
+
+#define STR_ELEM(cat) \
+ case tok_##cat: \
+ now = lr_token (ldfile, charmap, NULL); \
+ if (now->tok != tok_string) \
+ goto err_label; \
+ else if (time->cat != NULL) \
+ lr_error (ldfile, _("\
+%s: field `%s' declared more than once"), "LC_TIME", #cat); \
+ else if (!ignore_content && (now->val.str.startmb == NULL \
+ || now->val.str.startwc == NULL)) \
+ { \
+ lr_error (ldfile, _("%s: unknown character in field `%s'"), \
+ "LC_TIME", #cat); \
+ time->cat = ""; \
+ time->w##cat = empty_wstr; \
+ } \
+ else if (!ignore_content) \
+ { \
+ time->cat = now->val.str.startmb; \
+ time->w##cat = now->val.str.startwc; \
+ } \
+ break
+
+ STR_ELEM (d_t_fmt);
+ STR_ELEM (d_fmt);
+ STR_ELEM (t_fmt);
+ STR_ELEM (t_fmt_ampm);
+ STR_ELEM (era_year);
+ STR_ELEM (era_d_t_fmt);
+ STR_ELEM (era_d_fmt);
+ STR_ELEM (era_t_fmt);
+ STR_ELEM (timezone);
+
+#define INT_ELEM(cat) \
+ case tok_##cat: \
+ now = lr_token (ldfile, charmap, NULL); \
+ if (now->tok != tok_number) \
+ goto err_label; \
+ else if (time->cat != 0) \
+ lr_error (ldfile, _("%s: field `%s' declared more than once"), \
+ "LC_TIME", #cat); \
+ else if (!ignore_content) \
+ time->cat = now->val.num; \
+ break
+
+ INT_ELEM (first_weekday);
+ INT_ELEM (first_workday);
+ INT_ELEM (cal_direction);
+
+ case tok_week:
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_number)
+ goto err_label;
+ time->week_ndays = now->val.num;
+
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_semicolon)
+ goto err_label;
+
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_number)
+ goto err_label;
+ time->week_1stday = now->val.num;
+
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_semicolon)
+ goto err_label;
+
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_number)
+ goto err_label;
+ time->week_1stweek = now->val.num;
+
+ lr_ignore_rest (ldfile, 1);
+ break;
+
+ case tok_end:
+ /* Next we assume `LC_TIME'. */
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok == tok_eof)
+ break;
+ if (now->tok == tok_eol)
+ lr_error (ldfile, _("%s: incomplete `END' line"), "LC_TIME");
+ else if (now->tok != tok_lc_time)
+ lr_error (ldfile, _("\
+%1$s: definition does not end with `END %1$s'"), "LC_TIME");
+ lr_ignore_rest (ldfile, now->tok == tok_lc_time);
+ return;
+
+ default:
+ err_label:
+ SYNTAX_ERROR (_("%s: syntax error"), "LC_TIME");
+ }
+
+ /* Prepare for the next round. */
+ now = lr_token (ldfile, charmap, NULL);
+ nowtok = now->tok;
}
+
+ /* When we come here we reached the end of the file. */
+ lr_error (ldfile, _("%s: premature end of file"), "LC_TIME");
}
diff --git a/locale/programs/linereader.c b/locale/programs/linereader.c
index 31278d63c2..99ed0f2480 100644
--- a/locale/programs/linereader.c
+++ b/locale/programs/linereader.c
@@ -1,6 +1,6 @@
/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -28,22 +28,20 @@
#include <stdlib.h>
#include <string.h>
+#include "charmap.h"
#include "error.h"
#include "linereader.h"
-#include "charset.h"
+#include "localedef.h"
#include "stringtrans.h"
-void *xmalloc (size_t __n);
-void *xrealloc (void *__p, size_t __n);
-char *xstrdup (const char *__str);
-
-
+/* Prototypes for local functions. */
static struct token *get_toplvl_escape (struct linereader *lr);
static struct token *get_symname (struct linereader *lr);
static struct token *get_ident (struct linereader *lr);
static struct token *get_string (struct linereader *lr,
- const struct charset_t *charset);
+ const struct charmap_t *charmap,
+ const struct repertoire_t *repertoire);
struct linereader *
@@ -126,9 +124,14 @@ lr_next (struct linereader *lr)
if (n > 1 && lr->buf[n - 2] == lr->escape_char && lr->buf[n - 1] == '\n')
{
+#if 0
+ /* XXX Is this correct? */
/* An escaped newline character is substituted with a single <SP>. */
--n;
lr->buf[n - 1] = ' ';
+#else
+ n -= 2;
+#endif
}
lr->buf[n] = '\0';
@@ -149,7 +152,8 @@ extern char *program_name;
struct token *
-lr_token (struct linereader *lr, const struct charset_t *charset)
+lr_token (struct linereader *lr, const struct charmap_t *charmap,
+ const struct repertoire_t *repertoire)
{
int ch;
@@ -193,12 +197,29 @@ lr_token (struct linereader *lr, const struct charset_t *charset)
return get_toplvl_escape (lr);
/* Match ellipsis. */
- if (ch == '.' && strncmp (&lr->buf[lr->idx], "..", 2) == 0)
+ if (ch == '.')
{
- lr_getc (lr);
- lr_getc (lr);
- lr->token.tok = tok_ellipsis;
- return &lr->token;
+ if (strncmp (&lr->buf[lr->idx], "...", 3) == 0)
+ {
+ lr_getc (lr);
+ lr_getc (lr);
+ lr_getc (lr);
+ lr->token.tok = tok_ellipsis4;
+ return &lr->token;
+ }
+ if (strncmp (&lr->buf[lr->idx], "..", 2) == 0)
+ {
+ lr_getc (lr);
+ lr_getc (lr);
+ lr->token.tok = tok_ellipsis3;
+ return &lr->token;
+ }
+ if (lr->buf[lr->idx] == '.')
+ {
+ lr_getc (lr);
+ lr->token.tok = tok_ellipsis2;
+ return &lr->token;
+ }
}
switch (ch)
@@ -238,7 +259,7 @@ lr_token (struct linereader *lr, const struct charset_t *charset)
return &lr->token;
case '"':
- return get_string (lr, charset);
+ return get_string (lr, charmap, repertoire);
case '-':
ch = lr_getc (lr);
@@ -261,7 +282,7 @@ get_toplvl_escape (struct linereader *lr)
/* This is supposed to be a numeric value. We return the
numerical value and the number of bytes. */
size_t start_idx = lr->idx - 1;
- unsigned int value = 0;
+ char *bytes = lr->token.val.charcode.bytes;
int nbytes = 0;
int ch;
@@ -287,11 +308,11 @@ get_toplvl_escape (struct linereader *lr)
|| (base != 16 && (ch < '0' || ch >= (int) ('0' + base))))
{
esc_error:
- lr->token.val.str.start = &lr->buf[start_idx];
+ lr->token.val.str.startmb = &lr->buf[start_idx];
while (ch != EOF && !isspace (ch))
ch = lr_getc (lr);
- lr->token.val.str.len = lr->idx - start_idx;
+ lr->token.val.str.lenmb = lr->idx - start_idx;
lr->token.tok = tok_error;
return &lr->token;
@@ -300,7 +321,7 @@ get_toplvl_escape (struct linereader *lr)
if (isdigit (ch))
byte = ch - '0';
else
- byte = _tolower (ch) - 'a' + 10;
+ byte = tolower (ch) - 'a' + 10;
ch = lr_getc (lr);
if ((base == 16 && !isxdigit (ch))
@@ -311,7 +332,7 @@ get_toplvl_escape (struct linereader *lr)
if (isdigit (ch))
byte += ch - '0';
else
- byte += _tolower (ch) - 'a' + 10;
+ byte += tolower (ch) - 'a' + 10;
ch = lr_getc (lr);
if (base != 16 && isdigit (ch))
@@ -322,10 +343,7 @@ get_toplvl_escape (struct linereader *lr)
ch = lr_getc (lr);
}
- value *= 256;
- value += byte;
-
- ++nbytes;
+ bytes[nbytes++] = byte;
}
while (ch == lr->escape_char && nbytes < 4);
@@ -335,23 +353,52 @@ get_toplvl_escape (struct linereader *lr)
lr_ungetn (lr, 1);
lr->token.tok = tok_charcode;
- lr->token.val.charcode.val = value;
lr->token.val.charcode.nbytes = nbytes;
return &lr->token;
}
-#define ADDC(ch) \
- do \
- { \
- if (bufact == bufmax) \
- { \
- bufmax *= 2; \
- buf = xrealloc (buf, bufmax); \
- } \
- buf[bufact++] = (ch); \
- } \
+#define ADDC(ch) \
+ do \
+ { \
+ if (bufact == bufmax) \
+ { \
+ bufmax *= 2; \
+ buf = xrealloc (buf, bufmax); \
+ } \
+ buf[bufact++] = (ch); \
+ } \
+ while (0)
+
+
+#define ADDS(s, l) \
+ do \
+ { \
+ size_t _l = (l); \
+ if (bufact + _l > bufmax) \
+ { \
+ if (bufact < _l) \
+ bufact = _l; \
+ bufmax *= 2; \
+ buf = xrealloc (buf, bufmax); \
+ } \
+ memcpy (&buf[bufact], s, _l); \
+ bufact += _l; \
+ } \
+ while (0)
+
+
+#define ADDWC(ch) \
+ do \
+ { \
+ if (buf2act == buf2max) \
+ { \
+ buf2max *= 2; \
+ buf2 = xrealloc (buf2, buf2max * 4); \
+ } \
+ buf2[buf2act++] = (ch); \
+ } \
while (0)
@@ -399,9 +446,8 @@ get_symname (struct linereader *lr)
if (cp == &buf[bufact - 1])
{
/* Yes, it is. */
- lr->token.tok = bufact == 6 ? tok_ucs2 : tok_ucs4;
- lr->token.val.charcode.val = strtoul (buf, NULL, 16);
- lr->token.val.charcode.nbytes = lr->token.tok == tok_ucs2 ? 2 : 4;
+ lr->token.tok = tok_ucs4;
+ lr->token.val.ucs4 = strtoul (buf + 1, NULL, 16);
return &lr->token;
}
@@ -422,8 +468,8 @@ get_symname (struct linereader *lr)
buf[bufact] = '\0';
buf = xrealloc (buf, bufact + 1);
- lr->token.val.str.start = buf;
- lr->token.val.str.len = bufact - 1;
+ lr->token.val.str.startmb = buf;
+ lr->token.val.str.lenmb = bufact - 1;
}
return &lr->token;
@@ -446,8 +492,18 @@ get_ident (struct linereader *lr)
while (!isspace ((ch = lr_getc (lr))) && ch != '"' && ch != ';'
&& ch != '<' && ch != ',')
- /* XXX Handle escape sequences? */
- ADDC (ch);
+ {
+ if (ch == lr->escape_char)
+ {
+ ch = lr_getc (lr);
+ if (ch == '\n' || ch == EOF)
+ {
+ lr_error (lr, _("invalid escape sequence"));
+ break;
+ }
+ }
+ ADDC (ch);
+ }
lr_ungetn (lr, 1);
@@ -465,8 +521,8 @@ get_ident (struct linereader *lr)
buf[bufact] = '\0';
buf = xrealloc (buf, bufact + 1);
- lr->token.val.str.start = buf;
- lr->token.val.str.len = bufact;
+ lr->token.val.str.startmb = buf;
+ lr->token.val.str.lenmb = bufact;
}
return &lr->token;
@@ -474,113 +530,247 @@ get_ident (struct linereader *lr)
static struct token *
-get_string (struct linereader *lr, const struct charset_t *charset)
+get_string (struct linereader *lr, const struct charmap_t *charmap,
+ const struct repertoire_t *repertoire)
{
- int illegal_string = 0;
- char *buf, *cp;
+ int return_widestr = lr->return_widestr;
+ char *buf;
+ char *buf2 = NULL;
size_t bufact;
size_t bufmax = 56;
- int ch;
+ /* We must return two different strings. */
buf = xmalloc (bufmax);
bufact = 0;
- while ((ch = lr_getc (lr)) != '"' && ch != '\n' && ch != EOF)
- if (ch != '<' || charset == NULL)
- {
- if (ch == lr->escape_char)
- {
- ch = lr_getc (lr);
- if (ch == '\n' || ch == EOF)
- break;
- }
+ /* We know it'll be a string. */
+ lr->token.tok = tok_string;
+
+ /* If we need not translate the strings (i.e., expand <...> parts)
+ we can run a simple loop. */
+ if (!lr->translate_strings)
+ {
+ int ch;
+
+ buf2 = NULL;
+ while ((ch = lr_getc (lr)) != '"' && ch != '\n' && ch != EOF)
ADDC (ch);
- }
- else
- {
- /* We have to get the value of the symbol. */
- unsigned int value;
- size_t startidx = bufact;
-
- if (!lr->translate_strings)
- ADDC ('<');
-
- while ((ch = lr_getc (lr)) != '>' && ch != '\n' && ch != EOF)
- {
- if (ch == lr->escape_char)
- {
- ch = lr_getc (lr);
- if (ch == '\n' || ch == EOF)
- break;
- }
- ADDC (ch);
- }
-
- if (ch == '\n' || ch == EOF)
- lr_error (lr, _("unterminated string"));
- else
- if (!lr->translate_strings)
- ADDC ('>');
-
- if (lr->translate_strings)
- {
- value = charset_find_value (&charset->char_table, &buf[startidx],
- bufact - startidx);
- if ((wchar_t) value == ILLEGAL_CHAR_VALUE)
+
+ /* Catch errors with trailing escape character. */
+ if (bufact > 0 && buf[bufact - 1] == lr->escape_char
+ && (bufact == 1 || buf[bufact - 2] != lr->escape_char))
+ {
+ lr_error (lr, _("illegal escape sequence at end of string"));
+ --bufact;
+ }
+ else if (ch == '\n' || ch == EOF)
+ lr_error (lr, _("unterminated string"));
+
+ ADDC ('\0');
+ }
+ else
+ {
+ int illegal_string = 0;
+ size_t buf2act = 0;
+ size_t buf2max = 56 * sizeof (uint32_t);
+ int ch;
+ int warned = 0;
+
+ /* We have to provide the wide character result as well. */
+ if (return_widestr)
+ buf2 = xmalloc (buf2max);
+
+ /* Read until the end of the string (or end of the line or file). */
+ while ((ch = lr_getc (lr)) != '"' && ch != '\n' && ch != EOF)
+ {
+ size_t startidx;
+ uint32_t wch;
+ struct charseq *seq;
+
+ if (ch != '<')
+ {
+ /* The standards leave it up to the implementation to decide
+ what to do with character which stand for themself. We
+ could jump through hoops to find out the value relative to
+ the charmap and the repertoire map, but instead we leave
+ it up to the locale definition author to write a better
+ definition. We assume here that every character which
+ stands for itself is encoded using ISO 8859-1. Using the
+ escape character is allowed. */
+ if (ch == lr->escape_char)
+ {
+ ch = lr_getc (lr);
+ if (ch == '\n' || ch == EOF)
+ break;
+ }
+
+ if (verbose && !warned)
+ {
+ lr_error (lr, _("\
+non-symbolic character value should not be used"));
+ warned = 1;
+ }
+
+ ADDC (ch);
+ if (return_widestr)
+ ADDWC ((uint32_t) ch);
+
+ continue;
+ }
+
+ /* Now we have to search for the end of the symbolic name, i.e.,
+ the closing '>'. */
+ startidx = bufact;
+ while ((ch = lr_getc (lr)) != '>' && ch != '\n' && ch != EOF)
+ {
+ if (ch == lr->escape_char)
+ {
+ ch = lr_getc (lr);
+ if (ch == '\n' || ch == EOF)
+ break;
+ }
+ ADDC (ch);
+ }
+ if (ch == '\n' || ch == EOF)
+ /* Not a correct string. */
+ break;
+ if (bufact == startidx)
+ {
+ /* <> is no correct name. Ignore it and also signal an
+ error. */
illegal_string = 1;
- bufact = startidx;
+ continue;
+ }
- if (bufmax - bufact < 8)
- {
- bufmax *= 2;
- buf = (char *) xrealloc (buf, bufmax);
- }
+ /* It might be a Uxxxx symbol. */
+ if (buf[startidx] == 'U'
+ && (bufact - startidx == 5 || bufact - startidx == 9))
+ {
+ char *cp = buf + startidx + 1;
+ while (cp < &buf[bufact] && isxdigit (*cp))
+ ++cp;
+
+ if (cp == &buf[bufact])
+ {
+ const char *symbol = NULL;
+
+ /* Yes, it is. */
+ ADDC ('\0');
+ wch = strtoul (buf + startidx + 1, NULL, 16);
+
+ /* Now forget about the name we just added. */
+ bufact = startidx;
+
+ if (return_widestr)
+ ADDWC (wch);
+
+ /* Now determine from the repertoire the name of the
+ character and find it in the charmap. */
+ if (repertoire != NULL)
+ symbol = repertoire_find_symbol (repertoire, wch);
+
+ if (symbol == NULL)
+ {
+ /* We cannot generate a string since we cannot map
+ from the Unicode number to the character symbol. */
+ lr_error (lr,
+ _("character <U%0*X> not in repertoire map"),
+ wch > 0xffff ? 8 : 4, wch);
+
+ illegal_string = 1;
+ }
+ else
+ {
+ seq = charmap_find_value (charmap, symbol,
+ strlen (symbol));
+
+ if (seq == NULL)
+ {
+ /* Not a known name. */
+ lr_error (lr,
+ _("symbol `%s' not in charmap"), symbol);
+ illegal_string = 1;
+ }
+ else
+ ADDS (seq->bytes, seq->nbytes);
+ }
+
+ continue;
+ }
+ }
+
+ if (return_widestr)
+ {
+ /* We now have the symbolic name in buf[startidx] to
+ buf[bufact-1]. Now find out the value for this
+ character in the repertoire map as well as in the
+ charmap (in this order). */
+ wch = repertoire_find_value (repertoire, &buf[startidx],
+ bufact - startidx);
+ if (wch == ILLEGAL_CHAR_VALUE)
+ {
+ /* This name is not in the repertoire map. */
+ lr_error (lr, _("symbol `%.*s' not in repertoire map"),
+ bufact - startidx, &buf[startidx]);
+ illegal_string = 1;
+ }
+ else
+ ADDWC (wch);
+ }
+
+ /* Now the same for the multibyte representation. */
+ seq = charmap_find_value (charmap, &buf[startidx],
+ bufact - startidx);
- cp = &buf[bufact];
- if (encode_char (value, &cp))
+ if (seq == NULL)
+ {
+ /* This name is not in the charmap. */
+ lr_error (lr, _("symbol `%.*s' not in charmap"),
+ bufact - startidx, &buf[startidx]);
illegal_string = 1;
- bufact = cp - buf;
- }
- }
+ /* Now forget about the name we just added. */
+ bufact = startidx;
+ }
+ else
+ {
+ /* Now forget about the name we just added. */
+ bufact = startidx;
- /* Catch errors with trailing escape character. */
- if (bufact > 0 && buf[bufact - 1] == lr->escape_char
- && (bufact == 1 || buf[bufact - 2] != lr->escape_char))
- {
- lr_error (lr, _("illegal escape sequence at end of string"));
- --bufact;
- }
- else if (ch == '\n' || ch == EOF)
- lr_error (lr, _("unterminated string"));
+ ADDS (seq->bytes, seq->nbytes);
+ }
+ }
- /* Terminate string if necessary. */
- if (lr->translate_strings)
- {
- cp = &buf[bufact];
- if (encode_char (0, &cp))
- illegal_string = 1;
+ if (ch == '\n' || ch == EOF)
+ {
+ lr_error (lr, _("unterminated string"));
+ illegal_string = 1;
+ }
- bufact = cp - buf;
- }
- else
- ADDC ('\0');
+ if (illegal_string)
+ {
+ free (buf);
+ if (buf2 != NULL)
+ free (buf2);
+ lr->token.val.str.startmb = NULL;
+ lr->token.val.str.lenmb = 0;
- lr->token.tok = tok_string;
+ return &lr->token;
+ }
- if (illegal_string)
- {
- free (buf);
- lr->token.val.str.start = NULL;
- lr->token.val.str.len = 0;
- }
- else
- {
- buf = xrealloc (buf, bufact + 1);
+ ADDC ('\0');
- lr->token.val.str.start = buf;
- lr->token.val.str.len = bufact;
+ if (return_widestr)
+ {
+ ADDWC (0);
+ lr->token.val.str.startwc = xrealloc (buf2,
+ buf2act * sizeof (uint32_t));
+ lr->token.val.str.lenwc = buf2act;
+ }
}
+ lr->token.val.str.startmb = xrealloc (buf, bufact);
+ lr->token.val.str.lenmb = bufact;
+
return &lr->token;
}
diff --git a/locale/programs/linereader.h b/locale/programs/linereader.h
index 6f81b81597..1c98f686c1 100644
--- a/locale/programs/linereader.h
+++ b/locale/programs/linereader.h
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
+ Contributed by Ulrich Drepper, <drepper@gnu.org>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -22,13 +22,16 @@
#include <ctype.h>
#include <libintl.h>
+#include <stdint.h>
#include <stdio.h>
+#include "charmap.h"
#include "error.h"
#include "locfile-token.h"
+#include "repertoire.h"
-typedef const struct keyword_t *(*kw_hash_fct_t) (const char *, int);
+typedef const struct keyword_t *(*kw_hash_fct_t) (const char *, unsigned int);
struct charset_t;
@@ -39,15 +42,20 @@ struct token
{
struct
{
- char *start;
- size_t len;
+ char *startmb;
+ size_t lenmb;
+ uint32_t *startwc;
+ size_t lenwc;
} str;
unsigned long int num;
struct
{
- unsigned int val;
+ /* This element is sized on the safe expectation that no single
+ character in any character set uses more then 16 bytes. */
+ unsigned char bytes[16];
int nbytes;
} charcode;
+ uint32_t ucs4;
} val;
};
@@ -69,18 +77,20 @@ struct linereader
struct token token;
int translate_strings;
+ int return_widestr;
kw_hash_fct_t hash_fct;
};
/* Functions defined in linereader.c. */
-struct linereader *lr_open (const char *fname, kw_hash_fct_t hf);
-int lr_eof (struct linereader *lr);
-void lr_close (struct linereader *lr);
-int lr_next (struct linereader *lr);
-struct token *lr_token (struct linereader *lr,
- const struct charset_t *charset);
+extern struct linereader *lr_open (const char *fname, kw_hash_fct_t hf);
+extern int lr_eof (struct linereader *lr);
+extern void lr_close (struct linereader *lr);
+extern int lr_next (struct linereader *lr);
+extern struct token *lr_token (struct linereader *lr,
+ const struct charmap_t *charmap,
+ const struct repertoire_t *repertoire);
#define lr_error(lr, fmt, args...) \
diff --git a/locale/programs/locale-spec.c b/locale/programs/locale-spec.c
index 9ba49f0a4d..368306c1c6 100644
--- a/locale/programs/locale-spec.c
+++ b/locale/programs/locale-spec.c
@@ -109,7 +109,7 @@ locale_special (const char *name, int show_category_name,
{
printf ("%s<%s>", first ? "" : ",",
&__collate_symbol_strings[__collate_symbol_hash[2 * cnt]]);
-#if 1
+#if 0
{
size_t idx = __collate_symbol_hash[2 * cnt + 1];
size_t cls;
diff --git a/locale/programs/locale.c b/locale/programs/locale.c
index 9d6a931123..775500e44f 100644
--- a/locale/programs/locale.c
+++ b/locale/programs/locale.c
@@ -1,7 +1,7 @@
/* Implementation of the locale program according to POSIX 9945-2.
- Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -129,7 +129,7 @@ struct category
/* We have all categories defined in `categories.def'. Now construct
the description and data structure used for all categories. */
#define DEFINE_ELEMENT(Item, More...) { Item, ## More },
-#define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
+#define DEFINE_CATEGORY(category, name, items, postload) \
static struct cat_item category##_desc[] = \
{ \
NO_PAREN items \
@@ -140,7 +140,7 @@ struct category
static struct category category[] =
{
-#define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
+#define DEFINE_CATEGORY(category, name, items, postload) \
[category] = { _NL_NUM_##category, name, NELEMS (category##_desc), \
category##_desc },
#include "categories.def"
diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c
index 69e9dc5555..5eadbf3570 100644
--- a/locale/programs/localedef.c
+++ b/locale/programs/localedef.c
@@ -1,6 +1,6 @@
/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -30,26 +30,16 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#ifdef _POSIX2_LOCALEDEF
-# include <sys/mman.h>
-#endif
+#include <sys/mman.h>
#include <sys/stat.h>
#include "error.h"
-#include "charset.h"
+#include "charmap.h"
#include "locfile.h"
-#include "locales.h"
-
-/* This is a special entry of the copylist. For all categories we don't
- have a definition we use the data for the POSIX locale. */
-struct copy_def_list_t copy_posix =
-{
- next: NULL,
- name: "POSIX",
- mask: (1 << LC_ALL) - 1,
- locale: NULL
-};
+/* Undefine the following line in the production version. */
+/* #define NDEBUG 1 */
+#include <assert.h>
/* List of copied locales. */
@@ -74,7 +64,10 @@ static const char *charmap_file;
static const char *input_file;
/* Name of the repertoire map file. */
-const char *repertoiremap;
+const char *repertoire_global;
+
+/* List of all locales. */
+static struct localedef_t *locales;
/* Name and version of program. */
@@ -88,11 +81,10 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
static const struct argp_option options[] =
{
{ NULL, 0, NULL, 0, N_("Input Files:") },
- { "charmap", 'f', N_("FILE"), 0,
+ { "charmap", 'f', "FILE", 0,
N_("Symbolic character names defined in FILE") },
- { "inputfile", 'i', N_("FILE"), 0,
- N_("Source definitions are found in FILE") },
- { "repertoire-map", 'u', N_("FILE"), 0,
+ { "inputfile", 'i', "FILE", 0, N_("Source definitions are found in FILE") },
+ { "repertoire-map", 'u', "FILE", 0,
N_("FILE contains mapping from symbolic names to UCS4 values") },
{ NULL, 0, NULL, 0, N_("Output control:") },
@@ -125,7 +117,7 @@ static struct argp argp =
/* Prototypes for global functions. */
-void *xmalloc (size_t __n);
+extern void *xmalloc (size_t __n);
/* Prototypes for local functions. */
static void error_print (void);
@@ -138,12 +130,12 @@ main (int argc, char *argv[])
{
const char *output_path;
int cannot_write_why;
- struct charset_t *charset;
- struct localedef_t *localedef;
- struct copy_def_list_t *act_add_locdef;
+ struct charmap_t *charmap;
+ struct localedef_t global;
int remaining;
/* Set initial values for global variables. */
+ copy_list = NULL;
posix_conformance = getenv ("POSIXLY_CORRECT") != NULL;
error_print_progname = error_print;
@@ -187,135 +179,37 @@ main (int argc, char *argv[])
error (3, 0, _("FATAL: system does not define `_POSIX2_LOCALEDEF'"));
/* Process charmap file. */
- charset = charmap_read (charmap_file);
+ charmap = charmap_read (charmap_file);
+
+ /* Add the first entry in the locale list. */
+ memset (&global, '\0', sizeof (struct localedef_t));
+ global.name = input_file;
+ global.needed = ALL_LOCALES;
+ locales = &global;
/* Now read the locale file. */
- localedef = locfile_read (input_file, charset);
- if (localedef->failed != 0)
+ if (locfile_read (&global, charmap) != 0)
error (4, errno, _("cannot open locale definition file `%s'"), input_file);
- /* Make sure all categories are defined. */
- copy_posix.next = copy_list;
- copy_list = &copy_posix;
-
- /* Perhaps we saw some `copy' instructions. Process the given list.
- We use a very simple algorithm: we look up the list from the
- beginning every time. */
- do
+ /* Perhaps we saw some `copy' instructions. */
+ while (1)
{
- int cat = 0;
+ struct localedef_t *runp = locales;
- for (act_add_locdef = copy_list; act_add_locdef != NULL;
- act_add_locdef = act_add_locdef->next)
- {
- for (cat = LC_CTYPE; cat <= LC_MESSAGES; ++cat)
- if ((act_add_locdef->mask & (1 << cat)) != 0)
- {
- act_add_locdef->mask &= ~(1 << cat);
- break;
- }
- if (cat <= LC_MESSAGES)
- break;
- }
+ while (runp != NULL && runp->needed == runp->avail)
+ runp = runp->next;
- if (act_add_locdef != NULL)
- {
- int avail = 0;
-
- if (act_add_locdef->locale == NULL)
- {
- /* Saving the mask is an ugly trick to prevent the reader
- from modifying `copy_posix' if we currently process it. */
- int save_mask = act_add_locdef->mask;
- act_add_locdef->locale = locfile_read (act_add_locdef->name,
- charset);
- act_add_locdef->mask = save_mask;
- }
-
- if (! act_add_locdef->locale->failed)
- {
- avail = act_add_locdef->locale->categories[cat].generic != NULL;
- if (avail)
- {
- localedef->categories[cat].generic
- = act_add_locdef->locale->categories[cat].generic;
- localedef->avail |= 1 << cat;
- }
- }
-
- if (! avail)
- {
- static const char *locale_names[] =
- {
- "LC_COLLATE", "LC_CTYPE", "LC_MONETARY",
- "LC_NUMERIC", "LC_TIME", "LC_MESSAGES"
- };
- char *fname;
- int fd;
- struct stat st;
-
- asprintf (&fname, LOCALEDIR "/%s/%s", act_add_locdef->name,
- locale_names[cat]);
- fd = open (fname, O_RDONLY);
- if (fd == -1)
- {
- free (fname);
-
- asprintf (&fname, LOCALEDIR "/%s/%s/SYS_%s",
- act_add_locdef->name, locale_names[cat],
- locale_names[cat]);
-
- fd = open (fname, O_RDONLY);
- if (fd == -1)
- error (5, 0, _("\
-locale file `%s', used in `copy' statement, not found"),
- act_add_locdef->name);
- }
-
- if (fstat (fd, &st) < 0)
- error (5, errno, _("\
-cannot `stat' locale file `%s'"),
- fname);
-
- localedef->len[cat] = st.st_size;
-#ifdef _POSIX_MAPPED_FILES
- localedef->categories[cat].generic
- = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-
- if (localedef->categories[cat].generic == MAP_FAILED)
-#endif /* _POSIX_MAPPED_FILES */
- {
- size_t left = st.st_size;
- void *read_ptr;
-
- localedef->categories[cat].generic
- = xmalloc (st.st_size);
- read_ptr = localedef->categories[cat].generic;
-
- do
- {
- long int n;
- n = read (fd, read_ptr, left);
- if (n == -1)
- error (5, errno, _("cannot read locale file `%s'"),
- fname);
- read_ptr += n;
- left -= n;
- }
- while (left > 0);
- }
-
- close (fd);
- free (fname);
-
- localedef->binary |= 1 << cat;
- }
- }
+ if (runp == NULL)
+ /* Everything read. */
+ break;
+
+ if (locfile_read (runp, charmap) != 0)
+ error (4, errno, _("cannot open locale definition file `%s'"),
+ runp->name);
}
- while (act_add_locdef != NULL);
/* Check the categories we processed in source form. */
- check_all_categories (localedef, charset);
+ check_all_categories (locales, charmap);
/* We are now able to write the data files. If warning were given we
do it only if it is explicitly requested (--force). */
@@ -325,7 +219,7 @@ cannot `stat' locale file `%s'"),
error (4, cannot_write_why, _("cannot write output files to `%s'"),
output_path);
else
- write_all_categories (localedef, charset, output_path);
+ write_all_categories (locales, charmap, output_path);
}
else
error (4, 0, _("no output file produced because warning were issued"));
@@ -357,7 +251,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
input_file = arg;
break;
case 'u':
- repertoiremap = arg;
+ repertoire_global = arg;
break;
case 'v':
verbose = 1;
@@ -406,50 +300,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
}
-void
-def_to_process (const char *name, int category)
-{
- struct copy_def_list_t *new, **rp;
-
- for (rp = &copy_list; *rp != NULL; rp = &(*rp)->next)
- if (strcmp (name, (*rp)->name) == 0)
- break;
-
- if (*rp == NULL)
- {
- size_t cnt;
-
- *rp = (struct copy_def_list_t *) xmalloc (sizeof (**rp));
-
- (*rp)->next = NULL;
- (*rp)->name = name;
- (*rp)->mask = 0;
- (*rp)->locale = NULL;
-
- for (cnt = 0; cnt < 6; ++cnt)
- {
- (*rp)->binary[cnt].data = NULL;
- (*rp)->binary[cnt].len = 0;
- }
- }
- new = *rp;
-
- if ((new->mask & category) != 0)
- /* We already have the information. This cannot happen. */
- error (5, 0, _("\
-category data requested more than once: should not happen"));
-
- new->mask |= category;
-}
-
-
/* The address of this function will be assigned to the hook in the error
functions. */
static void
-error_print ()
+error_print (void)
{
- /* We don't want the program name to be printed in messages. Emacs'
- compile.el does not like this. */
}
@@ -461,13 +316,15 @@ construct_output_path (char *path)
{
const char *normal = NULL;
char *result;
+ char *endp;
if (strchr (path, '/') == NULL)
{
/* This is a system path. First examine whether the locale name
contains a reference to the codeset. This should be
normalized. */
- char *startp, *endp;
+ char *startp;
+ size_t n;
startp = path;
/* We must be prepared for finding a CEN name or a location of
@@ -493,17 +350,20 @@ construct_output_path (char *path)
the end of the function we need another byte for the trailing
'/'. */
if (normal == NULL)
- asprintf (&result, "%s/%s%c", LOCALEDIR, path, '\0');
+ n = asprintf (&result, "%s/%s%c", LOCALEDIR, path, '\0');
else
- asprintf (&result, "%s/%.*s%s%s%c", LOCALEDIR, startp - path, path,
- normal, endp, '\0');
+ n = asprintf (&result, "%s/%.*s%s%s%c", LOCALEDIR, startp - path, path,
+ normal, endp, '\0');
+
+ endp = result + n;
}
else
{
/* This is a user path. Please note the additional byte in the
memory allocation. */
- result = xmalloc (strlen (path) + 2);
- strcpy (result, path);
+ size_t len = strlen (path) + 1;
+ result = xmalloc (len + 1);
+ endp = mempcpy (result, path, len);
}
errno = 0;
@@ -516,11 +376,13 @@ construct_output_path (char *path)
mkdir (result, 0777);
}
- strcat (result, "/");
+ *endp++ = '/';
+ *endp = '\0';
return result;
}
+
/* Normalize codeset name. There is no standard for the codeset
names. Normalization allows the user to use any of the common
names. */
@@ -555,7 +417,7 @@ normalize_codeset (codeset, name_len)
for (cnt = 0; cnt < name_len; ++cnt)
if (isalpha (codeset[cnt]))
- *wp++ = _tolower (codeset[cnt]);
+ *wp++ = tolower (codeset[cnt]);
else if (isdigit (codeset[cnt]))
*wp++ = codeset[cnt];
@@ -564,3 +426,52 @@ normalize_codeset (codeset, name_len)
return (const char *) retval;
}
+
+
+struct localedef_t *
+add_to_readlist (int locale, const char *name, const char *repertoire_name)
+{
+ struct localedef_t *runp = locales;
+
+ while (runp != NULL && strcmp (name, runp->name) != 0)
+ runp = runp->next;
+
+ if (runp == NULL)
+ {
+ /* Add a new entry at the end. */
+ struct localedef_t *newp = xcalloc (1, sizeof (struct localedef_t));
+ newp->name = name;
+ newp->repertoire_name = repertoire_name;
+
+ if (locales == NULL)
+ runp = locales = newp;
+ else
+ {
+ runp = locales;
+ while (runp->next != NULL)
+ runp = runp->next;
+ runp = runp->next = newp;
+ }
+ }
+
+ if ((runp->needed & (1 << locale)) != 0)
+ error (5, 0, _("circular dependencies between locale definitions"));
+
+ runp->needed |= 1 << locale;
+
+ return runp;
+}
+
+
+struct localedef_t *
+find_locale (int locale, const char *name, const char *repertoire_name,
+ struct charmap_t *charmap)
+{
+ struct localedef_t *result = add_to_readlist (locale, name, repertoire_name);
+
+ if (locfile_read (result, charmap) != 0)
+ error (4, errno, _("cannot open locale definition file `%s'"),
+ result->name);
+
+ return result;
+}
diff --git a/locale/programs/localedef.h b/locale/programs/localedef.h
new file mode 100644
index 0000000000..075cf8982f
--- /dev/null
+++ b/locale/programs/localedef.h
@@ -0,0 +1,131 @@
+/* General definitions for localedef(1).
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _LOCALEDEF_H
+#define _LOCALEDEF_H 1
+
+/* Get the basic locale definitions. */
+#include <locale.h>
+#include <stddef.h>
+
+#include "repertoire.h"
+
+
+/* We need a bitmask for the locales. */
+enum
+{
+ CTYPE_LOCALE = 1 << LC_CTYPE,
+ NUMERIC_LOCALE = 1 << LC_NUMERIC,
+ TIME_LOCALE = 1 << LC_TIME,
+ COLLATE_LOCALE = 1 << LC_COLLATE,
+ MONETARY_LOCALE = 1 << LC_MONETARY,
+ MESSAGES_LOCALE = 1 << LC_MESSAGES,
+ PAPER_LOCALE = 1 << LC_PAPER,
+ NAME_LOCALE = 1 << LC_NAME,
+ ADDRESS_LOCALE = 1 << LC_ADDRESS,
+ TELEPHONE_LOCALE = 1 << LC_TELEPHONE,
+ MEASUREMENT_LOCALE = 1 << LC_MEASUREMENT,
+ IDENTIFICATION_LOCALE = 1 << LC_IDENTIFICATION,
+ ALL_LOCALES = (1 << LC_CTYPE
+ | 1 << LC_NUMERIC
+ | 1 << LC_TIME
+ | 1 << LC_COLLATE
+ | 1 << LC_MONETARY
+ | 1 << LC_MESSAGES
+ | 1 << LC_PAPER
+ | 1 << LC_NAME
+ | 1 << LC_ADDRESS
+ | 1 << LC_TELEPHONE
+ | 1 << LC_MEASUREMENT
+ | 1 << LC_IDENTIFICATION)
+};
+
+
+/* Opaque types for the different locales. */
+struct locale_ctype_t;
+struct locale_collate_t;
+struct locale_monetary_t;
+struct locale_numeric_t;
+struct locale_time_t;
+struct locale_messages_t;
+struct locale_paper_t;
+struct locale_name_t;
+struct locale_address_t;
+struct locale_telephone_t;
+struct locale_measurement_t;
+struct locale_identification_t;
+
+
+/* Definitions for the locale. */
+struct localedef_t
+{
+ struct localedef_t *next;
+
+ const char *name;
+
+ int needed;
+ int avail;
+
+ union
+ {
+ void *generic;
+ struct locale_ctype_t *ctype;
+ struct locale_collate_t *collate;
+ struct locale_monetary_t *monetary;
+ struct locale_numeric_t *numeric;
+ struct locale_time_t *time;
+ struct locale_messages_t *messages;
+ struct locale_paper_t *paper;
+ struct locale_name_t *name;
+ struct locale_address_t *address;
+ struct locale_telephone_t *telephone;
+ struct locale_measurement_t *measurement;
+ struct locale_identification_t *identification;
+ } categories[12];
+
+ size_t len[12];
+
+ const char *repertoire_name;
+};
+
+
+/* Global variables of the localedef program. */
+extern int verbose;
+extern int be_quiet;
+extern const char *repertoire_global;
+
+
+/* Prototypes for a few program-wide used functions. */
+extern void *xmalloc (size_t __n);
+extern void *xcalloc (size_t __n, size_t __size);
+extern void *xrealloc (void *__p, size_t __n);
+extern char *xstrdup (const char *__str);
+
+
+/* Mark given locale as to be read. */
+extern struct localedef_t *add_to_readlist (int locale, const char *name,
+ const char *repertoire_name);
+
+/* Find the information for the locale NAME. */
+extern struct localedef_t *find_locale (int locale, const char *name,
+ const char *repertoire_name,
+ struct charmap_t *charmap);
+
+#endif /* localedef.h */
diff --git a/locale/programs/locfile-kw.gperf b/locale/programs/locfile-kw.gperf
index 991e9dd6f9..91c20891f1 100644
--- a/locale/programs/locfile-kw.gperf
+++ b/locale/programs/locfile-kw.gperf
@@ -1,7 +1,7 @@
%{
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -24,77 +24,175 @@
%}
struct keyword_t ;
%%
-escape_char, tok_escape_char, 0
-comment_char, tok_comment_char, 0
-repertoiremap, tok_repertoiremap, 0
-LC_CTYPE, tok_lc_ctype, 0
-END, tok_end, 0
-copy, tok_copy, 0
-upper, tok_upper, 0
-lower, tok_lower, 0
-alpha, tok_alpha, 0
-digit, tok_digit, 0
-alnum, tok_alnum, 0
-space, tok_space, 0
-cntrl, tok_cntrl, 0
-punct, tok_punct, 0
-graph, tok_graph, 0
-print, tok_print, 0
-xdigit, tok_xdigit, 0
-blank, tok_blank, 0
-charclass, tok_charclass, 0
-charconv, tok_charconv, 0
-toupper, tok_toupper, 0
-tolower, tok_tolower, 0
-LC_COLLATE, tok_lc_collate, 0
-collating-element, tok_collating_element, 0
-collating-symbol, tok_collating_symbol, 0
-order_start, tok_order_start, 0
-order_end, tok_order_end, 0
-from, tok_from, 0
-forward, tok_forward, 0
-backward, tok_backward, 0
-position, tok_position, 0
-UNDEFINED, tok_undefined, 0
-IGNORE, tok_ignore, 0
-LC_MONETARY, tok_lc_monetary, 0
-int_curr_symbol, tok_int_curr_symbol, 0
-currency_symbol, tok_currency_symbol, 0
-mon_decimal_point, tok_mon_decimal_point, 0
-mon_thousands_sep, tok_mon_thousands_sep, 0
-mon_grouping, tok_mon_grouping, 0
-positive_sign, tok_positive_sign, 0
-negative_sign, tok_negative_sign, 0
-int_frac_digits, tok_int_frac_digits, 0
-frac_digits, tok_frac_digits, 0
-p_cs_precedes, tok_p_cs_precedes, 0
-p_sep_by_space, tok_p_sep_by_space, 0
-n_cs_precedes, tok_n_cs_precedes, 0
-n_sep_by_space, tok_n_sep_by_space, 0
-p_sign_posn, tok_p_sign_posn, 0
-n_sign_posn, tok_n_sign_posn, 0
-LC_NUMERIC, tok_lc_numeric, 0
-decimal_point, tok_decimal_point, 0
-thousands_sep, tok_thousands_sep, 0
-grouping, tok_grouping, 0
-LC_TIME, tok_lc_time, 0
-abday, tok_abday, 0
-day, tok_day, 0
-abmon, tok_abmon, 0
-mon, tok_mon, 0
-d_t_fmt, tok_d_t_fmt, 0
-d_fmt, tok_d_fmt, 0
-t_fmt, tok_t_fmt, 0
-am_pm, tok_am_pm, 0
-t_fmt_ampm, tok_t_fmt_ampm, 0
-era, tok_era, 0
-era_year, tok_era_year, 0
-era_d_fmt, tok_era_d_fmt, 0
-era_d_t_fmt, tok_era_d_t_fmt, 0
-era_t_fmt, tok_era_t_fmt, 0
-alt_digits, tok_alt_digits, 0
-LC_MESSAGES, tok_lc_messages, 0
-yesexpr, tok_yesexpr, 0
-noexpr, tok_noexpr, 0
-yesstr, tok_yesstr, 0
-nostr, tok_nostr, 0
+escape_char, tok_escape_char, 0
+comment_char, tok_comment_char, 0
+repertoiremap, tok_repertoiremap, 0
+include, tok_include, 0
+LC_CTYPE, tok_lc_ctype, 0
+END, tok_end, 0
+copy, tok_copy, 0
+upper, tok_upper, 0
+lower, tok_lower, 0
+alpha, tok_alpha, 0
+digit, tok_digit, 0
+outdigit, tok_outdigit, 0
+alnum, tok_alnum, 0
+space, tok_space, 0
+cntrl, tok_cntrl, 0
+punct, tok_punct, 0
+graph, tok_graph, 0
+print, tok_print, 0
+xdigit, tok_xdigit, 0
+blank, tok_blank, 0
+charclass, tok_charclass, 0
+class, tok_class, 0
+charconv, tok_charconv, 0
+toupper, tok_toupper, 0
+tolower, tok_tolower, 0
+map, tok_map, 0
+translit_start, tok_translit_start, 0
+translit_end, tok_translit_end, 0
+default_missing, tok_default_missing, 0
+LC_COLLATE, tok_lc_collate, 0
+coll_weight_max, tok_coll_weight_max, 0
+section-symbol, tok_section_symbol, 0
+collating-element, tok_collating_element, 0
+collating-symbol, tok_collating_symbol, 0
+symbol-equivalence, tok_symbol_equivalence, 0
+order_start, tok_order_start, 0
+order_end, tok_order_end, 0
+from, tok_from, 0
+forward, tok_forward, 0
+backward, tok_backward, 0
+position, tok_position, 0
+UNDEFINED, tok_undefined, 0
+IGNORE, tok_ignore, 0
+reorder-after, tok_reorder_after, 0
+reorder-end, tok_reorder_end, 0
+reorder-sections-after, tok_reorder_sections_after, 0
+reorder-sections-end, tok_reorder_sections_end, 0
+define, tok_define, 0
+undef, tok_undef, 0
+ifdef, tok_ifdef, 0
+else, tok_else, 0
+elif, tok_elif, 0
+endif, tok_endif, 0
+LC_MONETARY, tok_lc_monetary, 0
+int_curr_symbol, tok_int_curr_symbol, 0
+currency_symbol, tok_currency_symbol, 0
+mon_decimal_point, tok_mon_decimal_point, 0
+mon_thousands_sep, tok_mon_thousands_sep, 0
+mon_grouping, tok_mon_grouping, 0
+positive_sign, tok_positive_sign, 0
+negative_sign, tok_negative_sign, 0
+int_frac_digits, tok_int_frac_digits, 0
+frac_digits, tok_frac_digits, 0
+p_cs_precedes, tok_p_cs_precedes, 0
+p_sep_by_space, tok_p_sep_by_space, 0
+n_cs_precedes, tok_n_cs_precedes, 0
+n_sep_by_space, tok_n_sep_by_space, 0
+p_sign_posn, tok_p_sign_posn, 0
+n_sign_posn, tok_n_sign_posn, 0
+int_p_cs_precedes, tok_int_p_cs_precedes, 0
+int_p_sep_by_space, tok_int_p_sep_by_space, 0
+int_n_cs_precedes, tok_int_n_cs_precedes, 0
+int_n_sep_by_space, tok_int_n_sep_by_space, 0
+int_p_sign_posn, tok_int_p_sign_posn, 0
+int_n_sign_posn, tok_int_n_sign_posn, 0
+duo_int_curr_symbol, tok_duo_int_curr_symbol, 0
+duo_currency_symbol, tok_duo_currency_symbol, 0
+duo_int_frac_digits, tok_duo_int_frac_digits, 0
+duo_frac_digits, tok_duo_frac_digits, 0
+duo_p_cs_precedes, tok_duo_p_cs_precedes, 0
+duo_p_sep_by_space, tok_duo_p_sep_by_space, 0
+duo_n_cs_precedes, tok_duo_n_cs_precedes, 0
+duo_n_sep_by_space, tok_duo_n_sep_by_space, 0
+duo_int_p_cs_precedes, tok_duo_int_p_cs_precedes, 0
+duo_int_p_sep_by_space, tok_duo_int_p_sep_by_space, 0
+duo_int_n_cs_precedes, tok_duo_int_n_cs_precedes, 0
+duo_int_n_sep_by_space, tok_duo_int_n_sep_by_space, 0
+duo_p_sign_posn, tok_duo_p_sign_posn, 0
+duo_n_sign_posn, tok_duo_n_sign_posn, 0
+duo_int_p_sign_posn, tok_duo_int_p_sign_posn, 0
+duo_int_n_sign_posn, tok_duo_int_n_sign_posn, 0
+uno_valid_from, tok_uno_valid_from, 0
+uno_valid_to, tok_uno_valid_to, 0
+duo_valid_from, tok_duo_valid_from, 0
+duo_valid_to, tok_duo_valid_to, 0
+conversion_rate, tok_conversion_rate, 0
+LC_NUMERIC, tok_lc_numeric, 0
+decimal_point, tok_decimal_point, 0
+thousands_sep, tok_thousands_sep, 0
+grouping, tok_grouping, 0
+LC_TIME, tok_lc_time, 0
+abday, tok_abday, 0
+day, tok_day, 0
+week, tok_week, 0
+abmon, tok_abmon, 0
+mon, tok_mon, 0
+d_t_fmt, tok_d_t_fmt, 0
+d_fmt, tok_d_fmt, 0
+t_fmt, tok_t_fmt, 0
+am_pm, tok_am_pm, 0
+t_fmt_ampm, tok_t_fmt_ampm, 0
+era, tok_era, 0
+era_year, tok_era_year, 0
+era_d_fmt, tok_era_d_fmt, 0
+era_d_t_fmt, tok_era_d_t_fmt, 0
+era_t_fmt, tok_era_t_fmt, 0
+alt_digits, tok_alt_digits, 0
+first_weekday, tok_first_weekday, 0
+first_workday, tok_first_workday, 0
+cal_direction, tok_cal_direction, 0
+timezone, tok_timezone, 0
+LC_MESSAGES, tok_lc_messages, 0
+yesexpr, tok_yesexpr, 0
+noexpr, tok_noexpr, 0
+yesstr, tok_yesstr, 0
+nostr, tok_nostr, 0
+LC_PAPER, tok_lc_paper, 0
+height, tok_height, 0
+width, tok_width, 0
+LC_NAME, tok_lc_name, 0
+name_fmt, tok_name_fmt, 0
+name_gen, tok_name_gen, 0
+name_mr, tok_name_mr, 0
+name_mrs, tok_name_mrs, 0
+name_miss, tok_name_miss, 0
+name_ms, tok_name_ms, 0
+LC_ADDRESS, tok_lc_address, 0
+postal_fmt, tok_postal_fmt, 0
+country_name, tok_country_name, 0
+country_post, tok_country_post, 0
+country_ab2, tok_country_ab2, 0
+country_ab3, tok_country_ab3, 0
+country_num, tok_country_num, 0
+country_car, tok_country_car, 0
+country_isbn, tok_country_isbn, 0
+lang_name, tok_lang_name, 0
+lang_ab, tok_lang_ab, 0
+lang_term, tok_lang_term, 0
+lang_lib, tok_lang_lib, 0
+LC_TELEPHONE, tok_lc_telephone, 0
+tel_int_fmt, tok_tel_int_fmt, 0
+tel_dom_fmt, tok_tel_dom_fmt, 0
+int_select, tok_int_select, 0
+int_prefix, tok_int_prefix, 0
+LC_MEASUREMENT, tok_lc_measurement, 0
+measurement, tok_measurement, 0
+LC_IDENTIFICATION, tok_lc_identification, 0
+title, tok_title, 0
+source, tok_source, 0
+address, tok_address, 0
+contact, tok_contact, 0
+email, tok_email, 0
+tel, tok_tel, 0
+fax, tok_fax, 0
+language, tok_language, 0
+territory, tok_territory, 0
+audience, tok_audience, 0
+application, tok_application, 0
+abbreviation, tok_abbreviation, 0
+revision, tok_revision, 0
+date, tok_date, 0
+category, tok_category, 0
diff --git a/locale/programs/locfile-kw.h b/locale/programs/locfile-kw.h
index bd80618e77..811234b25d 100644
--- a/locale/programs/locfile-kw.h
+++ b/locale/programs/locfile-kw.h
@@ -1,8 +1,8 @@
-/* C code produced by gperf version 2.5 (GNU C++ version) */
-/* Command-line: gperf -acCgopt -k1,2,5,$ -N locfile_hash programs/locfile-kw.gperf */
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* ANSI-C code produced by gperf version 2.7.1 (19981006 egcs) */
+/* Command-line: gperf -acCgopt -k1,2,5,9,$ -L ANSI-C -N locfile_hash programs/locfile-kw.gperf */
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -24,174 +24,368 @@
#include "locfile-token.h"
struct keyword_t ;
-#define TOTAL_KEYWORDS 74
+#define TOTAL_KEYWORDS 172
#define MIN_WORD_LENGTH 3
-#define MAX_WORD_LENGTH 17
+#define MAX_WORD_LENGTH 22
#define MIN_HASH_VALUE 3
-#define MAX_HASH_VALUE 178
-/* maximum key range = 176, duplicates = 0 */
+#define MAX_HASH_VALUE 545
+/* maximum key range = 543, duplicates = 0 */
#ifdef __GNUC__
-inline
+__inline
#endif
static unsigned int
-hash (register const char *str, register int len)
+hash (register const char *str, register unsigned int len)
{
- static const unsigned char asso_values[] =
+ static const unsigned short asso_values[] =
{
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 0, 0, 0,
- 0, 0, 179, 0, 179, 179, 0, 179, 0, 45,
- 179, 179, 0, 0, 0, 5, 179, 179, 179, 10,
- 179, 179, 179, 179, 179, 5, 179, 0, 5, 0,
- 15, 20, 5, 20, 40, 20, 179, 25, 15, 50,
- 10, 0, 0, 179, 45, 50, 0, 30, 0, 5,
- 10, 60, 179, 179, 179, 179, 179, 179,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 5, 0, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 20, 546, 0, 0, 0,
+ 5, 30, 0, 0, 546, 546, 0, 546, 0, 0,
+ 546, 546, 10, 0, 5, 10, 546, 546, 546, 0,
+ 546, 546, 546, 546, 546, 30, 546, 0, 10, 125,
+ 5, 0, 105, 30, 5, 95, 546, 0, 105, 155,
+ 135, 50, 75, 0, 5, 45, 0, 55, 0, 30,
+ 25, 25, 10, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
+ 546, 546, 546, 546, 546, 546
};
register int hval = len;
switch (hval)
{
default:
+ case 9:
+ hval += asso_values[(unsigned char)str[8]];
+ case 8:
+ case 7:
+ case 6:
case 5:
- hval += asso_values[str[4]];
+ hval += asso_values[(unsigned char)str[4]];
case 4:
case 3:
case 2:
- hval += asso_values[str[1]];
+ hval += asso_values[(unsigned char)str[1]];
case 1:
- hval += asso_values[str[0]];
+ hval += asso_values[(unsigned char)str[0]];
break;
}
- return hval + asso_values[str[len - 1]];
+ return hval + asso_values[(unsigned char)str[len - 1]];
}
#ifdef __GNUC__
-inline
+__inline
#endif
const struct keyword_t *
-locfile_hash (register const char *str, register int len)
+locfile_hash (register const char *str, register unsigned int len)
{
static const struct keyword_t wordlist[] =
{
- {"",}, {"",}, {"",},
- {"END", tok_end, 0},
- {"",}, {"",},
- {"IGNORE", tok_ignore, 0},
- {"LC_TIME", tok_lc_time, 0},
- {"LC_CTYPE", tok_lc_ctype, 0},
- {"",},
- {"t_fmt", tok_t_fmt, 0},
- {"LC_MESSAGES", tok_lc_messages, 0},
- {"",}, {"",},
- {"UNDEFINED", tok_undefined, 0},
- {"LC_NUMERIC", tok_lc_numeric, 0},
- {"",},
- {"collating-element", tok_collating_element, 0},
- {"position", tok_position, 0},
- {"",},
- {"alpha", tok_alpha, 0},
- {"",}, {"",},
- {"positive_sign", tok_positive_sign, 0},
- {"",},
- {"d_fmt", tok_d_fmt, 0},
- {"",},
- {"forward", tok_forward, 0},
- {"",}, {"",},
- {"abmon", tok_abmon, 0},
- {"collating-symbol", tok_collating_symbol, 0},
- {"d_t_fmt", tok_d_t_fmt, 0},
- {"backward", tok_backward, 0},
- {"",},
- {"punct", tok_punct, 0},
- {"",}, {"",}, {"",},
- {"p_sep_by_space", tok_p_sep_by_space, 0},
- {"digit", tok_digit, 0},
- {"",}, {"",}, {"",}, {"",},
- {"cntrl", tok_cntrl, 0},
- {"p_sign_posn", tok_p_sign_posn, 0},
- {"",},
- {"charconv", tok_charconv, 0},
- {"n_sep_by_space", tok_n_sep_by_space, 0},
- {"print", tok_print, 0},
- {"xdigit", tok_xdigit, 0},
- {"toupper", tok_toupper, 0},
- {"negative_sign", tok_negative_sign, 0},
- {"",},
- {"LC_COLLATE", tok_lc_collate, 0},
- {"n_sign_posn", tok_n_sign_posn, 0},
- {"tolower", tok_tolower, 0},
- {"",}, {"",},
- {"int_curr_symbol", tok_int_curr_symbol, 0},
- {"noexpr", tok_noexpr, 0},
- {"",},
- {"mon", tok_mon, 0},
- {"copy", tok_copy, 0},
- {"t_fmt_ampm", tok_t_fmt_ampm, 0},
- {"LC_MONETARY", tok_lc_monetary, 0},
- {"mon_thousands_sep", tok_mon_thousands_sep, 0},
- {"era", tok_era, 0},
- {"",}, {"",}, {"",}, {"",},
- {"p_cs_precedes", tok_p_cs_precedes, 0},
- {"era_t_fmt", tok_era_t_fmt, 0},
- {"blank", tok_blank, 0},
- {"",},
- {"comment_char", tok_comment_char, 0},
- {"day", tok_day, 0},
- {"",},
- {"currency_symbol", tok_currency_symbol, 0},
- {"",},
- {"mon_decimal_point", tok_mon_decimal_point, 0},
- {"n_cs_precedes", tok_n_cs_precedes, 0},
- {"",}, {"",}, {"",}, {"",}, {"",},
- {"era_d_fmt", tok_era_d_fmt, 0},
- {"alt_digits", tok_alt_digits, 0},
- {"era_d_t_fmt", tok_era_d_t_fmt, 0},
- {"",},
- {"grouping", tok_grouping, 0},
- {"",},
- {"space", tok_space, 0},
- {"",}, {"",},
- {"decimal_point", tok_decimal_point, 0},
- {"charclass", tok_charclass, 0},
- {"int_frac_digits", tok_int_frac_digits, 0},
- {"order_start", tok_order_start, 0},
- {"mon_grouping", tok_mon_grouping, 0},
- {"thousands_sep", tok_thousands_sep, 0},
- {"from", tok_from, 0},
- {"nostr", tok_nostr, 0},
- {"",}, {"",}, {"",}, {"",},
- {"lower", tok_lower, 0},
- {"",}, {"",}, {"",},
- {"order_end", tok_order_end, 0},
- {"",},
- {"frac_digits", tok_frac_digits, 0},
- {"",}, {"",}, {"",},
- {"alnum", tok_alnum, 0},
- {"",}, {"",},
- {"repertoiremap", tok_repertoiremap, 0},
- {"",},
- {"upper", tok_upper, 0},
- {"escape_char", tok_escape_char, 0},
- {"",}, {"",}, {"",},
- {"abday", tok_abday, 0},
- {"yesstr", tok_yesstr, 0},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",},
- {"yesexpr", tok_yesexpr, 0},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"graph", tok_graph, 0},
- {"",}, {"",}, {"",}, {"",},
- {"am_pm", tok_am_pm, 0},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",},
- {"era_year", tok_era_year, 0},
+ {""}, {""}, {""},
+ {"END", tok_end, 0},
+ {""}, {""}, {""},
+ {"LC_TIME", tok_lc_time, 0},
+ {"era", tok_era, 0},
+ {"date", tok_date, 0},
+ {"LC_ADDRESS", tok_lc_address, 0},
+ {""},
+ {"LC_TELEPHONE", tok_lc_telephone, 0},
+ {"LC_CTYPE", tok_lc_ctype, 0},
+ {"era_t_fmt", tok_era_t_fmt, 0},
+ {"LC_COLLATE", tok_lc_collate, 0},
+ {"height", tok_height, 0},
+ {"LC_IDENTIFICATION", tok_lc_identification, 0},
+ {""},
+ {"era_d_fmt", tok_era_d_fmt, 0},
+ {"LC_NUMERIC", tok_lc_numeric, 0},
+ {""}, {""}, {""},
+ {"UNDEFINED", tok_undefined, 0},
+ {""},
+ {"reorder-end", tok_reorder_end, 0},
+ {"LC_NAME", tok_lc_name, 0},
+ {"reorder-after", tok_reorder_after, 0},
+ {"LC_MEASUREMENT", tok_lc_measurement, 0},
+ {""},
+ {"LC_MONETARY", tok_lc_monetary, 0},
+ {""},
+ {"day", tok_day, 0},
+ {"week", tok_week, 0},
+ {"t_fmt", tok_t_fmt, 0},
+ {"yesstr", tok_yesstr, 0},
+ {""},
+ {"LC_PAPER", tok_lc_paper, 0},
+ {""},
+ {"d_fmt", tok_d_fmt, 0},
+ {"LC_MESSAGES", tok_lc_messages, 0},
+ {""},
+ {"era_year", tok_era_year, 0},
+ {""}, {""},
+ {"IGNORE", tok_ignore, 0},
+ {""}, {""}, {""},
+ {"graph", tok_graph, 0},
+ {""}, {""},
+ {"backward", tok_backward, 0},
+ {""}, {""}, {""},
+ {"address", tok_address, 0},
+ {""}, {""}, {""}, {""},
+ {"yesexpr", tok_yesexpr, 0},
+ {"audience", tok_audience, 0},
+ {""},
+ {"abday", tok_abday, 0},
+ {""}, {""}, {""}, {""}, {""},
+ {"order_start", tok_order_start, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"order_end", tok_order_end, 0},
+ {"reorder-sections-end", tok_reorder_sections_end, 0},
+ {""},
+ {"reorder-sections-after", tok_reorder_sections_after, 0},
+ {""}, {""},
+ {"print", tok_print, 0},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ {"tolower", tok_tolower, 0},
+ {""},
+ {"translit_start", tok_translit_start, 0},
+ {""}, {""},
+ {"translit_end", tok_translit_end, 0},
+ {""}, {""},
+ {"title", tok_title, 0},
+ {""}, {""},
+ {"repertoiremap", tok_repertoiremap, 0},
+ {""},
+ {"digit", tok_digit, 0},
+ {""}, {""},
+ {"tel", tok_tel, 0},
+ {"else", tok_else, 0},
+ {"alpha", tok_alpha, 0},
+ {""}, {""},
+ {"timezone", tok_timezone, 0},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ {"blank", tok_blank, 0},
+ {"tel_dom_fmt", tok_tel_dom_fmt, 0},
+ {""}, {""}, {""},
+ {"space", tok_space, 0},
+ {"era_d_t_fmt", tok_era_d_t_fmt, 0},
+ {"duo_valid_to", tok_duo_valid_to, 0},
+ {""}, {""}, {""},
+ {"xdigit", tok_xdigit, 0},
+ {""},
+ {"fax", tok_fax, 0},
+ {""},
+ {"punct", tok_punct, 0},
+ {""},
+ {"toupper", tok_toupper, 0},
+ {"symbol-equivalence", tok_symbol_equivalence, 0},
+ {""},
+ {"width", tok_width, 0},
+ {"escape_char", tok_escape_char, 0},
+ {""}, {""},
+ {"lang_name", tok_lang_name, 0},
+ {"upper", tok_upper, 0},
+ {"define", tok_define, 0},
+ {"d_t_fmt", tok_d_t_fmt, 0},
+ {"grouping", tok_grouping, 0},
+ {""}, {""}, {""},
+ {"lang_ab", tok_lang_ab, 0},
+ {"lang_lib", tok_lang_lib, 0},
+ {"territory", tok_territory, 0},
+ {""}, {""},
+ {"abbreviation", tok_abbreviation, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"alt_digits", tok_alt_digits, 0},
+ {""},
+ {"forward", tok_forward, 0},
+ {"language", tok_language, 0},
+ {""},
+ {"lower", tok_lower, 0},
+ {""}, {""},
+ {"name_fmt", tok_name_fmt, 0},
+ {""}, {""}, {""},
+ {"name_mr", tok_name_mr, 0},
+ {""}, {""}, {""}, {""},
+ {"contact", tok_contact, 0},
+ {"thousands_sep", tok_thousands_sep, 0},
+ {""}, {""},
+ {"country_ab3", tok_country_ab3, 0},
+ {""},
+ {"category", tok_category, 0},
+ {""}, {""},
+ {"country_ab2", tok_country_ab2, 0},
+ {""},
+ {"revision", tok_revision, 0},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ {"nostr", tok_nostr, 0},
+ {""}, {""}, {""},
+ {"copy", tok_copy, 0},
+ {""}, {""}, {""},
+ {"outdigit", tok_outdigit, 0},
+ {""}, {""},
+ {"tel_int_fmt", tok_tel_int_fmt, 0},
+ {""}, {""},
+ {"elif", tok_elif, 0},
+ {""}, {""},
+ {"name_ms", tok_name_ms, 0},
+ {"name_mrs", tok_name_mrs, 0},
+ {""}, {""},
+ {"measurement", tok_measurement, 0},
+ {"collating-element", tok_collating_element, 0},
+ {""},
+ {"p_sep_by_space", tok_p_sep_by_space, 0},
+ {""},
+ {"source", tok_source, 0},
+ {"duo_p_cs_precedes", tok_duo_p_cs_precedes, 0},
+ {"duo_p_sep_by_space", tok_duo_p_sep_by_space, 0},
+ {""}, {""}, {""}, {""},
+ {"map", tok_map, 0},
+ {"duo_valid_from", tok_duo_valid_from, 0},
+ {""}, {""}, {""},
+ {"first_weekday", tok_first_weekday, 0},
+ {""},
+ {"conversion_rate", tok_conversion_rate, 0},
+ {""}, {""},
+ {"first_workday", tok_first_workday, 0},
+ {""}, {""}, {""}, {""},
+ {"decimal_point", tok_decimal_point, 0},
+ {""}, {""}, {""},
+ {"duo_int_p_sep_by_space", tok_duo_int_p_sep_by_space, 0},
+ {""}, {""},
+ {"duo_frac_digits", tok_duo_frac_digits, 0},
+ {""},
+ {"uno_valid_to", tok_uno_valid_to, 0},
+ {""}, {""},
+ {"default_missing", tok_default_missing, 0},
+ {""},
+ {"country_post", tok_country_post, 0},
+ {"charconv", tok_charconv, 0},
+ {"name_miss", tok_name_miss, 0},
+ {""}, {""}, {""},
+ {"position", tok_position, 0},
+ {"from", tok_from, 0},
+ {"t_fmt_ampm", tok_t_fmt_ampm, 0},
+ {"noexpr", tok_noexpr, 0},
+ {""}, {""}, {""},
+ {"coll_weight_max", tok_coll_weight_max, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"n_sep_by_space", tok_n_sep_by_space, 0},
+ {"abmon", tok_abmon, 0},
+ {""},
+ {"duo_n_cs_precedes", tok_duo_n_cs_precedes, 0},
+ {"duo_n_sep_by_space", tok_duo_n_sep_by_space, 0},
+ {""},
+ {"postal_fmt", tok_postal_fmt, 0},
+ {"frac_digits", tok_frac_digits, 0},
+ {"include", tok_include, 0},
+ {""}, {""}, {""},
+ {"duo_int_p_cs_precedes", tok_duo_int_p_cs_precedes, 0},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ {"positive_sign", tok_positive_sign, 0},
+ {"section-symbol", tok_section_symbol, 0},
+ {""}, {""}, {""},
+ {"name_gen", tok_name_gen, 0},
+ {"duo_currency_symbol", tok_duo_currency_symbol, 0},
+ {""}, {""},
+ {"duo_int_n_sep_by_space", tok_duo_int_n_sep_by_space, 0},
+ {"negative_sign", tok_negative_sign, 0},
+ {""},
+ {"duo_p_sign_posn", tok_duo_p_sign_posn, 0},
+ {"country_car", tok_country_car, 0},
+ {"comment_char", tok_comment_char, 0},
+ {"p_cs_precedes", tok_p_cs_precedes, 0},
+ {""}, {""}, {""},
+ {"country_name", tok_country_name, 0},
+ {""},
+ {"duo_int_frac_digits", tok_duo_int_frac_digits, 0},
+ {"class", tok_class, 0},
+ {"collating-symbol", tok_collating_symbol, 0},
+ {""}, {""}, {""},
+ {"currency_symbol", tok_currency_symbol, 0},
+ {"p_sign_posn", tok_p_sign_posn, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""},
+ {"mon_thousands_sep", tok_mon_thousands_sep, 0},
+ {"mon", tok_mon, 0},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ {"endif", tok_endif, 0},
+ {""},
+ {"mon_grouping", tok_mon_grouping, 0},
+ {""},
+ {"charclass", tok_charclass, 0},
+ {""},
+ {"duo_int_n_cs_precedes", tok_duo_int_n_cs_precedes, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"uno_valid_from", tok_uno_valid_from, 0},
+ {""}, {""}, {""}, {""}, {""},
+ {"email", tok_email, 0},
+ {""}, {""}, {""}, {""},
+ {"duo_n_sign_posn", tok_duo_n_sign_posn, 0},
+ {""}, {""},
+ {"n_cs_precedes", tok_n_cs_precedes, 0},
+ {""}, {""}, {""},
+ {"mon_decimal_point", tok_mon_decimal_point, 0},
+ {""},
+ {"duo_int_p_sign_posn", tok_duo_int_p_sign_posn, 0},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ {"n_sign_posn", tok_n_sign_posn, 0},
+ {""}, {""}, {""}, {""}, {""},
+ {"int_p_cs_precedes", tok_int_p_cs_precedes, 0},
+ {"int_p_sep_by_space", tok_int_p_sep_by_space, 0},
+ {""}, {""}, {""}, {""},
+ {"cal_direction", tok_cal_direction, 0},
+ {"duo_int_curr_symbol", tok_duo_int_curr_symbol, 0},
+ {"undef", tok_undef, 0},
+ {""}, {""}, {""}, {""},
+ {"int_select", tok_int_select, 0},
+ {"application", tok_application, 0},
+ {""}, {""}, {""},
+ {"ifdef", tok_ifdef, 0},
+ {""},
+ {"country_isbn", tok_country_isbn, 0},
+ {""}, {""},
+ {"alnum", tok_alnum, 0},
+ {""}, {""}, {""}, {""},
+ {"int_frac_digits", tok_int_frac_digits, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"int_prefix", tok_int_prefix, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"duo_int_n_sign_posn", tok_duo_int_n_sign_posn, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"lang_term", tok_lang_term, 0},
+ {""}, {""},
+ {"int_n_cs_precedes", tok_int_n_cs_precedes, 0},
+ {"int_n_sep_by_space", tok_int_n_sep_by_space, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""},
+ {"am_pm", tok_am_pm, 0},
+ {""}, {""}, {""}, {""},
+ {"cntrl", tok_cntrl, 0},
+ {"country_num", tok_country_num, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {"int_p_sign_posn", tok_int_p_sign_posn, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""},
+ {"int_curr_symbol", tok_int_curr_symbol, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""},
+ {"int_n_sign_posn", tok_int_n_sign_posn, 0}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
@@ -202,7 +396,7 @@ locfile_hash (register const char *str, register int len)
{
register const char *s = wordlist[key].name;
- if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
return &wordlist[key];
}
}
diff --git a/locale/programs/locfile-token.h b/locale/programs/locfile-token.h
index 7845b4ba76..97945f8f1a 100644
--- a/locale/programs/locfile-token.h
+++ b/locale/programs/locfile-token.h
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -28,17 +28,19 @@ enum token_t
tok_eol,
tok_bsymbol,
tok_ident,
- tok_ellipsis,
+ tok_ellipsis2,
+ tok_ellipsis3,
+ tok_ellipsis4,
tok_semicolon,
tok_comma,
tok_open_brace,
tok_close_brace,
tok_charcode,
- tok_ucs2,
tok_ucs4,
tok_number,
tok_minus1,
tok_string,
+ tok_include,
tok_escape_char,
tok_comment_char,
@@ -48,6 +50,8 @@ enum token_t
tok_g1esc,
tok_g2esc,
tok_g3esc,
+ tok_escseq,
+ tok_addset,
tok_charids,
@@ -62,6 +66,7 @@ enum token_t
tok_lc_ctype,
tok_copy,
+ /* Keep the following entries up to the next comment in this order! */
tok_upper,
tok_lower,
tok_alpha,
@@ -74,12 +79,22 @@ enum token_t
tok_cntrl,
tok_punct,
tok_alnum,
+ /* OK, shuffling allowed again. */
+ tok_outdigit,
tok_charclass,
+ tok_class,
tok_toupper,
tok_tolower,
+ tok_map,
+ tok_translit_start,
+ tok_translit_end,
+ tok_default_missing,
tok_lc_collate,
+ tok_coll_weight_max,
+ tok_section_symbol,
tok_collating_element,
tok_collating_symbol,
+ tok_symbol_equivalence,
tok_order_start,
tok_order_end,
tok_from,
@@ -88,6 +103,17 @@ enum token_t
tok_position,
tok_undefined,
tok_ignore,
+ tok_reorder_after,
+ tok_reorder_end,
+ tok_reorder_sections_after,
+ tok_reorder_sections_end,
+ tok_define,
+ tok_undef,
+ tok_ifdef,
+ tok_ifndef,
+ tok_else,
+ tok_elif,
+ tok_endif,
tok_lc_monetary,
tok_int_curr_symbol,
tok_currency_symbol,
@@ -104,6 +130,33 @@ enum token_t
tok_n_sep_by_space,
tok_p_sign_posn,
tok_n_sign_posn,
+ tok_int_p_cs_precedes,
+ tok_int_p_sep_by_space,
+ tok_int_n_cs_precedes,
+ tok_int_n_sep_by_space,
+ tok_int_p_sign_posn,
+ tok_int_n_sign_posn,
+ tok_duo_int_curr_symbol,
+ tok_duo_currency_symbol,
+ tok_duo_int_frac_digits,
+ tok_duo_frac_digits,
+ tok_duo_p_cs_precedes,
+ tok_duo_p_sep_by_space,
+ tok_duo_n_cs_precedes,
+ tok_duo_n_sep_by_space,
+ tok_duo_int_p_cs_precedes,
+ tok_duo_int_p_sep_by_space,
+ tok_duo_int_n_cs_precedes,
+ tok_duo_int_n_sep_by_space,
+ tok_duo_p_sign_posn,
+ tok_duo_n_sign_posn,
+ tok_duo_int_p_sign_posn,
+ tok_duo_int_n_sign_posn,
+ tok_uno_valid_from,
+ tok_uno_valid_to,
+ tok_duo_valid_from,
+ tok_duo_valid_to,
+ tok_conversion_rate,
tok_lc_numeric,
tok_decimal_point,
tok_thousands_sep,
@@ -124,11 +177,61 @@ enum token_t
tok_era_d_t_fmt,
tok_era_t_fmt,
tok_alt_digits,
+ tok_week,
+ tok_first_weekday,
+ tok_first_workday,
+ tok_cal_direction,
+ tok_timezone,
tok_lc_messages,
tok_yesexpr,
tok_noexpr,
tok_yesstr,
tok_nostr,
+ tok_lc_paper,
+ tok_height,
+ tok_lc_name,
+ tok_name_fmt,
+ tok_name_gen,
+ tok_name_mr,
+ tok_name_mrs,
+ tok_name_miss,
+ tok_name_ms,
+ tok_lc_address,
+ tok_postal_fmt,
+ tok_country_name,
+ tok_country_post,
+ tok_country_ab2,
+ tok_country_ab3,
+ tok_country_num,
+ tok_country_car,
+ tok_country_isbn,
+ tok_lang_name,
+ tok_lang_ab,
+ tok_lang_term,
+ tok_lang_lib,
+ tok_lc_telephone,
+ tok_tel_int_fmt,
+ tok_tel_dom_fmt,
+ tok_int_select,
+ tok_int_prefix,
+ tok_lc_measurement,
+ tok_measurement,
+ tok_lc_identification,
+ tok_title,
+ tok_source,
+ tok_address,
+ tok_contact,
+ tok_email,
+ tok_tel,
+ tok_fax,
+ tok_language,
+ tok_territory,
+ tok_audience,
+ tok_application,
+ tok_abbreviation,
+ tok_revision,
+ tok_date,
+ tok_category,
tok_error
};
diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c
index 79d6ab13e6..fd858e2541 100644
--- a/locale/programs/locfile.c
+++ b/locale/programs/locfile.c
@@ -23,63 +23,36 @@
#include <errno.h>
#include <fcntl.h>
-#include <locale.h>
-#include <malloc.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
-#include <libintl.h>
+#include <sys/param.h>
#include <sys/stat.h>
-#include <sys/uio.h>
+#include "localedef.h"
#include "locfile.h"
-#include "linereader.h"
-#include "localeinfo.h"
-#include "locales.h"
-
-/* Uncomment the following line in the production version. */
-/* #define NDEBUG 1 */
-#include <assert.h>
-
-/* Define the lookup function. */
#include "locfile-kw.h"
-/* Some useful macros. */
-#define MIN(a, b) (__extension__ ({ typeof (a) _a = (a); \
- typeof (b) _b = (b); \
- _a < _b ? _a : _b; }))
-
-
-void *xmalloc (size_t __n);
-char *xstrdup (const char *__str);
-
-struct localedef_t *
-locfile_read (const char *filename, struct charset_t *charset)
+int
+locfile_read (struct localedef_t *result, struct charmap_t *charmap)
{
- struct repertoire_t *repertoire = NULL;
+ const char *filename = result->name;
+ const char *repertoire_name = result->repertoire_name;
+ int locale_mask = result->needed ^ result->avail;
struct linereader *ldfile;
- struct localedef_t *result;
- int state;
- enum token_t expected_tok = tok_none;
- const char *expected_str = NULL;
- enum token_t ctype_tok_sym = tok_none;
- const char *ctype_tok_str = NULL;
- int copy_category = 0;
- int cnt;
- /* Allocate space for result. */
- result = (struct localedef_t *) xmalloc (sizeof (struct localedef_t));
- memset (result, '\0', sizeof (struct localedef_t));
+ /* If no repertoire name was specified use the global one. */
+ if (repertoire_name == NULL)
+ repertoire_name = repertoire_global;
+ /* Open the locale definition file. */
ldfile = lr_open (filename, locfile_hash);
if (ldfile == NULL)
{
if (filename[0] != '/')
{
- char *i18npath = __secure_getenv ("I18NPATH");
+ char *i18npath = getenv ("I18NPATH");
if (i18npath != NULL && *i18npath != '\0')
{
char path[strlen (filename) + 1 + strlen (i18npath)
@@ -94,6 +67,13 @@ locfile_read (const char *filename, struct charset_t *charset)
stpcpy (stpcpy (stpcpy (path, next), "/locales/"), filename);
ldfile = lr_open (path, locfile_hash);
+
+ if (ldfile == NULL)
+ {
+ stpcpy (stpcpy (path, next), filename);
+
+ ldfile = lr_open (path, locfile_hash);
+ }
}
}
@@ -108,965 +88,219 @@ locfile_read (const char *filename, struct charset_t *charset)
}
if (ldfile == NULL)
- {
- result->failed = 1;
- return result;
- }
+ return 1;
}
-#define HANDLE_COPY(category, token, string) \
- if (nowtok == tok_copy) \
- { \
- copy_posix.mask &= ~(1 << category); \
- copy_category = category; \
- expected_tok = token; \
- expected_str = string; \
- state = 8; \
- continue; \
- } \
- ++state
-
-#define LOCALE_PROLOG(token, string) \
- if (nowtok == tok_eol) \
- /* Ignore empty lines. */ \
- continue; \
- if (nowtok == tok_end) \
- { \
- expected_tok = token; \
- expected_str = string; \
- state = 4; \
- continue; \
- } \
- if (nowtok == tok_copy) \
- goto only_copy;
-
-
-#define READ_STRING(fn, errlabel) \
- do \
- { \
- arg = lr_token (ldfile, charset); \
- if (arg->tok != tok_string) \
- goto errlabel; \
- fn (ldfile, result, nowtok, arg, charset); \
- lr_ignore_rest (ldfile, 1); \
- } \
- while (0)
-
-#define READ_STRING_LIST(fn, errlabel) \
- do \
- { \
- arg = lr_token (ldfile, charset); \
- while (arg->tok == tok_string) \
- { \
- fn (ldfile, result, nowtok, arg, charset); \
- arg = lr_token (ldfile, charset); \
- if (arg->tok != tok_semicolon) \
- break; \
- arg = lr_token (ldfile, charset); \
- } \
- if (arg->tok != tok_eol) \
- goto errlabel; \
- } \
- while (0)
-
-#define READ_NUMBER(fn, errlabel) \
- do \
- { \
- arg = lr_token (ldfile, charset); \
- if (arg->tok != tok_minus1 && arg->tok != tok_number) \
- goto errlabel; \
- fn (ldfile, result, nowtok, arg, charset); \
- lr_ignore_rest (ldfile, 1); \
- } \
- while (0)
-
-#define READ_NUMBER_LIST(fn, errlabel) \
- do \
- { \
- arg = lr_token (ldfile, charset); \
- while (arg->tok == tok_minus1 || arg->tok == tok_number) \
- { \
- fn (ldfile, result, nowtok, arg, charset); \
- arg = lr_token (ldfile, charset); \
- if (arg->tok != tok_semicolon) \
- break; \
- arg = lr_token (ldfile, charset); \
- } \
- if (arg->tok != tok_eol) \
- goto errlabel; \
- } \
- while (0)
-
-#define SYNTAX_ERROR(string) \
- lr_error (ldfile, string); \
- lr_ignore_rest (ldfile, 0);
-
-
- /* Parse locale definition file and store result in RESULT. */
- state = 1;
+ /* Parse locale definition file and store result in RESULT. */
while (1)
{
- /* What's on? */
- struct token *now = lr_token (ldfile, charset);
+ struct token *now = lr_token (ldfile, charmap, NULL);
enum token_t nowtok = now->tok;
struct token *arg;
if (nowtok == tok_eof)
break;
- switch (state)
- {
- case 1:
- /* The beginning. We expect the special declarations, EOL or
- the start of any locale. */
- if (nowtok == tok_eol)
- /* Ignore empty lines. */
- continue;
-
- switch (nowtok)
- {
- case tok_escape_char:
- case tok_comment_char:
- /* We need an argument. */
- arg = lr_token (ldfile, charset);
-
- if (arg->tok != tok_ident)
- {
- SYNTAX_ERROR (_("bad argument"));
- continue;
- }
-
- if (arg->val.str.len != 1)
- {
- lr_error (ldfile, _("\
-argument to `%s' must be a single character"),
- nowtok == tok_escape_char ? "escape_char"
- : "comment_char");
-
- lr_ignore_rest (ldfile, 0);
- continue;
- }
-
- if (nowtok == tok_escape_char)
- ldfile->escape_char = *arg->val.str.start;
- else
- ldfile->comment_char = *arg->val.str.start;
- break;
-
- case tok_repertoiremap:
- /* We need an argument. */
- arg = lr_token (ldfile, charset);
-
- if (arg->tok != tok_ident)
- {
- SYNTAX_ERROR (_("bad argument"));
- continue;
- }
-
- if (repertoiremap == NULL)
- {
- repertoiremap = memcpy (xmalloc (arg->val.str.len + 1),
- arg->val.str.start,
- arg->val.str.len);
- ((char *) repertoiremap)[arg->val.str.len] = '\0';
- }
-
- lr_ignore_rest (ldfile, 1);
- continue;
-
- case tok_lc_ctype:
- if (repertoire == NULL)
- {
- /* Read the repertoire map now. */
- if (repertoiremap == NULL)
- /* This is fatal. */
- error (4, 0,
- _("no repertoire map specified: cannot proceed"));
-
- repertoire = repertoire_read (repertoiremap);
- if (repertoire == NULL)
- /* This is also fatal. */
- error (4, errno, _("cannot read repertoire map `%s'"),
- repertoiremap);
- }
- state = 2;
- break;
-
- case tok_lc_collate:
- if (repertoire == NULL)
- {
- /* Read the repertoire map now. */
- if (repertoiremap == NULL)
- /* This is fatal. */
- error (4, 0,
- _("no repertoire map specified: cannot proceed"));
-
- repertoire = repertoire_read (repertoiremap);
- if (repertoire == NULL)
- /* This is also fatal. */
- error (4, errno, _("cannot read repertoire map `%s'"),
- repertoiremap);
- }
- state = 10;
- break;
-
- case tok_lc_monetary:
- if (repertoire == NULL)
- {
- /* Read the repertoire map now. */
- if (repertoiremap == NULL)
- /* This is fatal. */
- error (4, 0,
- _("no repertoire map specified: cannot proceed"));
-
- repertoire = repertoire_read (repertoiremap);
- if (repertoire == NULL)
- /* This is also fatal. */
- error (4, errno, _("cannot read repertoire map `%s'"),
- repertoiremap);
- }
- state = 20;
- break;
+ if (nowtok == tok_eol)
+ /* Ignore empty lines. */
+ continue;
- case tok_lc_numeric:
- if (repertoire == NULL)
- {
- /* Read the repertoire map now. */
- if (repertoiremap == NULL)
- /* This is fatal. */
- error (4, 0,
- _("no repertoire map specified: cannot proceed"));
-
- repertoire = repertoire_read (repertoiremap);
- if (repertoire == NULL)
- /* This is also fatal. */
- error (4, errno, _("cannot read repertoire map `%s'"),
- repertoiremap);
- }
- state = 30;
- break;
-
- case tok_lc_time:
- if (repertoire == NULL)
- {
- /* Read the repertoire map now. */
- if (repertoiremap == NULL)
- /* This is fatal. */
- error (4, 0,
- _("no repertoire map specified: cannot proceed"));
-
- repertoire = repertoire_read (repertoiremap);
- if (repertoire == NULL)
- /* This is also fatal. */
- error (4, errno, _("cannot read repertoire map `%s'"),
- repertoiremap);
- }
- state = 40;
- break;
-
- case tok_lc_messages:
- if (repertoire == NULL)
- {
- /* Read the repertoire map now. */
- if (repertoiremap == NULL)
- /* This is fatal. */
- error (4, 0,
- _("no repertoire map specified: cannot proceed"));
-
- repertoire = repertoire_read (repertoiremap);
- if (repertoire == NULL)
- /* This is also fatal. */
- error (4, errno, _("cannot read repertoire map `%s'"),
- repertoiremap);
- }
- state = 50;
- break;
-
- default:
- SYNTAX_ERROR (_("\
-syntax error: not inside a locale definition section"));
- continue;
- }
- lr_ignore_rest (ldfile, 1);
- continue;
-
- case 2:
- HANDLE_COPY (LC_CTYPE, tok_lc_ctype, "LC_CTYPE");
-
- ctype_startup (ldfile, result, charset);
- /* FALLTHROUGH */
-
- case 3:
- /* Here we accept all the character classes, tolower/toupper,
- and following ANSI C:1995 self-defined classes. */
- LOCALE_PROLOG (tok_lc_ctype, "LC_CTYPE");
+ switch (nowtok)
+ {
+ case tok_escape_char:
+ case tok_comment_char:
+ /* We need an argument. */
+ arg = lr_token (ldfile, charmap, NULL);
- if (nowtok == tok_charclass)
+ if (arg->tok != tok_ident)
{
- READ_STRING_LIST (ctype_class_new, bad_new_charclass);
- continue;
- bad_new_charclass:
- SYNTAX_ERROR (_("\
-syntax error in definition of new character class"));
+ SYNTAX_ERROR (_("bad argument"));
continue;
}
- if (nowtok == tok_charconv)
+ if (arg->val.str.lenmb != 1)
{
- READ_STRING_LIST (ctype_map_new, bad_new_charconv);
- continue;
- bad_new_charconv:
- SYNTAX_ERROR (_("\
-syntax error in definition of new character map"));
- continue;
- }
+ lr_error (ldfile, _("\
+argument to `%s' must be a single character"),
+ nowtok == tok_escape_char
+ ? "escape_char" : "comment_char");
- if (nowtok == tok_upper || nowtok == tok_lower
- || nowtok == tok_alpha || nowtok == tok_digit
- || nowtok == tok_alnum || nowtok == tok_space
- || nowtok == tok_cntrl || nowtok == tok_punct
- || nowtok == tok_graph || nowtok == tok_print
- || nowtok == tok_xdigit || nowtok == tok_blank)
- {
- ctype_tok_sym = nowtok;
- ctype_tok_str = NULL;
- state = 5;
+ lr_ignore_rest (ldfile, 0);
continue;
}
- if (nowtok == tok_toupper|| nowtok == tok_tolower)
- {
- ctype_tok_sym = nowtok;
- ctype_tok_str = NULL;
- state = 6;
- continue;
- }
+ if (nowtok == tok_escape_char)
+ ldfile->escape_char = *arg->val.str.startmb;
+ else
+ ldfile->comment_char = *arg->val.str.startmb;
+ break;
- if (nowtok != tok_ident)
- goto bad_charclass;
+ case tok_repertoiremap:
+ /* We need an argument. */
+ arg = lr_token (ldfile, charmap, NULL);
- /* We possibly have a self-defined character class. */
- if (ctype_is_charclass (ldfile, result, now->val.str.start))
+ if (arg->tok != tok_ident)
{
- ctype_tok_sym = nowtok;
- ctype_tok_str = now->val.str.start;
- state = 5;
+ SYNTAX_ERROR (_("bad argument"));
continue;
}
- /* ...or a self-defined character map. */
- if (ctype_is_charconv (ldfile, result, now->val.str.start))
+ if (repertoire_name == NULL)
{
- ctype_tok_sym = nowtok;
- ctype_tok_str = now->val.str.start;
- state = 6;
- continue;
+ repertoire_name = memcpy (xmalloc (arg->val.str.lenmb + 1),
+ arg->val.str.startmb,
+ arg->val.str.lenmb);
+ ((char *) repertoire_name)[arg->val.str.lenmb] = '\0';
}
+ break;
- SYNTAX_ERROR (_("syntax error in definition of LC_CTYPE category"));
+ case tok_lc_ctype:
+ ctype_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & CTYPE_LOCALE) == 0);
+ result->avail |= locale_mask & CTYPE_LOCALE;
continue;
- case 4:
- /* Handle `END xxx'. */
- if (nowtok != expected_tok)
- lr_error (ldfile, _("\
-`%1$s' definition does not end with `END %1$s'"), expected_str);
-
- lr_ignore_rest (ldfile, nowtok == expected_tok);
- state = 1;
+ case tok_lc_collate:
+ collate_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & COLLATE_LOCALE) == 0);
+ result->avail |= locale_mask & COLLATE_LOCALE;
continue;
- case 5:
- /* Here we expect a semicolon separated list of bsymbols. The
- bit to be set in the word is given in CHARCLASS_BIT. */
- arg = now;
-
- ctype_class_start (ldfile, result, ctype_tok_sym, ctype_tok_str,
- charset);
-
- while (arg->tok != tok_eol)
- {
- /* Any token other than a bsymbol is an error. */
- if (arg->tok != tok_bsymbol)
- {
- bad_charclass:
- SYNTAX_ERROR (_("\
-syntax error in character class definition"));
- break;
- }
-
- /* Lookup value for token and write into array. */
- ctype_class_from (ldfile, result, arg, charset);
-
- arg = lr_token (ldfile, charset);
- if (arg->tok == tok_semicolon)
- arg = lr_token (ldfile, charset);
- else if (arg->tok != tok_eol)
- goto bad_charclass;
-
- /* Look for ellipsis. */
- if (arg->tok == tok_ellipsis)
- {
- arg = lr_token (ldfile, charset);
- if (arg->tok != tok_semicolon)
- goto bad_charclass;
-
- arg = lr_token (ldfile, charset);
- if (arg->tok != tok_bsymbol)
- goto bad_charclass;
-
- /* Write range starting at LAST to ARG->VAL. */
- ctype_class_to (ldfile, result, arg, charset);
-
- arg = lr_token (ldfile, charset);
- if (arg->tok == tok_semicolon)
- arg = lr_token (ldfile, charset);
- else if (arg->tok != tok_eol)
- goto bad_charclass;
- }
- }
-
- /* Mark class as already seen. */
- ctype_class_end (ldfile, result);
- state = 3;
-
+ case tok_lc_monetary:
+ monetary_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & MONETARY_LOCALE) == 0);
+ result->avail |= locale_mask & MONETARY_LOCALE;
continue;
- case 6:
- /* Here we expect a list of character mappings. Note: the
- first opening brace is already matched. */
- ctype_map_start (ldfile, result, ctype_tok_sym, ctype_tok_str,
- charset);
-
- while (1)
- {
- /* Match ( bsymbol , bsymbol ) */
- if (now->tok != tok_open_brace)
- goto bad_charconv;
-
- now = lr_token (ldfile, charset);
- if (now->tok != tok_bsymbol)
- {
- bad_charconv:
- SYNTAX_ERROR (_("\
-syntax error in character conversion definition"));
- state = 3;
- break;
- }
-
- /* Lookup arg and assign to FROM. */
- ctype_map_from (ldfile, result, now, charset);
-
- now = lr_token (ldfile, charset);
- if (now->tok != tok_comma)
- goto bad_charconv;
-
- now = lr_token (ldfile, charset);
- if (now->tok != tok_bsymbol)
- goto bad_charconv;
-
- /* Lookup arg and assign to TO. */
- ctype_map_to (ldfile, result, now, charset);
-
- now = lr_token (ldfile, charset);
- if (now->tok != tok_close_brace)
- goto bad_charconv;
-
- now = lr_token (ldfile, charset);
- if (now->tok == tok_eol)
- {
- state = 3;
- break;
- }
- if (now->tok != tok_semicolon)
- goto bad_charconv;
-
- now = lr_token (ldfile, charset);
- }
-
- ctype_map_end (ldfile, result);
+ case tok_lc_numeric:
+ numeric_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & NUMERIC_LOCALE) == 0);
+ result->avail |= locale_mask & NUMERIC_LOCALE;
continue;
- case 8:
- {
- /* We have seen `copy'. First match the argument. */
- int warned = 0;
-
- if (nowtok != tok_string)
- lr_error (ldfile, _("expect string argument for `copy'"));
- else
- def_to_process (now->val.str.start, 1 << copy_category);
-
- lr_ignore_rest (ldfile, nowtok == tok_string);
-
- /* The rest of the line must be empty
- and the next keyword must be `END xxx'. */
-
- while (lr_token (ldfile, charset)->tok != tok_end)
- {
- if (warned == 0)
- {
- only_copy:
- lr_error (ldfile, _("\
-no other keyword shall be specified when `copy' is used"));
- warned = 1;
- }
-
- lr_ignore_rest (ldfile, 0);
- }
-
- state = 4;
- }
+ case tok_lc_time:
+ time_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & TIME_LOCALE) == 0);
+ result->avail |= locale_mask & TIME_LOCALE;
continue;
- case 10:
- HANDLE_COPY (LC_COLLATE, tok_lc_collate, "LC_COLLATE");
-
- collate_startup (ldfile, result, charset);
- /* FALLTHROUGH */
-
- case 11:
- /* Process the LC_COLLATE section. We expect `END LC_COLLATE'
- any of the collation specifications, or any bsymbol. */
- LOCALE_PROLOG (tok_lc_collate, "LC_COLLATE");
-
- if (nowtok == tok_order_start)
- {
- state = 12;
- continue;
- }
-
- if (nowtok != tok_collating_element
- && nowtok != tok_collating_symbol)
- {
- bad_collation:
- lr_error (ldfile, _("\
-syntax error in collation definition"));
- lr_ignore_rest (ldfile, 0);
- continue;
- }
-
- /* Get argument. */
- arg = lr_token (ldfile, charset);
- if (arg->tok != tok_bsymbol)
- {
- lr_error (ldfile, _("\
-collation symbol expected after `%s'"),
- nowtok == tok_collating_element
- ? "collating-element" : "collating-symbol");
- lr_ignore_rest (ldfile, 0);
- continue;
- }
-
- if (nowtok == tok_collating_element)
- {
- /* Save to-value as new name. */
- collate_element_to (ldfile, result, arg, charset);
-
- arg = lr_token (ldfile, charset);
- if (arg->tok != tok_from)
- {
- lr_error (ldfile, _("\
-`from' expected after first argument to `collating-element'"));
- lr_ignore_rest (ldfile, 0);
- continue;
- }
-
- arg = lr_token (ldfile, charset);
- if (arg->tok != tok_string)
- {
- lr_error (ldfile, _("\
-from-value of `collating-element' must be a string"));
- lr_ignore_rest (ldfile, 0);
- continue;
- }
-
- /* Enter new collating element. */
- collate_element_from (ldfile, result, arg, charset);
- }
- else
- /* Enter new collating symbol into table. */
- collate_symbol (ldfile, result, arg, charset);
-
- lr_ignore_rest (ldfile, 1);
- continue;
-
- case 12:
- /* We parse the rest of the line containing `order_start'.
- In any case we continue with parsing the symbols. */
- state = 13;
-
- cnt = 0;
- while (now->tok != tok_eol)
- {
- int collation_method = 0;
-
- ++cnt;
-
- do
- {
- if (now->tok == tok_forward)
- collation_method |= sort_forward;
- else if (now->tok == tok_backward)
- collation_method |= sort_backward;
- else if (now->tok == tok_position)
- collation_method |= sort_position;
- else
- {
- lr_error (ldfile, _("unknown collation directive"));
- lr_ignore_rest (ldfile, 0);
- continue;
- }
-
- now = lr_token (ldfile, charset);
- }
- while (now->tok == tok_comma
- && ((now = lr_token (ldfile, charset)) != tok_none));
-
- /* Check for consistency: forward and backwards are
- mutually exclusive. */
- if ((collation_method & sort_forward) != 0
- && (collation_method & sort_backward) != 0)
- {
- lr_error (ldfile, _("\
-sorting order `forward' and `backward' are mutually exclusive"));
- /* The recover clear the backward flag. */
- collation_method &= ~sort_backward;
- }
-
- /* ??? I don't know whether this is correct but while
- thinking about the `strcoll' functions I found that I
- need a direction when performing position depended
- collation. So I assume here that implicitly the
- direction `forward' is given when `position' alone is
- written. --drepper */
- if (collation_method == sort_position)
- collation_method |= sort_forward;
-
- /* Enter info about next collation order. */
- collate_new_order (ldfile, result, collation_method);
-
- if (now->tok != tok_eol && now->tok != tok_semicolon)
- {
- lr_error (ldfile, _("\
-syntax error in `order_start' directive"));
- lr_ignore_rest (ldfile, 0);
- break;
- }
-
- if (now->tok == tok_semicolon)
- now = lr_token (ldfile, charset);
- }
-
- /* If no argument to `order_start' is given, one `forward'
- argument is implicitly assumed. */
- if (cnt == 0)
- collate_new_order (ldfile, result, sort_forward);
-
-
- /* We now know about all sorting rules. */
- collate_build_arrays (ldfile, result);
-
+ case tok_lc_messages:
+ messages_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & MESSAGES_LOCALE) == 0);
+ result->avail |= locale_mask & MESSAGES_LOCALE;
continue;
- case 13:
- /* We read one symbol a line until `order_end' is found. */
- {
- static int last_correct = 1;
-
- if (nowtok == tok_order_end)
- {
- state = 14;
- lr_ignore_rest (ldfile, 1);
- continue;
- }
-
- /* Ignore empty lines. */
- if (nowtok == tok_eol)
- continue;
-
- if (nowtok != tok_bsymbol && nowtok != tok_undefined
- && nowtok != tok_ellipsis)
- {
- if (last_correct == 1)
- {
- lr_error (ldfile, _("\
-syntax error in collating order definition"));
- last_correct = 0;
- }
- lr_ignore_rest (ldfile, 0);
- continue;
- }
- else
- {
- last_correct = 1;
-
- /* Remember current token. */
- if (collate_order_elem (ldfile, result, now, charset) < 0)
- continue;
- }
-
- /* Read optional arguments. */
- arg = lr_token (ldfile, charset);
- while (arg->tok != tok_eol)
- {
- if (arg->tok != tok_ignore && arg->tok != tok_ellipsis
- && arg->tok != tok_bsymbol && arg->tok != tok_string)
- break;
-
- if (arg->tok == tok_ignore || arg->tok == tok_ellipsis
- || arg->tok == tok_string)
- {
- /* Call handler for simple weights. */
- if (collate_simple_weight (ldfile, result, arg, charset)
- < 0)
- goto illegal_weight;
-
- arg = lr_token (ldfile, charset);
- }
- else
- do
- {
- /* Collect char. */
- int ok = collate_weight_bsymbol (ldfile, result, arg,
- charset);
- if (ok < 0)
- goto illegal_weight;
-
- arg = lr_token (ldfile, charset);
- }
- while (arg->tok == tok_bsymbol);
-
- /* Are there more weights? */
- if (arg->tok != tok_semicolon)
- break;
-
- /* Yes, prepare next weight. */
- if (collate_next_weight (ldfile, result) < 0)
- goto illegal_weight;
-
- arg = lr_token (ldfile, charset);
- }
-
- if (arg->tok != tok_eol)
- {
- SYNTAX_ERROR (_("syntax error in order specification"));
- }
-
- collate_end_weight (ldfile, result);
- illegal_weight:
- }
+ case tok_lc_paper:
+ paper_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & PAPER_LOCALE) == 0);
+ result->avail |= locale_mask & PAPER_LOCALE;
continue;
- case 14:
- /* Following to the `order_end' keyword we don't expect
- anything but the `END'. */
- if (nowtok == tok_eol)
- continue;
-
- if (nowtok != tok_end)
- goto bad_collation;
-
- expected_tok = tok_lc_collate;
- expected_str = "LC_COLLATE";
- state = 4;
-
- ldfile->translate_strings = 1;
+ case tok_lc_name:
+ name_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & NAME_LOCALE) == 0);
+ result->avail |= locale_mask & NAME_LOCALE;
continue;
- case 20:
- HANDLE_COPY (LC_MONETARY, tok_lc_monetary, "LC_MONETARY");
-
- monetary_startup (ldfile, result, charset);
- /* FALLTHROUGH */
-
- case 21:
- LOCALE_PROLOG (tok_lc_monetary, "LC_MONETARY");
-
- switch (nowtok)
- {
- case tok_int_curr_symbol:
- case tok_currency_symbol:
- case tok_mon_decimal_point:
- case tok_mon_thousands_sep:
- case tok_positive_sign:
- case tok_negative_sign:
- READ_STRING (monetary_add, bad_monetary);
- break;
-
- case tok_int_frac_digits:
- case tok_frac_digits:
- case tok_p_cs_precedes:
- case tok_p_sep_by_space:
- case tok_n_cs_precedes:
- case tok_n_sep_by_space:
- case tok_p_sign_posn:
- case tok_n_sign_posn:
- READ_NUMBER (monetary_add, bad_monetary);
- break;
-
- case tok_mon_grouping:
- /* We have a semicolon separated list of integers. */
- READ_NUMBER_LIST (monetary_add, bad_monetary);
- break;
-
- default:
- bad_monetary:
- SYNTAX_ERROR (_("syntax error in monetary locale definition"));
- }
+ case tok_lc_address:
+ address_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & ADDRESS_LOCALE) == 0);
+ result->avail |= locale_mask & ADDRESS_LOCALE;
continue;
- case 30:
- HANDLE_COPY (LC_NUMERIC, tok_lc_numeric, "LC_NUMERIC");
-
- numeric_startup (ldfile, result, charset);
- /* FALLTHROUGH */
-
- case 31:
- LOCALE_PROLOG (tok_lc_numeric, "LC_NUMERIC");
-
- switch (nowtok)
- {
- case tok_decimal_point:
- case tok_thousands_sep:
- READ_STRING (numeric_add, bad_numeric);
- break;
-
- case tok_grouping:
- /* We have a semicolon separated list of integers. */
- READ_NUMBER_LIST (numeric_add, bad_numeric);
- break;
-
- default:
- bad_numeric:
- SYNTAX_ERROR (_("syntax error in numeric locale definition"));
- }
+ case tok_lc_telephone:
+ telephone_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & TELEPHONE_LOCALE) == 0);
+ result->avail |= locale_mask & TELEPHONE_LOCALE;
continue;
- case 40:
- HANDLE_COPY (LC_TIME, tok_lc_time, "LC_TIME");
-
- time_startup (ldfile, result, charset);
- /* FALLTHROUGH */
-
- case 41:
- LOCALE_PROLOG (tok_lc_time, "LC_TIME");
-
- switch (nowtok)
- {
- case tok_abday:
- case tok_day:
- case tok_abmon:
- case tok_mon:
- case tok_am_pm:
- case tok_alt_digits:
- case tok_era:
- READ_STRING_LIST (time_add, bad_time);
- continue;
-
- case tok_d_t_fmt:
- case tok_d_fmt:
- case tok_t_fmt:
- case tok_t_fmt_ampm:
- case tok_era_year:
- case tok_era_d_t_fmt:
- case tok_era_d_fmt:
- case tok_era_t_fmt:
- READ_STRING (time_add, bad_time);
- break;
-
- default:
- bad_time:
- SYNTAX_ERROR (_("syntax error in time locale definition"));
- }
+ case tok_lc_measurement:
+ measurement_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & MEASUREMENT_LOCALE) == 0);
+ result->avail |= locale_mask & MEASUREMENT_LOCALE;
continue;
- case 50:
- HANDLE_COPY (LC_MESSAGES, tok_lc_messages, "LC_MESSAGES");
-
- messages_startup (ldfile, result, charset);
- /* FALLTHROUGH */
-
- case 51:
- LOCALE_PROLOG (tok_lc_messages, "LC_MESSAGES");
-
- switch (nowtok)
- {
- case tok_yesexpr:
- case tok_noexpr:
- case tok_yesstr:
- case tok_nostr:
- READ_STRING (messages_add, bad_message);
- break;
-
- default:
- bad_message:
- SYNTAX_ERROR (_("syntax error in message locale definition"));
- }
+ case tok_lc_identification:
+ identification_read (ldfile, result, charmap, repertoire_name,
+ (locale_mask & IDENTIFICATION_LOCALE) == 0);
+ result->avail |= locale_mask & IDENTIFICATION_LOCALE;
continue;
default:
- error (5, 0, _("%s: error in state machine"), __FILE__);
- /* NOTREACHED */
+ SYNTAX_ERROR (_("\
+syntax error: not inside a locale definition section"));
+ continue;
}
- break;
+ /* The rest of the line must be empty. */
+ lr_ignore_rest (ldfile, 1);
}
/* We read all of the file. */
lr_close (ldfile);
- /* Let's see what information is available. */
- for (cnt = LC_CTYPE; cnt <= LC_MESSAGES; ++cnt)
- if (result->categories[cnt].generic != NULL)
- result->avail |= 1 << cnt;
-
- return result;
+ return 0;
}
+static void (*const check_funcs[]) (struct localedef_t *,
+ struct charmap_t *) =
+{
+ [LC_CTYPE] = ctype_finish,
+ [LC_COLLATE] = collate_finish,
+ [LC_MESSAGES] = messages_finish,
+ [LC_MONETARY] = monetary_finish,
+ [LC_NUMERIC] = numeric_finish,
+ [LC_TIME] = time_finish,
+ [LC_PAPER] = paper_finish,
+ [LC_NAME] = name_finish,
+ [LC_ADDRESS] = address_finish,
+ [LC_TELEPHONE] = telephone_finish,
+ [LC_MEASUREMENT] = measurement_finish,
+ [LC_IDENTIFICATION] = identification_finish
+};
+
+
void
-check_all_categories (struct localedef_t *locale, struct charset_t *charset)
+check_all_categories (struct localedef_t *definitions,
+ struct charmap_t *charmap)
{
- /* Call the finishing functions for all locales. */
- if ((locale->avail & (1 << LC_CTYPE)) != 0
- && (locale->binary & (1 << LC_CTYPE)) == 0)
- ctype_finish (locale, charset);
- if ((locale->avail & (1 << LC_COLLATE)) != 0
- && (locale->binary & (1 << LC_COLLATE)) == 0)
- collate_finish (locale, charset);
- if ((locale->avail & (1 << LC_MONETARY)) != 0
- && (locale->binary & (1 << LC_MONETARY)) == 0)
- monetary_finish (locale);
- if ((locale->avail & (1 << LC_NUMERIC)) != 0
- && (locale->binary & (1 << LC_NUMERIC)) == 0)
- numeric_finish (locale);
- if ((locale->avail & (1 << LC_TIME)) != 0
- && (locale->binary & (1 << LC_TIME)) == 0)
- time_finish (locale);
- if ((locale->avail & (1 << LC_MESSAGES)) != 0
- && (locale->binary & (1 << LC_MESSAGES)) == 0)
- messages_finish (locale);
+ int cnt;
+
+ for (cnt = 0; cnt < sizeof (check_funcs) / sizeof (check_funcs[0]); ++cnt)
+ if (check_funcs[cnt] != NULL)
+ check_funcs[cnt] (definitions, charmap);
}
+static void (*const write_funcs[]) (struct localedef_t *, struct charmap_t *,
+ const char *) =
+{
+ [LC_CTYPE] = ctype_output,
+ [LC_COLLATE] = collate_output,
+ [LC_MESSAGES] = messages_output,
+ [LC_MONETARY] = monetary_output,
+ [LC_NUMERIC] = numeric_output,
+ [LC_TIME] = time_output,
+ [LC_PAPER] = paper_output,
+ [LC_NAME] = name_output,
+ [LC_ADDRESS] = address_output,
+ [LC_TELEPHONE] = telephone_output,
+ [LC_MEASUREMENT] = measurement_output,
+ [LC_IDENTIFICATION] = identification_output
+};
+
+
void
-write_all_categories (struct localedef_t *locale, struct charset_t *charset,
+write_all_categories (struct localedef_t *definitions,
+ struct charmap_t *charmap,
const char *output_path)
{
- /* Call all functions to write locale data. */
- if ((locale->avail & (1 << LC_CTYPE)) != 0)
- ctype_output (locale, charset, output_path);
- if ((locale->avail & (1 << LC_COLLATE)) != 0)
- collate_output (locale, charset, output_path);
- if ((locale->avail & (1 << LC_MONETARY)) != 0)
- monetary_output (locale, output_path);
- if ((locale->avail & (1 << LC_NUMERIC)) != 0)
- numeric_output (locale, output_path);
- if ((locale->avail & (1 << LC_TIME)) != 0)
- time_output (locale, output_path);
- if ((locale->avail & (1 << LC_MESSAGES)) != 0)
- messages_output (locale, output_path);
+ int cnt;
+
+ for (cnt = 0; cnt < sizeof (write_funcs) / sizeof (write_funcs[0]); ++cnt)
+ if (check_funcs[cnt] != NULL)
+ write_funcs[cnt] (definitions, charmap, output_path);
}
@@ -1086,7 +320,7 @@ write_locale_data (const char *output_path, const char *category,
But for LC_MESSAGES we have to take care for the translation
data. This means we need to have a directory LC_MESSAGES in
which we place the file under the name SYS_LC_MESSAGES. */
- sprintf (fname, "%s%s", output_path, category);
+ sprintf (fname, "%s/%s", output_path, category);
if (strcmp (category, "LC_MESSAGES") == 0)
{
struct stat st;
@@ -1118,7 +352,7 @@ write_locale_data (const char *output_path, const char *category,
if (errno == EISDIR)
{
- sprintf (fname, "%1$s%2$s/SYS_%2$s", output_path, category);
+ sprintf (fname, "%1$s/%2$s/SYS_%2$s", output_path, category);
fd = creat (fname, 0666);
if (fd == -1)
save_err = errno;
diff --git a/locale/programs/locfile.h b/locale/programs/locfile.h
index 697af64979..6f670398c0 100644
--- a/locale/programs/locfile.h
+++ b/locale/programs/locfile.h
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -18,61 +18,241 @@
Boston, MA 02111-1307, USA. */
#ifndef _LOCFILE_H
-#define _LOCFILE_H
+#define _LOCFILE_H 1
#include <sys/uio.h>
-#include "charset.h"
+#include "linereader.h"
+#include "localedef.h"
-/* Opaque types for the different locales. */
-struct locale_ctype_t;
-struct locale_collate_t;
-struct locale_monetary_t;
-struct locale_numeric_t;
-struct locale_time_t;
-struct locale_messages_t;
-struct localedef_t
+/* Header of the locale data files. */
+struct locale_file
{
- int failed;
-
- int avail;
- int binary;
-
- union
- {
- void *generic;
- struct locale_ctype_t *ctype;
- struct locale_collate_t *collate;
- struct locale_monetary_t *monetary;
- struct locale_numeric_t *numeric;
- struct locale_time_t *time;
- struct locale_messages_t *messages;
- } categories[6];
-
- size_t len[6];
+ int magic;
+ int n;
};
-/* Declared in localedef.c. */
-extern int be_quiet;
-extern const char *repertoiremap;
-/* Found in localedef.c. */
-void def_to_process (const char *name, int category);
+/* Macros used in the parser. */
+#define SYNTAX_ERROR(string, args...) \
+ do \
+ { \
+ lr_error (ldfile, string, ## args); \
+ lr_ignore_rest (ldfile, 0); \
+ } \
+ while (0)
+
+
+/* General handling of `copy'. */
+static inline void
+handle_copy (struct linereader *ldfile, struct charmap_t *charmap,
+ struct repertoire_t *repertoire, enum token_t token, int locale,
+ const char *locale_name, int ignore_content)
+{
+ struct token *now;
+ int warned = 0;
+
+ now = lr_token (ldfile, charmap, NULL);
+ if (now->tok != tok_string)
+ lr_error (ldfile, _("expect string argument for `copy'"));
+ else if (!ignore_content)
+ {
+ if (now->val.str.startmb == NULL)
+ lr_error (ldfile, _("\
+locale name should consist only of portable characters"));
+ else
+ (void) add_to_readlist (locale, now->val.str.startmb,
+ repertoire->name);
+ }
+
+ lr_ignore_rest (ldfile, now->tok == tok_string);
+
+ /* The rest of the line must be empty and the next keyword must be
+ `END xxx'. */
+ while (lr_token (ldfile, charmap, NULL)->tok != tok_end)
+ {
+ if (warned == 0)
+ {
+ lr_error (ldfile, _("\
+no other keyword shall be specified when `copy' is used"));
+ warned = 1;
+ }
+
+ lr_ignore_rest (ldfile, 0);
+ }
+
+ /* Handle `END xxx'. */
+ if (now->tok != token)
+ lr_error (ldfile, _("\
+`%1$s' definition does not end with `END %1$s'"), locale_name);
+
+ lr_ignore_rest (ldfile, now->tok == token);
+}
/* Found in locfile.c. */
-struct localedef_t *locfile_read (const char *filename,
- struct charset_t *charset);
+extern int locfile_read (struct localedef_t *result,
+ struct charmap_t *charmap);
+
+/* Check validity of all the locale data. */
+extern void check_all_categories (struct localedef_t *definitions,
+ struct charmap_t *charmap);
+
+/* Write out all locale categories. */
+extern void write_all_categories (struct localedef_t *definitions,
+ struct charmap_t *charmap,
+ const char *output_path);
+
+/* Write out the data. */
+extern void write_locale_data (const char *output_path, const char *category,
+ size_t n_elem, struct iovec *vec);
+
+
+/* Entrypoints for the parsers of the individual categories. */
+
+/* Handle LC_CTYPE category. */
+extern void ctype_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void ctype_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void ctype_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
+
+/* Handle LC_COLLATE category. */
+extern void collate_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void collate_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void collate_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
+
+/* Handle LC_MONETARY category. */
+extern void monetary_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void monetary_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void monetary_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
+
+/* Handle LC_NUMERIC category. */
+extern void numeric_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void numeric_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void numeric_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
+
+/* Handle LC_MESSAGES category. */
+extern void messages_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void messages_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void messages_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
+
+/* Handle LC_TIME category. */
+extern void time_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void time_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void time_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
+
+/* Handle LC_PAPER category. */
+extern void paper_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void paper_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void paper_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
+
+/* Handle LC_NAME category. */
+extern void name_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void name_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void name_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
-void check_all_categories (struct localedef_t *locale,
- struct charset_t *charset);
+/* Handle LC_ADDRESS category. */
+extern void address_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void address_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void address_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
-void write_all_categories (struct localedef_t *locale,
- struct charset_t *charset, const char *output_path);
+/* Handle LC_TELEPHONE category. */
+extern void telephone_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void telephone_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void telephone_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
+/* Handle LC_MEASUREMENT category. */
+extern void measurement_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void measurement_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void measurement_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
-void write_locale_data (const char *output_path, const char *category,
- size_t n_elem, struct iovec *vec);
+/* Handle LC_IDENTIFICATION category. */
+extern void identification_read (struct linereader *ldfile,
+ struct localedef_t *result,
+ struct charmap_t *charmap,
+ const char *repertoire_name,
+ int ignore_content);
+extern void identification_finish (struct localedef_t *locale,
+ struct charmap_t *charmap);
+extern void identification_output (struct localedef_t *locale,
+ struct charmap_t *charmap,
+ const char *output_path);
#endif /* locfile.h */
diff --git a/locale/programs/repertoire.c b/locale/programs/repertoire.c
index a03021fdbf..aabe20181e 100644
--- a/locale/programs/repertoire.c
+++ b/locale/programs/repertoire.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -24,22 +24,30 @@
#include <errno.h>
#include <error.h>
#include <limits.h>
+#include <obstack.h>
+#include <search.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <libintl.h>
#include "linereader.h"
-#include "charset.h"
+#include "charmap.h"
#include "repertoire.h"
#include "simple-hash.h"
-
-
-extern void *xmalloc (size_t __n);
+#include "localedef.h"
/* Simple keyword hashing for the repertoiremap. */
-static const struct keyword_t *repertoiremap_hash (const char *str, int len);
+static const struct keyword_t *repertoiremap_hash (const char *str,
+ unsigned int len);
+static void repertoire_new_char (struct linereader *lr, hash_table *ht,
+ hash_table *rt, struct obstack *ob,
+ uint32_t value, const char *from,
+ const char *to, int decimal_ellipsis);
+static int repertoire_compare (const void *p1, const void *p2);
+
+/* Already known repertoire maps. */
+static void *known;
struct repertoire_t *
@@ -47,9 +55,17 @@ repertoire_read (const char *filename)
{
struct linereader *repfile;
struct repertoire_t *result;
+ struct repertoire_t **resultp;
+ struct repertoire_t search;
int state;
char *from_name = NULL;
char *to_name = NULL;
+ enum token_t ellipsis = tok_none;
+
+ search.name = filename;
+ resultp = tfind (&search, &known, &repertoire_compare);
+ if (resultp != NULL)
+ return *resultp;
/* Determine path. */
repfile = lr_open (filename, repertoiremap_hash);
@@ -57,7 +73,7 @@ repertoire_read (const char *filename)
{
if (strchr (filename, '/') == NULL)
{
- char *i18npath = __secure_getenv ("I18NPATH");
+ char *i18npath = getenv ("I18NPATH");
if (i18npath != NULL && *i18npath != '\0')
{
char path[strlen (filename) + 1 + strlen (i18npath)
@@ -73,6 +89,13 @@ repertoire_read (const char *filename)
filename);
repfile = lr_open (path, repertoiremap_hash);
+
+ if (repfile == NULL)
+ {
+ stpcpy (stpcpy (path, next), filename);
+
+ repfile = lr_open (path, repertoiremap_hash);
+ }
}
}
@@ -98,15 +121,22 @@ repertoire_read (const char *filename)
}
}
+ /* We don't want symbolic names in string to be translated. */
+ repfile->translate_strings = 0;
+
/* Allocate room for result. */
result = (struct repertoire_t *) xmalloc (sizeof (struct repertoire_t));
memset (result, '\0', sizeof (struct repertoire_t));
+ result->name = xstrdup (filename);
+
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
obstack_init (&result->mem_pool);
- if (init_hash (&result->char_table, 256))
+ if (init_hash (&result->char_table, 256)
+ || init_hash (&result->reverse_table, 256)
+ || init_hash (&result->seq_table, 256))
{
free (result);
return NULL;
@@ -118,7 +148,7 @@ repertoire_read (const char *filename)
while (1)
{
/* What's on? */
- struct token *now = lr_token (repfile, NULL);
+ struct token *now = lr_token (repfile, NULL, NULL);
enum token_t nowtok = now->tok;
struct token *arg;
@@ -137,7 +167,7 @@ repertoire_read (const char *filename)
if (nowtok == tok_escape_char || nowtok == tok_comment_char)
{
/* We know that we need an argument. */
- arg = lr_token (repfile, NULL);
+ arg = lr_token (repfile, NULL, NULL);
if (arg->tok != tok_ident)
{
@@ -148,7 +178,7 @@ repertoire_read (const char *filename)
continue;
}
- if (arg->val.str.len != 1)
+ if (arg->val.str.lenmb != 1)
{
lr_error (repfile, _("\
argument to <%s> must be a single character"),
@@ -160,9 +190,9 @@ argument to <%s> must be a single character"),
}
if (nowtok == tok_escape_char)
- repfile->escape_char = *arg->val.str.start;
+ repfile->escape_char = *arg->val.str.startmb;
else
- repfile->comment_char = *arg->val.str.start;
+ repfile->comment_char = *arg->val.str.startmb;
lr_ignore_rest (repfile, 1);
continue;
@@ -209,8 +239,8 @@ argument to <%s> must be a single character"),
obstack_free (&result->mem_pool, from_name);
from_name = (char *) obstack_copy0 (&result->mem_pool,
- now->val.str.start,
- now->val.str.len);
+ now->val.str.startmb,
+ now->val.str.lenmb);
to_name = NULL;
state = 3;
@@ -219,8 +249,10 @@ argument to <%s> must be a single character"),
case 3:
/* We have two possibilities: We can see an ellipsis or an
encoding value. */
- if (nowtok == tok_ellipsis)
+ if (nowtok == tok_ellipsis3 || nowtok == tok_ellipsis4
+ || nowtok == tok_ellipsis2)
{
+ ellipsis = nowtok;
state = 4;
continue;
}
@@ -232,7 +264,7 @@ argument to <%s> must be a single character"),
state = 2;
errno = 0;
- if (nowtok != tok_ucs2 && nowtok != tok_ucs4)
+ if (nowtok != tok_ucs4)
{
lr_error (repfile,
_("syntax error in repertoire map definition: %s"),
@@ -243,8 +275,10 @@ argument to <%s> must be a single character"),
}
/* We've found a new valid definition. */
- charset_new_char (repfile, &result->char_table, 4,
- now->val.charcode.val, from_name, to_name);
+ repertoire_new_char (repfile, &result->char_table,
+ &result->reverse_table, &result->mem_pool,
+ now->val.ucs4, from_name, to_name,
+ ellipsis != tok_ellipsis2);
/* Ignore the rest of the line. */
lr_ignore_rest (repfile, 0);
@@ -268,8 +302,8 @@ argument to <%s> must be a single character"),
/* Copy the to-name in a safe place. */
to_name = (char *) obstack_copy0 (&result->mem_pool,
- repfile->token.val.str.start,
- repfile->token.val.str.len);
+ repfile->token.val.str.startmb,
+ repfile->token.val.str.lenmb);
state = 5;
continue;
@@ -291,12 +325,26 @@ argument to <%s> must be a single character"),
lr_close (repfile);
+ if (tsearch (result, &known, &repertoire_compare) == NULL)
+ /* Something went wrong. */
+ error (0, errno, _("cannot safe new repertoire map"));
+
return result;
}
+static int
+repertoire_compare (const void *p1, const void *p2)
+{
+ struct repertoire_t *r1 = (struct repertoire_t *) p1;
+ struct repertoire_t *r2 = (struct repertoire_t *) p2;
+
+ return strcmp (r1->name, r2->name);
+}
+
+
static const struct keyword_t *
-repertoiremap_hash (const char *str, int len)
+repertoiremap_hash (const char *str, unsigned int len)
{
static const struct keyword_t wordlist[0] =
{
@@ -317,3 +365,134 @@ repertoiremap_hash (const char *str, int len)
return NULL;
}
+
+
+static void
+repertoire_new_char (struct linereader *lr, hash_table *ht, hash_table *rt,
+ struct obstack *ob, uint32_t value, const char *from,
+ const char *to, int decimal_ellipsis)
+{
+ char *from_end;
+ char *to_end;
+ const char *cp;
+ char *buf = NULL;
+ int prefix_len, len1, len2;
+ unsigned int from_nr, to_nr, cnt;
+
+ if (to == NULL)
+ {
+ insert_entry (ht, from, strlen (from),
+ (void *) (unsigned long int) value);
+ /* Please note that it isn't a bug if a symbol is defined more
+ than once. All later definitions are simply discarded. */
+
+ insert_entry (rt, obstack_copy (ob, &value, sizeof (value)),
+ sizeof (value), (void *) from);
+
+ return;
+ }
+
+ /* We have a range: the names must have names with equal prefixes
+ and an equal number of digits, where the second number is greater
+ or equal than the first. */
+ len1 = strlen (from);
+ len2 = strlen (to);
+
+ if (len1 != len2)
+ {
+ invalid_range:
+ lr_error (lr, _("invalid names for character range"));
+ return;
+ }
+
+ cp = &from[len1 - 1];
+ if (decimal_ellipsis)
+ while (isdigit (*cp) && cp >= from)
+ --cp;
+ else
+ while (isxdigit (*cp) && cp >= from)
+ {
+ if (!isdigit (*cp) && !isupper (*cp))
+ lr_error (lr, _("\
+hexadecimal range format should use only capital characters"));
+ --cp;
+ }
+
+ prefix_len = (cp - from) + 1;
+
+ if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
+ goto invalid_range;
+
+ errno = 0;
+ from_nr = strtoul (&from[prefix_len], &from_end, decimal_ellipsis ? 10 : 16);
+ if (*from_end != '\0' || (from_nr == ULONG_MAX && errno == ERANGE)
+ || ((to_nr = strtoul (&to[prefix_len], &to_end,
+ decimal_ellipsis ? 10 : 16)) == ULONG_MAX
+ && errno == ERANGE)
+ || *to_end != '\0')
+ {
+ lr_error (lr, _("<%s> and <%s> are invalid names for range"));
+ return;
+ }
+
+ if (from_nr > to_nr)
+ {
+ lr_error (lr, _("upper limit in range is not smaller then lower limit"));
+ return;
+ }
+
+ for (cnt = from_nr; cnt <= to_nr; ++cnt)
+ {
+ uint32_t this_value = value + (cnt - from_nr);
+
+ obstack_printf (ob, decimal_ellipsis ? "%.*s%0*d" : "%.*s%0*X",
+ prefix_len, from, len1 - prefix_len, cnt);
+
+ insert_entry (ht, buf, len1,
+ (void *) (unsigned long int) this_value);
+ /* Please note we don't examine the return value since it is no error
+ if we have two definitions for a symbol. */
+
+ insert_entry (rt, obstack_copy (ob, &this_value, sizeof (this_value)),
+ sizeof (this_value), (void *) from);
+ }
+}
+
+
+uint32_t
+repertoire_find_value (const struct repertoire_t *rep, const char *name,
+ size_t len)
+{
+ void *result;
+
+ if (find_entry ((hash_table *) &rep->char_table, name, len, &result) < 0)
+ return ILLEGAL_CHAR_VALUE;
+
+ return (uint32_t) ((unsigned long int) result);
+}
+
+
+const char *
+repertoire_find_symbol (const struct repertoire_t *rep, uint32_t ucs)
+{
+ void *result;
+
+ if (find_entry ((hash_table *) &rep->reverse_table, &ucs, sizeof (ucs),
+ &result) < 0)
+ return NULL;
+
+ return (const char *) result;
+}
+
+
+struct charseq *
+repertoire_find_seq (const struct repertoire_t *rep, uint32_t ucs)
+{
+ void *result;
+
+ if (find_entry ((hash_table *) &rep->seq_table, &ucs, sizeof (ucs),
+ &result) < 0)
+ return NULL;
+
+ return (struct charseq *) result;
+}
diff --git a/locale/programs/repertoire.h b/locale/programs/repertoire.h
index 7befeb4e0d..ef80369ae4 100644
--- a/locale/programs/repertoire.h
+++ b/locale/programs/repertoire.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@@ -21,18 +21,43 @@
#define _REPERTOIREMAP_H 1
#include <obstack.h>
+#include <stdint.h>
+#include "charmap.h"
#include "simple-hash.h"
-#include "linereader.h"
struct repertoire_t
{
+ const char *name;
struct obstack mem_pool;
hash_table char_table;
+ hash_table reverse_table;
+ hash_table seq_table;
};
+/* We need one value to mark the error case. Let's use 0xffffffff.
+ I.e., it is placed in the last page of ISO 10646. For now only the
+ first is used and we have plenty of room. */
+#define ILLEGAL_CHAR_VALUE ((uint32_t) 0xffffffffu)
+
+/* Another value is needed to signal that a value is not yet determined. */
+#define UNINITIALIZED_CHAR_VALUE ((uint32_t) 0xfffffffeu)
+
+
/* Prototypes for repertoire map handling functions. */
-struct repertoire_t *repertoire_read (const char *filename);
+extern struct repertoire_t *repertoire_read (const char *filename);
+
+/* Return UCS4 value of character with given NAME. */
+extern uint32_t repertoire_find_value (const struct repertoire_t *repertoire,
+ const char *name, size_t len);
+
+/* Return symbol for given UCS4 value. */
+extern const char *repertoire_find_symbol (const struct repertoire_t *repertoire,
+ uint32_t ucs);
+
+/* Query the has table to memoize mapping from UCS4 to byte sequences. */
+extern struct charseq *repertoire_find_seq (const struct repertoire_t *rep,
+ uint32_t ucs);
#endif /* repertoiremap.h */
diff --git a/locale/programs/simple-hash.h b/locale/programs/simple-hash.h
index f26790b21b..b72e3acaca 100644
--- a/locale/programs/simple-hash.h
+++ b/locale/programs/simple-hash.h
@@ -1,6 +1,6 @@
-/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -24,8 +24,8 @@
typedef struct hash_table
{
- unsigned long size;
- unsigned long filled;
+ unsigned long int size;
+ unsigned long int filled;
void *first;
void *table;
struct obstack mem_pool;
@@ -33,18 +33,18 @@ typedef struct hash_table
hash_table;
-int init_hash __P ((hash_table *htab, unsigned long int init_size));
-int delete_hash __P ((hash_table *htab));
-int insert_entry __P ((hash_table *htab, const void *key, size_t keylen,
- void *data));
-int find_entry __P ((hash_table *htab, const void *key, size_t keylen,
- void **result));
-int set_entry __P ((hash_table *htab, const void *key, size_t keylen,
- void *newval));
+extern int init_hash __P ((hash_table *htab, unsigned long int init_size));
+extern int delete_hash __P ((hash_table *htab));
+extern int insert_entry __P ((hash_table *htab, const void *key, size_t keylen,
+ void *data));
+extern int find_entry __P ((hash_table *htab, const void *key, size_t keylen,
+ void **result));
+extern int set_entry __P ((hash_table *htab, const void *key, size_t keylen,
+ void *newval));
-int iterate_table __P ((hash_table *htab, void **ptr,
- const void **key, size_t *keylen, void **data));
+extern int iterate_table __P ((hash_table *htab, void **ptr,
+ const void **key, size_t *keylen, void **data));
-unsigned long next_prime __P ((unsigned long int seed));
+extern unsigned long int next_prime __P ((unsigned long int seed));
#endif /* simple-hash.h */
diff --git a/locale/programs/stringtrans.c b/locale/programs/stringtrans.c
index 17f9670025..b810129678 100644
--- a/locale/programs/stringtrans.c
+++ b/locale/programs/stringtrans.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
@@ -21,6 +21,7 @@
# include <config.h>
#endif
+#include <assert.h>
#include <stdlib.h>
#include "charset.h"
@@ -77,8 +78,11 @@ translate_string (char *str, struct charset_t *charset)
tp = &str[1];
while (tp[0] != '\0' && tp[0] != '>')
- if (tp[0] == '\\' && tp[1] != '\0')
- tp += 2;
+ if (tp[0] == '\\')
+ if (tp[1] != '\0')
+ tp += 2;
+ else
+ ++tp;
else
++tp;
diff --git a/locale/setlocale.c b/locale/setlocale.c
index 1482465f43..f053895573 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -34,16 +34,17 @@
This contains the built-in "C"/"POSIX" locale's data for CATEGORY.
Both are weak references; if &_nl_current_CATEGORY is zero,
then nothing is using the locale data. */
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
extern struct locale_data *_nl_current_##category; \
extern struct locale_data _nl_C_##category;
#include "categories.def"
#undef DEFINE_CATEGORY
-/* Array indexed by category of pointers to _nl_current_CATEGORY slots. */
+/* Array indexed by category of pointers to _nl_current_CATEGORY slots.
+ Elements are zero for categories whose data is never used. */
struct locale_data * *const _nl_current[] =
{
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = &_nl_current_##category,
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -56,7 +57,7 @@ struct locale_data * *const _nl_current[] =
Elements are zero for categories whose data is never used. */
struct locale_data *const _nl_C[] =
{
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = &_nl_C_##category,
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -64,14 +65,10 @@ struct locale_data *const _nl_C[] =
/* Define an array of category names (also the environment variable names),
- indexed by integral category.
-
- We have entries of fixed width (16 for now) do avoid an array of
- pointers. Update the size of the outer array if new, longer locale
- names are introduced. */
-const char _nl_category_names[][16] =
+ indexed by integral category. */
+const char *const _nl_category_names[] =
{
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = category_name,
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -80,7 +77,7 @@ const char _nl_category_names[][16] =
/* An array of their lengths, for convenience. */
const size_t _nl_category_name_sizes[] =
{
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = sizeof (category_name) - 1,
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -91,7 +88,7 @@ const size_t _nl_category_name_sizes[] =
/* Declare the postload functions used below. */
#undef NO_POSTLOAD
#define NO_POSTLOAD _nl_postload_ctype /* Harmless thing known to exist. */
-#define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, postload) \
extern void postload (void);
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -101,7 +98,7 @@ extern void postload (void);
loading and installing that category's data. */
static void (*const _nl_category_postload[]) (void) =
{
-#define DEFINE_CATEGORY(category, category_name, items, postload, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, postload) \
[category] = postload,
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -112,7 +109,7 @@ static void (*const _nl_category_postload[]) (void) =
Each is malloc'd unless it is nl_C_name. */
static const char *_nl_current_names[] =
{
-#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
+#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = _nl_C_name,
#include "categories.def"
#undef DEFINE_CATEGORY
@@ -134,7 +131,7 @@ __libc_lock_define_initialized (, __libc_setlocale_lock)
/* Construct a new composite name. */
static inline char *
-new_composite_name (int category, const char *newnames[LC_ALL])
+new_composite_name (int category, const char *newnames[__LC_LAST])
{
size_t last_len = 0;
size_t cumlen = 0;
@@ -142,22 +139,23 @@ new_composite_name (int category, const char *newnames[LC_ALL])
char *new, *p;
int same = 1;
- for (i = 0; i < LC_ALL; ++i)
- {
- const char *name = (category == LC_ALL ? newnames[i] :
- category == i ? newnames[0] :
- _nl_current_names[i]);
- last_len = strlen (name);
- cumlen += _nl_category_name_sizes[i] + 1 + last_len + 1;
- if (same && strcmp (name, newnames[0]) != 0)
- same = 0;
- }
+ for (i = 0; i < __LC_LAST; ++i)
+ if (i != LC_ALL)
+ {
+ const char *name = (category == LC_ALL ? newnames[i] :
+ category == i ? newnames[0] :
+ _nl_current_names[i]);
+ last_len = strlen (name);
+ cumlen += _nl_category_name_sizes[i] + 1 + last_len + 1;
+ if (i > 0 && same && strcmp (name, newnames[0]) != 0)
+ same = 0;
+ }
if (same)
{
/* All the categories use the same name. */
- if (strcmp (newnames[0], _nl_C_name) == 0
- || strcmp (newnames[0], _nl_POSIX_name) == 0)
+ if (strcmp (newnames[0], "C") == 0
+ || strcmp (newnames[0], "POSIX") == 0)
return (char *) _nl_C_name;
new = malloc (last_len + 1);
@@ -169,17 +167,18 @@ new_composite_name (int category, const char *newnames[LC_ALL])
if (new == NULL)
return NULL;
p = new;
- for (i = 0; i < LC_ALL; ++i)
- {
- /* Add "CATEGORY=NAME;" to the string. */
- const char *name = (category == LC_ALL ? newnames[i] :
- category == i ? newnames[0] :
- _nl_current_names[i]);
- p = __stpcpy (p, _nl_category_names[i]);
- *p++ = '=';
- p = __stpcpy (p, name);
- *p++ = ';';
- }
+ for (i = 0; i < __LC_LAST; ++i)
+ if (i != LC_ALL)
+ {
+ /* Add "CATEGORY=NAME;" to the string. */
+ const char *name = (category == LC_ALL ? newnames[i] :
+ category == i ? newnames[0] :
+ _nl_current_names[i]);
+ p = __stpcpy (p, _nl_category_names[i]);
+ *p++ = '=';
+ p = __stpcpy (p, name);
+ *p++ = ';';
+ }
p[-1] = '\0'; /* Clobber the last ';'. */
return new;
}
@@ -221,7 +220,7 @@ setlocale (int category, const char *locale)
char *composite;
/* Sanity check for CATEGORY argument. */
- if (category < 0 || category > LC_ALL)
+ if (category < 0 || category >= __LC_LAST)
ERROR_RETURN;
/* Does user want name of current locale? */
@@ -254,12 +253,13 @@ setlocale (int category, const char *locale)
for the individual categories can be selected by using a
composite locale name. This is a semi-colon separated list
of entries of the form `CATEGORY=VALUE'. */
- const char *newnames[LC_ALL];
- struct locale_data *newdata[LC_ALL];
+ const char *newnames[__LC_LAST];
+ struct locale_data *newdata[__LC_LAST];
/* Set all name pointers to the argument name. */
- for (category = 0; category < LC_ALL; ++category)
- newnames[category] = (char *) locale;
+ for (category = 0; category < __LC_LAST; ++category)
+ if (category != LC_ALL)
+ newnames[category] = (char *) locale;
if (strchr (locale, ';') != NULL)
{
@@ -270,12 +270,13 @@ setlocale (int category, const char *locale)
while ((cp = strchr (np, '=')) != NULL)
{
- for (cnt = 0; cnt < LC_ALL; ++cnt)
- if ((size_t) (cp - np) == _nl_category_name_sizes[cnt]
+ for (cnt = 0; cnt < __LC_LAST; ++cnt)
+ if (cnt != LC_ALL
+ && (size_t) (cp - np) == _nl_category_name_sizes[cnt]
&& memcmp (np, _nl_category_names[cnt], cp - np) == 0)
break;
- if (cnt == LC_ALL)
+ if (cnt == __LC_LAST)
/* Bogus category name. */
ERROR_RETURN;
@@ -293,8 +294,8 @@ setlocale (int category, const char *locale)
break;
}
- for (cnt = 0; cnt < LC_ALL; ++cnt)
- if (newnames[cnt] == locale)
+ for (cnt = 0; cnt < __LC_LAST; ++cnt)
+ if (cnt != LC_ALL && newnames[cnt] == locale)
/* The composite name did not specify all categories. */
ERROR_RETURN;
}
@@ -305,6 +306,13 @@ setlocale (int category, const char *locale)
/* Load the new data for each category. */
while (category-- > 0)
{
+ /* XXX hack. Remove when collation works. */
+ if (category == LC_COLLATE)
+ {
+ newdata[category] = NULL;
+ continue;
+ }
+
newdata[category] = _nl_find_locale (locale_path, locale_path_len,
category,
&newnames[category]);
@@ -327,11 +335,12 @@ setlocale (int category, const char *locale)
else
{
/* Now we have loaded all the new data. Put it in place. */
- for (category = 0; category < LC_ALL; ++category)
- {
- setdata (category, newdata[category]);
- setname (category, newnames[category]);
- }
+ for (category = 0; category < __LC_LAST; ++category)
+ if (category != LC_ALL)
+ {
+ setdata (category, newdata[category]);
+ setname (category, newnames[category]);
+ }
setname (LC_ALL, composite);
}
@@ -343,6 +352,11 @@ setlocale (int category, const char *locale)
return composite;
}
+ else if (category == LC_COLLATE)
+ {
+ /* XXX Remove when LC_COLLATE works. */
+ return NULL;
+ }
else
{
struct locale_data *newdata = NULL;
@@ -401,21 +415,22 @@ free_mem (void)
{
int category;
- for (category = 0; category < LC_ALL; ++category)
- {
- struct locale_data *here = *_nl_current[category];
+ for (category = 0; category < __LC_LAST; ++category)
+ if (category != LC_ALL)
+ {
+ struct locale_data *here = *_nl_current[category];
- /* If this category is already "C" don't do anything. */
- if (here == _nl_C[category])
- continue;
+ /* If this category is already "C" don't do anything. */
+ if (here == _nl_C[category])
+ continue;
- /* We have to be prepared that sometime later me still might
- need the locale information. */
- setdata (category, _nl_C[category]);
- setname (category, _nl_C_name);
+ /* We have to be prepared that sometime later me still might
+ need the locale information. */
+ setdata (category, _nl_C[category]);
+ setname (category, _nl_C_name);
- _nl_unload_locale (here);
- }
+ _nl_unload_locale (here);
+ }
setname (LC_ALL, _nl_C_name);
}
diff --git a/locale/weight.h b/locale/weight.h
index c110bf6afc..6e31e2d495 100644
--- a/locale/weight.h
+++ b/locale/weight.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper, <drepper@cygnus.com>.
@@ -37,7 +37,7 @@ typedef struct weight_t
struct data_pair
{
int number;
- const u_int32_t *value;
+ const uint32_t *value;
} data[0];
} weight_t;
@@ -52,9 +52,9 @@ typedef struct weight_t
# define collate_hash_layers \
(_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_HASH_LAYERS))
# define collate_undefined \
- (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_UNDEFINED))
+ (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_UNDEFINED_WC))
# define collate_rules \
- ((u_int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_RULES))
+ ((uint32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_RULES))
static __inline void get_weight (const STRING_TYPE **str, weight_t *result);
static __inline void
@@ -67,18 +67,18 @@ get_weight (const STRING_TYPE **str, weight_t *result)
# define collate_hash_layers \
current->values[_NL_ITEM_INDEX (_NL_COLLATE_HASH_LAYERS)].word
# define collate_undefined \
- current->values[_NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].word
+ current->values[_NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED_WC)].word
# define collate_rules \
- ((u_int32_t *) current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULES)].string)
+ ((uint32_t *) current->values[_NL_ITEM_INDEX (_NL_COLLATE_RULES)].string)
static __inline void get_weight (const STRING_TYPE **str, weight_t *result,
struct locale_data *current,
- const u_int32_t *__collate_table,
- const u_int32_t *__collate_extra);
+ const uint32_t *__collate_tablewc,
+ const uint32_t *__collate_extrawc);
static __inline void
get_weight (const STRING_TYPE **str, weight_t *result,
- struct locale_data *current, const u_int32_t *__collate_table,
- const u_int32_t *__collate_extra)
+ struct locale_data *current, const uint32_t *__collate_tablewc,
+ const uint32_t *__collate_extrawc)
#endif
{
unsigned int ch = *((USTRING_TYPE *) (*str))++;
@@ -94,9 +94,9 @@ get_weight (const STRING_TYPE **str, weight_t *result,
slot = (ch % collate_hash_size) * (collate_nrules + 1);
level = 0;
- while (__collate_table[slot] != (u_int32_t) ch)
+ while (__collate_tablewc[slot] != (uint32_t) ch)
{
- if (__collate_table[slot + 1] == 0
+ if (__collate_tablewc[slot + 1] == 0
|| ++level >= collate_hash_layers)
{
size_t idx = collate_undefined;
@@ -104,8 +104,8 @@ get_weight (const STRING_TYPE **str, weight_t *result,
for (cnt = 0; cnt < collate_nrules; ++cnt)
{
- result->data[cnt].number = __collate_extra[idx++];
- result->data[cnt].value = &__collate_extra[idx];
+ result->data[cnt].number = __collate_extrawc[idx++];
+ result->data[cnt].value = &__collate_extrawc[idx];
idx += result->data[cnt].number;
}
/* The Unix standard requires that a character outside
@@ -117,7 +117,7 @@ get_weight (const STRING_TYPE **str, weight_t *result,
}
}
- if (__collate_table[slot + 1] != (u_int32_t) FORWARD_CHAR)
+ if (__collate_tablewc[slot + 1] != (uint32_t) FORWARD_CHAR)
{
/* We have a simple form. One value for each weight. */
size_t cnt;
@@ -125,7 +125,7 @@ get_weight (const STRING_TYPE **str, weight_t *result,
for (cnt = 0; cnt < collate_nrules; ++cnt)
{
result->data[cnt].number = 1;
- result->data[cnt].value = &__collate_table[slot + 1 + cnt];
+ result->data[cnt].value = &__collate_tablewc[slot + 1 + cnt];
}
return;
}
@@ -134,21 +134,21 @@ get_weight (const STRING_TYPE **str, weight_t *result,
There might none, but the last list member is a catch-all case
because it is simple the character CH. The value of this entry
might be the same as UNDEFINED. */
- slot = __collate_table[slot + 2];
+ slot = __collate_tablewc[slot + 2];
while (1)
{
size_t idx;
- /* This is a comparison between a u_int32_t array (aka wchar_t) and
+ /* This is a comparison between a uint32_t array (aka wchar_t) and
an 8-bit string. */
- for (idx = 0; __collate_extra[slot + 2 + idx] != 0; ++idx)
- if (__collate_extra[slot + 2 + idx] != ((USTRING_TYPE *) *str)[idx])
+ for (idx = 0; __collate_extrawc[slot + 2 + idx] != 0; ++idx)
+ if (__collate_extrawc[slot + 2 + idx] != (uint32_t) (*str)[idx])
break;
- /* When the loop finished with all characters of the collation
+ /* When the loop finished with all character of the collation
element used, we found the longest prefix. */
- if (__collate_extra[slot + 2 + idx] == 0)
+ if (__collate_extrawc[slot + 2 + idx] == 0)
{
size_t cnt;
@@ -156,15 +156,15 @@ get_weight (const STRING_TYPE **str, weight_t *result,
idx += slot + 3;
for (cnt = 0; cnt < collate_nrules; ++cnt)
{
- result->data[cnt].number = __collate_extra[idx++];
- result->data[cnt].value = &__collate_extra[idx];
+ result->data[cnt].number = __collate_extrawc[idx++];
+ result->data[cnt].value = &__collate_extrawc[idx];
idx += result->data[cnt].number;
}
return;
}
/* To next entry in list. */
- slot += __collate_extra[slot];
+ slot += __collate_extrawc[slot];
}
}
@@ -178,10 +178,10 @@ get_weight (const STRING_TYPE **str, weight_t *result,
We have this strange extra macro since the functions which use the
given locale (not the global one) cannot use the global tables. */
#ifndef USE_IN_EXTENDED_LOCALE_MODEL
-# define call_get_weight(strp, newp) get_weight (strp, newp)
+# define call_get_weight(strp, newp) get_weight ((strp), (newp))
#else
# define call_get_weight(strp, newp) \
- get_weight (strp, newp, current, collate_table, collate_extra)
+ get_weight ((strp), (newp), current, collate_table, collate_extra)
#endif
#define get_string(str, forw, backw) \
diff --git a/string/strcoll.c b/string/strcoll.c
index 1aab47e3be..96a83133e8 100644
--- a/string/strcoll.c
+++ b/string/strcoll.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
@@ -34,6 +34,23 @@
# define STRCMP strcmp
#endif
+#ifndef USE_IN_EXTENDED_LOCALE_MODEL
+int
+STRCOLL (s1, s2)
+ const STRING_TYPE *s1;
+ const STRING_TYPE *s2;
+#else
+int
+STRCOLL (s1, s2, l)
+ const STRING_TYPE *s1;
+ const STRING_TYPE *s2;
+ __locale_t l;
+#endif
+{
+ return STRCMP (s1, s2);
+}
+
+#if 0
/* Include the shared helper functions. `strxfrm'/`wcsxfrm' also use
these functions. */
#include "../locale/weight.h"
@@ -208,3 +225,4 @@ STRCOLL (s1, s2, l)
return 0;
}
+#endif
diff --git a/string/strxfrm.c b/string/strxfrm.c
index c2b8f48310..2a3a8a9032 100644
--- a/string/strxfrm.c
+++ b/string/strxfrm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
@@ -34,6 +34,21 @@
# define STPNCPY __stpncpy
#endif
+#ifndef USE_IN_EXTENDED_LOCALE_MODEL
+size_t
+STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n)
+#else
+size_t
+STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
+#endif
+{
+ if (n != 0)
+ STPNCPY (dest, src, n);
+
+ return STRLEN (src);
+}
+
+#if 0
/* Include the shared helper functions. `strxfrm'/`wcsxfrm' also use
these functions. */
#include "../locale/weight.h"
@@ -280,3 +295,4 @@ STRXFRM (STRING_TYPE *dest, const STRING_TYPE *src, size_t n, __locale_t l)
/* Return length without counting the terminating '\0'. */
return written;
}
+#endif
diff --git a/time/strftime.c b/time/strftime.c
index 60c8123afa..9ad16b2372 100644
--- a/time/strftime.c
+++ b/time/strftime.c
@@ -86,10 +86,15 @@ extern char *tzname[];
#endif
#ifdef COMPILE_WIDE
+# include <endian.h>
# define CHAR_T wchar_t
# define UCHAR_T unsigned int
# define L_(Str) L##Str
-# define NLW(Sym) _NL_W##Sym
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define NLW(Sym) _NL_W##Sym##_EL
+# else
+# define NLW(Sym) _NL_W##Sym##_EB
+# endif
# define MEMCPY(d, s, n) wmemcpy (d, s, n)
# define STRLEN(s) wcslen (s)
@@ -833,11 +838,11 @@ my_strftime (s, maxsize, format, tp ut_argument)
if (era)
{
# ifdef COMPILE_WIDE
- /* XXX For the time being there is no equivalent to
- _nl_get_era_entry to get a wide character variant. */
- wchar_t *ws;
- size_t len;
- widen (era->name_fmt, ws, len);
+ /* The wide name is after the single byte name and
+ format. */
+ char *tcp = strchr (era->name_fmt, '\0') + 1;
+ wchar_t *ws = (wchar_t *) (strchr (tcp, '\0') + 1);
+ size_t len = wcslen (ws);
cpy (len, ws);
# else
size_t len = strlen (era->name_fmt);
@@ -909,13 +914,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
/* Get the locale specific alternate representation of
the number NUMBER_VALUE. If none exist NULL is returned. */
# ifdef COMPILE_WIDE
- const char *ncp = _nl_get_alt_digit (number_value);
- wchar_t *cp = NULL;
- if (ncp != NULL)
- {
- size_t len;
- widen (ncp, cp, len);
- }
+ const wchar_t *cp = _nl_get_walt_digit (number_value);
# else
const char *cp = _nl_get_alt_digit (number_value);
# endif
@@ -1200,13 +1199,12 @@ my_strftime (s, maxsize, format, tp ut_argument)
if (era)
{
# ifdef COMPILE_WIDE
- /* XXX For the time being there is no wide character
- equivalent or _nl_get_era_entry. */
- const char *ncp = strchr (era->name_fmt, '\0') + 1;
+ /* The wide name is after the single byte name and
+ format. */
+ char *tcp = strchr (era->name_fmt, '\0') + 1;
size_t len;
- wchar_t *s;
- widen (ncp, s, len);
- subfmt = s;
+ subfmt = (wchar_t *) (strchr (tcp, '\0') + 1);
+ subfmt = wcschr (subfmt, L'\0') + 1;
# else
subfmt = strchr (era->name_fmt, '\0') + 1;
# endif
diff --git a/time/strptime.c b/time/strptime.c
index 5f8271e250..20b39dbfe3 100644
--- a/time/strptime.c
+++ b/time/strptime.c
@@ -156,7 +156,6 @@ localtime_r (t, tp)
#ifdef _LIBC
/* This is defined in locale/C-time.c in the GNU libc. */
-extern const struct locale_data _nl_C_LC_TIME;
extern const unsigned short int __mon_yday[2][13];
# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string)
diff --git a/wctype/cname-lookup.h b/wctype/cname-lookup.h
index 77186d4aa4..ffe677b7cf 100644
--- a/wctype/cname-lookup.h
+++ b/wctype/cname-lookup.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1996.
@@ -37,23 +37,35 @@ cname_lookup (wint_t wc, __locale_t locale)
#ifndef USE_IN_EXTENDED_LOCALE_MODEL
extern unsigned int *__ctype_names;
- hash_size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_HASH_SIZE);
- hash_layers = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_HASH_LAYERS);
+# if BYTE_ORDER == BIG_ENDIAN
+ hash_size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_HASH_SIZE_EB);
+ hash_layers = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_HASH_LAYERS_EB);
+# elif BYTE_ORDER == LITTLE_ENDIAN
+ hash_size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_HASH_SIZE_EL);
+ hash_layers = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_HASH_LAYERS_EL);
+# else
+# error bizarre byte order
+# endif
+
#else
struct locale_data *current = locale->__locales[LC_CTYPE];
-#if BYTE_ORDER == BIG_ENDIAN
+# if BYTE_ORDER == BIG_ENDIAN
unsigned int *__ctype_names =
(unsigned int *) current->values[_NL_ITEM_INDEX (_NL_CTYPE_NAMES_EB)].string;
-#elif BYTE_ORDER == LITTLE_ENDIAN
+ hash_size =
+ current->values[_NL_ITEM_INDEX (_NL_CTYPE_HASH_SIZE_EB)].word;
+ hash_layers =
+ current->values[_NL_ITEM_INDEX (_NL_CTYPE_HASH_LAYERS_EB)].word;
+# elif BYTE_ORDER == LITTLE_ENDIAN
unsigned int *__ctype_names =
(unsigned int *) current->values[_NL_ITEM_INDEX (_NL_CTYPE_NAMES_EL)].string;
-#else
-# error bizarre byte order
-#endif
hash_size =
- current->values[_NL_ITEM_INDEX (_NL_CTYPE_HASH_SIZE)].word;
+ current->values[_NL_ITEM_INDEX (_NL_CTYPE_HASH_SIZE_EL)].word;
hash_layers =
- current->values[_NL_ITEM_INDEX (_NL_CTYPE_HASH_LAYERS)].word;
+ current->values[_NL_ITEM_INDEX (_NL_CTYPE_HASH_LAYERS_EL)].word;
+# else
+# error bizarre byte order
+# endif
#endif
result = wc % hash_size;