]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Fix the --width option to not split multibyte characters, and respect the
authorBruno Haible <bruno@clisp.org>
Tue, 6 Mar 2001 15:09:27 +0000 (15:09 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 6 Mar 2001 15:09:27 +0000 (15:09 +0000)
wcwidth of the characters.

25 files changed:
lib/.cvsignore [new file with mode: 0644]
lib/3level.h [new file with mode: 0644]
lib/ChangeLog
lib/Makefile.am
lib/c-ctype.c [new file with mode: 0644]
lib/c-ctype.h [new file with mode: 0644]
lib/config.charset [new file with mode: 0755]
lib/gen-lbrkprop.c [new file with mode: 0644]
lib/lbrkprop.h [new file with mode: 0644]
lib/linebreak.c [new file with mode: 0644]
lib/linebreak.h [new file with mode: 0644]
lib/localcharset.c [new file with mode: 0644]
lib/ref-add.sin [new file with mode: 0644]
lib/ref-del.sin [new file with mode: 0644]
src/ChangeLog
src/FILES
src/Makefile.am
src/message.c
src/message.h
src/msgcomm.c
src/msgmerge.c
src/msgunfmt.c
src/write-po.c [new file with mode: 0644]
src/write-po.h [new file with mode: 0644]
src/xgettext.c

diff --git a/lib/.cvsignore b/lib/.cvsignore
new file mode 100644 (file)
index 0000000..55e86d8
--- /dev/null
@@ -0,0 +1 @@
+lbrkprop.txt
diff --git a/lib/3level.h b/lib/3level.h
new file mode 100644 (file)
index 0000000..e9f08ef
--- /dev/null
@@ -0,0 +1,322 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Bruno Haible <haible@clisp.cons.org>, 2000.
+
+
+   NOTE: The canonical source of this file is maintained with the GNU C Library.
+   Bugs can be reported to bug-glibc@gnu.org.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* Construction of sparse 3-level tables.
+   See wchar-lookup.h or coll-lookup.h for their structure and the
+   meaning of p and q.
+
+   Before including this file, set
+     TABLE        to the name of the structure to be defined
+     ELEMENT      to the type of every entry
+     DEFAULT      to the default value for empty entries
+     ITERATE      if you want the TABLE_iterate function to be defined
+     NO_FINALIZE  if you don't want the TABLE_finalize function to be defined
+
+   This will define
+
+     struct TABLE;
+     void TABLE_init (struct TABLE *t);
+     ELEMENT TABLE_get (struct TABLE *t, uint32_t wc);
+     void TABLE_add (struct TABLE *t, uint32_t wc, ELEMENT value);
+     void TABLE_iterate (struct TABLE *t,
+                        void (*fn) (uint32_t wc, ELEMENT value));
+     void TABLE_finalize (struct TABLE *t);
+*/
+
+#define CONCAT(a,b) CONCAT1(a,b)
+#define CONCAT1(a,b) a##b
+
+struct TABLE
+{
+  /* Parameters.  */
+  unsigned int p;
+  unsigned int q;
+  /* Working representation.  */
+  size_t level1_alloc;
+  size_t level1_size;
+  uint32_t *level1;
+  size_t level2_alloc;
+  size_t level2_size;
+  uint32_t *level2;
+  size_t level3_alloc;
+  size_t level3_size;
+  ELEMENT *level3;
+  /* Compressed representation.  */
+  size_t result_size;
+  char *result;
+};
+
+/* Initialize.  Assumes t->p and t->q have already been set.  */
+static inline void
+CONCAT(TABLE,_init) (struct TABLE *t)
+{
+  t->level1 = NULL;
+  t->level1_alloc = t->level1_size = 0;
+  t->level2 = NULL;
+  t->level2_alloc = t->level2_size = 0;
+  t->level3 = NULL;
+  t->level3_alloc = t->level3_size = 0;
+}
+
+/* Retrieve an entry.  */
+static inline ELEMENT
+CONCAT(TABLE,_get) (struct TABLE *t, uint32_t wc)
+{
+  uint32_t index1 = wc >> (t->q + t->p);
+  if (index1 < t->level1_size)
+    {
+      uint32_t lookup1 = t->level1[index1];
+      if (lookup1 != ~((uint32_t) 0))
+       {
+         uint32_t index2 = ((wc >> t->p) & ((1 << t->q) - 1))
+                           + (lookup1 << t->q);
+         uint32_t lookup2 = t->level2[index2];
+         if (lookup2 != ~((uint32_t) 0))
+           {
+             uint32_t index3 = (wc & ((1 << t->p) - 1))
+                               + (lookup2 << t->p);
+             ELEMENT lookup3 = t->level3[index3];
+
+             return lookup3;
+           }
+       }
+    }
+  return DEFAULT;
+}
+
+/* Add one entry.  */
+static void
+CONCAT(TABLE,_add) (struct TABLE *t, uint32_t wc, ELEMENT value)
+{
+  uint32_t index1 = wc >> (t->q + t->p);
+  uint32_t index2 = (wc >> t->p) & ((1 << t->q) - 1);
+  uint32_t index3 = wc & ((1 << t->p) - 1);
+  size_t i, i1, i2;
+
+  if (value == CONCAT(TABLE,_get) (t, wc))
+    return;
+
+  if (index1 >= t->level1_size)
+    {
+      if (index1 >= t->level1_alloc)
+       {
+         size_t alloc = 2 * t->level1_alloc;
+         if (alloc <= index1)
+           alloc = index1 + 1;
+         t->level1 = (uint32_t *) xrealloc ((char *) t->level1,
+                                            alloc * sizeof (uint32_t));
+         t->level1_alloc = alloc;
+       }
+      while (index1 >= t->level1_size)
+       t->level1[t->level1_size++] = ~((uint32_t) 0);
+    }
+
+  if (t->level1[index1] == ~((uint32_t) 0))
+    {
+      if (t->level2_size == t->level2_alloc)
+       {
+         size_t alloc = 2 * t->level2_alloc + 1;
+         t->level2 = (uint32_t *) xrealloc ((char *) t->level2,
+                                            (alloc << t->q) * sizeof (uint32_t));
+         t->level2_alloc = alloc;
+       }
+      i1 = t->level2_size << t->q;
+      i2 = (t->level2_size + 1) << t->q;
+      for (i = i1; i < i2; i++)
+       t->level2[i] = ~((uint32_t) 0);
+      t->level1[index1] = t->level2_size++;
+    }
+
+  index2 += t->level1[index1] << t->q;
+
+  if (t->level2[index2] == ~((uint32_t) 0))
+    {
+      if (t->level3_size == t->level3_alloc)
+       {
+         size_t alloc = 2 * t->level3_alloc + 1;
+         t->level3 = (ELEMENT *) xrealloc ((char *) t->level3,
+                                           (alloc << t->p) * sizeof (ELEMENT));
+         t->level3_alloc = alloc;
+       }
+      i1 = t->level3_size << t->p;
+      i2 = (t->level3_size + 1) << t->p;
+      for (i = i1; i < i2; i++)
+       t->level3[i] = DEFAULT;
+      t->level2[index2] = t->level3_size++;
+    }
+
+  index3 += t->level2[index2] << t->p;
+
+  t->level3[index3] = value;
+}
+
+#ifdef ITERATE
+/* Apply a function to all entries in the table.  */
+static void
+CONCAT(TABLE,_iterate) (struct TABLE *t,
+                       void (*fn) (uint32_t wc, ELEMENT value))
+{
+  uint32_t index1;
+  for (index1 = 0; index1 < t->level1_size; index1++)
+    {
+      uint32_t lookup1 = t->level1[index1];
+      if (lookup1 != ~((uint32_t) 0))
+       {
+         uint32_t lookup1_shifted = lookup1 << t->q;
+         uint32_t index2;
+         for (index2 = 0; index2 < (1 << t->q); index2++)
+           {
+             uint32_t lookup2 = t->level2[index2 + lookup1_shifted];
+             if (lookup2 != ~((uint32_t) 0))
+               {
+                 uint32_t lookup2_shifted = lookup2 << t->p;
+                 uint32_t index3;
+                 for (index3 = 0; index3 < (1 << t->p); index3++)
+                   {
+                     ELEMENT lookup3 = t->level3[index3 + lookup2_shifted];
+                     if (lookup3 != DEFAULT)
+                       fn ((((index1 << t->q) + index2) << t->p) + index3,
+                           lookup3);
+                   }
+               }
+           }
+       }
+    }
+}
+#endif
+
+#ifndef NO_FINALIZE
+/* Finalize and shrink.  */
+static void
+CONCAT(TABLE,_finalize) (struct TABLE *t)
+{
+  size_t i, j, k;
+  uint32_t reorder3[t->level3_size];
+  uint32_t reorder2[t->level2_size];
+  uint32_t level1_offset, level2_offset, level3_offset, last_offset;
+
+  /* Uniquify level3 blocks.  */
+  k = 0;
+  for (j = 0; j < t->level3_size; j++)
+    {
+      for (i = 0; i < k; i++)
+       if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
+                   (1 << t->p) * sizeof (ELEMENT)) == 0)
+         break;
+      /* Relocate block j to block i.  */
+      reorder3[j] = i;
+      if (i == k)
+       {
+         if (i != j)
+           memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
+                   (1 << t->p) * sizeof (ELEMENT));
+         k++;
+       }
+    }
+  t->level3_size = k;
+
+  for (i = 0; i < (t->level2_size << t->q); i++)
+    if (t->level2[i] != ~((uint32_t) 0))
+      t->level2[i] = reorder3[t->level2[i]];
+
+  /* Uniquify level2 blocks.  */
+  k = 0;
+  for (j = 0; j < t->level2_size; j++)
+    {
+      for (i = 0; i < k; i++)
+       if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
+                   (1 << t->q) * sizeof (uint32_t)) == 0)
+         break;
+      /* Relocate block j to block i.  */
+      reorder2[j] = i;
+      if (i == k)
+       {
+         if (i != j)
+           memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
+                   (1 << t->q) * sizeof (uint32_t));
+         k++;
+       }
+    }
+  t->level2_size = k;
+
+  for (i = 0; i < t->level1_size; i++)
+    if (t->level1[i] != ~((uint32_t) 0))
+      t->level1[i] = reorder2[t->level1[i]];
+
+  /* Create and fill the resulting compressed representation.  */
+  last_offset =
+    5 * sizeof (uint32_t)
+    + t->level1_size * sizeof (uint32_t)
+    + (t->level2_size << t->q) * sizeof (uint32_t)
+    + (t->level3_size << t->p) * sizeof (ELEMENT);
+  t->result_size = (last_offset + 3) & ~3ul;
+  t->result = (char *) xmalloc (t->result_size);
+
+  level1_offset =
+    5 * sizeof (uint32_t);
+  level2_offset =
+    5 * sizeof (uint32_t)
+    + t->level1_size * sizeof (uint32_t);
+  level3_offset =
+    5 * sizeof (uint32_t)
+    + t->level1_size * sizeof (uint32_t)
+    + (t->level2_size << t->q) * sizeof (uint32_t);
+
+  ((uint32_t *) t->result)[0] = t->q + t->p;
+  ((uint32_t *) t->result)[1] = t->level1_size;
+  ((uint32_t *) t->result)[2] = t->p;
+  ((uint32_t *) t->result)[3] = (1 << t->q) - 1;
+  ((uint32_t *) t->result)[4] = (1 << t->p) - 1;
+
+  for (i = 0; i < t->level1_size; i++)
+    ((uint32_t *) (t->result + level1_offset))[i] =
+      (t->level1[i] == ~((uint32_t) 0)
+       ? 0
+       : (t->level1[i] << t->q) * sizeof (uint32_t) + level2_offset);
+
+  for (i = 0; i < (t->level2_size << t->q); i++)
+    ((uint32_t *) (t->result + level2_offset))[i] =
+      (t->level2[i] == ~((uint32_t) 0)
+       ? 0
+       : (t->level2[i] << t->p) * sizeof (ELEMENT) + level3_offset);
+
+  for (i = 0; i < (t->level3_size << t->p); i++)
+    ((ELEMENT *) (t->result + level3_offset))[i] = t->level3[i];
+
+  if (last_offset < t->result_size)
+    memset (t->result + last_offset, 0, t->result_size - last_offset);
+
+  if (t->level1_alloc > 0)
+    free (t->level1);
+  if (t->level2_alloc > 0)
+    free (t->level2);
+  if (t->level3_alloc > 0)
+    free (t->level3);
+}
+#endif
+
+#undef TABLE
+#undef ELEMENT
+#undef DEFAULT
+#undef ITERATE
+#undef NO_FINALIZE
index c61c225495a3f7d45733253db60c58be75505b5a..973a85eb66c724e54d76d917f4c761b151825ff9 100644 (file)
@@ -1,3 +1,35 @@
+2001-03-03  Bruno Haible  <haible@clisp.cons.org>
+
+       * gen-lbrkprop.c: New file.
+       * 3level.h: New file.
+       * lbrkprop.h: New file, generated by gen-lbrkprop.
+       * linebreak.h: New file.
+       * linebreak.c: New file.
+       * Makefile.am (EXTRA_DIST): Add gen-lbrkprop.c, 3level.h.
+       (libnlsut_a_SOURCES): Add linebreak.c.
+       (noinst_HEADERS): Add linebreak.h, lbrkprop.h.
+
+       * c-ctype.h: New file.
+       * c-ctype.c: New file.
+       * Makefile.am (libnlsut_a_SOURCES): Add c-ctype.c.
+       (noinst_HEADERS): Add c-ctype.h.
+
+       Allow the use of locale_charset() in src.
+       * config.charset: New file, from ../intl/.
+       * localcharset.c: New file, from ../intl/.
+       * ref-add.sin: New file, from ../intl/.
+       * ref-del.sin: New file, from ../intl/.
+       * Makefile.am (EXTRA_DIST): Add config.charset, ref-{add,del}.sin.
+       (libnlsut_a_SOURCES): Add localcharset.c.
+       (DEFS): Define to set LIBDIR.
+       (INCLUDES): Add -I. -I$(srcdir) -I.. to compensate for automake's
+       default DEFS setting.
+       (all-local, install-exec-local, uninstall-local, charset.alias): New
+       targets.
+       (SUFFIXES): New variable.
+       (.sin.sed): New rule.
+       (CLEANFILES): New variable.
+
 2001-03-03  Bruno Haible  <haible@clisp.cons.org>
 
        * printf.h (PARAMS): GNU C always supports prototypes.
index 3cab0b02f127f829237e461295d60080d4a4379a..9059a5aad5b9503defb7e2008da2d13a453c3183 100644 (file)
@@ -1,5 +1,5 @@
 ## Makefile for the support lib subdirectory of the GNU NLS Utilities
-## Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+## Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
 ##
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -21,16 +21,67 @@ AUTOMAKE_OPTIONS = 1.2 gnits
 
 noinst_LIBRARIES = libnlsut.a
 
-EXTRA_DIST = alloca.c error.c getline.c memset.c memmove.c \
-printf-prs.c stpcpy.c stpncpy.c strcasecmp.c strcspn.c  strncasecmp.c \
-strstr.c strtol.c strtoul.c vasprintf.c
+EXTRA_DIST = alloca.c config.charset error.c getline.c memset.c memmove.c \
+printf-prs.c ref-add.sin ref-del.sin stpcpy.c stpncpy.c strcasecmp.c \
+strcspn.c strncasecmp.c strstr.c strtol.c strtoul.c vasprintf.c \
+gen-lbrkprop.c 3level.h
 
-libnlsut_a_SOURCES = basename.c fstrcmp.c getopt.c getopt1.c hash.c obstack.c \
-xgetcwd.c xmalloc.c xstrdup.c
+libnlsut_a_SOURCES = basename.c c-ctype.c fstrcmp.c getopt.c getopt1.c \
+hash.c linebreak.c localcharset.c obstack.c xgetcwd.c xmalloc.c xstrdup.c
 
 libnlsut_a_LIBADD = @ALLOCA@ @LIBOBJS@
 
-noinst_HEADERS = error.h fstrcmp.h getline.h getopt.h hash.h obstack.h \
-printf-parse.h printf.h system.h pathmax.h
+noinst_HEADERS = c-ctype.h error.h fstrcmp.h getline.h getopt.h hash.h \
+lbrkprop.h linebreak.h obstack.h printf-parse.h printf.h system.h pathmax.h
 
-INCLUDES = -I../intl
+DEFS = -DLIBDIR=\"$(libdir)\" @DEFS@
+INCLUDES = -I. -I$(srcdir) -I.. -I../intl
+
+
+# The following is needed in order to install a simple file in $(libdir)
+# which is shared with other installed packages. We use a list of referencing
+# packages so that "make uninstall" will remove the file if and only if it
+# is not used by another installed package.
+# On systems with glibc-2.1 or newer, the file is redundant, therefore we
+# avoid installing it.
+
+all-local: charset.alias ref-add.sed ref-del.sed
+
+charset_alias = $(DESTDIR)$(libdir)/charset.alias
+charset_tmp = $(DESTDIR)$(libdir)/charset.tmp
+install-exec-local: all-local
+       $(mkinstalldirs) $(DESTDIR)$(libdir)
+       if test -f $(charset_alias); then \
+         sed -f ref-add.sed $(charset_alias) > $(charset_tmp) ; \
+         $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \
+         rm -f $(charset_tmp) ; \
+       else \
+         if test @GLIBC21@ = no; then \
+           sed -f ref-add.sed charset.alias > $(charset_tmp) ; \
+           $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \
+           rm -f $(charset_tmp) ; \
+         fi ; \
+       fi
+
+uninstall-local: all-local
+       if test -f $(charset_alias); then \
+         sed -f ref-del.sed $(charset_alias) > $(charset_tmp); \
+         if grep '^# Packages using this file: $$' $(charset_tmp) \
+             > /dev/null; then \
+           rm -f $(charset_alias); \
+         else \
+           $(INSTALL_DATA) $(charset_tmp) $(charset_alias); \
+         fi; \
+         rm -f $(charset_tmp); \
+       fi
+
+charset.alias: config.charset
+       $(SHELL) $(srcdir)/config.charset '@host@' > t-$@
+       mv t-$@ $@
+
+SUFFIXES = .sed .sin
+.sin.sed:
+       sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $< > t-$@
+       mv t-$@ $@
+
+CLEANFILES = charset.alias ref-add.sed ref-del.sed
diff --git a/lib/c-ctype.c b/lib/c-ctype.c
new file mode 100644 (file)
index 0000000..476c216
--- /dev/null
@@ -0,0 +1,410 @@
+/* Character handling in C locale.
+
+   Copyright 2000, 2001 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "c-ctype.h"
+
+#undef c_isalnum
+#undef c_isalpha
+#undef c_isascii
+#undef c_isblank
+#undef c_iscntrl
+#undef c_isdigit
+#undef c_islower
+#undef c_isgraph
+#undef c_isprint
+#undef c_ispunct
+#undef c_isspace
+#undef c_isupper
+#undef c_isxdigit
+#undef c_tolower
+#undef c_toupper
+
+/* The function isascii is not locale dependent. Its use in EBCDIC is
+   questionable. */
+int
+c_isascii (c)
+     int c;
+{
+  return ((c & ~0x7f) == 0);
+}
+
+int
+c_isalnum (c)
+     int c;
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return ((c >= '0' && c <= '9')
+          || (c >= 'A' && c <= 'Z')
+          || (c >= 'a' && c <= 'z'));
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_isalpha (c)
+     int c;
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
+#else
+  switch (c)
+    {
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_isblank (c)
+     int c;
+{
+  return (c == ' ' || c == '\t');
+}
+
+int
+c_iscntrl (c)
+     int c;
+{
+#if C_CTYPE_ASCII
+  return ((c & ~0x1f) == 0 || c == 0x7f);
+#else
+  switch (c)
+    {
+    case ' ': case '!': case '"': case '#': case '$': case '%':
+    case '&': case '\'': case '(': case ')': case '*': case '+':
+    case ',': case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 0;
+    default:
+      return 1;
+    }
+#endif
+}
+
+int
+c_isdigit (c)
+     int c;
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS
+  return (c >= '0' && c <= '9');
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_islower (c)
+     int c;
+{
+#if C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'a' && c <= 'z');
+#else
+  switch (c)
+    {
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_isgraph (c)
+     int c;
+{
+#if C_CTYPE_ASCII
+  return (c >= '!' && c <= '~');
+#else
+  switch (c)
+    {
+    case '!': case '"': case '#': case '$': case '%': case '&':
+    case '\'': case '(': case ')': case '*': case '+': case ',':
+    case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_isprint (c)
+     int c;
+{
+#if C_CTYPE_ASCII
+  return (c >= ' ' && c <= '~');
+#else
+  switch (c)
+    {
+    case ' ': case '!': case '"': case '#': case '$': case '%':
+    case '&': case '\'': case '(': case ')': case '*': case '+':
+    case ',': case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_ispunct (c)
+     int c;
+{
+#if C_CTYPE_ASCII
+  return ((c >= '!' && c <= '~')
+          && !((c >= '0' && c <= '9')
+               || (c >= 'A' && c <= 'Z')
+               || (c >= 'a' && c <= 'z')));
+#else
+  switch (c)
+    {
+    case '!': case '"': case '#': case '$': case '%': case '&':
+    case '\'': case '(': case ')': case '*': case '+': case ',':
+    case '-': case '.': case '/':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_isspace (c)
+     int c;
+{
+  return (c == ' ' || c == '\t'
+          || c == '\n' || c == '\v' || c == '\f' || c == '\r');
+}
+
+int
+c_isupper (c)
+     int c;
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE
+  return (c >= 'A' && c <= 'Z');
+#else
+  switch (c)
+    {
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_isxdigit (c)
+     int c;
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return ((c >= '0' && c <= '9')
+          || (c >= 'A' && c <= 'F')
+          || (c >= 'a' && c <= 'f'));
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_tolower (c)
+     int c;
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c);
+#else
+  switch (c)
+    {
+    case 'A': return 'a';
+    case 'B': return 'b';
+    case 'C': return 'c';
+    case 'D': return 'd';
+    case 'E': return 'e';
+    case 'F': return 'f';
+    case 'G': return 'g';
+    case 'H': return 'h';
+    case 'I': return 'i';
+    case 'J': return 'j';
+    case 'K': return 'k';
+    case 'L': return 'l';
+    case 'M': return 'm';
+    case 'N': return 'n';
+    case 'O': return 'o';
+    case 'P': return 'p';
+    case 'Q': return 'q';
+    case 'R': return 'r';
+    case 'S': return 's';
+    case 'T': return 't';
+    case 'U': return 'u';
+    case 'V': return 'v';
+    case 'W': return 'w';
+    case 'X': return 'x';
+    case 'Y': return 'y';
+    case 'Z': return 'z';
+    default: return c;
+    }
+#endif
+}
+
+int
+c_toupper (c)
+     int c;
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c);
+#else
+  switch (c)
+    {
+    case 'a': return 'A';
+    case 'b': return 'B';
+    case 'c': return 'C';
+    case 'd': return 'D';
+    case 'e': return 'E';
+    case 'f': return 'F';
+    case 'g': return 'G';
+    case 'h': return 'H';
+    case 'i': return 'I';
+    case 'j': return 'J';
+    case 'k': return 'K';
+    case 'l': return 'L';
+    case 'm': return 'M';
+    case 'n': return 'N';
+    case 'o': return 'O';
+    case 'p': return 'P';
+    case 'q': return 'Q';
+    case 'r': return 'R';
+    case 's': return 'S';
+    case 't': return 'T';
+    case 'u': return 'U';
+    case 'v': return 'V';
+    case 'w': return 'W';
+    case 'x': return 'X';
+    case 'y': return 'Y';
+    case 'z': return 'Z';
+    default: return c;
+    }
+#endif
+}
diff --git a/lib/c-ctype.h b/lib/c-ctype.h
new file mode 100644 (file)
index 0000000..9197102
--- /dev/null
@@ -0,0 +1,229 @@
+/* Character handling in C locale.
+
+   These functions work like the corresponding functions in <ctype.h>,
+   except that they have the C (POSIX) locale hardwired, whereas the
+   <ctype.h> functions' behaviour depends on the current locale set via
+   setlocale.
+
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef C_CTYPE_H
+#define C_CTYPE_H
+
+#ifndef PARAMS
+# if defined (__GNUC__) || __STDC__
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+
+/* Check whether the ASCII optimizations apply. */
+
+#if ('0' <= '9') \
+    && ('0' + 1 == '1') && ('1' + 1 == '2') && ('2' + 1 == '3') \
+    && ('3' + 1 == '4') && ('4' + 1 == '5') && ('5' + 1 == '6') \
+    && ('6' + 1 == '7') && ('7' + 1 == '8') && ('8' + 1 == '9')
+#define C_CTYPE_CONSECUTIVE_DIGITS 1
+#endif
+
+#if ('A' <= 'Z') \
+    && ('A' + 1 == 'B') && ('B' + 1 == 'C') && ('C' + 1 == 'D') \
+    && ('D' + 1 == 'E') && ('E' + 1 == 'F') && ('F' + 1 == 'G') \
+    && ('G' + 1 == 'H') && ('H' + 1 == 'I') && ('I' + 1 == 'J') \
+    && ('J' + 1 == 'K') && ('K' + 1 == 'L') && ('L' + 1 == 'M') \
+    && ('M' + 1 == 'N') && ('N' + 1 == 'O') && ('O' + 1 == 'P') \
+    && ('P' + 1 == 'Q') && ('Q' + 1 == 'R') && ('R' + 1 == 'S') \
+    && ('S' + 1 == 'T') && ('T' + 1 == 'U') && ('U' + 1 == 'V') \
+    && ('V' + 1 == 'W') && ('W' + 1 == 'X') && ('X' + 1 == 'Y') \
+    && ('Y' + 1 == 'Z')
+#define C_CTYPE_CONSECUTIVE_UPPERCASE 1
+#endif
+
+#if ('a' <= 'z') \
+    && ('a' + 1 == 'b') && ('b' + 1 == 'c') && ('c' + 1 == 'd') \
+    && ('d' + 1 == 'e') && ('e' + 1 == 'f') && ('f' + 1 == 'g') \
+    && ('g' + 1 == 'h') && ('h' + 1 == 'i') && ('i' + 1 == 'j') \
+    && ('j' + 1 == 'k') && ('k' + 1 == 'l') && ('l' + 1 == 'm') \
+    && ('m' + 1 == 'n') && ('n' + 1 == 'o') && ('o' + 1 == 'p') \
+    && ('p' + 1 == 'q') && ('q' + 1 == 'r') && ('r' + 1 == 's') \
+    && ('s' + 1 == 't') && ('t' + 1 == 'u') && ('u' + 1 == 'v') \
+    && ('v' + 1 == 'w') && ('w' + 1 == 'x') && ('x' + 1 == 'y') \
+    && ('y' + 1 == 'z')
+#define C_CTYPE_CONSECUTIVE_LOWERCASE 1
+#endif
+
+#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+    && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+    && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+    && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+    && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+    && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+    && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+    && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+    && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+    && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+    && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+    && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+    && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+    && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+    && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+    && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+    && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+    && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+    && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+    && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+    && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+    && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+    && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
+/* The character set is ISO-646, not EBCDIC. */
+#define C_CTYPE_ASCII 1
+#endif
+
+
+/* Function declarations. */
+
+extern int c_isascii PARAMS ((int c)); /* not locale dependent */
+
+extern int c_isalnum PARAMS ((int c));
+extern int c_isalpha PARAMS ((int c));
+extern int c_isblank PARAMS ((int c));
+extern int c_iscntrl PARAMS ((int c));
+extern int c_isdigit PARAMS ((int c));
+extern int c_islower PARAMS ((int c));
+extern int c_isgraph PARAMS ((int c));
+extern int c_isprint PARAMS ((int c));
+extern int c_ispunct PARAMS ((int c));
+extern int c_isspace PARAMS ((int c));
+extern int c_isupper PARAMS ((int c));
+extern int c_isxdigit PARAMS ((int c));
+
+extern int c_tolower PARAMS ((int c));
+extern int c_toupper PARAMS ((int c));
+
+
+#if defined __GNUC__ && defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__
+
+/* ASCII optimizations. */
+
+#define c_isascii(c) \
+  ({ int __c = (c); \
+     ((__c & ~0x7f) == 0); \
+   })
+
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#define c_isalnum(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || (__c >= 'A' && __c <= 'Z') \
+      || (__c >= 'a' && __c <= 'z')); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#define c_isalpha(c) \
+  ({ int __c = (c); \
+     ((__c >= 'A' && __c <= 'Z') || (__c >= 'a' && __c <= 'z')); \
+   })
+#endif
+
+#define c_isblank(c) \
+  ({ int __c = (c); \
+     (__c == ' ' || __c == '\t'); \
+   })
+
+#if C_CTYPE_ASCII
+#define c_iscntrl(c) \
+  ({ int __c = (c); \
+     ((__c & ~0x1f) == 0 || __c == 0x7f); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_DIGITS
+#define c_isdigit(c) \
+  ({ int __c = (c); \
+     (__c >= '0' && __c <= '9'); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_LOWERCASE
+#define c_islower(c) \
+  ({ int __c = (c); \
+     (__c >= 'a' && __c <= 'z'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#define c_isgraph(c) \
+  ({ int __c = (c); \
+     (__c >= '!' && __c <= '~'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#define c_isprint(c) \
+  ({ int __c = (c); \
+     (__c >= ' ' && __c <= '~'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#define c_ispunct(c) \
+  ({ int _c = (c); \
+     (c_isgraph (_c) && ! c_isalnum (_c)); \
+   })
+#endif
+
+#define c_isspace(c) \
+  ({ int __c = (c); \
+     (__c == ' ' || __c == '\t' \
+      || __c == '\n' || __c == '\v' || __c == '\f' || __c == '\r'); \
+   })
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE
+#define c_isupper(c) \
+  ({ int __c = (c); \
+     (__c >= 'A' && __c <= 'Z'); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#define c_isxdigit(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || (__c >= 'A' && __c <= 'F') \
+      || (__c >= 'a' && __c <= 'f')); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#define c_tolower(c) \
+  ({ int __c = (c); \
+     (__c >= 'A' && __c <= 'Z' ? __c - 'A' + 'a' : __c); \
+   })
+#define c_toupper(c) \
+  ({ int __c = (c); \
+     (__c >= 'a' && __c <= 'z' ? __c - 'a' + 'A' : __c); \
+   })
+#endif
+
+#endif /* optimizing for speed */
+
+#endif /* C_CTYPE_H */
diff --git a/lib/config.charset b/lib/config.charset
new file mode 100755 (executable)
index 0000000..bf21d99
--- /dev/null
@@ -0,0 +1,246 @@
+#! /bin/sh
+# Output a system dependent table of character encoding aliases.
+#
+#   Copyright (C) 2000-2001 Free Software Foundation, Inc.
+#
+#   This program 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, or (at your option)
+#   any later version.
+#
+#   This program 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 this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#   USA.
+#
+# The table consists of lines of the form
+#    ALIAS  CANONICAL
+#
+# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)".
+# ALIAS is compared in a case sensitive way.
+#
+# CANONICAL is the GNU canonical name for this character encoding.
+# It must be an encoding supported by libiconv. Support by GNU libc is
+# also desirable. CANONICAL is case insensitive. Usually an upper case
+# MIME charset name is preferred.
+# The current list of GNU canonical charset names is as follows.
+#
+#       name                         used by which systems         a MIME name?
+#   ASCII, ANSI_X3.4-1968     glibc solaris freebsd
+#   ISO-8859-1                glibc aix hpux irix osf solaris freebsd   yes
+#   ISO-8859-2                glibc aix hpux irix solaris freebsd       yes
+#   ISO-8859-3                glibc                                     yes
+#   ISO-8859-4                solaris freebsd                           yes
+#   ISO-8859-5                glibc aix hpux irix solaris freebsd       yes
+#   ISO-8859-6                glibc aix hpux solaris                    yes
+#   ISO-8859-7                glibc aix hpux irix osf solaris           yes
+#   ISO-8859-8                glibc aix hpux solaris                    yes
+#   ISO-8859-9                glibc aix hpux irix osf solaris           yes
+#   ISO-8859-13               glibc
+#   ISO-8859-15               glibc aix solaris freebsd
+#   KOI8-R                    glibc solaris freebsd                     yes
+#   KOI8-U                    glibc freebsd                             yes
+#   CP850                     aix osf
+#   CP856                     aix
+#   CP866                     freebsd
+#   CP874                     win32
+#   CP922                     aix
+#   CP932                     aix win32
+#   CP943                     aix
+#   CP949                     win32
+#   CP950                     win32
+#   CP1046                    aix
+#   CP1124                    aix
+#   CP1129                    aix
+#   CP1250                    win32
+#   CP1251                    glibc win32
+#   CP1252                    aix win32
+#   CP1253                    win32
+#   CP1254                    win32
+#   CP1255                    win32
+#   CP1256                    win32
+#   CP1257                    win32
+#   GB2312                    glibc aix hpux irix solaris freebsd       yes
+#   EUC-JP                    glibc aix hpux irix solaris freebsd       yes
+#   EUC-KR                    glibc aix hpux irix solaris freebsd       yes
+#   EUC-TW                    glibc aix hpux irix solaris
+#   BIG5                      glibc aix hpux solaris freebsd            yes
+#   BIG5HKSCS                 glibc
+#   GBK                       aix win32
+#   GB18030                   glibc
+#   SJIS                      hpux solaris freebsd
+#   JOHAB                     glibc win32
+#   TIS-620                   glibc aix hpux solaris
+#   VISCII                    glibc                                     yes
+#   HP-ROMAN8                 hpux
+#   HP-ARABIC8                hpux
+#   HP-GREEK8                 hpux
+#   HP-HEBREW8                hpux
+#   HP-TURKISH8               hpux
+#   HP-KANA8                  hpux
+#   UTF-8                     glibc aix hpux solaris                    yes
+#
+# Note: Names which are not marked as being a MIME name should not be used in
+# Internet protocols for information interchange (mail, news, etc.).
+#
+# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
+# must understand both names and treat them as equivalent.
+#
+# The first argument passed to this file is the canonical host specification,
+#    CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+#    CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+
+host="$1"
+os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'`
+echo "# This file contains a table of character encoding aliases,"
+echo "# suitable for operating system '${os}'."
+echo "# It was automatically generated from config.charset."
+# List of references, updated during installation:
+echo "# Packages using this file: "
+case "$os" in
+    linux* | *-gnu*)
+       # With glibc-2.1 or newer, we don't need any canonicalization,
+       # because glibc has iconv and both glibc and libiconv support all
+       # GNU canonical names directly. Therefore, the Makefile does not
+       # need to install the alias file at all.
+       # The following applies only to glibc-2.0.x and older libcs.
+       echo "ISO_646.IRV:1983 ASCII"
+       ;;
+    aix*)
+       echo "ISO8859-1 ISO-8859-1"
+       echo "ISO8859-2 ISO-8859-2"
+       echo "ISO8859-5 ISO-8859-5"
+       echo "ISO8859-6 ISO-8859-6"
+       echo "ISO8859-7 ISO-8859-7"
+       echo "ISO8859-8 ISO-8859-8"
+       echo "ISO8859-9 ISO-8859-9"
+       echo "ISO8859-15 ISO-8859-15"
+       echo "IBM-850 CP850"
+       echo "IBM-856 CP856"
+       echo "IBM-921 ISO-8859-13"
+       echo "IBM-922 CP922"
+       echo "IBM-932 CP932"
+       echo "IBM-943 CP943"
+       echo "IBM-1046 CP1046"
+       echo "IBM-1124 CP1124"
+       echo "IBM-1129 CP1129"
+       echo "IBM-1252 CP1252"
+       echo "IBM-eucCN GB2312"
+       echo "IBM-eucJP EUC-JP"
+       echo "IBM-eucKR EUC-KR"
+       echo "IBM-eucTW EUC-TW"
+       echo "big5 BIG5"
+       echo "GBK GBK"
+       echo "TIS-620 TIS-620"
+       echo "UTF-8 UTF-8"
+       ;;
+    hpux*)
+       echo "iso88591 ISO-8859-1"
+       echo "iso88592 ISO-8859-2"
+       echo "iso88595 ISO-8859-5"
+       echo "iso88596 ISO-8859-6"
+       echo "iso88597 ISO-8859-7"
+       echo "iso88598 ISO-8859-8"
+       echo "iso88599 ISO-8859-9"
+       echo "iso885915 ISO-8859-15"
+       echo "roman8 HP-ROMAN8"
+       echo "arabic8 HP-ARABIC8"
+       echo "greek8 HP-GREEK8"
+       echo "hebrew8 HP-HEBREW8"
+       echo "turkish8 HP-TURKISH8"
+       echo "kana8 HP-KANA8"
+       echo "tis620 TIS-620"
+       echo "big5 BIG5"
+       echo "eucJP EUC-JP"
+       echo "eucKR EUC-KR"
+       echo "eucTW EUC-TW"
+       echo "hp15CN GB2312"
+       #echo "ccdc ?" # what is this?
+       echo "SJIS SJIS"
+       echo "utf8 UTF-8"
+       ;;
+    irix*)
+       echo "ISO8859-1 ISO-8859-1"
+       echo "ISO8859-2 ISO-8859-2"
+       echo "ISO8859-5 ISO-8859-5"
+       echo "ISO8859-7 ISO-8859-7"
+       echo "ISO8859-9 ISO-8859-9"
+       echo "eucCN GB2312"
+       echo "eucJP EUC-JP"
+       echo "eucKR EUC-KR"
+       echo "eucTW EUC-TW"
+       ;;
+    osf*)
+       echo "ISO8859-1 ISO-8859-1"
+       echo "ISO8859-7 ISO-8859-7"
+       echo "ISO8859-9 ISO-8859-9"
+       echo "cp850 CP850"
+       ;;
+    solaris*)
+       echo "646 ASCII"
+       echo "ISO8859-1 ISO-8859-1"
+       echo "ISO8859-2 ISO-8859-2"
+       echo "ISO8859-4 ISO-8859-4"
+       echo "ISO8859-5 ISO-8859-5"
+       echo "ISO8859-6 ISO-8859-6"
+       echo "ISO8859-7 ISO-8859-7"
+       echo "ISO8859-8 ISO-8859-8"
+       echo "ISO8859-9 ISO-8859-9"
+       echo "ISO8859-15 ISO-8859-15"
+       echo "koi8-r KOI8-R"
+       echo "BIG5 BIG5"
+       echo "gb2312 GB2312"
+       echo "cns11643 EUC-TW"
+       echo "5601 EUC-KR"
+       echo "eucJP EUC-JP"
+       echo "PCK SJIS"
+       echo "TIS620.2533 TIS-620"
+       #echo "sun_eu_greek ?" # what is this?
+       echo "UTF-8 UTF-8"
+       ;;
+    freebsd*)
+       # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore
+       # localcharset.c falls back to using the full locale name
+       # from the environment variables.
+       echo "C ASCII"
+       echo "US-ASCII ASCII"
+       for l in la_LN lt_LN; do
+         echo "$l.ASCII ASCII"
+       done
+       for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
+                 fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \
+                 lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do
+         echo "$l.ISO_8859-1 ISO-8859-1"
+         echo "$l.DIS_8859-15 ISO-8859-15"
+       done
+       for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do
+         echo "$l.ISO_8859-2 ISO-8859-2"
+       done
+       for l in la_LN lt_LT; do
+         echo "$l.ISO_8859-4 ISO-8859-4"
+       done
+       for l in ru_RU ru_SU; do
+         echo "$l.KOI8-R KOI8-R"
+         echo "$l.ISO_8859-5 ISO-8859-5"
+         echo "$l.CP866 CP866"
+       done
+       echo "uk_UA.KOI8-U KOI8-U"
+       echo "zh_TW.BIG5 BIG5"
+       echo "zh_TW.Big5 BIG5"
+       echo "zh_CN.EUC GB2312"
+       echo "ja_JP.EUC EUC-JP"
+       echo "ja_JP.SJIS SJIS"
+       echo "ja_JP.Shift_JIS SJIS"
+       echo "ko_KR.EUC EUC-KR"
+       ;;
+    beos*)
+       # BeOS has a single locale, and it has UTF-8 encoding.
+       echo "C UTF-8"
+       ;;
+esac
diff --git a/lib/gen-lbrkprop.c b/lib/gen-lbrkprop.c
new file mode 100644 (file)
index 0000000..52a28e1
--- /dev/null
@@ -0,0 +1,981 @@
+/* Generate a Unicode conforming Line Break Properties tables from a
+   UnicodeData file.
+   Written by Bruno Haible <haible@clisp.cons.org>, 2000-2001.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Usage example:
+     $ gen-lbrkprop /usr/local/share/Unidata/UnicodeData.txt \
+                   /usr/local/share/Unidata/PropList.txt \
+                   /usr/local/share/Unidata/EastAsianWidth.txt \
+                   3.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+
+/* This structure represents one line in the UnicodeData.txt file.  */
+struct unicode_attribute
+{
+  const char *name;           /* Character name */
+  const char *category;       /* General category */
+  const char *combining;      /* Canonical combining classes */
+  const char *bidi;           /* Bidirectional category */
+  const char *decomposition;  /* Character decomposition mapping */
+  const char *decdigit;       /* Decimal digit value */
+  const char *digit;          /* Digit value */
+  const char *numeric;        /* Numeric value */
+  int mirrored;               /* mirrored */
+  const char *oldname;        /* Old Unicode 1.0 name */
+  const char *comment;        /* Comment */
+  unsigned int upper;         /* Uppercase mapping */
+  unsigned int lower;         /* Lowercase mapping */
+  unsigned int title;         /* Titlecase mapping */
+};
+
+/* Missing fields are represented with "" for strings, and NONE for
+   characters.  */
+#define NONE (~(unsigned int)0)
+
+/* The entire contents of the UnicodeData.txt file.  */
+struct unicode_attribute unicode_attributes [0x10000];
+
+/* Stores in unicode_attributes[i] the values from the given fields.  */
+static void
+fill_attribute (unsigned int i,
+               const char *field1, const char *field2,
+               const char *field3, const char *field4,
+               const char *field5, const char *field6,
+               const char *field7, const char *field8,
+               const char *field9, const char *field10,
+               const char *field11, const char *field12,
+               const char *field13, const char *field14)
+{
+  struct unicode_attribute * uni;
+
+  if (i >= 0x10000)
+    {
+      fprintf (stderr, "index too large\n");
+      exit (1);
+    }
+  uni = &unicode_attributes[i];
+  /* Copy the strings.  */
+  uni->name          = strdup (field1);
+  uni->category      = (field2[0] == '\0' ? "" : strdup (field2));
+  uni->combining     = (field3[0] == '\0' ? "" : strdup (field3));
+  uni->bidi          = (field4[0] == '\0' ? "" : strdup (field4));
+  uni->decomposition = (field5[0] == '\0' ? "" : strdup (field5));
+  uni->decdigit      = (field6[0] == '\0' ? "" : strdup (field6));
+  uni->digit         = (field7[0] == '\0' ? "" : strdup (field7));
+  uni->numeric       = (field8[0] == '\0' ? "" : strdup (field8));
+  uni->mirrored      = (field9[0] == 'Y');
+  uni->oldname       = (field10[0] == '\0' ? "" : strdup (field10));
+  uni->comment       = (field11[0] == '\0' ? "" : strdup (field11));
+  uni->upper = (field12[0] =='\0' ? NONE : strtoul (field12, NULL, 16));
+  uni->lower = (field13[0] =='\0' ? NONE : strtoul (field13, NULL, 16));
+  uni->title = (field14[0] =='\0' ? NONE : strtoul (field14, NULL, 16));
+}
+
+/* Maximum length of a field in the UnicodeData.txt file.  */
+#define FIELDLEN 120
+
+/* Reads the next field from STREAM.  The buffer BUFFER has size FIELDLEN.
+   Reads up to (but excluding) DELIM.
+   Returns 1 when a field was successfully read, otherwise 0.  */
+static int
+getfield (FILE *stream, char *buffer, int delim)
+{
+  int count = 0;
+  int c;
+
+  for (; (c = getc (stream)), (c != EOF && c != delim); )
+    {
+      /* The original unicode.org UnicodeData.txt file happens to have
+        CR/LF line terminators.  Silently convert to LF.  */
+      if (c == '\r')
+       continue;
+
+      /* Put c into the buffer.  */
+      if (++count >= FIELDLEN - 1)
+       {
+         fprintf (stderr, "field too long\n");
+         exit (1);
+       }
+      *buffer++ = c;
+    }
+
+  if (c == EOF)
+    return 0;
+
+  *buffer = '\0';
+  return 1;
+}
+
+/* Stores in unicode_attributes[] the entire contents of the UnicodeData.txt
+   file.  */
+static void
+fill_attributes (const char *unicodedata_filename)
+{
+  unsigned int i, j;
+  FILE *stream;
+  char field0[FIELDLEN];
+  char field1[FIELDLEN];
+  char field2[FIELDLEN];
+  char field3[FIELDLEN];
+  char field4[FIELDLEN];
+  char field5[FIELDLEN];
+  char field6[FIELDLEN];
+  char field7[FIELDLEN];
+  char field8[FIELDLEN];
+  char field9[FIELDLEN];
+  char field10[FIELDLEN];
+  char field11[FIELDLEN];
+  char field12[FIELDLEN];
+  char field13[FIELDLEN];
+  char field14[FIELDLEN];
+  int lineno = 0;
+
+  for (i = 0; i < 0x10000; i++)
+    unicode_attributes[i].name = NULL;
+
+  stream = fopen (unicodedata_filename, "r");
+  if (stream == NULL)
+    {
+      fprintf (stderr, "error during fopen of '%s'\n", unicodedata_filename);
+      exit (1);
+    }
+
+  for (;;)
+    {
+      int n;
+
+      lineno++;
+      n = getfield (stream, field0, ';');
+      n += getfield (stream, field1, ';');
+      n += getfield (stream, field2, ';');
+      n += getfield (stream, field3, ';');
+      n += getfield (stream, field4, ';');
+      n += getfield (stream, field5, ';');
+      n += getfield (stream, field6, ';');
+      n += getfield (stream, field7, ';');
+      n += getfield (stream, field8, ';');
+      n += getfield (stream, field9, ';');
+      n += getfield (stream, field10, ';');
+      n += getfield (stream, field11, ';');
+      n += getfield (stream, field12, ';');
+      n += getfield (stream, field13, ';');
+      n += getfield (stream, field14, '\n');
+      if (n == 0)
+       break;
+      if (n != 15)
+       {
+         fprintf (stderr, "short line in'%s':%d\n",
+                  unicodedata_filename, lineno);
+         exit (1);
+       }
+      i = strtoul (field0, NULL, 16);
+      if (field1[0] == '<'
+         && strlen (field1) >= 9
+         && !strcmp (field1 + strlen(field1) - 8, ", First>"))
+       {
+         /* Deal with a range. */
+         lineno++;
+         n = getfield (stream, field0, ';');
+         n += getfield (stream, field1, ';');
+         n += getfield (stream, field2, ';');
+         n += getfield (stream, field3, ';');
+         n += getfield (stream, field4, ';');
+         n += getfield (stream, field5, ';');
+         n += getfield (stream, field6, ';');
+         n += getfield (stream, field7, ';');
+         n += getfield (stream, field8, ';');
+         n += getfield (stream, field9, ';');
+         n += getfield (stream, field10, ';');
+         n += getfield (stream, field11, ';');
+         n += getfield (stream, field12, ';');
+         n += getfield (stream, field13, ';');
+         n += getfield (stream, field14, '\n');
+         if (n != 15)
+           {
+             fprintf (stderr, "missing end range in '%s':%d\n",
+                      unicodedata_filename, lineno);
+             exit (1);
+           }
+         if (!(field1[0] == '<'
+               && strlen (field1) >= 8
+               && !strcmp (field1 + strlen (field1) - 7, ", Last>")))
+           {
+             fprintf (stderr, "missing end range in '%s':%d\n",
+                      unicodedata_filename, lineno);
+             exit (1);
+           }
+         field1[strlen (field1) - 7] = '\0';
+         j = strtoul (field0, NULL, 16);
+         for (; i <= j; i++)
+           fill_attribute (i, field1+1, field2, field3, field4, field5,
+                              field6, field7, field8, field9, field10,
+                              field11, field12, field13, field14);
+       }
+      else
+       {
+         /* Single character line */
+         fill_attribute (i, field1, field2, field3, field4, field5,
+                            field6, field7, field8, field9, field10,
+                            field11, field12, field13, field14);
+       }
+    }
+  if (ferror (stream) || fclose (stream))
+    {
+      fprintf (stderr, "error reading from '%s'\n", unicodedata_filename);
+      exit (1);
+    }
+}
+
+/* The combining property from the PropList.txt file.  */
+char unicode_combining[0x10000];
+
+/* Stores in unicode_combining[] the Combining property from the
+   PropList.txt file.  */
+static void
+fill_combining (const char *proplist_filename)
+{
+  unsigned int i;
+  FILE *stream;
+  char buf[100+1];
+
+  for (i = 0; i < 0x10000; i++)
+    unicode_combining[i] = 0;
+
+  stream = fopen (proplist_filename, "r");
+  if (stream == NULL)
+    {
+      fprintf (stderr, "error during fopen of '%s'\n", proplist_filename);
+      exit (1);
+    }
+
+  /* Search for the "Property dump for: 0x20000004 (Combining)" line.  */
+  do
+    {
+      if (fscanf (stream, "%100[^\n]\n", buf) < 1)
+       {
+         fprintf (stderr, "no combining property found in '%s'\n",
+                  proplist_filename);
+         exit (1);
+       }
+    }
+  while (strstr (buf, "(Combining)") == NULL);
+
+  for (;;)
+    {
+      unsigned int i1, i2;
+
+      if (fscanf (stream, "%100[^\n]\n", buf) < 1)
+       {
+         fprintf (stderr, "premature end of combining property in '%s'\n",
+                  proplist_filename);
+         exit (1);
+       }
+      if (buf[0] == '*')
+       break;
+      if (strlen (buf) >= 10 && buf[4] == '.' && buf[5] == '.')
+       {
+         if (sscanf (buf, "%4X..%4X", &i1, &i2) < 2)
+           {
+             fprintf (stderr, "parse error in combining property in '%s'\n",
+                      proplist_filename);
+             exit (1);
+           }
+       }
+      else if (strlen (buf) >= 4)
+       {
+         if (sscanf (buf, "%4X", &i1) < 1)
+           {
+             fprintf (stderr, "parse error in combining property in '%s'\n",
+                      proplist_filename);
+             exit (1);
+           }
+         i2 = i1;
+       }
+      else
+       {
+         fprintf (stderr, "parse error in combining property in '%s'\n",
+                  proplist_filename);
+         exit (1);
+       }
+      for (i = i1; i <= i2; i++)
+       unicode_combining[i] = 1;
+    }
+  if (ferror (stream) || fclose (stream))
+    {
+      fprintf (stderr, "error reading from '%s'\n", proplist_filename);
+      exit (1);
+    }
+}
+
+/* The width property from the EastAsianWidth.txt file.
+   Each is NULL (unassigned) or "N", "A", "H", "W", "F", "Na".  */
+const char * unicode_width[0x10000];
+
+/* Stores in unicode_width[] the width property from the PropList.txt
+   file.  */
+static void
+fill_width (const char *width_filename)
+{
+  unsigned int i, j;
+  FILE *stream;
+  char field0[FIELDLEN];
+  char field1[FIELDLEN];
+  char field2[FIELDLEN];
+  int lineno = 0;
+
+  for (i = 0; i < 0x10000; i++)
+    unicode_width[i] = (unicode_attributes[i].name != NULL ? "N" : NULL);
+
+  stream = fopen (width_filename, "r");
+  if (stream == NULL)
+    {
+      fprintf (stderr, "error during fopen of '%s'\n", width_filename);
+      exit (1);
+    }
+
+  for (;;)
+    {
+      int n;
+      int c;
+
+      lineno++;
+      c = getc (stream);
+      if (c == EOF)
+       break;
+      if (c == '#')
+       {
+         do c = getc (stream); while (c != EOF && c != '\n');
+         continue;
+       }
+      ungetc (c, stream);
+      n = getfield (stream, field0, ';');
+      n += getfield (stream, field1, ';');
+      n += getfield (stream, field2, '\n');
+      if (n == 0)
+       break;
+      if (n != 3)
+       {
+         fprintf (stderr, "short line in '%s':%d\n", width_filename, lineno);
+         exit (1);
+       }
+      i = strtoul (field0, NULL, 16);
+      if (field2[0] == '<'
+         && strlen (field2) >= 9
+         && !strcmp (field2 + strlen(field2) - 8, ", First>"))
+       {
+         /* Deal with a range. */
+         lineno++;
+         n = getfield (stream, field0, ';');
+         n += getfield (stream, field1, ';');
+         n += getfield (stream, field2, '\n');
+         if (n != 3)
+           {
+             fprintf (stderr, "missing end range in '%s':%d\n",
+                      width_filename, lineno);
+             exit (1);
+           }
+         if (!(field2[0] == '<'
+               && strlen (field2) >= 8
+               && !strcmp (field2 + strlen (field2) - 7, ", Last>")))
+           {
+             fprintf (stderr, "missing end range in '%s':%d\n",
+                      width_filename, lineno);
+             exit (1);
+           }
+         field2[strlen (field2) - 7] = '\0';
+         j = strtoul (field0, NULL, 16);
+         for (; i <= j; i++)
+           unicode_width[i] = strdup (field1);
+       }
+      else
+       {
+         /* Single character line */
+         unicode_width[i] = strdup (field1);
+       }
+    }
+  if (ferror (stream) || fclose (stream))
+    {
+      fprintf (stderr, "error reading from '%s'\n", width_filename);
+      exit (1);
+    }
+}
+
+/* Line breaking classification.  */
+
+enum
+{
+  /* Values >= 20 are resolved at run time. */
+  LBP_BK =  0, /* mandatory break */
+/*LBP_CR,         carriage return - not used here because it's a DOSism */
+/*LBP_LF,         line feed - not used here because it's a DOSism */
+  LBP_CM = 20, /* attached characters and combining marks */
+/*LBP_SG,         surrogates - not used here because they are not characters */
+  LBP_ZW =  1, /* zero width space */
+  LBP_IN =  2, /* inseparable */
+  LBP_GL =  3, /* non-breaking (glue) */
+  LBP_CB = 22, /* contingent break opportunity */
+  LBP_SP = 21, /* space */
+  LBP_BA =  4, /* break opportunity after */
+  LBP_BB =  5, /* break opportunity before */
+  LBP_B2 =  6, /* break opportunity before and after */
+  LBP_HY =  7, /* hyphen */
+  LBP_NS =  8, /* non starter */
+  LBP_OP =  9, /* opening punctuation */
+  LBP_CL = 10, /* closing punctuation */
+  LBP_QU = 11, /* ambiguous quotation */
+  LBP_EX = 12, /* exclamation/interrogation */
+  LBP_ID = 13, /* ideographic */
+  LBP_NU = 14, /* numeric */
+  LBP_IS = 15, /* infix separator (numeric) */
+  LBP_SY = 16, /* symbols allowing breaks */
+  LBP_AL = 17, /* ordinary alphabetic and symbol characters */
+  LBP_PR = 18, /* prefix (numeric) */
+  LBP_PO = 19, /* postfix (numeric) */
+  LBP_SA = 23, /* complex context (South East Asian) */
+  LBP_AI = 24, /* ambiguous (alphabetic or ideograph) */
+  LBP_XX = 25  /* unknown */
+};
+
+/* Returns the line breaking classification for ch, as a bit mask.  */
+static int
+get_lbp (unsigned int ch)
+{
+  int attr = 0;
+
+  if (unicode_attributes[ch].name != NULL)
+    {
+      /* mandatory break */
+      if (ch == 0x000A || ch == 0x000D || ch == 0x0085 /* newline */
+         || ch == 0x000C /* form feed */
+         || ch == 0x2028 /* LINE SEPARATOR */
+         || ch == 0x2029 /* PARAGRAPH SEPARATOR */)
+       attr |= 1 << LBP_BK;
+
+      /* zero width space */
+      if (ch == 0x200B /* ZERO WIDTH SPACE */)
+       attr |= 1 << LBP_ZW;
+
+      /* inseparable */
+      if (ch == 0x2024 /* ONE DOT LEADER */
+         || ch == 0x2025 /* TWO DOT LEADER */
+         || ch == 0x2026 /* HORIZONTAL ELLIPSIS */)
+       attr |= 1 << LBP_IN;
+
+      /* non-breaking (glue) */
+      if (ch == 0xFEFF /* ZERO WIDTH NO-BREAK SPACE */
+         || ch == 0x00A0 /* NO-BREAK SPACE */
+         || ch == 0x202F /* NARROW NO-BREAK SPACE */
+         || ch == 0x2007 /* FIGURE SPACE */
+         || ch == 0x2011 /* NON-BREAKING HYPHEN */
+         || ch == 0x0F0C /* TIBETAN MARK DELIMITER TSHEG BSTAR */)
+       attr |= 1 << LBP_GL;
+
+      /* contingent break opportunity */
+      if (ch == 0xFFFC /* OBJECT REPLACEMENT CHARACTER */)
+       attr |= 1 << LBP_CB;
+
+      /* space */
+      if (ch == 0x0020 /* SPACE */)
+       attr |= 1 << LBP_SP;
+
+      /* break opportunity after */
+      if (ch == 0x2000 /* EN QUAD */
+         || ch == 0x2001 /* EM QUAD */
+         || ch == 0x2002 /* EN SPACE */
+         || ch == 0x2003 /* EM SPACE */
+         || ch == 0x2004 /* THREE-PER-EM SPACE */
+         || ch == 0x2005 /* FOUR-PER-EM SPACE */
+         || ch == 0x2006 /* SIX-PER-EM SPACE */
+         || ch == 0x2008 /* PUNCTUATION SPACE */
+         || ch == 0x2009 /* THIN SPACE */
+         || ch == 0x200A /* HAIR SPACE */
+         || ch == 0x0009 /* tab */
+         || ch == 0x2010 /* HYPHEN */
+         || ch == 0x058A /* ARMENIAN HYPHEN */
+         || ch == 0x00AD /* SOFT HYPHEN */
+         || ch == 0x0F0B /* TIBETAN MARK INTERSYLLABIC TSHEG */
+         || ch == 0x1361 /* ETHIOPIC WORDSPACE */
+         || ch == 0x1680 /* OGHAM SPACE MARK */
+         || ch == 0x17D5 /* KHMER SIGN BARIYOOSAN */
+         || ch == 0x2027 /* HYPHENATION POINT */
+         || ch == 0x007C /* VERTICAL LINE */)
+       attr |= 1 << LBP_BA;
+
+      /* break opportunity before */
+      if (ch == 0x00B4 /* ACUTE ACCENT */
+         || ch == 0x02C8 /* MODIFIER LETTER VERTICAL LINE */
+         || ch == 0x02CC /* MODIFIER LETTER LOW VERTICAL LINE */
+         || ch == 0x1806 /* MONGOLIAN TODO SOFT HYPHEN */)
+       attr |= 1 << LBP_BB;
+
+      /* break opportunity before and after */
+      if (ch == 0x2014 /* EM DASH */)
+       attr |= 1 << LBP_B2;
+
+      /* hyphen */
+      if (ch == 0x002D /* HYPHEN-MINUS */)
+       attr |= 1 << LBP_HY;
+
+      /* exclamation/interrogation */
+      if (ch == 0x0021 /* EXCLAMATION MARK */
+         || ch == 0x003F /* QUESTION MARK */
+         || ch == 0xFE56 /* SMALL QUESTION MARK */
+         || ch == 0xFE57 /* SMALL EXCLAMATION MARK */
+         || ch == 0xFF01 /* FULLWIDTH EXCLAMATION MARK */
+         || ch == 0xFF1F /* FULLWIDTH QUESTION MARK */)
+       attr |= 1 << LBP_EX;
+
+      /* opening punctuation */
+      if (unicode_attributes[ch].category[0] == 'P'
+         && unicode_attributes[ch].category[1] == 's')
+       attr |= 1 << LBP_OP;
+
+      /* closing punctuation */
+      if (ch == 0x3001 /* IDEOGRAPHIC COMMA */
+         || ch == 0x3002 /* IDEOGRAPHIC FULL STOP */
+         || ch == 0xFF0C /* FULLWIDTH COMMA */
+         || ch == 0xFF0E /* FULLWIDTH FULL STOP */
+         || ch == 0xFE50 /* SMALL COMMA */
+         || ch == 0xFE52 /* SMALL FULL STOP */
+         || ch == 0xFF61 /* HALFWIDTH IDEOGRAPHIC FULL STOP */
+         || ch == 0xFF64 /* HALFWIDTH IDEOGRAPHIC COMMA */
+         || (unicode_attributes[ch].category[0] == 'P'
+             && unicode_attributes[ch].category[1] == 'e'))
+       attr |= 1 << LBP_CL;
+
+      /* ambiguous quotation */
+      if (ch == 0x0022 /* QUOTATION MARK */
+         || ch == 0x0027 /* APOSTROPHE */
+         || (unicode_attributes[ch].category[0] == 'P'
+             && (unicode_attributes[ch].category[1] == 'f'
+                 || unicode_attributes[ch].category[1] == 'i')))
+       attr |= 1 << LBP_QU;
+
+      /* attached characters and combining marks */
+      if ((unicode_attributes[ch].category[0] == 'M'
+          && (unicode_attributes[ch].category[1] == 'n'
+              || unicode_attributes[ch].category[1] == 'c'
+              || unicode_attributes[ch].category[1] == 'e'))
+         || (ch >= 0x1160 && ch <= 0x11F9)
+         || (unicode_attributes[ch].category[0] == 'C'
+             && (unicode_attributes[ch].category[1] == 'c'
+                 || unicode_attributes[ch].category[1] == 'f')))
+       if (!(attr & ((1 << LBP_BK) | (1 << LBP_BA) | (1 << LBP_GL))))
+         attr |= 1 << LBP_CM;
+
+      /* non starter */
+      if (ch == 0x0E5A /* THAI CHARACTER ANGKHANKHU */
+         || ch == 0x0E5B /* THAI CHARACTER KHOMUT */
+         || ch == 0x17D4 /* KHMER SIGN KHAN */
+         || ch == 0x17D6 /* KHMER SIGN CAMNUC PII KUUH */
+         || ch == 0x17D7 /* KHMER SIGN LEK TOO */
+         || ch == 0x17D8 /* KHMER SIGN BEYYAL */
+         || ch == 0x17D9 /* KHMER SIGN PHNAEK MUAN */
+         || ch == 0x17DA /* KHMER SIGN KOOMUUT */
+         || ch == 0x203C /* DOUBLE EXCLAMATION MARK */
+         || ch == 0x2044 /* FRACTION SLASH */
+         || ch == 0x301C /* WAVE DASH */
+         || ch == 0x30FB /* KATAKANA MIDDLE DOT */
+         || ch == 0x3005 /* IDEOGRAPHIC ITERATION MARK */
+         || ch == 0x309B /* KATAKANA-HIRAGANA VOICED SOUND MARK */
+         || ch == 0x309C /* KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+         || ch == 0x309D /* HIRAGANA ITERATION MARK */
+         || ch == 0x309E /* HIRAGANA VOICED ITERATION MARK */
+         || ch == 0x30FD /* KATAKANA ITERATION MARK */
+         || ch == 0xFE54 /* SMALL SEMICOLON */
+         || ch == 0xFE55 /* SMALL COLON */
+         || ch == 0xFF1A /* FULLWIDTH COLON */
+         || ch == 0xFF1B /* FULLWIDTH SEMICOLON */
+         || ch == 0xFF65 /* HALFWIDTH KATAKANA MIDDLE DOT */
+         || ch == 0xFF70 /* HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+         || (unicode_attributes[ch].category[0] == 'L'
+             && unicode_attributes[ch].category[1] == 'm'
+             && (unicode_width[ch][0] == 'W'
+                 || unicode_width[ch][0] == 'H'))
+         || (unicode_attributes[ch].category[0] == 'S'
+             && unicode_attributes[ch].category[1] == 'k'
+             && unicode_width[ch][0] == 'W')
+         || strstr (unicode_attributes[ch].name, "HIRAGANA LETTER SMALL ") != NULL
+         || strstr (unicode_attributes[ch].name, "KATAKANA LETTER SMALL ") != NULL)
+       attr |= 1 << LBP_NS;
+
+      /* numeric */
+      if (unicode_attributes[ch].category[0] == 'N'
+         && unicode_attributes[ch].category[1] == 'd'
+         && strstr (unicode_attributes[ch].name, "FULLWIDTH") == NULL)
+       attr |= 1 << LBP_NU;
+
+      /* infix separator (numeric) */
+      if (ch == 0x002C /* COMMA */
+         || ch == 0x002E /* FULL STOP */
+         || ch == 0x003A /* COLON */
+         || ch == 0x003B /* SEMICOLON */
+         || ch == 0x0589 /* ARMENIAN FULL STOP */)
+       attr |= 1 << LBP_IS;
+
+      /* symbols allowing breaks */
+      if (ch == 0x002F /* SOLIDUS */)
+       attr |= 1 << LBP_SY;
+
+      /* postfix (numeric) */
+      if (ch == 0x0025 /* PERCENT SIGN */
+         || ch == 0x00A2 /* CENT SIGN */
+         || ch == 0x00B0 /* DEGREE SIGN */
+         || ch == 0x2030 /* PER MILLE SIGN */
+         || ch == 0x2031 /* PER TEN THOUSAND SIGN */
+         || ch == 0x2032 /* PRIME */
+         || ch == 0x2033 /* DOUBLE PRIME */
+         || ch == 0x2034 /* TRIPLE PRIME */
+         || ch == 0x2035 /* REVERSED PRIME */
+         || ch == 0x20A7 /* PESETA SIGN */
+         || ch == 0x2103 /* DEGREE CELSIUS */
+         || ch == 0x2109 /* DEGREE FAHRENHEIT */
+         || ch == 0x2126 /* OHM SIGN */
+         || ch == 0xFE6A /* SMALL PERCENT SIGN */
+         || ch == 0xFF05 /* FULLWIDTH PERCENT SIGN */
+         || ch == 0xFFE0 /* FULLWIDTH DIGIT ZERO */)
+       attr |= 1 << LBP_PO;
+
+      /* prefix (numeric) */
+      if (ch == 0x002B /* PLUS SIGN */
+         || ch == 0x005C /* REVERSE SOLIDUS */
+         || ch == 0x00B1 /* PLUS-MINUS SIGN */
+         || ch == 0x2212 /* MINUS SIGN */
+         || ch == 0x2116 /* NUMERO SIGN */
+         || ch == 0x2213 /* MINUS-OR-PLUS SIGN */
+         || (unicode_attributes[ch].category[0] == 'S'
+             && unicode_attributes[ch].category[1] == 'c'))
+       if (!(attr & (1 << LBP_PO)))
+         attr |= 1 << LBP_PR;
+
+      /* complex context (South East Asian) */
+      if ((ch >= 0x0E00 && ch <= 0x0EFF)
+         || (ch >= 0x1000 && ch <= 0x109F)
+         || (ch >= 0x1780 && ch <= 0x17FF))
+       if (!(attr & ((1 << LBP_CM) | (1 << LBP_NS) | (1 << LBP_NU) | (1 << LBP_BA) | (1 << LBP_PR))))
+         attr |= 1 << LBP_SA;
+
+      /* ideographic */
+      if ((ch >= 0x4E00 && ch <= 0x9FAF) /* CJK Ideograph */
+         || (ch >= 0x3400 && ch <= 0x4DBF) /* CJK Ideograph Extension A */
+         || (ch >= 0xF900 && ch <= 0xFAFF) /* CJK COMPATIBILITY IDEOGRAPH */
+         || ch == 0x3000 /* IDEOGRAPHIC SPACE */
+         || (ch >= 0xAC00 && ch <= 0xD7AF) /* HANGUL SYLLABLE */
+         || (ch >= 0x3130 && ch <= 0x318F) /* HANGUL LETTER */
+         || (ch >= 0x1100 && ch <= 0x115F) /* HANGUL CHOSEONG */
+         || (ch >= 0xA000 && ch <= 0xA48C) /* YI SYLLABLE */
+         || (ch >= 0xA490 && ch <= 0xACFF) /* YI RADICAL */
+         || (ch >= 0x2E80 && ch <= 0x2FFF) /* CJK RADICAL, KANGXI RADICAL, IDEOGRAPHIC DESCRIPTION */
+         || ch == 0xFE62 /* SMALL PLUS SIGN */
+         || ch == 0xFE63 /* SMALL HYPHEN-MINUS */
+         || ch == 0xFE64 /* SMALL LESS-THAN SIGN */
+         || ch == 0xFE65 /* SMALL GREATER-THAN SIGN */
+         || ch == 0xFE66 /* SMALL EQUALS SIGN */
+         || (ch >= 0xFF10 && ch <= 0xFF19) /* FULLWIDTH DIGIT */
+         || strstr (unicode_attributes[ch].name, "FULLWIDTH LATIN ") != NULL
+         || (ch >= 0x3000 && ch <= 0x33FF
+             && !(attr & ((1 << LBP_CM) | (1 << LBP_NS) | (1 << LBP_OP) | (1 << LBP_CL)))))
+       {
+         /* ambiguous (ideograph) ? */
+         if (unicode_width[ch] != NULL
+             && unicode_width[ch][0] == 'A')
+           attr |= 1 << LBP_AI;
+         else
+           attr |= 1 << LBP_ID;
+       }
+
+      /* ordinary alphabetic and symbol characters */
+      if ((unicode_attributes[ch].category[0] == 'L'
+          && (unicode_attributes[ch].category[1] == 'u'
+              || unicode_attributes[ch].category[1] == 'l'
+              || unicode_attributes[ch].category[1] == 't'
+              || unicode_attributes[ch].category[1] == 'm'
+              || unicode_attributes[ch].category[1] == 'o'))
+         || (unicode_attributes[ch].category[0] == 'S'
+             && (unicode_attributes[ch].category[1] == 'm'
+                 || unicode_attributes[ch].category[1] == 'c'
+                 || unicode_attributes[ch].category[1] == 'k'
+                 || unicode_attributes[ch].category[1] == 'o')))
+       if (!(attr & ((1 << LBP_CM) | (1 << LBP_NS) | (1 << LBP_ID) | (1 << LBP_BA) | (1 << LBP_BB) | (1 << LBP_PO) | (1 << LBP_PR) | (1 << LBP_SA) | (1 << LBP_CB))))
+         {
+           /* ambiguous (alphabetic) ? */
+           if (unicode_width[ch] != NULL
+               && unicode_width[ch][0] == 'A')
+             attr |= 1 << LBP_AI;
+           else
+             attr |= 1 << LBP_AL;
+         }
+    }
+
+  if (attr == 0)
+    /* unknown */
+    attr |= 1 << LBP_XX;
+
+  return attr;
+}
+
+/* Output the line breaking properties in a human readable format.  */
+static void
+debug_output_lbp (FILE *stream)
+{
+  unsigned int i;
+
+  for (i = 0; i < 0x10000; i++)
+    {
+      int attr = get_lbp (i);
+      if (attr != 1 << LBP_XX)
+       {
+         fprintf (stream, "0x%04X", i);
+#define PRINT_BIT(attr,bit) \
+  if (attr & (1 << bit)) fprintf (stream, " " ## #bit);
+         PRINT_BIT(attr,LBP_BK);
+         PRINT_BIT(attr,LBP_CM);
+         PRINT_BIT(attr,LBP_ZW);
+         PRINT_BIT(attr,LBP_IN);
+         PRINT_BIT(attr,LBP_GL);
+         PRINT_BIT(attr,LBP_CB);
+         PRINT_BIT(attr,LBP_SP);
+         PRINT_BIT(attr,LBP_BA);
+         PRINT_BIT(attr,LBP_BB);
+         PRINT_BIT(attr,LBP_B2);
+         PRINT_BIT(attr,LBP_HY);
+         PRINT_BIT(attr,LBP_NS);
+         PRINT_BIT(attr,LBP_OP);
+         PRINT_BIT(attr,LBP_CL);
+         PRINT_BIT(attr,LBP_QU);
+         PRINT_BIT(attr,LBP_EX);
+         PRINT_BIT(attr,LBP_ID);
+         PRINT_BIT(attr,LBP_NU);
+         PRINT_BIT(attr,LBP_IS);
+         PRINT_BIT(attr,LBP_SY);
+         PRINT_BIT(attr,LBP_AL);
+         PRINT_BIT(attr,LBP_PR);
+         PRINT_BIT(attr,LBP_PO);
+         PRINT_BIT(attr,LBP_SA);
+         PRINT_BIT(attr,LBP_XX);
+         PRINT_BIT(attr,LBP_AI);
+#undef PRINT_BIT
+         fprintf (stream, "\n");
+       }
+    }
+}
+
+/* Construction of sparse 3-level tables.  */
+#define TABLE lbp_table
+#define ELEMENT unsigned char
+#define DEFAULT LBP_XX
+#define xmalloc malloc
+#define xrealloc realloc
+#include "3level.h"
+
+static void
+output_lbp (FILE *stream)
+{
+  unsigned int i;
+  struct lbp_table t;
+  unsigned int level1_offset, level2_offset, level3_offset;
+
+  t.p = 7;
+  t.q = 9;
+  lbp_table_init (&t);
+
+  for (i = 0; i < 0x10000; i++)
+    {
+      int attr = get_lbp (i);
+
+      /* Now attr should contain exactly one bit.  */
+      if (attr == 0 || ((attr & (attr - 1)) != 0))
+       abort ();
+
+      if (attr != 1 << LBP_XX)
+       {
+         unsigned int log2_attr;
+         for (log2_attr = 0; attr > 1; attr >>= 1, log2_attr++);
+
+         lbp_table_add (&t, i, log2_attr);
+       }
+    }
+
+  lbp_table_finalize (&t);
+
+  level1_offset =
+    5 * sizeof (uint32_t);
+  level2_offset =
+    5 * sizeof (uint32_t)
+    + t.level1_size * sizeof (uint32_t);
+  level3_offset =
+    5 * sizeof (uint32_t)
+    + t.level1_size * sizeof (uint32_t)
+    + (t.level2_size << t.q) * sizeof (uint32_t);
+
+  for (i = 0; i < 5; i++)
+    fprintf (stream, "#define lbrkprop_header_%d %d\n", i,
+            ((uint32_t *) t.result)[i]);
+  fprintf (stream, "static const\n");
+  fprintf (stream, "struct\n");
+  fprintf (stream, "  {\n");
+  fprintf (stream, "    int level1[%d];\n", t.level1_size);
+  fprintf (stream, "    int level2[%d << %d];\n", t.level2_size, t.q);
+  fprintf (stream, "    unsigned char level3[%d << %d];\n", t.level3_size, t.p);
+  fprintf (stream, "  }\n");
+  fprintf (stream, "lbrkprop =\n");
+  fprintf (stream, "{\n");
+  fprintf (stream, "  { ");
+  for (i = 0; i < t.level1_size; i++)
+    fprintf (stream, "%d%s ",
+            (((uint32_t *) (t.result + level1_offset))[i] - level2_offset) / sizeof (uint32_t),
+            (i+1 < t.level1_size ? "," : ""));
+  fprintf (stream, "},\n");
+  fprintf (stream, "  {");
+  if (t.level2_size << t.q > 8)
+    fprintf (stream, "\n   ");
+  for (i = 0; i < t.level2_size << t.q; i++)
+    {
+      if (i > 0 && (i % 8) == 0)
+       fprintf (stream, "\n   ");
+      fprintf (stream, " %5d%s",
+              (((uint32_t *) (t.result + level2_offset))[i] - level3_offset) / sizeof (uint8_t),
+              (i+1 < t.level2_size << t.q ? "," : ""));
+    }
+  if (t.level2_size << t.q > 8)
+    fprintf (stream, "\n ");
+  fprintf (stream, " },\n");
+  fprintf (stream, "  {");
+  if (t.level3_size << t.p > 8)
+    fprintf (stream, "\n   ");
+  for (i = 0; i < t.level3_size << t.p; i++)
+    {
+      unsigned char value = ((unsigned char *) (t.result + level3_offset))[i];
+      const char *value_string;
+      switch (value)
+       {
+#define CASE(x) case x: value_string = #x; break;
+         CASE(LBP_BK);
+         CASE(LBP_CM);
+         CASE(LBP_ZW);
+         CASE(LBP_IN);
+         CASE(LBP_GL);
+         CASE(LBP_CB);
+         CASE(LBP_SP);
+         CASE(LBP_BA);
+         CASE(LBP_BB);
+         CASE(LBP_B2);
+         CASE(LBP_HY);
+         CASE(LBP_NS);
+         CASE(LBP_OP);
+         CASE(LBP_CL);
+         CASE(LBP_QU);
+         CASE(LBP_EX);
+         CASE(LBP_ID);
+         CASE(LBP_NU);
+         CASE(LBP_IS);
+         CASE(LBP_SY);
+         CASE(LBP_AL);
+         CASE(LBP_PR);
+         CASE(LBP_PO);
+         CASE(LBP_SA);
+         CASE(LBP_XX);
+         CASE(LBP_AI);
+#undef CASE
+         default:
+           abort ();
+       }
+      if (i > 0 && (i % 8) == 0)
+       fprintf (stream, "\n   ");
+      fprintf (stream, " %s%s", value_string,
+              (i+1 < t.level3_size << t.p ? "," : ""));
+    }
+  if (t.level3_size << t.p > 8)
+    fprintf (stream, "\n ");
+  fprintf (stream, " }\n");
+  fprintf (stream, "};\n");
+}
+
+static void
+debug_output_tables (const char *filename)
+{
+  FILE *stream;
+
+  stream = fopen (filename, "w");
+  if (stream == NULL)
+    {
+      fprintf (stderr, "cannot open '%s' for writing\n", filename);
+      exit (1);
+    }
+
+  debug_output_lbp (stream);
+
+  if (ferror (stream) || fclose (stream))
+    {
+      fprintf (stderr, "error writing to '%s'\n", filename);
+      exit (1);
+    }
+}
+
+static void
+output_tables (const char *filename, const char *version)
+{
+  FILE *stream;
+
+  stream = fopen (filename, "w");
+  if (stream == NULL)
+    {
+      fprintf (stderr, "cannot open '%s' for writing\n", filename);
+      exit (1);
+    }
+
+  fprintf (stream, "/* Line breaking properties of Unicode characters.  */\n");
+  fprintf (stream, "/* Generated automatically by gen-lbrkprop for Unicode %s.  */\n",
+          version);
+  fprintf (stream, "\n");
+
+  output_lbp (stream);
+
+  if (ferror (stream) || fclose (stream))
+    {
+      fprintf (stderr, "error writing to '%s'\n", filename);
+      exit (1);
+    }
+}
+
+int
+main (int argc, char * argv[])
+{
+  if (argc != 5)
+    {
+      fprintf (stderr, "Usage: %s UnicodeData.txt PropList.txt EastAsianWidth.txt version\n",
+              argv[0]);
+      exit (1);
+    }
+
+  fill_attributes (argv[1]);
+  fill_combining (argv[2]);
+  fill_width (argv[3]);
+
+  debug_output_tables ("lbrkprop.txt");
+
+  output_tables ("lbrkprop.h", argv[4]);
+
+  return 0;
+}
diff --git a/lib/lbrkprop.h b/lib/lbrkprop.h
new file mode 100644 (file)
index 0000000..1a9a220
--- /dev/null
@@ -0,0 +1,1479 @@
+/* Line breaking properties of Unicode characters.  */
+/* Generated automatically by gen-lbrkprop for Unicode 3.0.  */
+
+#define lbrkprop_header_0 16
+#define lbrkprop_header_1 1
+#define lbrkprop_header_2 7
+#define lbrkprop_header_3 511
+#define lbrkprop_header_4 127
+static const
+struct
+  {
+    int level1[1];
+    int level2[1 << 9];
+    unsigned char level3[87 << 7];
+  }
+lbrkprop =
+{
+  { 0 },
+  {
+        0,   128,   256,   384,   512,   640,   768,   896,
+     1024,  1152,  1280,  1408,  1536,  1664,  1792,  1920,
+    -2072, -2072,  2048,  2176,  2304,  2432,  2560,  2688,
+     2816,  2944,  3072,  3200,  3328,  3456,  3584,  3712,
+     3840,  3968,  4096,  4224,  4352,  4480,  4608,  4736,
+     4864,  4992,  4992,  4992,  5120,  5248, -2072,  5376,
+     5504,  5632, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072,  4992,  5760,  5888,  6016,
+     6144,  6272,  6400,  6528,  6656,  6784,  6912,  7040,
+     7168,  7296,  7424,  7552,  7680, -2072,  7808,  7936,
+     4992,  4992, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072,  8064,  8192,  8320,
+     8448,  8576,  8704,  8832,  8960,  9088,  9216,  9344,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  9472,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  9600,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  9728, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
+     8192,  8192,  8192,  8192,  8192,  8192,  8192,  9856,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072, -2072, -2072, -2072, -2072, -2072, -2072,
+    -2072, -2072,  8192,  8192,  9984, -2072, 10112, 10240,
+     4992,  4992, 10368, 10496, 10624, 10752, 10880, 11008
+  },
+  {
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_BA, LBP_BK, LBP_CM, LBP_BK, LBP_BK, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_SP, LBP_EX, LBP_QU, LBP_XX, LBP_PR, LBP_PO, LBP_XX, LBP_QU,
+    LBP_OP, LBP_CL, LBP_XX, LBP_PR, LBP_IS, LBP_HY, LBP_IS, LBP_SY,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_IS, LBP_IS, LBP_AL, LBP_AL, LBP_AL, LBP_EX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_PR, LBP_CL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_BA, LBP_CL, LBP_AL, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_BK, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_GL, LBP_XX, LBP_PO, LBP_PR, LBP_PR, LBP_PR, LBP_AL, LBP_AI,
+    LBP_AI, LBP_AL, LBP_AI, LBP_QU, LBP_AL, LBP_BA, LBP_AL, LBP_AL,
+    LBP_PO, LBP_PR, LBP_XX, LBP_XX, LBP_BB, LBP_AL, LBP_AI, LBP_XX,
+    LBP_AI, LBP_XX, LBP_AI, LBP_QU, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI,
+    LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL,
+    LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL,
+    LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI,
+    LBP_BB, LBP_AI, LBP_AI, LBP_AI, LBP_BB, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_XX, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX,
+    LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL,
+    LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_IS, LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM,
+    LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_CM,
+    LBP_CM, LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM,
+    LBP_AL, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_AL, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_AL, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL,
+    LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_CM,
+    LBP_CM, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL,
+    LBP_AL, LBP_AL, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_AL, LBP_AL, LBP_PR, LBP_PR, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_CM, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL,
+    LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM,
+    LBP_CM, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_AL, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM,
+    LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL,
+    LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_CM, LBP_AL, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_CM,
+    LBP_CM, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_CM, LBP_SA, LBP_SA, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_PR,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_SA,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_NS, LBP_NS, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_XX, LBP_XX, LBP_SA,
+    LBP_SA, LBP_XX, LBP_SA, LBP_XX, LBP_XX, LBP_SA, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_XX, LBP_SA,
+    LBP_XX, LBP_XX, LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_CM, LBP_SA, LBP_SA, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM, LBP_SA, LBP_XX, LBP_XX,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_SA, LBP_SA, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_BA, LBP_GL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_CM, LBP_CM, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_CM, LBP_AL, LBP_CM,
+    LBP_AL, LBP_CM, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_CM, LBP_CM,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_CM, LBP_CM,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_CM, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_XX, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_XX, LBP_SA, LBP_SA, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_ID,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_BA, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_BA, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_SA,
+    LBP_SA, LBP_SA, LBP_SA, LBP_SA, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_NS, LBP_BA, LBP_NS, LBP_NS,
+    LBP_NS, LBP_NS, LBP_NS, LBP_PR, LBP_SA, LBP_XX, LBP_XX, LBP_XX,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_BB, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX,
+    LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU, LBP_NU,
+    LBP_NU, LBP_NU, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_BA, LBP_GL,
+    LBP_BA, LBP_BA, LBP_BA, LBP_ZW, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_BA, LBP_GL, LBP_XX, LBP_XX, LBP_B2, LBP_XX, LBP_XX, LBP_XX,
+    LBP_QU, LBP_QU, LBP_OP, LBP_QU, LBP_QU, LBP_QU, LBP_OP, LBP_QU,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_IN, LBP_IN, LBP_IN, LBP_BA,
+    LBP_BK, LBP_BK, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_GL,
+    LBP_PO, LBP_PO, LBP_PO, LBP_PO, LBP_PO, LBP_PO, LBP_XX, LBP_XX,
+    LBP_XX, LBP_QU, LBP_QU, LBP_XX, LBP_NS, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_NS, LBP_OP, LBP_CL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_AI,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PO,
+    LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR, LBP_PR,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_PO, LBP_AL, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AL, LBP_PO, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_PR, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_PO, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AI,
+    LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AI,
+    LBP_AL, LBP_AI, LBP_PR, LBP_PR, LBP_AL, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_OP, LBP_CL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI, LBP_AL,
+    LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AI,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AI, LBP_AL, LBP_AI, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AL, LBP_AI, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI,
+    LBP_AI, LBP_AI, LBP_AI, LBP_AL, LBP_AI, LBP_AI, LBP_AL, LBP_AI,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_CL, LBP_CL, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_ID,
+    LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL,
+    LBP_OP, LBP_CL, LBP_ID, LBP_ID, LBP_OP, LBP_CL, LBP_OP, LBP_CL,
+    LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_NS, LBP_OP, LBP_CL, LBP_CL,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_CM,
+    LBP_ID, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_ID, LBP_ID,
+    LBP_XX, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS,
+    LBP_ID, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_XX,
+    LBP_XX, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS,
+    LBP_ID, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID, LBP_NS, LBP_ID, LBP_NS,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_NS, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_ID, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_CM, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX,
+    LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_OP, LBP_CL,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CM, LBP_CM, LBP_CM, LBP_CM, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_OP, LBP_CL, LBP_OP,
+    LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP,
+    LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_CL, LBP_XX, LBP_CL, LBP_XX, LBP_NS, LBP_NS, LBP_EX, LBP_EX,
+    LBP_XX, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_OP, LBP_CL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_XX,
+    LBP_XX, LBP_PR, LBP_PO, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_AL, LBP_XX, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_GL,
+    LBP_XX, LBP_EX, LBP_XX, LBP_XX, LBP_PR, LBP_PO, LBP_XX, LBP_XX,
+    LBP_OP, LBP_CL, LBP_XX, LBP_AL, LBP_CL, LBP_XX, LBP_CL, LBP_XX,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_NS, LBP_NS, LBP_AL, LBP_AL, LBP_AL, LBP_EX,
+    LBP_XX, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_OP, LBP_XX, LBP_CL, LBP_AL, LBP_XX,
+    LBP_AL, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID, LBP_ID,
+    LBP_ID, LBP_ID, LBP_ID, LBP_OP, LBP_AL, LBP_CL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_CL, LBP_OP, LBP_CL, LBP_CL, LBP_NS, LBP_AL, LBP_NS,
+    LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS, LBP_NS,
+    LBP_NS, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_NS, LBP_NS,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL,
+    LBP_XX, LBP_XX, LBP_AL, LBP_AL, LBP_AL, LBP_XX, LBP_XX, LBP_XX,
+    LBP_PO, LBP_PR, LBP_AL, LBP_AL, LBP_AL, LBP_PR, LBP_PR, LBP_XX,
+    LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_AL, LBP_XX,
+    LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX, LBP_XX,
+    LBP_XX, LBP_CM, LBP_CM, LBP_CM, LBP_CB, LBP_AI, LBP_XX, LBP_XX
+  }
+};
diff --git a/lib/linebreak.c b/lib/linebreak.c
new file mode 100644 (file)
index 0000000..bd15abf
--- /dev/null
@@ -0,0 +1,1956 @@
+/* linebreak.c - line breaking of Unicode strings
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; 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 <stddef.h>
+#include "linebreak.h"
+#include "c-ctype.h"
+
+
+/* Return the length (number of units) of the first character in S, putting
+   its 'ucs4_t' representation in *PUC.  */
+static int
+u8_mbtouc_aux (puc, s, n)
+     unsigned int *puc;
+     const unsigned char *s;
+     size_t n;
+{
+  unsigned char c = *s;
+
+  if (c >= 0xc2)
+    {
+      if (c < 0xe0)
+        {
+          if (n >= 2)
+            {
+              if ((s[1] ^ 0x80) < 0x40)
+                {
+                  *puc = ((unsigned int) (c & 0x1f) << 6)
+                         | (unsigned int) (s[1] ^ 0x80);
+                  return 2;
+                }
+              /* invalid multibyte character */
+            }
+          else
+            {
+              /* incomplete multibyte character */
+              *puc = 0xfffd;
+              return n;
+            }
+        }
+      else if (c < 0xf0)
+        {
+          if (n >= 3)
+            {
+              if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                  && (c >= 0xe1 || s[1] >= 0xa0))
+                {
+                  *puc = ((unsigned int) (c & 0x0f) << 12)
+                         | ((unsigned int) (s[1] ^ 0x80) << 6)
+                         | (unsigned int) (s[2] ^ 0x80);
+                  return 3;
+                }
+              /* invalid multibyte character */
+            }
+          else
+            {
+              /* incomplete multibyte character */
+              *puc = 0xfffd;
+              return n;
+            }
+        }
+      else if (c < 0xf8)
+        {
+          if (n >= 4)
+            {
+              if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                  && (s[3] ^ 0x80) < 0x40
+                  && (c >= 0xf1 || s[1] >= 0x90))
+                {
+                  *puc = ((unsigned int) (c & 0x07) << 18)
+                         | ((unsigned int) (s[1] ^ 0x80) << 12)
+                         | ((unsigned int) (s[2] ^ 0x80) << 6)
+                         | (unsigned int) (s[3] ^ 0x80);
+                  return 4;
+                }
+              /* invalid multibyte character */
+            }
+          else
+            {
+              /* incomplete multibyte character */
+              *puc = 0xfffd;
+              return n;
+            }
+        }
+#if 0
+      else if (c < 0xfc)
+        {
+          if (n >= 5)
+            {
+              if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                  && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                  && (c >= 0xf9 || s[1] >= 0x88))
+                {
+                  *puc = ((unsigned int) (c & 0x03) << 24)
+                         | ((unsigned int) (s[1] ^ 0x80) << 18)
+                         | ((unsigned int) (s[2] ^ 0x80) << 12)
+                         | ((unsigned int) (s[3] ^ 0x80) << 6)
+                         | (unsigned int) (s[4] ^ 0x80);
+                  return 5;
+                }
+              /* invalid multibyte character */
+            }
+          else
+            {
+              /* incomplete multibyte character */
+              *puc = 0xfffd;
+              return n;
+            }
+        }
+      else if (c < 0xfe)
+        {
+          if (n >= 6)
+            {
+              if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                  && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                  && (s[5] ^ 0x80) < 0x40
+                  && (c >= 0xfd || s[1] >= 0x84))
+                {
+                  *puc = ((unsigned int) (c & 0x01) << 30)
+                         | ((unsigned int) (s[1] ^ 0x80) << 24)
+                         | ((unsigned int) (s[2] ^ 0x80) << 18)
+                         | ((unsigned int) (s[3] ^ 0x80) << 12)
+                         | ((unsigned int) (s[4] ^ 0x80) << 6)
+                         | (unsigned int) (s[5] ^ 0x80);
+                  return 6;
+                }
+              /* invalid multibyte character */
+            }
+          else
+            {
+              /* incomplete multibyte character */
+              *puc = 0xfffd;
+              return n;
+            }
+        }
+#endif
+    }
+  /* invalid multibyte character */
+  *puc = 0xfffd;
+  return 1;
+}
+static inline int
+u8_mbtouc (puc, s, n)
+     unsigned int *puc;
+     const unsigned char *s;
+     size_t n;
+{
+  unsigned char c = *s;
+
+  if (c < 0x80)
+    {
+      *puc = c;
+      return 1;
+    }
+  else
+    return u8_mbtouc_aux (puc, s, n);
+}
+
+#ifdef unused
+static int
+u16_mbtouc_aux (puc, s, n)
+     unsigned int *puc;
+     const unsigned short *s;
+     size_t n;
+{
+  unsigned short c = *s;
+
+  if (c < 0xdc00)
+    {
+      if (n >= 2)
+        {
+          if (s[1] >= 0xdc00 && s[1] < 0xe000)
+            {
+              *puc = 0x10000 + ((c - 0xd800) << 10) + (s[1] - 0xdc00);
+              return 2;
+            }
+          /* invalid multibyte character */
+        }
+      else
+        {
+          /* incomplete multibyte character */
+          *puc = 0xfffd;
+          return n;
+        }
+    }
+  /* invalid multibyte character */
+  *puc = 0xfffd;
+  return 1;
+}
+static inline int
+u16_mbtouc (puc, s, n)
+     unsigned int *puc;
+     const unsigned short *s;
+     size_t n;
+{
+  unsigned short c = *s;
+
+  if (c < 0xd800 || c >= 0xe000)
+    {
+      *puc = c;
+      return 1;
+    }
+  else
+    return u16_mbtouc_aux (puc, s, n);
+}
+
+static inline int
+u32_mbtouc (puc, s, n)
+     unsigned int *puc;
+     const unsigned int *s;
+     size_t n;
+{
+  *puc = *s;
+  return 1;
+}
+#endif
+
+
+/* Help GCC to generate good code for string comparisons with
+   immediate strings. */
+#if defined (__GNUC__) && defined (__OPTIMIZE__)
+
+static inline int
+streq9 (const char *s1, const char *s2)
+{
+  return strcmp (s1 + 9, s2 + 9) == 0;
+}
+
+static inline int
+streq8 (const char *s1, const char *s2, char s28)
+{
+  if (s1[8] == s28)
+    {
+      if (s28 == 0)
+        return 1;
+      else
+        return streq9 (s1, s2);
+    }
+  else
+    return 0;
+}
+
+static inline int
+streq7 (const char *s1, const char *s2, char s27, char s28)
+{
+  if (s1[7] == s27)
+    {
+      if (s27 == 0)
+        return 1;
+      else
+        return streq8 (s1, s2, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+streq6 (const char *s1, const char *s2, char s26, char s27, char s28)
+{
+  if (s1[6] == s26)
+    {
+      if (s26 == 0)
+        return 1;
+      else
+        return streq7 (s1, s2, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+streq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28)
+{
+  if (s1[5] == s25)
+    {
+      if (s25 == 0)
+        return 1;
+      else
+        return streq6 (s1, s2, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+streq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28)
+{
+  if (s1[4] == s24)
+    {
+      if (s24 == 0)
+        return 1;
+      else
+        return streq5 (s1, s2, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+streq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28)
+{
+  if (s1[3] == s23)
+    {
+      if (s23 == 0)
+        return 1;
+      else
+        return streq4 (s1, s2, s24, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+streq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
+{
+  if (s1[2] == s22)
+    {
+      if (s22 == 0)
+        return 1;
+      else
+        return streq3 (s1, s2, s23, s24, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+streq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
+{
+  if (s1[1] == s21)
+    {
+      if (s21 == 0)
+        return 1;
+      else
+        return streq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+streq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28)
+{
+  if (s1[0] == s20)
+    {
+      if (s20 == 0)
+        return 1;
+      else
+        return streq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+#define STREQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
+  streq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
+
+#else
+
+#define STREQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
+  (strcmp (s1, s2) == 0)
+
+#endif
+
+
+static int
+is_cjk_encoding (encoding)
+     const char *encoding;
+{
+  if (0
+      /* Legacy Japanese encodings */
+      || STREQ (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0)
+      /* Legacy Chinese encodings */
+      || STREQ (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0)
+      || STREQ (encoding, "GBK", 'G', 'B', 'K', 0, 0, 0, 0, 0, 0)
+      || STREQ (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0)
+      || STREQ (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0)
+      /* Legacy Korean encodings */
+      || STREQ (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
+      || STREQ (encoding, "CP949", 'C', 'P', '9', '4', '9', 0, 0, 0, 0)
+      || STREQ (encoding, "JOHAB", 'J', 'O', 'H', 'A', 'B', 0, 0, 0, 0))
+    return 1;
+  return 0;
+}
+
+static int
+is_utf8_encoding (encoding)
+     const char *encoding;
+{
+  if (STREQ (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0 ,0))
+    return 1;
+  return 0;
+}
+
+
+/* Determine number of column positions required for UC. */
+int uc_width PARAMS ((unsigned int uc, const char *encoding));
+
+/*
+ * Non-spacing attribute table.
+ * See PropList.txt, or grep '^[^;]*;[^;]*;[^;]*;[^;]*;NSM;' UnicodeData.txt
+ * Control characters are also marked non-spacing here, because they are not
+ * printable. Zero width characters are also marked non-spacing here.
+ */
+static const unsigned char nonspacing_table_data[15*64] = {
+  /* 0x0000-0x01ff */
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0x0000-0x003f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x0040-0x007f */
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0x0080-0x00bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00c0-0x00ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0100-0x013f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0140-0x017f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0180-0x01bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x01c0-0x01ff */
+  /* 0x0200-0x03ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0200-0x023f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0240-0x027f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0280-0x02bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x02c0-0x02ff */
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x0300-0x033f */
+  0xff, 0x7f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, /* 0x0340-0x037f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0380-0x03bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x03c0-0x03ff */
+  /* 0x0400-0x05ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0400-0x043f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0440-0x047f */
+  0x78, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0480-0x04bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04c0-0x04ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0500-0x053f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0540-0x057f */
+  0x00, 0x00, 0xfe, 0xff, 0xfb, 0xff, 0xff, 0xbb, /* 0x0580-0x05bf */
+  0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x05c0-0x05ff */
+  /* 0x0600-0x07ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0600-0x063f */
+  0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, /* 0x0640-0x067f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0680-0x06bf */
+  0x00, 0x00, 0xc0, 0xff, 0x9f, 0x3d, 0x00, 0x00, /* 0x06c0-0x06ff */
+  0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, /* 0x0700-0x073f */
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0740-0x077f */
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, /* 0x0780-0x07bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x07c0-0x07ff */
+  /* 0x0800-0x09ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0800-0x083f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0840-0x087f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0880-0x08bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08c0-0x08ff */
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0900-0x093f */
+  0xfe, 0x21, 0x1e, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x0940-0x097f */
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0980-0x09bf */
+  0x1e, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, /* 0x09c0-0x09ff */
+  /* 0x0a00-0x0bff */
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0a00-0x0a3f */
+  0x86, 0x39, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, /* 0x0a40-0x0a7f */
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /* 0x0a80-0x0abf */
+  0xbe, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0ac0-0x0aff */
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, /* 0x0b00-0x0b3f */
+  0x0e, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b40-0x0b7f */
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b80-0x0bbf */
+  0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0bc0-0x0bff */
+  /* 0x0c00-0x0dff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, /* 0x0c00-0x0c3f */
+  0xc1, 0x3d, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c40-0x0c7f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x0c80-0x0cbf */
+  0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0cc0-0x0cff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d00-0x0d3f */
+  0x0e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d40-0x0d7f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d80-0x0dbf */
+  0x00, 0x04, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0dc0-0x0dff */
+  /* 0x0e00-0x0fff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x07, /* 0x0e00-0x0e3f */
+  0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e40-0x0e7f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x1b, /* 0x0e80-0x0ebf */
+  0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0ec0-0x0eff */
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa0, 0x02, /* 0x0f00-0x0f3f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, /* 0x0f40-0x0f7f */
+  0xdf, 0x00, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x1f, /* 0x0f80-0x0fbf */
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0fc0-0x0fff */
+  /* 0x1000-0x11ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xc5, 0x02, /* 0x1000-0x103f */
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, /* 0x1040-0x107f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1080-0x10bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10c0-0x10ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1100-0x113f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1140-0x117f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1180-0x11bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x11c0-0x11ff */
+  /* 0x1600-0x17ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1600-0x163f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1640-0x167f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1680-0x16bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x16c0-0x16ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1700-0x173f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1740-0x177f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, /* 0x1780-0x17bf */
+  0x40, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x17c0-0x17ff */
+  /* 0x1800-0x19ff */
+  0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1800-0x183f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1840-0x187f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x1880-0x18bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18c0-0x18ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1900-0x193f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1940-0x197f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1980-0x19bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x19c0-0x19ff */
+  /* 0x2000-0x21ff */
+  0x00, 0xf8, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, /* 0x2000-0x203f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, /* 0x2040-0x207f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2080-0x20bf */
+  0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, /* 0x20c0-0x20ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2100-0x213f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2140-0x217f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2180-0x21bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x21c0-0x21ff */
+  /* 0x3000-0x31ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, /* 0x3000-0x303f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3040-0x307f */
+  0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, /* 0x3080-0x30bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30c0-0x30ff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3100-0x313f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3140-0x317f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3180-0x31bf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x31c0-0x31ff */
+  /* 0xfa00-0xfbff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa00-0xfa3f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa40-0xfa7f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa80-0xfabf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfac0-0xfaff */
+  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, /* 0xfb00-0xfb3f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb40-0xfb7f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb80-0xfbbf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfbc0-0xfbff */
+  /* 0xfe00-0xffff */
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, /* 0xfe00-0xfe3f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe40-0xfe7f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe80-0xfebf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xfec0-0xfeff */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff00-0xff3f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff40-0xff7f */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff80-0xffbf */
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e  /* 0xffc0-0xffff */
+};
+static const signed char nonspacing_table_ind[128] = {
+   0,  1,  2,  3,  4,  5,  6,  7, /* 0x0000-0x0fff */
+   8, -1, -1,  9, 10, -1, -1, -1, /* 0x1000-0x1fff */
+  11, -1, -1, -1, -1, -1, -1, -1, /* 0x2000-0x2fff */
+  12, -1, -1, -1, -1, -1, -1, -1, /* 0x3000-0x3fff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0x4000-0x4fff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0x5000-0x5fff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0x6000-0x6fff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0x7000-0x7fff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0x8000-0x8fff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9000-0x9fff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0xa000-0xafff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb000-0xbfff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0xc000-0xcfff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0xd000-0xdfff */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* 0xe000-0xefff */
+  -1, -1, -1, -1, -1, 13, -1, 14  /* 0xf000-0xffff */
+};
+
+/* Determine number of column positions required for UC. */
+int
+uc_width (uc, encoding)
+     unsigned int uc;
+     const char *encoding;
+{
+  /* Test for non-spacing or control character. */
+  if ((uc >> 9) < 128)
+    {
+      int ind = nonspacing_table_ind[uc >> 9];
+      if (ind >= 0)
+        if ((nonspacing_table_data[64*ind + ((uc >> 3) & 63)] >> (uc & 7)) & 1)
+          {
+            if (uc > 0 && uc < 0x100)
+              return -1;
+            else
+              return 0;
+          }
+    }
+  /* Test for double-width character.
+   * Generated from "grep '^....;[WF]' EastAsianWidth.txt"
+   * and            "grep '^....;[^WF]' EastAsianWidth.txt"
+   */
+  if (uc >= 0x1100
+      && ((uc < 0x1160) /* Hangul Jamo */
+          || (uc >= 0x2e80 && uc < 0xa4d0  /* CJK ... Yi */
+              && !((uc & ~0x0011) == 0x300a || uc == 0x303f))
+          || (uc >= 0xac00 && uc < 0xd7a4) /* Hangul Syllables */
+          || (uc >= 0xf900 && uc < 0xfb00) /* CJK Compatibility Ideographs */
+          || (uc >= 0xfe30 && uc < 0xfe70) /* CJK Compatibility Forms */
+          || (uc >= 0xff00 && uc < 0xff60) /* Fullwidth Forms */
+          || (uc >= 0xffe0 && uc < 0xffe7)))
+    return 2;
+  /* In ancient CJK encodings, Cyrillic and most other characters are
+     double-width as well. */
+  if (uc >= 0x00A1 && uc < 0xFF60 && uc != 0x20A9
+      && is_cjk_encoding (encoding))
+    return 2;
+  return 1;
+}
+
+
+#ifdef unused
+
+/* Determine number of column positions required for first N units
+   (or fewer if S ends before this) in S.  */
+
+int
+u8_width (s, n, encoding)
+     const unsigned char *s;
+     size_t n;
+     const char *encoding;
+{
+  const unsigned char *s_end = s + n;
+  int width = 0;
+
+  while (s < s_end)
+    {
+      unsigned int uc;
+      int w;
+
+      s += u8_mbtouc (&uc, s, s_end - s);
+
+      if (uc == 0)
+        break; /* end of string reached */
+
+      w = uc_width (uc, encoding);
+      if (w >= 0) /* ignore control characters in the string */
+        width += w;
+    }
+
+  return width;
+}
+
+int
+u16_width (s, n, encoding)
+     const unsigned short *s;
+     size_t n;
+     const char *encoding;
+{
+  const unsigned short *s_end = s + n;
+  int width = 0;
+
+  while (s < s_end)
+    {
+      unsigned int uc;
+      int w;
+
+      s += u16_mbtouc (&uc, s, s_end - s);
+
+      if (uc == 0)
+        break; /* end of string reached */
+
+      w = uc_width (uc, encoding);
+      if (w >= 0) /* ignore control characters in the string */
+        width += w;
+    }
+
+  return width;
+}
+
+int
+u32_width (s, n, encoding)
+     const unsigned int *s;
+     size_t n;
+     const char *encoding;
+{
+  const unsigned int *s_end = s + n;
+  int width = 0;
+
+  while (s < s_end)
+    {
+      unsigned int uc = *s++;
+      int w;
+
+      if (uc == 0)
+        break; /* end of string reached */
+
+      w = uc_width (uc, encoding);
+      if (w >= 0) /* ignore control characters in the string */
+        width += w;
+    }
+
+  return width;
+}
+
+#endif
+
+
+/* Determine the line break points in S, and store the result at p[0..n-1].  */
+/* We don't support line breaking of complex-context dependent characters
+   (Thai, Lao, Myanmar, Khmer) yet, because it requires dictionary lookup. */
+
+/* Line breaking classification.  */
+
+enum
+{
+  /* Values >= 20 are resolved at run time. */
+  LBP_BK =  0, /* mandatory break */
+/*LBP_CR,         carriage return - not used here because it's a DOSism */
+/*LBP_LF,         line feed - not used here because it's a DOSism */
+  LBP_CM = 20, /* attached characters and combining marks */
+/*LBP_SG,         surrogates - not used here because they are not characters */
+  LBP_ZW =  1, /* zero width space */
+  LBP_IN =  2, /* inseparable */
+  LBP_GL =  3, /* non-breaking (glue) */
+  LBP_CB = 22, /* contingent break opportunity */
+  LBP_SP = 21, /* space */
+  LBP_BA =  4, /* break opportunity after */
+  LBP_BB =  5, /* break opportunity before */
+  LBP_B2 =  6, /* break opportunity before and after */
+  LBP_HY =  7, /* hyphen */
+  LBP_NS =  8, /* non starter */
+  LBP_OP =  9, /* opening punctuation */
+  LBP_CL = 10, /* closing punctuation */
+  LBP_QU = 11, /* ambiguous quotation */
+  LBP_EX = 12, /* exclamation/interrogation */
+  LBP_ID = 13, /* ideographic */
+  LBP_NU = 14, /* numeric */
+  LBP_IS = 15, /* infix separator (numeric) */
+  LBP_SY = 16, /* symbols allowing breaks */
+  LBP_AL = 17, /* ordinary alphabetic and symbol characters */
+  LBP_PR = 18, /* prefix (numeric) */
+  LBP_PO = 19, /* postfix (numeric) */
+  LBP_SA = 23, /* complex context (South East Asian) */
+  LBP_AI = 24, /* ambiguous (alphabetic or ideograph) */
+  LBP_XX = 25  /* unknown */
+};
+
+#include "lbrkprop.h"
+
+static inline unsigned char
+lbrkprop_lookup (uc)
+     unsigned int uc;
+{
+  unsigned int index1 = uc >> lbrkprop_header_0;
+  if (index1 < lbrkprop_header_1)
+    {
+      int lookup1 = lbrkprop.level1[index1];
+      if (lookup1 >= 0)
+        {
+          unsigned int index2 = (uc >> lbrkprop_header_2) & lbrkprop_header_3;
+          int lookup2 = lbrkprop.level2[lookup1 + index2];
+          if (lookup2 >= 0)
+            {
+              unsigned int index3 = uc & lbrkprop_header_4;
+              return lbrkprop.level3[lookup2 + index3];
+            }
+        }
+    }
+  return LBP_XX;
+}
+
+/* Table indexed by two line breaking classifications.  */
+#define D 1  /* direct break opportunity, empty in table 7.3 of UTR #14 */
+#define I 2  /* indirect break opportunity, '%' in table 7.3 of UTR #14 */
+#define P 3  /* prohibited break,           '^' in table 7.3 of UTR #14 */
+static const unsigned char lbrk_table[19][19] = {
+                                /* after */
+        /* ZW IN GL BA BB B2 HY NS OP CL QU EX ID NU IS SY AL PR PO */
+/* ZW */ { P, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, },
+/* IN */ { P, I, I, I, D, D, I, I, D, P, I, P, D, D, P, P, D, D, D, },
+/* GL */ { P, I, I, I, I, I, I, I, I, P, I, P, I, I, P, P, I, I, I, },
+/* BA */ { P, D, I, I, D, D, I, I, D, P, I, P, D, D, P, P, D, D, D, },
+/* BB */ { P, I, I, I, I, I, I, I, I, P, I, P, I, I, P, P, I, I, I, },
+/* B2 */ { P, D, I, I, D, P, I, I, D, P, I, P, D, D, P, P, D, D, D, },
+/* HY */ { P, D, I, I, D, D, I, I, D, P, I, P, D, D, P, P, D, D, D, },
+/* NS */ { P, D, I, I, D, D, I, I, D, P, I, P, D, D, P, P, D, D, D, },
+/* OP */ { P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, },
+/* CL */ { P, D, I, I, D, D, I, P, D, P, I, P, D, D, P, P, D, D, I, },
+/* QU */ { P, I, I, I, I, I, I, I, P, P, I, P, I, I, P, P, I, I, I, },
+/* EX */ { P, D, I, I, D, D, I, I, D, P, I, P, D, D, P, P, D, D, D, },
+/* ID */ { P, I, I, I, D, D, I, I, D, P, I, P, D, D, P, P, D, D, I, },
+/* NU */ { P, I, I, I, D, D, I, I, D, P, I, P, D, I, P, P, I, D, I, },
+/* IS */ { P, D, I, I, D, D, I, I, D, P, I, P, D, I, P, P, D, D, D, },
+/* SY */ { P, D, I, I, D, D, I, I, D, P, I, P, D, I, P, P, D, D, D, },
+/* AL */ { P, I, I, I, D, D, I, I, D, P, I, P, D, I, P, P, I, D, D, },
+/* PR */ { P, D, I, I, D, D, I, I, I, P, I, P, I, I, P, P, I, D, D, },
+/* PO */ { P, D, I, I, D, D, I, I, D, P, I, P, D, D, P, P, D, D, D, },
+/* "" */
+/* before */
+};
+/* Note: The (B2,B2) entry should probably be D instead of P.  */
+/* Note: The (PR,ID) entry should probably be D instead of I.  */
+
+void
+u8_possible_linebreaks (s, n, encoding, p)
+     const unsigned char *s;
+     size_t n;
+     const char *encoding;
+     char *p;
+{
+  int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
+  const unsigned char *s_end = s + n;
+  int last_prop = LBP_BK; /* line break property of last non-space character */
+  char *seen_space = NULL; /* Was a space seen after the last non-space character? */
+  char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
+
+  /* Don't break inside multibyte characters.  */
+  memset (p, UC_BREAK_PROHIBITED, n);
+
+  while (s < s_end)
+    {
+      unsigned int uc;
+      int count = u8_mbtouc (&uc, s, s_end - s);
+      int prop = lbrkprop_lookup (uc);
+
+      if (prop == LBP_BK)
+        {
+          /* Mandatory break.  */
+          *p = UC_BREAK_MANDATORY;
+          last_prop = LBP_BK;
+          seen_space = NULL;
+          seen_space2 = NULL;
+        }
+      else
+        {
+          char *q;
+
+          /* Resolve property values whose behaviour is not fixed.  */
+          switch (prop)
+            {
+              case LBP_AI:
+                /* Resolve ambiguous.  */
+                prop = LBP_AI_REPLACEMENT;
+                break;
+              case LBP_CB:
+                /* This is arbitrary.  */
+                prop = LBP_ID;
+                break;
+              case LBP_SA:
+                /* We don't handle complex scripts yet.
+                   Treat LBP_SA like LBP_XX.  */
+              case LBP_XX:
+                /* This is arbitrary.  */
+                prop = LBP_AL;
+                break;
+            }
+
+          /* Deal with combining characters.  */
+          q = p;
+          if (prop == LBP_CM)
+            {
+              /* Don't break just before a combining character.  */
+              *p = UC_BREAK_PROHIBITED;
+              /* A combining character turns a preceding space into LBP_AL.  */
+              if (seen_space != NULL)
+                {
+                  q = seen_space;
+                  seen_space = seen_space2;
+                  prop = LBP_AL;
+                  goto lookup_via_table;
+                }
+            }
+          else if (prop == LBP_SP)
+            {
+              /* Don't break just before a space.  */
+              *p = UC_BREAK_PROHIBITED;
+              seen_space2 = seen_space;
+              seen_space = p;
+            }
+          else
+            {
+             lookup_via_table:
+              /* prop must be usable as an index for table 7.3 of UTR #14.  */
+              if (!(prop >= 1 && prop <= sizeof(lbrk_table) / sizeof(lbrk_table[0])))
+                abort ();
+
+              if (last_prop == LBP_BK)
+                {
+                  /* Don't break at the beginning of a line.  */
+                  *q = UC_BREAK_PROHIBITED;
+                }
+              else
+                {
+                  switch (lbrk_table [last_prop-1] [prop-1])
+                    {
+                      case D:
+                        *q = UC_BREAK_POSSIBLE;
+                        break;
+                      case I:
+                        *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
+                        break;
+                      case P:
+                        *q = UC_BREAK_PROHIBITED;
+                        break;
+                      default:
+                        abort ();
+                    }
+                }
+              last_prop = prop;
+              seen_space = NULL;
+              seen_space2 = NULL;
+            }
+        }
+
+      s += count;
+      p += count;
+    }
+}
+
+#ifdef unused
+
+void
+u16_possible_linebreaks (s, n, encoding, p)
+     const unsigned short *s;
+     size_t n;
+     const char *encoding;
+     char *p;
+{
+  int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
+  const unsigned short *s_end = s + n;
+  int last_prop = LBP_BK; /* line break property of last non-space character */
+  char *seen_space = NULL; /* Was a space seen after the last non-space character? */
+  char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
+
+  /* Don't break inside multibyte characters.  */
+  memset (p, UC_BREAK_PROHIBITED, n);
+
+  while (s < s_end)
+    {
+      unsigned int uc;
+      int count = u16_mbtouc (&uc, s, s_end - s);
+      int prop = lbrkprop_lookup (uc);
+
+      if (prop == LBP_BK)
+        {
+          /* Mandatory break.  */
+          *p = UC_BREAK_MANDATORY;
+          last_prop = LBP_BK;
+          seen_space = NULL;
+          seen_space2 = NULL;
+        }
+      else
+        {
+          char *q;
+
+          /* Resolve property values whose behaviour is not fixed.  */
+          switch (prop)
+            {
+              case LBP_AI:
+                /* Resolve ambiguous.  */
+                prop = LBP_AI_REPLACEMENT;
+                break;
+              case LBP_CB:
+                /* This is arbitrary.  */
+                prop = LBP_ID;
+                break;
+              case LBP_SA:
+                /* We don't handle complex scripts yet.
+                   Treat LBP_SA like LBP_XX.  */
+              case LBP_XX:
+                /* This is arbitrary.  */
+                prop = LBP_AL;
+                break;
+            }
+
+          /* Deal with combining characters.  */
+          q = p;
+          if (prop == LBP_CM)
+            {
+              /* Don't break just before a combining character.  */
+              *p = UC_BREAK_PROHIBITED;
+              /* A combining character turns a preceding space into LBP_AL.  */
+              if (seen_space != NULL)
+                {
+                  q = seen_space;
+                  seen_space = seen_space2;
+                  prop = LBP_AL;
+                  goto lookup_via_table;
+                }
+            }
+          else if (prop == LBP_SP)
+            {
+              /* Don't break just before a space.  */
+              *p = UC_BREAK_PROHIBITED;
+              seen_space2 = seen_space;
+              seen_space = p;
+            }
+          else
+            {
+             lookup_via_table:
+              /* prop must be usable as an index for table 7.3 of UTR #14.  */
+              if (!(prop >= 1 && prop <= sizeof(lbrk_table) / sizeof(lbrk_table[0])))
+                abort ();
+
+              if (last_prop == LBP_BK)
+                {
+                  /* Don't break at the beginning of a line.  */
+                  *q = UC_BREAK_PROHIBITED;
+                }
+              else
+                {
+                  switch (lbrk_table [last_prop-1] [prop-1])
+                    {
+                      case D:
+                        *q = UC_BREAK_POSSIBLE;
+                        break;
+                      case I:
+                        *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
+                        break;
+                      case P:
+                        *q = UC_BREAK_PROHIBITED;
+                        break;
+                      default:
+                        abort ();
+                    }
+                }
+              last_prop = prop;
+              seen_space = NULL;
+              seen_space2 = NULL;
+            }
+        }
+
+      s += count;
+      p += count;
+    }
+}
+
+void
+u32_possible_linebreaks (s, n, encoding, p)
+     const unsigned int *s;
+     size_t n;
+     const char *encoding;
+     char *p;
+{
+  int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
+  const unsigned int *s_end = s + n;
+  int last_prop = LBP_BK; /* line break property of last non-space character */
+  char *seen_space = NULL; /* Was a space seen after the last non-space character? */
+  char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
+
+  while (s < s_end)
+    {
+      unsigned int uc = *s;
+      int prop = lbrkprop_lookup (uc);
+
+      if (prop == LBP_BK)
+        {
+          /* Mandatory break.  */
+          *p = UC_BREAK_MANDATORY;
+          last_prop = LBP_BK;
+          seen_space = NULL;
+          seen_space2 = NULL;
+        }
+      else
+        {
+          char *q;
+
+          /* Resolve property values whose behaviour is not fixed.  */
+          switch (prop)
+            {
+              case LBP_AI:
+                /* Resolve ambiguous.  */
+                prop = LBP_AI_REPLACEMENT;
+                break;
+              case LBP_CB:
+                /* This is arbitrary.  */
+                prop = LBP_ID;
+                break;
+              case LBP_SA:
+                /* We don't handle complex scripts yet.
+                   Treat LBP_SA like LBP_XX.  */
+              case LBP_XX:
+                /* This is arbitrary.  */
+                prop = LBP_AL;
+                break;
+            }
+
+          /* Deal with combining characters.  */
+          q = p;
+          if (prop == LBP_CM)
+            {
+              /* Don't break just before a combining character.  */
+              *p = UC_BREAK_PROHIBITED;
+              /* A combining character turns a preceding space into LBP_AL.  */
+              if (seen_space != NULL)
+                {
+                  q = seen_space;
+                  seen_space = seen_space2;
+                  prop = LBP_AL;
+                  goto lookup_via_table;
+                }
+            }
+          else if (prop == LBP_SP)
+            {
+              /* Don't break just before a space.  */
+              *p = UC_BREAK_PROHIBITED;
+              seen_space2 = seen_space;
+              seen_space = p;
+            }
+          else
+            {
+             lookup_via_table:
+              /* prop must be usable as an index for table 7.3 of UTR #14.  */
+              if (!(prop >= 1 && prop <= sizeof(lbrk_table) / sizeof(lbrk_table[0])))
+                abort ();
+
+              if (last_prop == LBP_BK)
+                {
+                  /* Don't break at the beginning of a line.  */
+                  *q = UC_BREAK_PROHIBITED;
+                }
+              else
+                {
+                  switch (lbrk_table [last_prop-1] [prop-1])
+                    {
+                      case D:
+                        *q = UC_BREAK_POSSIBLE;
+                        break;
+                      case I:
+                        *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
+                        break;
+                      case P:
+                        *q = UC_BREAK_PROHIBITED;
+                        break;
+                      default:
+                        abort ();
+                    }
+                }
+              last_prop = prop;
+              seen_space = NULL;
+              seen_space2 = NULL;
+            }
+        }
+
+      s++;
+      p++;
+    }
+}
+
+#endif
+
+
+/* Choose the best line breaks, assuming the uc_width function.  Return the
+   column after the end of the string.  */
+
+int
+u8_width_linebreaks (s, n, width, start_column, at_end_columns, encoding, p)
+     const unsigned char *s;
+     size_t n;
+     int width;
+     int start_column;
+     int at_end_columns;
+     const char *encoding;
+     char *p;
+{
+  const unsigned char *s_end;
+  char *last_p;
+  int last_column;
+  int piece_width;
+
+  u8_possible_linebreaks (s, n, encoding, p);
+
+  s_end = s + n;
+  last_p = NULL;
+  last_column = start_column;
+  piece_width = 0;
+  while (s < s_end)
+    {
+      unsigned int uc;
+      int count = u8_mbtouc (&uc, s, s_end - s);
+
+      if (*p == UC_BREAK_POSSIBLE || *p == UC_BREAK_MANDATORY)
+        {
+          /* An atomic piece of text ends here.  */
+          if (last_p != NULL && last_column + piece_width > width)
+            {
+              /* Insert a line break.  */
+              *last_p = UC_BREAK_POSSIBLE;
+              last_column = 0;
+            }
+        }
+
+      if (*p == UC_BREAK_MANDATORY)
+        {
+          /* uc is a line break character.  */
+          /* Start a new piece at column 0.  */
+          last_p = NULL;
+          last_column = 0;
+          piece_width = 0;
+        }
+      else
+        {
+          /* uc is not a line break character.  */
+          int w;
+
+          if (*p == UC_BREAK_POSSIBLE)
+            {
+              /* Start a new piece.  */
+              last_p = p;
+              last_column += piece_width;
+              piece_width = 0;
+              /* No line break for the moment, may be turned into
+                 UC_BREAK_POSSIBLE later, via last_p. */
+            }
+         
+          *p = UC_BREAK_PROHIBITED;
+
+          w = uc_width (uc, encoding);
+          if (w >= 0) /* ignore control characters in the string */
+            piece_width += w;
+         }
+
+      s += count;
+      p += count;
+    }
+
+  /* The last atomic piece of text ends here.  */
+  if (last_p != NULL && last_column + piece_width + at_end_columns > width)
+    {
+      /* Insert a line break.  */
+      *last_p = UC_BREAK_POSSIBLE;
+      last_column = 0;
+    }
+
+  return last_column + piece_width;
+}
+
+#ifdef unused
+
+int
+u16_width_linebreaks (s, n, width, start_column, at_end_columns, encoding, p)
+     const unsigned short *s;
+     size_t n;
+     int width;
+     int start_column;
+     int at_end_columns;
+     const char *encoding;
+     char *p;
+{
+  const unsigned short *s_end;
+  char *last_p;
+  int last_column;
+  int piece_width;
+
+  u16_possible_linebreaks (s, n, encoding, p);
+
+  s_end = s + n;
+  last_p = NULL;
+  last_column = start_column;
+  piece_width = 0;
+  while (s < s_end)
+    {
+      unsigned int uc;
+      int count = u16_mbtouc (&uc, s, s_end - s);
+
+      if (*p == UC_BREAK_POSSIBLE || *p == UC_BREAK_MANDATORY)
+        {
+          /* An atomic piece of text ends here.  */
+          if (last_p != NULL && last_column + piece_width > width)
+            {
+              /* Insert a line break.  */
+              *last_p = UC_BREAK_POSSIBLE;
+              last_column = 0;
+            }
+        }
+
+      if (*p == UC_BREAK_MANDATORY)
+        {
+          /* uc is a line break character.  */
+          /* Start a new piece at column 0.  */
+          last_p = NULL;
+          last_column = 0;
+          piece_width = 0;
+        }
+      else
+        {
+          /* uc is not a line break character.  */
+          int w;
+
+          if (*p == UC_BREAK_POSSIBLE)
+            {
+              /* Start a new piece.  */
+              last_p = p;
+              last_column += piece_width;
+              piece_width = 0;
+              /* No line break for the moment, may be turned into
+                 UC_BREAK_POSSIBLE later, via last_p. */
+            }
+         
+          *p = UC_BREAK_PROHIBITED;
+
+          w = uc_width (uc, encoding);
+          if (w >= 0) /* ignore control characters in the string */
+            piece_width += w;
+         }
+
+      s += count;
+      p += count;
+    }
+
+  /* The last atomic piece of text ends here.  */
+  if (last_p != NULL && last_column + piece_width + at_end_columns > width)
+    {
+      /* Insert a line break.  */
+      *last_p = UC_BREAK_POSSIBLE;
+      last_column = 0;
+    }
+
+  return last_column + piece_width;
+}
+
+int
+u32_width_linebreaks (s, n, width, start_column, at_end_columns, encoding, p)
+     const unsigned int *s;
+     size_t n;
+     int width;
+     int start_column;
+     int at_end_columns;
+     const char *encoding;
+     char *p;
+{
+  const unsigned int *s_end;
+  char *last_p;
+  int last_column;
+  int piece_width;
+
+  u32_possible_linebreaks (s, n, encoding, p);
+
+  s_end = s + n;
+  last_p = NULL;
+  last_column = start_column;
+  piece_width = 0;
+  while (s < s_end)
+    {
+      unsigned int uc = *s;
+
+      if (*p == UC_BREAK_POSSIBLE || *p == UC_BREAK_MANDATORY)
+        {
+          /* An atomic piece of text ends here.  */
+          if (last_p != NULL && last_column + piece_width > width)
+            {
+              /* Insert a line break.  */
+              *last_p = UC_BREAK_POSSIBLE;
+              last_column = 0;
+            }
+        }
+
+      if (*p == UC_BREAK_MANDATORY)
+        {
+          /* uc is a line break character.  */
+          /* Start a new piece at column 0.  */
+          last_p = NULL;
+          last_column = 0;
+          piece_width = 0;
+        }
+      else
+        {
+          /* uc is not a line break character.  */
+          int w;
+
+          if (*p == UC_BREAK_POSSIBLE)
+            {
+              /* Start a new piece.  */
+              last_p = p;
+              last_column += piece_width;
+              piece_width = 0;
+              /* No line break for the moment, may be turned into
+                 UC_BREAK_POSSIBLE later, via last_p. */
+            }
+         
+          *p = UC_BREAK_PROHIBITED;
+
+          w = uc_width (uc, encoding);
+          if (w >= 0) /* ignore control characters in the string */
+            piece_width += w;
+         }
+
+      s++;
+      p++;
+    }
+
+  /* The last atomic piece of text ends here.  */
+  if (last_p != NULL && last_column + piece_width + at_end_columns > width)
+    {
+      /* Insert a line break.  */
+      *last_p = UC_BREAK_POSSIBLE;
+      last_column = 0;
+    }
+
+  return last_column + piece_width;
+}
+
+#endif
+
+
+#ifdef TEST1
+
+#include <stdio.h>
+
+/* Read the contents of an input stream, and return it, terminated with a NUL
+   byte. */
+char *
+read_file (stream)
+     FILE *stream;
+{
+#define BUFSIZE 4096
+  char *buf = NULL;
+  int alloc = 0;
+  int size = 0;
+  int count;
+
+  while (! feof (stream))
+    {
+      if (size + BUFSIZE > alloc)
+        {
+          alloc = alloc + alloc / 2;
+          if (alloc < size + BUFSIZE)
+            alloc = size + BUFSIZE;
+          buf = realloc (buf, alloc);
+          if (buf == NULL)
+            {
+              fprintf (stderr, "out of memory\n");
+              exit (1);
+            }
+        }
+      count = fread (buf + size, 1, BUFSIZE, stream);
+      if (count == 0)
+        {
+          if (ferror (stream))
+            {
+              perror ("fread");
+              exit (1);
+            }
+        }
+      else
+        size += count;
+    }
+  buf = realloc (buf, size + 1);
+  if (buf == NULL)
+    {
+      fprintf (stderr, "out of memory\n");
+      exit (1);
+    }
+  buf[size] = '\0';
+  return buf;
+#undef BUFSIZE
+}
+
+int
+main (argc, argv)
+     int argc;
+     char * argv[];
+{
+  if (argc == 1)
+    {
+      /* Display all the break opportunities in the input string.  */
+      char *input = read_file (stdin);
+      int length = strlen (input);
+      char *breaks = malloc (length);
+      int i;
+
+      u8_possible_linebreaks ((unsigned char *) input, length, "UTF-8", breaks);
+
+      for (i = 0; i < length; i++)
+        {
+          switch (breaks[i])
+            {
+              case UC_BREAK_POSSIBLE:
+                /* U+2027 in UTF-8 encoding */
+                putc (0xe2, stdout); putc (0x80, stdout); putc (0xa7, stdout);
+                break;
+              case UC_BREAK_MANDATORY:
+                /* U+21B2 (or U+21B5) in UTF-8 encoding */
+                putc (0xe2, stdout); putc (0x86, stdout); putc (0xb2, stdout);
+                break;
+              case UC_BREAK_PROHIBITED:
+                break;
+              default:
+                abort ();
+            }
+          putc (input[i], stdout);
+        }
+
+      free (breaks);
+
+      return 0;
+    }
+  else if (argc == 2)
+    {
+      /* Insert line breaks for a given width.  */
+      int width = atoi (argv[1]);
+      char *input = read_file (stdin);
+      int length = strlen (input);
+      char *breaks = malloc (length);
+      int i;
+
+      u8_width_linebreaks ((unsigned char *) input, length, width, 0, 0, "UTF-8", breaks);
+
+      for (i = 0; i < length; i++)
+        {
+          switch (breaks[i])
+            {
+              case UC_BREAK_POSSIBLE:
+                putc ('\n', stdout);
+                break;
+              case UC_BREAK_MANDATORY:
+                break;
+              case UC_BREAK_PROHIBITED:
+                break;
+              default:
+                abort ();
+            }
+          putc (input[i], stdout);
+        }
+
+      free (breaks);
+
+      return 0;
+    }
+  else
+    return 1;
+}
+
+#endif /* TEST1 */
+
+
+/* Now the same thing with an arbitrary encoding.
+
+   We convert the input string to Unicode.
+
+   The standardized Unicode encodings are UTF-8, UCS-2, UCS-4, UTF-16,
+   UTF-16BE, UTF-16LE, UTF-7.  UCS-2 supports only characters up to
+   \U0000FFFF.  UTF-16 and variants support only characters up to
+   \U0010FFFF.  UTF-7 is way too complex and not supported by glibc-2.1.
+   UCS-4 specification leaves doubts about endianness and byte order mark.
+   glibc currently interprets it as big endian without byte order mark,
+   but this is not backed by an RFC.  So we use UTF-8. It supports
+   characters up to \U7FFFFFFF and is unambiguously defined.  */
+
+#if HAVE_ICONV
+
+#include <iconv.h>
+#include <errno.h>
+
+/* Luckily, the encoding's name is platform independent.  */
+#define UTF8_NAME "UTF-8"
+
+/* Return the length of a string after conversion through an iconv_t.  */
+static size_t
+iconv_string_length (cd, s, n)
+     iconv_t cd;
+     const char *s;
+     size_t n;
+{
+#define TMPBUFSIZE 4096
+  size_t count = 0;
+  char tmpbuf[TMPBUFSIZE];
+  const char *inptr = s;
+  size_t insize = n;
+  while (insize > 0)
+    {
+      char *outptr = tmpbuf;
+      size_t outsize = TMPBUFSIZE;
+      size_t res = iconv (cd, (ICONV_CONST char **) &inptr, &insize, &outptr, &outsize);
+      if (res == (size_t)(-1))
+        return (size_t)(-1);
+      count += outptr - tmpbuf;
+    }
+  /* Avoid glibc-2.1 bug and Solaris 2.7 bug.  */
+#if defined _LIBICONV_VERSION \
+   || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun)
+  {
+    char *outptr = tmpbuf;
+    size_t outsize = TMPBUFSIZE;
+    size_t res = iconv (cd, NULL, NULL, &outptr, &outsize);
+    if (res == (size_t)(-1))
+      return (size_t)(-1);
+    count += outptr - tmpbuf;
+  }
+#endif
+  /* return to the initial state */
+  iconv (cd, NULL, NULL, NULL, NULL);
+  return count;
+#undef TMPBUFSIZE
+}
+
+static void
+iconv_string_keeping_offsets (cd, s, n, offtable, t, m)
+     iconv_t cd;
+     const char *s;
+     size_t n;
+     size_t *offtable;
+     char *t;
+     size_t m;
+{
+  size_t i;
+  const char *s_end;
+  const char *inptr;
+  char *outptr;
+  size_t outsize;
+
+  for (i = 0; i < n; i++)
+    offtable[i] = (size_t)(-1);
+
+  s_end = s + n;
+  inptr = s;
+  outptr = t;
+  outsize = m;
+  while (inptr < s_end)
+    {
+      size_t insize;
+      size_t res;
+
+      offtable[inptr - s] = outptr - t;
+
+      res = (size_t)(-1);
+      for (insize = 1; inptr + insize <= s_end; insize++)
+        {
+          res = iconv (cd, (ICONV_CONST char **) &inptr, &insize, &outptr, &outsize);
+          if (!(res == (size_t)(-1) && errno == EINVAL))
+            break;
+        }
+      /* After we verified the convertibility and computed the translation's
+         size m, there shouldn't be any conversion error here. */
+      if (res == (size_t)(-1))
+        abort ();
+    }
+  /* Avoid glibc-2.1 bug and Solaris 2.7 bug.  */
+#if defined _LIBICONV_VERSION \
+   || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun)
+  if (iconv (cd, NULL, NULL, &outptr, &outsize) == (size_t)(-1))
+    abort ();
+#endif
+  /* We should have produced exactly m output bytes.  */
+  if (outsize != 0)
+    abort ();
+}
+
+#endif /* HAVE_ICONV */
+
+#if C_CTYPE_ASCII
+
+/* Tests whether a string is entirely ASCII.  Returns 1 if yes.
+   Returns 0 if the string is in an 8-bit encoding or an ISO-2022 encoding.  */
+static int
+is_all_ascii (s, n)
+     const char *s;
+     size_t n;
+{
+  for (; n > 0; s++, n--)
+    {
+      unsigned char c = (unsigned char) *s;
+
+      if (!(c_isprint (c) || c_isspace (c)))
+       return 0;
+    }
+  return 1;
+}
+
+#endif /* C_CTYPE_ASCII */
+
+#ifdef unused
+
+void
+mbs_possible_linebreaks (s, n, encoding, p)
+     const char *s;
+     size_t n;
+     const char *encoding;
+     char *p;
+{
+  if (is_utf8_encoding (encoding))
+    u8_possible_linebreaks ((const unsigned char *) s, n, encoding, p);
+  else
+    {
+#if HAVE_ICONV
+      iconv_t to_utf8 = iconv_open (UTF8_NAME, encoding);
+      if (to_utf8 != (iconv_t)(-1))
+        {
+          /* Determine the length of the resulting UTF-8 string.  */
+          size_t m = iconv_string_length (to_utf8, s, n);
+          if (m != (size_t)(-1))
+            {
+              /* Convert the string to UTF-8 and build a translation table
+                 from offsets into s to offsets into the translated string.  */
+              char *memory = malloc (n * sizeof (size_t) + m + m);
+              if (memory != NULL)
+                {
+                  size_t *offtable = (size_t *) memory;
+                  char *t = (char *) (offtable + n);
+                  char *q = (char *) (t + m);
+                  size_t i;
+
+                  iconv_string_keeping_offsets (to_utf8, s, n, offtable, t, m);
+
+                  /* Determine the possible line breaks of the UTF-8 string.  */
+                  u8_possible_linebreaks ((const unsigned char *) t, m, encoding, q);
+
+                  /* Translate the result back to the original string.  */
+                  memset (p, UC_BREAK_PROHIBITED, n);
+                  for (i = 0; i < n; i++)
+                    if (offtable[i] != (size_t)(-1))
+                      p[i] = q[offtable[i]];
+
+                  free (memory);
+                  iconv_close (to_utf8);
+                  return;
+                }
+            }
+          iconv_close (to_utf8);
+        }
+#endif
+      /* Impossible to convert.  */
+#if C_CTYPE_ASCII
+      if (is_all_ascii (s, n))
+       {
+         /* ASCII is a subset of UTF-8.  */
+         u8_possible_linebreaks ((const unsigned char *) s, n, encoding, p);
+         return;
+       }
+#endif
+      /* We have a non-ASCII string and cannot convert it.
+        Don't produce line breaks except those already present in the
+        input string.  All we assume here is that the encoding is
+        minimally ASCII compatible.  */
+      {
+        const char *s_end = s + n;
+        while (s < s_end)
+          {
+            *p = (*s == '\n' ? UC_BREAK_MANDATORY : UC_BREAK_PROHIBITED);
+            s++;
+            p++;
+          }
+      }
+    }
+}
+
+#endif
+
+int
+mbs_width_linebreaks (s, n, width, start_column, at_end_columns, encoding, p)
+     const char *s;
+     size_t n;
+     int width;
+     int start_column;
+     int at_end_columns;
+     const char *encoding;
+     char *p;
+{
+  if (is_utf8_encoding (encoding))
+    return u8_width_linebreaks ((const unsigned char *) s, n, width, start_column, at_end_columns, encoding, p);
+  else
+    {
+#if HAVE_ICONV
+      iconv_t to_utf8 = iconv_open (UTF8_NAME, encoding);
+      if (to_utf8 != (iconv_t)(-1))
+        {
+          /* Determine the length of the resulting UTF-8 string.  */
+          size_t m = iconv_string_length (to_utf8, s, n);
+          if (m != (size_t)(-1))
+            {
+              /* Convert the string to UTF-8 and build a translation table
+                 from offsets into s to offsets into the translated string.  */
+              char *memory = malloc (n * sizeof (size_t) + m + m);
+              if (memory != NULL)
+                {
+                  size_t *offtable = (size_t *) memory;
+                  char *t = (char *) (offtable + n);
+                  char *q = (char *) (t + m);
+                  int res_column;
+                  size_t i;
+
+                  iconv_string_keeping_offsets (to_utf8, s, n, offtable, t, m);
+
+                  /* Determine the line breaks of the UTF-8 string.  */
+                  res_column =
+                    u8_width_linebreaks ((const unsigned char *) t, m, width, start_column, at_end_columns, encoding, q);
+
+                  /* Translate the result back to the original string.  */
+                  memset (p, UC_BREAK_PROHIBITED, n);
+                  for (i = 0; i < n; i++)
+                    if (offtable[i] != (size_t)(-1))
+                      p[i] = q[offtable[i]];
+
+                  free (memory);
+                  iconv_close (to_utf8);
+                  return res_column;
+                }
+            }
+          iconv_close (to_utf8);
+        }
+#endif
+      /* Impossible to convert.  */
+#if C_CTYPE_ASCII
+      if (is_all_ascii (s, n))
+       {
+         /* ASCII is a subset of UTF-8.  */
+         return u8_width_linebreaks ((const unsigned char *) s, n, width, start_column, at_end_columns, encoding, p);
+       }
+#endif
+      /* We have a non-ASCII string and cannot convert it.
+        Don't produce line breaks except those already present in the
+        input string.  All we assume here is that the encoding is
+        minimally ASCII compatible.  */
+      {
+        const char *s_end = s + n;
+        while (s < s_end)
+          {
+            *p = (*s == '\n' ? UC_BREAK_MANDATORY : UC_BREAK_PROHIBITED);
+            s++;
+            p++;
+          }
+        /* We cannot compute widths in this case.  */
+        return start_column;
+      }
+    }
+}
+
+
+#ifdef TEST2
+
+#include <stdio.h>
+#include <locale.h>
+
+/* Read the contents of an input stream, and return it, terminated with a NUL
+   byte. */
+char *
+read_file (stream)
+     FILE *stream;
+{
+#define BUFSIZE 4096
+  char *buf = NULL;
+  int alloc = 0;
+  int size = 0;
+  int count;
+
+  while (! feof (stream))
+    {
+      if (size + BUFSIZE > alloc)
+        {
+          alloc = alloc + alloc / 2;
+          if (alloc < size + BUFSIZE)
+            alloc = size + BUFSIZE;
+          buf = realloc (buf, alloc);
+          if (buf == NULL)
+            {
+              fprintf (stderr, "out of memory\n");
+              exit (1);
+            }
+        }
+      count = fread (buf + size, 1, BUFSIZE, stream);
+      if (count == 0)
+        {
+          if (ferror (stream))
+            {
+              perror ("fread");
+              exit (1);
+            }
+        }
+      else
+        size += count;
+    }
+  buf = realloc (buf, size + 1);
+  if (buf == NULL)
+    {
+      fprintf (stderr, "out of memory\n");
+      exit (1);
+    }
+  buf[size] = '\0';
+  return buf;
+#undef BUFSIZE
+}
+
+int
+main (argc, argv)
+     int argc;
+     char * argv[];
+{
+  setlocale (LC_CTYPE, "");
+  if (argc == 1)
+    {
+      /* Display all the break opportunities in the input string.  */
+      char *input = read_file (stdin);
+      int length = strlen (input);
+      char *breaks = malloc (length);
+      int i;
+
+      mbs_possible_linebreaks (input, length, locale_charset (), breaks);
+
+      for (i = 0; i < length; i++)
+        {
+          switch (breaks[i])
+            {
+              case UC_BREAK_POSSIBLE:
+                putc ('|', stdout);
+                break;
+              case UC_BREAK_MANDATORY:
+                break;
+              case UC_BREAK_PROHIBITED:
+                break;
+              default:
+                abort ();
+            }
+          putc (input[i], stdout);
+        }
+
+      free (breaks);
+
+      return 0;
+    }
+  else if (argc == 2)
+    {
+      /* Insert line breaks for a given width.  */
+      int width = atoi (argv[1]);
+      char *input = read_file (stdin);
+      int length = strlen (input);
+      char *breaks = malloc (length);
+      int i;
+
+      mbs_width_linebreaks (input, length, width, 0, 0, locale_charset (), breaks);
+
+      for (i = 0; i < length; i++)
+        {
+          switch (breaks[i])
+            {
+              case UC_BREAK_POSSIBLE:
+                putc ('\n', stdout);
+                break;
+              case UC_BREAK_MANDATORY:
+                break;
+              case UC_BREAK_PROHIBITED:
+                break;
+              default:
+                abort ();
+            }
+          putc (input[i], stdout);
+        }
+
+      free (breaks);
+
+      return 0;
+    }
+  else
+    return 1;
+}
+
+#endif /* TEST2 */
diff --git a/lib/linebreak.h b/lib/linebreak.h
new file mode 100644 (file)
index 0000000..d0367ef
--- /dev/null
@@ -0,0 +1,82 @@
+/* linebreak.h - line breaking of Unicode strings
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _LINEBREAK_H
+#define _LINEBREAK_H
+
+#ifndef PARAMS
+# if defined (__GNUC__) || __STDC__
+#  define PARAMS(args) args
+# else
+#  define PARAMS(args) ()
+# endif
+#endif
+
+#include <stdlib.h>
+
+
+/* Display width.  */
+
+/* These functions are locale dependent.  The encoding argument identifies
+   the encoding (e.g. "ISO-8859-2" for Polish).  */
+
+/* Return the encoding of the current locale.  */
+extern const char * locale_charset PARAMS ((void));
+
+/* Determine number of column positions required for UC. */
+extern int uc_width PARAMS ((unsigned int uc, const char *encoding));
+
+/* Determine number of column positions required for first N units
+   (or fewer if S ends before this) in S.  */
+extern int u8_width PARAMS ((const unsigned char *s, size_t n, const char *encoding));
+extern int u16_width PARAMS ((const unsigned short *s, size_t n, const char *encoding));
+extern int u32_width PARAMS ((const unsigned int *s, size_t n, const char *encoding));
+
+
+/* Line breaking.  */
+
+enum {
+  UC_BREAK_PROHIBITED,
+  UC_BREAK_POSSIBLE,
+  UC_BREAK_MANDATORY,
+  UC_BREAK_HYPHENATION
+};
+
+/* Determine the line break points in S, and store the result at p[0..n-1].
+   p[i] = UC_BREAK_MANDATORY means that s[i] is a line break character.
+   p[i] = UC_BREAK_POSSIBLE means that a line break may be inserted between
+          s[i-1] and s[i].
+   p[i] = UC_BREAK_HYPHENATION means that a hyphen and a line break may be
+          inserted between s[i-1] and s[i].  But beware of language dependent
+          hyphenation rules.
+   p[i] = UC_BREAK_PROHIBITED means that s[i-1] and s[i] must not be separated.
+ */
+extern void u8_possible_linebreaks PARAMS ((const unsigned char *s, size_t n, const char *encoding, char *p));
+extern void u16_possible_linebreaks PARAMS ((const unsigned short *s, size_t n, const char *encoding, char *p));
+extern void u32_possible_linebreaks PARAMS ((const unsigned int *s, size_t n, const char *encoding, char *p));
+extern void mbs_possible_linebreaks PARAMS ((const char *s, size_t n, const char *encoding, char *p));
+
+/* Choose the best line breaks, assuming the uc_width function.  Return the
+   column after the end of the string.  */
+extern int u8_width_linebreaks PARAMS ((const unsigned char *s, size_t n, int width, int start_column, int at_end_columns, const char *encoding, char *p));
+extern int u16_width_linebreaks PARAMS ((const unsigned short *s, size_t n, int width, int start_column, int at_end_columns, const char *encoding, char *p));
+extern int u32_width_linebreaks PARAMS ((const unsigned int *s, size_t n, int width, int start_column, int at_end_columns, const char *encoding, char *p));
+extern int mbs_width_linebreaks PARAMS ((const char *s, size_t n, int width, int start_column, int at_end_columns, const char *encoding, char *p));
+
+
+#endif /* _LINEBREAK_H */
diff --git a/lib/localcharset.c b/lib/localcharset.c
new file mode 100644 (file)
index 0000000..12214b7
--- /dev/null
@@ -0,0 +1,265 @@
+/* Determine a canonical name for the current locale's character encoding.
+
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+   This program 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, or (at your option)
+   any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* Written by Bruno Haible <haible@clisp.cons.org>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+
+#include <stdio.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# undef WIN32   /* avoid warning on mingw32 */
+# define WIN32
+#endif
+
+#ifndef WIN32
+# if HAVE_LANGINFO_CODESET
+#  include <langinfo.h>
+# else
+#  if HAVE_SETLOCALE
+#   include <locale.h>
+#  endif
+# endif
+#else /* WIN32 */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+#ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+#endif
+
+#ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+#endif
+
+/* The following static variable is declared 'volatile' to avoid a
+   possible multithread problem in the function get_charset_aliases. If we
+   are running in a threaded environment, and if two threads initialize
+   'charset_aliases' simultaneously, both will produce the same value,
+   and everything will be ok if the two assignments to 'charset_aliases'
+   are atomic. But I don't know what will happen if the two assignments mix.  */
+#if __STDC__ != 1
+# define volatile /* empty */
+#endif
+/* Pointer to the contents of the charset.alias file, if it has already been
+   read, else NULL.  Its format is:
+   ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0'  */
+static char * volatile charset_aliases;
+
+/* Return a pointer to the contents of the charset.alias file.  */
+static const char *
+get_charset_aliases ()
+{
+  char *cp;
+
+  cp = charset_aliases;
+  if (cp == NULL)
+    {
+#ifndef WIN32
+      FILE *fp;
+      const char *dir = LIBDIR;
+      const char *base = "charset.alias";
+      char *file_name;
+
+      /* Concatenate dir and base into freshly allocated file_name.  */
+      {
+       size_t dir_len = strlen (dir);
+       size_t base_len = strlen (base);
+       int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
+       file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
+       if (file_name != NULL)
+         {
+           memcpy (file_name, dir, dir_len);
+           if (add_slash)
+             file_name[dir_len] = DIRECTORY_SEPARATOR;
+           memcpy (file_name + dir_len + add_slash, base, base_len + 1);
+         }
+      }
+
+      if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL)
+       /* Out of memory or file not found, treat it as empty.  */
+       cp = "";
+      else
+       {
+         /* Parse the file's contents.  */
+         int c;
+         char buf1[50+1];
+         char buf2[50+1];
+         char *res_ptr = NULL;
+         size_t res_size = 0;
+         size_t l1, l2;
+
+         for (;;)
+           {
+             c = getc (fp);
+             if (c == EOF)
+               break;
+             if (c == '\n' || c == ' ' || c == '\t')
+               continue;
+             if (c == '#')
+               {
+                 /* Skip comment, to end of line.  */
+                 do
+                   c = getc (fp);
+                 while (!(c == EOF || c == '\n'));
+                 if (c == EOF)
+                   break;
+                 continue;
+               }
+             ungetc (c, fp);
+             if (fscanf(fp, "%50s %50s", buf1, buf2) < 2)
+               break;
+             l1 = strlen (buf1);
+             l2 = strlen (buf2);
+             if (res_size == 0)
+               {
+                 res_size = l1 + 1 + l2 + 1;
+                 res_ptr = malloc (res_size + 1);
+               }
+             else
+               {
+                 res_size += l1 + 1 + l2 + 1;
+                 res_ptr = realloc (res_ptr, res_size + 1);
+               }
+             if (res_ptr == NULL)
+               {
+                 /* Out of memory. */
+                 res_size = 0;
+                 break;
+               }
+             strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
+             strcpy (res_ptr + res_size - (l2 + 1), buf2);
+           }
+         fclose (fp);
+         if (res_size == 0)
+           cp = "";
+         else
+           {
+             *(res_ptr + res_size) = '\0';
+             cp = res_ptr;
+           }
+       }
+
+      if (file_name != NULL)
+       free (file_name);
+
+#else /* WIN32 */
+
+      /* To avoid the troubles of installing a separate file in the same
+        directory as the DLL and of retrieving the DLL's directory at
+        runtime, simply inline the aliases here.  */
+
+      cp = "CP936" "\0" "GBK" "\0"
+          "CP1361" "\0" "JOHAB" "\0";
+#endif
+
+      charset_aliases = cp;
+    }
+
+  return cp;
+}
+
+/* Determine the current locale's character encoding, and canonicalize it
+   into one of the canonical names listed in config.charset.
+   The result must not be freed; it is statically allocated.
+   If the canonical name cannot be determined, the result is a non-canonical
+   name or NULL.  */
+
+#ifdef STATIC
+STATIC
+#endif
+const char *
+locale_charset ()
+{
+  const char *codeset;
+  const char *aliases;
+
+#ifndef WIN32
+
+# if HAVE_LANGINFO_CODESET
+
+  /* Most systems support nl_langinfo (CODESET) nowadays.  */
+  codeset = nl_langinfo (CODESET);
+
+# else
+
+  /* On old systems which lack it, use setlocale and getenv.  */
+  const char *locale = NULL;
+
+#  if HAVE_SETLOCALE
+  locale = setlocale (LC_CTYPE, NULL);
+#  endif
+  if (locale == NULL || locale[0] == '\0')
+    {
+      locale = getenv ("LC_ALL");
+      if (locale == NULL || locale[0] == '\0')
+       {
+         locale = getenv ("LC_CTYPE");
+         if (locale == NULL || locale[0] == '\0')
+           locale = getenv ("LANG");
+       }
+    }
+
+  /* On some old systems, one used to set locale = "iso8859_1". On others,
+     you set it to "language_COUNTRY.charset". In any case, we resolve it
+     through the charset.alias file.  */
+  codeset = locale;
+
+# endif
+
+#else /* WIN32 */
+
+  static char buf[2 + 10 + 1];
+
+  /* Win32 has a function returning the locale's codepage as a number.  */
+  sprintf (buf, "CP%u", GetACP ());
+  codeset = buf;
+
+#endif
+
+  if (codeset != NULL && codeset[0] != '\0')
+    {
+      /* Resolve alias. */
+      for (aliases = get_charset_aliases ();
+          *aliases != '\0';
+          aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
+       if (!strcmp (codeset, aliases))
+         {
+           codeset = aliases + strlen (aliases) + 1;
+           break;
+         }
+    }
+
+  return codeset;
+}
diff --git a/lib/ref-add.sin b/lib/ref-add.sin
new file mode 100644 (file)
index 0000000..167374e
--- /dev/null
@@ -0,0 +1,31 @@
+# Add this package to a list of references stored in a text file.
+#
+#   Copyright (C) 2000 Free Software Foundation, Inc.
+#
+#   This program 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, or (at your option)
+#   any later version.
+#
+#   This program 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 this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#   USA.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# Packages using this file: / {
+  s/# Packages using this file://
+  ta
+  :a
+  s/ @PACKAGE@ / @PACKAGE@ /
+  tb
+  s/ $/ @PACKAGE@ /
+  :b
+  s/^/# Packages using this file:/
+}
diff --git a/lib/ref-del.sin b/lib/ref-del.sin
new file mode 100644 (file)
index 0000000..613cf37
--- /dev/null
@@ -0,0 +1,26 @@
+# Remove this package from a list of references stored in a text file.
+#
+#   Copyright (C) 2000 Free Software Foundation, Inc.
+#
+#   This program 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, or (at your option)
+#   any later version.
+#
+#   This program 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 this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+#   USA.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# Packages using this file: / {
+  s/# Packages using this file://
+  s/ @PACKAGE@ / /
+  s/^/# Packages using this file:/
+}
index 7f4d64581425823cd63b558aba26af59c51254fc..ca1a4cf942863f4174579adb490ad1274d3d8803 100644 (file)
@@ -1,3 +1,45 @@
+2001-03-03  Bruno Haible  <haible@clisp.cons.org>
+
+       * write-po.h: New file, pieces of message.h.
+       * message.h (message_page_width_set, message_print_style_indent,
+       message_print_style_uniforum, message_print_style_escape,
+       message_list_print, message_list_sort_by_msgid,
+       message_list_sort_by_filepos): Move to write-po.h.
+       * write-po.c: New file, pieces of message.c.
+       (wrap): Add charset argument. Rewritten to use mbs_width_linebreaks().
+       Use c_isprint() instead of isprint().
+       (message_print): Add charset argument. Insert a space after '#' even
+       if the comment line's first character is a tab.
+       (message_print_obsolete): Likewise.
+       (message_list_print): Don't change locales. Extract the charset name
+       from the header entry.
+       (msgid_cmp, filepos_cmp): Always use strcmp, never use strcoll.
+       (message_list_sort_by_msgid, message_list_sort_by_filepos): Don't
+       change locales.
+       * message.c (indent, uniforum, escape, page_width,
+       make_c_format_description_string, significant_c_format_p,
+       make_c_width_description_string, message_print_style_indent,
+       message_print_style_uniforum, message_print_style_escape, wrap,
+       print_blank_line, message_print, message_print_obsolete,
+       message_list_print, msgid_cmp, message_list_sort_by_msgid,
+       filepos_cmp, message_list_sort_by_filepos, message_page_width_set):
+       Move to write-po.c.
+       * msgmerge.c: Include write-po.h.
+       * msgunfmt.c: Likewise.
+       * xgettext.c: Likewise.
+       * msgcomm.c: Likewise.
+       * Makefile.am (noinst_HEADERS): Add write-po.h.
+       (msgmerge_SOURCES): Add write-po.c.
+       (msgunfmt_SOURCES): Likewise.
+       (xgettext_SOURCES): Likewise.
+       (msgcomm_SOURCES): Likewise.
+       (msgmerge_LDADD, msgunfmt_LDADD, xgettext_LDADD, msgcomm_LDADD): New
+       variables.
+
+2001-03-03  Bruno Haible  <haible@clisp.cons.org>
+
+       * msgcmp.c (compare): Internationalize error message.
+
 2001-02-10  Bruno Haible  <haible@clisp.cons.org>
 
        * msgunfmt.c (main): Accept -e and -E options.
index cb8d47ce6a65702cce23e5d9dba69b01a30d8df3..0dd327f032d93476a5534da849466bd7dadd82cd 100644 (file)
--- a/src/FILES
+++ b/src/FILES
@@ -26,6 +26,10 @@ message.c
                 A list-of-messages type.
                 A list-of-lists-of-messages type.
 
+write-po.h
+write-po.c
+                Output of a list-of-messages to a PO file.
+
 msgunfmt.c      Main source for the 'msgunfmt' program.
 
 open-po.h
index 4db82f169288419019c7506b33454ce6128d0ae3..eab2f5360ccea2776470ea5887ada44b657438d6 100644 (file)
@@ -22,7 +22,7 @@ AUTOMAKE_OPTIONS = 1.2 gnits
 bin_PROGRAMS = gettext msgcmp msgfmt msgmerge msgunfmt xgettext msgcomm
 
 noinst_HEADERS = pos.h message.h po-gram.h po-hash.h po-lex.h po.h open-po.h \
-str-list.h xget-lex.h dir-list.h po-gram-gen.h po-hash-gen.h
+str-list.h write-po.h xget-lex.h dir-list.h po-gram-gen.h po-hash-gen.h
 
 EXTRA_DIST = FILES
 
@@ -44,12 +44,18 @@ po-lex.c po.c str-list.c dir-list.c
 msgfmt_SOURCES = msgfmt.c open-po.c po-gram-gen.y po-hash-gen.y po-lex.c po.c \
 str-list.c message.c dir-list.c
 msgmerge_SOURCES = message.c msgmerge.c open-po.c po-gram-gen.y po-hash-gen.y \
-po-lex.c po.c str-list.c dir-list.c
-msgunfmt_SOURCES = message.c msgunfmt.c str-list.c
+po-lex.c po.c str-list.c dir-list.c write-po.c
+msgunfmt_SOURCES = message.c msgunfmt.c str-list.c write-po.c
 xgettext_SOURCES = message.c open-po.c po-gram-gen.y po-hash-gen.y po-lex.c \
-po.c str-list.c xget-lex.c xgettext.c dir-list.c
+po.c str-list.c xget-lex.c xgettext.c dir-list.c write-po.c
 msgcomm_SOURCES = msgcomm.c message.c po-gram-gen.y po-hash-gen.y po-lex.c \
-open-po.c po.c str-list.c dir-list.c
+open-po.c po.c str-list.c dir-list.c write-po.c
+
+# Link dependencies. write-po.c pulls in linebreak.c which may need -liconv.
+msgmerge_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
+msgunfmt_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
+xgettext_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
+msgcomm_LDADD = ../lib/libnlsut.a @INTLLIBS@ @LIBICONV@
 
 BUILT_SOURCES = po-gram-gen.c po-hash-gen.c po-gram-gen.h po-hash-gen.h
 
index 4d527422bd89343a2cbb9fce70b92ce4e11451e2..b819f825a3936a106f453cdce2cb7867e9b918bf 100644 (file)
@@ -21,58 +21,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 # include <config.h>
 #endif
 
-#include <errno.h>
-#include <ctype.h>
-#include <stdio.h>
-
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#include <locale.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "fstrcmp.h"
 #include "message.h"
 #include "system.h"
-#include "error.h"
-#include "libgettext.h"
-
-
-/* Our regular abbreviation.  */
-#define _(str) gettext (str)
-
-
-/* These two variables control the output style of the message_print
-   function.  Interface functions for them are to be used.  */
-static int indent;
-static int uniforum;
-static int escape;
-
-/* This variable controls the page width when printing messages.
-   Defaults to PAGE_WIDTH if not set.  Zero (0) given to message_page_-
-   width_set will result in no wrapping being performed.  */
-static size_t page_width = PAGE_WIDTH;
 
 
 /* Prototypes for local functions.  */
-static void wrap PARAMS ((FILE *__fp, const char *__line_prefix,
-                         const char *__name, const char *__value,
-                         enum is_wrap do_wrap));
-static void print_blank_line PARAMS ((FILE *__fp));
-static void message_print PARAMS ((const message_ty *__mp, FILE *__fp,
-                                  const char *__domain, int blank_line,
-                                  int __debug));
-static void message_print_obsolete PARAMS ((const message_ty *__mp, FILE *__fp,
-                                           const char *__domain,
-                                           int blank_line));
-static int msgid_cmp PARAMS ((const void *__va, const void *__vb));
-static int filepos_cmp PARAMS ((const void *__va, const void *__vb));
-static const char *make_c_format_description_string PARAMS ((enum is_c_format,
-                                                            int debug));
-static const char *make_c_width_description_string PARAMS ((enum is_c_format));
-static int significant_c_format_p PARAMS ((enum is_c_format __is_c_format));
-
 static message_ty *message_list_search_fuzzy_inner PARAMS ((
        message_list_ty *__mlp, const char *__msgid, double *__best_weight_p));
 
@@ -94,42 +51,6 @@ parse_c_format_description_string (s)
 }
 
 
-static const char *
-make_c_format_description_string (is_c_format, debug)
-     enum is_c_format is_c_format;
-     int debug;
-{
-  const char *result = NULL;
-
-  switch (is_c_format)
-    {
-    case possible:
-      if (debug)
-       {
-         result = " possible-c-format";
-         break;
-       }
-      /* FALLTHROUGH */
-    case yes:
-      result = " c-format";
-      break;
-    case impossible:
-      result = " impossible-c-format";
-      break;
-    case no:
-      result = " no-c-format";
-      break;
-    case undecided:
-      result = " undecided";
-      break;
-    default:
-      abort ();
-    }
-
-  return result;
-}
-
-
 int
 possible_c_format_p (is_c_format)
      enum is_c_format is_c_format;
@@ -138,14 +59,6 @@ possible_c_format_p (is_c_format)
 }
 
 
-static int
-significant_c_format_p (is_c_format)
-     enum is_c_format is_c_format;
-{
-  return is_c_format != undecided && is_c_format != impossible;
-}
-
-
 enum is_c_format
 parse_c_width_description_string (s)
      const char *s;
@@ -158,28 +71,6 @@ parse_c_width_description_string (s)
 }
 
 
-static const char *
-make_c_width_description_string (do_wrap)
-     enum is_wrap do_wrap;
-{
-  const char *result = NULL;
-
-  switch (do_wrap)
-    {
-    case yes:
-      result = " wrap";
-      break;
-    case no:
-      result = " no-wrap";
-      break;
-    default:
-      abort ();
-    }
-
-  return result;
-}
-
-
 message_ty *
 message_alloc (msgid, msgid_plural)
      char *msgid;
@@ -599,28 +490,6 @@ message_comment_filepos (mp, name, line)
 }
 
 
-void
-message_print_style_indent ()
-{
-  indent = 1;
-}
-
-
-void
-message_print_style_uniforum ()
-{
-  uniforum = 1;
-}
-
-
-void
-message_print_style_escape (flag)
-     int flag;
-{
-  escape = (flag != 0);
-}
-
-
 message_list_ty *
 message_list_alloc ()
 {
@@ -847,726 +716,3 @@ message_list_list_free (mllp)
     free (mllp->item);
   free (mllp);
 }
-
-
-/* Local functions.  */
-
-static void
-wrap (fp, line_prefix, name, value, do_wrap)
-     FILE *fp;
-     const char *line_prefix;
-     const char *name;
-     const char *value;
-     enum is_wrap do_wrap;
-{
-  const char *s;
-  int first_line;
-  /* The \a and \v escapes were added by the ANSI C Standard.  Prior
-     to the Standard, most compilers did not have them.  Because we
-     need the same program on all platforms we don't provide support
-     for them here.  */
-  static const char escapes[] = "\b\f\n\r\t";
-  static const char escape_names[] = "bfnrt";
-
-  /* The empty string is a special case.  */
-  if (*value == '\0')
-    {
-      if (line_prefix != NULL)
-       fputs (line_prefix, fp);
-      fputs (name, fp);
-      putc (indent ? '\t' : ' ', fp);
-      fputs ("\"\"\n", fp);
-      return;
-    }
-
-  s = value;
-  first_line = 1;
-  while (*s)
-    {
-      const char *ep;
-      int ocol;
-
-      /* The line starts with different things depending on whether it
-         is the first line, and if we are using the indented style.  */
-      if (first_line)
-       {
-         ocol = strlen (name) + (line_prefix ? strlen (line_prefix) : 0);
-         if (indent && ocol < 8)
-           ocol = 8;
-         else
-           ++ocol;
-       }
-      else
-       ocol = (indent ? 8 : 0);
-
-      /* Allow room for the opening quote character. */
-      ++ocol;
-
-      /* Work out how many characters from the string will fit on a
-         line.  Natural breaks occur at embedded newline characters.  */
-      for (ep = s; *ep; ++ep)
-       {
-         const char *esc;
-         int cw;
-         int c;
-
-         c = (unsigned char) *ep;
-         /* FIXME This is the wrong locale.  While message_list_print
-            set the "C" locale for LC_CTYPE, the need is to use the
-            correct locale for the file's contents.  */
-         esc = strchr (escapes, c);
-         if (esc == NULL && (!escape || isprint (c)))
-           cw = 1 + (c == '\\' || c == '"');
-         else
-           cw = esc != NULL ? 2 : 4;
-         /* Allow 1 character for the closing quote.  */
-         if (ocol + cw >= (do_wrap == no ? INT_MAX : page_width))
-           break;
-         ocol += cw;
-         if (c == '\n')
-           {
-             ++ep;
-             break;
-           }
-       }
-
-      /* The above loop detects if a line is too long.  If it is too
-        long, see if there is a better place to break the line.  */
-      if (*ep)
-       {
-         const char *bp;
-
-         for (bp = ep; bp > s; --bp)
-           if (bp[-1] == ' ' || bp[-1] == '\n')
-             {
-               ep = bp;
-               break;
-             }
-       }
-
-      /* If this is the first line, and we are not using the indented
-         style, and the line would wrap, then use an empty first line
-         and restart.  */
-      if (first_line && !indent && *ep != '\0')
-       {
-         fprintf (fp, "%s%s \"\"\n", line_prefix ? line_prefix : "", name);
-         s = value;
-         first_line = 0;
-         continue;
-       }
-
-      /* Print the beginning of the line.  This will depend on whether
-        this is the first line, and if the indented style is being
-        used.  */
-      if (first_line)
-       {
-         first_line = 0;
-         if (line_prefix != NULL)
-           fputs (line_prefix, fp);
-         fputs (name, fp);
-         putc (indent ? '\t' : ' ', fp);
-       }
-      else
-       {
-         if (line_prefix != NULL)
-           fputs (line_prefix, fp);
-         if (indent)
-           putc ('\t', fp);
-       }
-
-      /* Print the body of the line.  C escapes are used for
-        unprintable characters.  */
-      putc ('"', fp);
-      while (s < ep)
-       {
-         const char *esc;
-         int c;
-
-         c = (unsigned char) *s++;
-         /* FIXME This is the wrong locale.  While message_list_print
-            set the "C" locale for LC_CTYPE, the need is to use the
-            correct locale for the file's contents.  */
-         esc = strchr (escapes, c);
-         if (esc == NULL && (!escape || isprint (c)))
-           {
-             if (c == '\\' || c == '"')
-               putc ('\\', fp);
-             putc (c, fp);
-           }
-         else if (esc != NULL)
-           {
-             c = escape_names[esc - escapes];
-
-             putc ('\\', fp);
-             putc (c, fp);
-
-             /* We warn about any use of escape sequences beside
-                '\n' and '\t'.  */
-             if (c != 'n' && c != 't')
-               error (0, 0, _("\
-internationalized messages should not contain the `\\%c' escape sequence"),
-                      c);
-           }
-         else
-           fprintf (fp, "\\%3.3o", c);
-       }
-      fputs ("\"\n", fp);
-    }
-}
-
-
-static void
-print_blank_line (fp)
-     FILE *fp;
-{
-  if (uniforum)
-    fputs ("#\n", fp);
-  else
-    putc ('\n', fp);
-}
-
-
-static void
-message_print (mp, fp, domain, blank_line, debug)
-     const message_ty *mp;
-     FILE *fp;
-     const char *domain;
-     int blank_line;
-     int debug;
-{
-  message_variant_ty *mvp;
-  int first;
-  size_t j;
-
-  /* Find the relevant message variant.  If there isn't one, remember
-     this using a NULL pointer.  */
-  mvp = NULL;
-  first = 0;
-
-  for (j = 0; j < mp->variant_count; ++j)
-    {
-      if (strcmp (domain, mp->variant[j].domain) == 0)
-       {
-         mvp = &mp->variant[j];
-         first = (j == 0);
-         break;
-       }
-    }
-
-  /* Separate messages with a blank line.  Uniforum doesn't like blank
-     lines, so use an empty comment (unless there already is one).  */
-  if (blank_line && (!uniforum
-                    || mp->comment == NULL
-                    || mp->comment->nitems == 0
-                    || mp->comment->item[0][0] != '\0'))
-    print_blank_line (fp);
-
-  /* The first variant of a message will have the comments attached to
-     it.  We can't attach them to all variants in case we are read in
-     again, multiplying the number of comment lines.  Usually there is
-     only one variant.  */
-  if (first)
-    {
-      if (mp->comment != NULL)
-       for (j = 0; j < mp->comment->nitems; ++j)
-         {
-           const char *s = mp->comment->item[j];
-           do
-             {
-               const char *e;
-               putc ('#', fp);
-              /* FIXME This is the wrong locale.  While
-                 message_list_print set the "C" locale for LC_CTYPE,
-                 the need to use the correct locale for the file's
-                 contents.  */
-               if (*s != '\0' && !isspace (*s))
-                 putc (' ', fp);
-               e = strchr (s, '\n');
-               if (e == NULL)
-                 {
-                   fputs (s, fp);
-                   s = NULL;
-                 }
-               else
-                 {
-                   fwrite (s, 1, e - s, fp);
-                   s = e + 1;
-                 }
-               putc ('\n', fp);
-             }
-           while (s != NULL);
-         }
-
-      if (mp->comment_dot != NULL)
-       for (j = 0; j < mp->comment_dot->nitems; ++j)
-         {
-           const char *s = mp->comment_dot->item[j];
-           putc ('#', fp);
-           putc ('.', fp);
-           /* FIXME This is the wrong locale.  While
-              message_list_print set the "C" locale for LC_CTYPE, the
-              need to use the correct locale for the file's contents.  */
-           if (*s && !isspace (*s))
-             putc (' ', fp);
-           fputs (s, fp);
-           putc ('\n', fp);
-         }
-    }
-
-  /* Print the file position comments for every domain.  This will
-     help a human who is trying to navigate the sources.  There is no
-     problem of getting repeat positions, because duplicates are
-     checked for.  */
-  if (mp->filepos_count != 0)
-    {
-      if (uniforum)
-       for (j = 0; j < mp->filepos_count; ++j)
-         {
-           lex_pos_ty *pp = &mp->filepos[j];
-           char *cp = pp->file_name;
-           while (cp[0] == '.' && cp[1] == '/')
-             cp += 2;
-           /* There are two Sun formats to choose from: SunOS and
-              Solaris.  Use the Solaris form here.  */
-           fprintf (fp, "# File: %s, line: %ld\n",
-                    cp, (long) pp->line_number);
-         }
-      else
-       {
-         size_t column;
-
-         fputs ("#:", fp);
-         column = 2;
-         for (j = 0; j < mp->filepos_count; ++j)
-           {
-             lex_pos_ty *pp;
-             char buffer[20];
-             char *cp;
-             size_t len;
-
-             pp = &mp->filepos[j];
-             cp = pp->file_name;
-             while (cp[0] == '.' && cp[1] == '/')
-               cp += 2;
-             sprintf (buffer, "%ld", (long) pp->line_number);
-             len = strlen (cp) + strlen (buffer) + 2;
-             if (column > 2 && column + len >= page_width)
-               {
-                 fputs ("\n#:", fp);
-                 column = 2;
-               }
-             fprintf (fp, " %s:%s", cp, buffer);
-             column += len;
-           }
-         putc ('\n', fp);
-       }
-    }
-
-  /* Print flag information in special comment.  */
-  if (first && ((mp->is_fuzzy && mvp != NULL && mvp->msgstr[0] != '\0')
-               || significant_c_format_p (mp->is_c_format)
-               || mp->do_wrap == no))
-    {
-      int first_flag = 1;
-
-      putc ('#', fp);
-      putc (',', fp);
-
-      /* We don't print the fuzzy flag if the msgstr is empty.  This
-        might be introduced by the user but we want to normalize the
-        output.  */
-      if (mp->is_fuzzy && mvp != NULL && mvp->msgstr[0] != '\0')
-       {
-         fputs (" fuzzy", fp);
-         first_flag = 0;
-       }
-
-      if (significant_c_format_p (mp->is_c_format))
-       {
-         if (!first_flag)
-           putc (',', fp);
-
-         fputs (make_c_format_description_string (mp->is_c_format, debug),
-                fp);
-         first_flag = 0;
-       }
-
-      if (mp->do_wrap == no)
-       {
-         if (!first_flag)
-           putc (',', fp);
-
-         fputs (make_c_width_description_string (mp->do_wrap), fp);
-         first_flag = 0;
-       }
-
-      putc ('\n', fp);
-    }
-
-  /* Print each of the message components.  Wrap them nicely so they
-     are as readable as possible.  If there is no recorded msgstr for
-     this domain, emit an empty string.  */
-  wrap (fp, NULL, "msgid", mp->msgid, mp->do_wrap);
-  if (mp->msgid_plural != NULL)
-    wrap (fp, NULL, "msgid_plural", mp->msgid_plural, mp->do_wrap);
-
-  if (mp->msgid_plural == NULL)
-    wrap (fp, NULL, "msgstr", mvp ? mvp->msgstr : "", mp->do_wrap);
-  else
-    {
-      char prefix_buf[20];
-      unsigned int i;
-
-      if (mvp)
-       {
-         const char *p;
-
-         for (p = mvp->msgstr, i = 0;
-              p < mvp->msgstr + mvp->msgstr_len;
-              p += strlen (p) + 1, i++)
-           {
-             sprintf (prefix_buf, "msgstr[%u]", i);
-             wrap (fp, NULL, prefix_buf, p, mp->do_wrap);
-           }
-       }
-      else
-       {
-         for (i = 0; i < 2; i++)
-           {
-             sprintf (prefix_buf, "msgstr[%u]", i);
-             wrap (fp, NULL, prefix_buf, "", mp->do_wrap);
-           }
-       }
-    }
-}
-
-
-static void
-message_print_obsolete (mp, fp, domain, blank_line)
-     const message_ty *mp;
-     FILE *fp;
-     const char *domain;
-     int blank_line;
-{
-  message_variant_ty *mvp;
-  size_t j;
-
-  /* Find the relevant message variant.  If there isn't one, remember
-     this using a NULL pointer.  */
-  mvp = NULL;
-
-  for (j = 0; j < mp->variant_count; ++j)
-    {
-      if (strcmp (domain, mp->variant[j].domain) == 0)
-       {
-         mvp = &mp->variant[j];
-         break;
-       }
-    }
-
-  /* If no msgstr is found or it is the empty string we print nothing.  */
-  if (mvp == NULL || mvp->msgstr[0] == '\0')
-    return;
-
-  /* Separate messages with a blank line.  Uniforum doesn't like blank
-     lines, so use an empty comment (unless there already is one).  */
-  if (blank_line)
-    print_blank_line (fp);
-
-  /* Print translator comment if available.  */
-  if (mp->comment)
-    for (j = 0; j < mp->comment->nitems; ++j)
-      {
-       const char *s = mp->comment->item[j];
-       do
-         {
-           const char *e;
-           putc ('#', fp);
-           /* FIXME This is the wrong locale.  While
-              message_list_print set the "C" locale for LC_CTYPE, the
-              need to use the correct locale for the file's contents.  */
-           if (*s != '\0' && !isspace (*s))
-             putc (' ', fp);
-           e = strchr (s, '\n');
-           if (e == NULL)
-             {
-               fputs (s, fp);
-               s = NULL;
-             }
-           else
-             {
-               fwrite (s, 1, e - s, fp);
-               s = e + 1;
-             }
-           putc ('\n', fp);
-         }
-       while (s != NULL);
-      }
-
-  /* Print flag information in special comment.  */
-  if (mp->is_fuzzy)
-    {
-      int first = 1;
-
-      putc ('#', fp);
-      putc (',', fp);
-
-      if (mp->is_fuzzy)
-       {
-         fputs (" fuzzy", fp);
-         first = 0;
-       }
-
-      putc ('\n', fp);
-    }
-
-  /* Print each of the message components.  Wrap them nicely so they
-     are as readable as possible.  */
-  wrap (fp, "#~ ", "msgid", mp->msgid, mp->do_wrap);
-  if (mp->msgid_plural != NULL)
-    wrap (fp, "#~ ", "msgid_plural", mp->msgid_plural, mp->do_wrap);
-
-  if (mp->msgid_plural == NULL)
-    wrap (fp, "#~ ", "msgstr", mvp->msgstr, mp->do_wrap);
-  else
-    {
-      char prefix_buf[20];
-      unsigned int i;
-      const char *p;
-
-      for (p = mvp->msgstr, i = 0;
-          p < mvp->msgstr + mvp->msgstr_len;
-          p += strlen (p) + 1, i++)
-       {
-         sprintf (prefix_buf, "msgstr[%u]", i);
-         wrap (fp, "#~ ", prefix_buf, p, mp->do_wrap);
-       }
-    }
-}
-
-
-void
-message_list_print (mlp, filename, force, debug)
-     message_list_ty *mlp;
-     const char *filename;
-     int force;
-     int debug;
-{
-  FILE *fp;
-  size_t j, k;
-  string_list_ty *dl;
-  int blank_line;
-#ifdef HAVE_SETLOCALE
-  char *old_locale;
-#endif
-
-  /* We will not write anything if we have no message or only the
-     header entry.  */
-  if (force == 0
-      && (mlp->nitems == 0
-         || (mlp->nitems == 1 && *mlp->item[0]->msgid == '\0')))
-    return;
-
-  /* Build the list of domains.  */
-  dl = string_list_alloc ();
-  for (j = 0; j < mlp->nitems; ++j)
-    {
-      message_ty *mp = mlp->item[j];
-      for (k = 0; k < mp->variant_count; ++k)
-       string_list_append_unique (dl, mp->variant[k].domain);
-    }
-
-  /* Open the output file.  */
-  if (filename != NULL && strcmp (filename, "-") != 0
-      && strcmp (filename, "/dev/stdout") != 0)
-    {
-      fp = fopen (filename, "w");
-      if (fp == NULL)
-       error (EXIT_FAILURE, errno, _("cannot create output file \"%s\""),
-              filename);
-    }
-  else
-    {
-      fp = stdout;
-      /* xgettext:no-c-format */
-      filename = _("standard output");
-    }
-
-#ifdef HAVE_SETLOCALE
-  /* FIXME This is the wrong locale.  The program is currently set for
-     the user's native language locale, for the error messages.  This
-     code sets it to the "C" locale, but that isn't right either.  The
-     need is to use the correct locale for the file's contents.  */
-  old_locale = setlocale (LC_CTYPE, "C");
-  if (old_locale)
-    old_locale = xstrdup (old_locale);
-#endif
-
-  /* Write out the messages for each domain.  */
-  blank_line = 0;
-  for (k = 0; k < dl->nitems; ++k)
-    {
-      /* If there is only one domain, and that domain is the default,
-        don't bother emitting the domain name, because it is the
-        default.  */
-      if (dl->nitems != 1 || strcmp (dl->item[0], MESSAGE_DOMAIN_DEFAULT) != 0)
-       {
-         if (blank_line)
-           print_blank_line (fp);
-         fprintf (fp, "domain \"%s\"\n", dl->item[k]);
-         blank_line = 1;
-       }
-
-      /* Write out each of the messages for this domain.  */
-      for (j = 0; j < mlp->nitems; ++j)
-       if (mlp->item[j]->obsolete == 0)
-         {
-           message_print (mlp->item[j], fp, dl->item[k], blank_line, debug);
-           blank_line = 1;
-         }
-
-      /* Write out each of the obsolete messages for this domain.  */
-      for (j = 0; j < mlp->nitems; ++j)
-       if (mlp->item[j]->obsolete != 0)
-         {
-           message_print_obsolete (mlp->item[j], fp, dl->item[k], blank_line);
-           blank_line = 1;
-         }
-    }
-  string_list_free (dl);
-
-  /* Restore the old locale.  Do this before emitting error messages,
-     so that the correct locale is used for the error.  (Ideally,
-     error should ensure this before calling gettext for the format
-     string.)  */
-#ifdef HAVE_SETLOCALE
-  if (old_locale)
-    {
-      setlocale (LC_CTYPE, old_locale);
-      free (old_locale);
-    }
-#endif
-
-  /* Make sure nothing went wrong.  */
-  if (fflush (fp))
-    error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"),
-          filename);
-  fclose (fp);
-}
-
-
-static int
-msgid_cmp (va, vb)
-     const void *va;
-     const void *vb;
-{
-  const message_ty *a = *(const message_ty **) va;
-  const message_ty *b = *(const message_ty **) vb;
-#ifdef HAVE_STRCOLL
-  return strcoll (a->msgid, b->msgid);
-#else
-  return strcmp (a->msgid, b->msgid);
-#endif
-}
-
-
-void
-message_list_sort_by_msgid (mlp)
-     message_list_ty *mlp;
-{
-  /* FIXME This is the wrong locale.  The program is currently set for
-     the user's native language locale, for the error messages.  This
-     code sets it to the "C" locale, but that isn't right either.  The
-     need is to use the correct locale for the file's contents.  */
-#ifdef HAVE_SETLOCALE
-  char *tmp = setlocale (LC_COLLATE, "C");
-  if (tmp)
-    tmp = xstrdup (tmp);
-#endif
-  qsort (mlp->item, mlp->nitems, sizeof (mlp->item[0]), msgid_cmp);
-#ifdef HAVE_SETLOCALE
-  if (tmp)
-    {
-      setlocale (LC_COLLATE, tmp);
-      free (tmp);
-    }
-#endif
-}
-
-
-static int
-filepos_cmp (va, vb)
-     const void *va;
-     const void *vb;
-{
-  const message_ty *a = *(const message_ty **) va;
-  const message_ty *b = *(const message_ty **) vb;
-  int cmp;
-
-  /* No filepos is smaller than any other filepos.  */
-  if (a->filepos_count == 0)
-  {
-    if (b->filepos_count != 0)
-      return -1;
-  }
-  if (b->filepos_count == 0)
-    return 1;
-
-  /* Compare on the file names...  */
-  cmp = strcmp (a->filepos[0].file_name, b->filepos[0].file_name);
-  if (cmp != 0)
-       return cmp;
-
-  /* If they are equal, compare on the line numbers...  */
-  cmp = a->filepos[0].line_number - b->filepos[0].line_number;
-  if (cmp != 0)
-       return cmp;
-
-  /* If they are equal, compare on the msgid strings.  */
-#ifdef HAVE_STRCOLL
-  return strcoll (a->msgid, b->msgid);
-#else
-  return strcmp (a->msgid, b->msgid);
-#endif
-}
-
-
-void
-message_list_sort_by_filepos (mlp)
-    message_list_ty *mlp;
-{
-  /* FIXME This is the wrong locale.  The program is currently set for
-     the user's native language locale, for the error messages.  This
-     code sets it to the "C" locale, but that isn't right either.  The
-     need is to use the correct locale for the file's contents.  */
-#ifdef HAVE_SETLOCALE
-  char *tmp = setlocale (LC_COLLATE, "C");
-  if (tmp)
-    tmp = xstrdup (tmp);
-#endif
-  qsort (mlp->item, mlp->nitems, sizeof (mlp->item[0]), filepos_cmp);
-#ifdef HAVE_SETLOCALE
-  if (tmp)
-    {
-      setlocale (LC_COLLATE, tmp);
-      free (tmp);
-    }
-#endif
-}
-
-
-void
-message_page_width_set (n)
-     size_t n;
-{
-  if (n == 0)
-    {
-      page_width = INT_MAX;
-      return;
-    }
-
-  if (n < 20)
-    n = 20;
-
-  page_width = n;
-}
index 95e6e3db9e6eee753fcf3f05559f2dc1a55cf5fa..af5da2702d1759ac51d51873326fa71c04228538 100644 (file)
@@ -1,5 +1,5 @@
 /* GNU gettext - internationalization aids
-   Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
 
    This file was written by Peter Miller <millerp@canb.auug.org.au>
 
@@ -56,7 +56,6 @@ enum is_wrap
 #endif
 
 extern enum is_wrap parse_c_width_description_string PARAMS ((const char *s));
-extern void message_page_width_set PARAMS ((size_t width));
 
 
 typedef struct message_variant_ty message_variant_ty;
@@ -124,9 +123,6 @@ void message_comment_dot_append PARAMS ((message_ty *, const char *));
 message_ty *message_copy PARAMS ((message_ty *));
 message_ty *message_merge PARAMS ((message_ty *def, message_ty *ref));
 void message_comment_filepos PARAMS ((message_ty *, const char *, size_t));
-void message_print_style_indent PARAMS ((void));
-void message_print_style_uniforum PARAMS ((void));
-void message_print_style_escape PARAMS ((int));
 
 
 typedef struct message_list_ty message_list_ty;
@@ -144,9 +140,6 @@ void message_list_delete_nth PARAMS ((message_list_ty *, size_t));
 message_ty *message_list_search PARAMS ((message_list_ty *, const char *));
 message_ty *message_list_search_fuzzy PARAMS ((message_list_ty *,
                                               const char *));
-void message_list_print PARAMS ((message_list_ty *, const char *, int, int));
-void message_list_sort_by_msgid PARAMS ((message_list_ty *));
-void message_list_sort_by_filepos PARAMS ((message_list_ty *));
 
 
 typedef struct message_list_list_ty message_list_list_ty;
index f932ac7e4bde61da9b9830873cedfa1403596c9a..7804a59ad8a4dd0c925e8852742e7452c840050f 100644 (file)
@@ -42,6 +42,7 @@
 #include "getline.h"
 #include "libgettext.h"
 #include "message.h"
+#include "write-po.h"
 #include "po.h"
 #include "system.h"
 
index c70e6b4647d903a98b476dc05325e07ddb404ab1..b2be1cb8f1b248ff089ff37db81d549300aca506 100644 (file)
@@ -30,6 +30,7 @@
 #include "dir-list.h"
 #include "error.h"
 #include "message.h"
+#include "write-po.h"
 #include <system.h>
 #include "libgettext.h"
 #include "po.h"
index 89ce45033ea22000e443cae996ded57216d20b90..90f91cda7b513f7d8a713c912623ca0030ccc411 100644 (file)
@@ -40,6 +40,7 @@
 #include "hash-string.h"
 #include "libgettext.h"
 #include "message.h"
+#include "write-po.h"
 
 #define _(str) gettext (str)
 
diff --git a/src/write-po.c b/src/write-po.c
new file mode 100644 (file)
index 0000000..28eb1fb
--- /dev/null
@@ -0,0 +1,880 @@
+/* GNU gettext - internationalization aids
+   Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+
+   This file was written by Peter Miller <millerp@canb.auug.org.au>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; 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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include "write-po.h"
+#include "c-ctype.h"
+#include "linebreak.h"
+#include "system.h"
+#include "error.h"
+#include "libgettext.h"
+
+
+/* Our regular abbreviation.  */
+#define _(str) gettext (str)
+
+
+/* Prototypes for local functions.  */
+static const char *make_c_format_description_string PARAMS ((enum is_c_format,
+                                                            int debug));
+static const char *make_c_width_description_string PARAMS ((enum is_c_format));
+static int significant_c_format_p PARAMS ((enum is_c_format __is_c_format));
+static void wrap PARAMS ((FILE *__fp, const char *__line_prefix,
+                         const char *__name, const char *__value,
+                         enum is_wrap do_wrap, const char *__charset));
+static void print_blank_line PARAMS ((FILE *__fp));
+static void message_print PARAMS ((const message_ty *__mp, FILE *__fp,
+                                  const char *__domain, const char *__charset,
+                                  int blank_line, int __debug));
+static void message_print_obsolete PARAMS ((const message_ty *__mp, FILE *__fp,
+                                           const char *__domain,
+                                           const char *__charset,
+                                           int blank_line));
+static int msgid_cmp PARAMS ((const void *__va, const void *__vb));
+static int filepos_cmp PARAMS ((const void *__va, const void *__vb));
+
+
+/* This variable controls the page width when printing messages.
+   Defaults to PAGE_WIDTH if not set.  Zero (0) given to message_page_-
+   width_set will result in no wrapping being performed.  */
+static size_t page_width = PAGE_WIDTH;
+
+void
+message_page_width_set (n)
+     size_t n;
+{
+  if (n == 0)
+    {
+      page_width = INT_MAX;
+      return;
+    }
+
+  if (n < 20)
+    n = 20;
+
+  page_width = n;
+}
+
+
+/* These three variables control the output style of the message_print
+   function.  Interface functions for them are to be used.  */
+static int indent;
+static int uniforum;
+static int escape;
+
+void
+message_print_style_indent ()
+{
+  indent = 1;
+}
+
+void
+message_print_style_uniforum ()
+{
+  uniforum = 1;
+}
+
+void
+message_print_style_escape (flag)
+     int flag;
+{
+  escape = (flag != 0);
+}
+
+
+/* Local functions.  */
+
+
+static const char *
+make_c_format_description_string (is_c_format, debug)
+     enum is_c_format is_c_format;
+     int debug;
+{
+  const char *result = NULL;
+
+  switch (is_c_format)
+    {
+    case possible:
+      if (debug)
+       {
+         result = " possible-c-format";
+         break;
+       }
+      /* FALLTHROUGH */
+    case yes:
+      result = " c-format";
+      break;
+    case impossible:
+      result = " impossible-c-format";
+      break;
+    case no:
+      result = " no-c-format";
+      break;
+    case undecided:
+      result = " undecided";
+      break;
+    default:
+      abort ();
+    }
+
+  return result;
+}
+
+
+static int
+significant_c_format_p (is_c_format)
+     enum is_c_format is_c_format;
+{
+  return is_c_format != undecided && is_c_format != impossible;
+}
+
+
+static const char *
+make_c_width_description_string (do_wrap)
+     enum is_wrap do_wrap;
+{
+  const char *result = NULL;
+
+  switch (do_wrap)
+    {
+    case yes:
+      result = " wrap";
+      break;
+    case no:
+      result = " no-wrap";
+      break;
+    default:
+      abort ();
+    }
+
+  return result;
+}
+
+
+static void
+wrap (fp, line_prefix, name, value, do_wrap, charset)
+     FILE *fp;
+     const char *line_prefix;
+     const char *name;
+     const char *value;
+     enum is_wrap do_wrap;
+     const char *charset;
+{
+  const char *s;
+  int first_line;
+
+  /* Loop over the '\n' delimited portions of value.  */
+  s = value;
+  first_line = 1;
+  do
+    {
+      /* The \a and \v escapes were added by the ANSI C Standard.
+         Prior to the Standard, most compilers did not have them.
+         Because we need the same program on all platforms we don't
+         provide support for them here.  */
+      static const char escapes[] = "\b\f\n\r\t";
+      static const char escape_names[] = "bfnrt";
+
+      const char *es;
+      const char *ep;
+      size_t portion_len;
+      char *portion;
+      char *linebreaks;
+      char *pp;
+      int startcol, startcol_after_break, width, endcols;
+      size_t i;
+
+      for (es = s; *es != '\0'; )
+       if (*es++ == '\n')
+         break;
+
+      /* Expand escape sequences in each portion.  */
+      for (ep = s, portion_len = 0; ep < es; ep++)
+       {
+         char c = *ep;
+         const char *esc = strchr (escapes, c);
+         if (esc != NULL)
+           portion_len += 2;
+         else if (escape && !c_isprint ((unsigned char) c))
+           portion_len += 4;
+         else
+           portion_len += 1 + (c == '\\' || c == '"');
+       }
+      portion = (char *) xmalloc (portion_len);
+      for (ep = s, pp = portion; ep < es; ep++)
+       {
+         char c = *ep;
+         const char *esc = strchr (escapes, c);
+         if (esc != NULL)
+           {
+             *pp++ = '\\';
+             *pp++ = c = escape_names[esc - escapes];
+             /* We warn about any use of escape sequences beside
+                '\n' and '\t'.  */
+             if (c != 'n' && c != 't')
+               error (0, 0, _("\
+internationalized messages should not contain the `\\%c' escape sequence"),
+                      c);
+           }
+         else if (escape && !c_isprint ((unsigned char) c))
+           {
+             *pp++ = '\\';
+             *pp++ = '0' + (((unsigned char) c >> 6) & 7);
+             *pp++ = '0' + (((unsigned char) c >> 3) & 7);
+             *pp++ = '0' + ((unsigned char) c & 7);
+           }
+         else
+           {
+             if (c == '\\' || c == '"')
+               *pp++ = '\\';
+             *pp++ = c;
+           }
+       }
+
+      linebreaks = (char *) xmalloc (portion_len);
+
+      /* Subsequent lines after a break are all indented.
+        See INDENT-S.  */
+      startcol_after_break = (line_prefix ? strlen (line_prefix) : 0);
+      if (indent)
+       startcol_after_break = (startcol_after_break + 8) & ~7;
+      startcol_after_break++;
+
+      /* The line width.  Allow room for the closing quote character.  */
+      width = (do_wrap == no ? INT_MAX : page_width) - 1;
+      /* Adjust for indentation of subsequent lines.  */
+      width -= startcol_after_break;
+
+    recompute:
+      /* The line starts with different things depending on whether it
+        is the first line, and if we are using the indented style.
+        See INDENT-F.  */
+      startcol = (line_prefix ? strlen (line_prefix) : 0);
+      if (first_line)
+       {
+         startcol += strlen (name);
+         if (indent)
+           startcol = (startcol + 8) & ~7;
+         else
+           startcol++;
+       }
+      else
+       {
+         if (indent)
+           startcol = (startcol + 8) & ~7;
+       }
+      /* Allow room for the opening quote character.  */
+      startcol++;
+      /* Adjust for indentation of subsequent lines.  */
+      startcol -= startcol_after_break;
+
+      /* Do line breaking on the portion.
+        But don't break immediately before the "\n" at the end.  */
+      endcols = 0;
+      if (es > s && es[-1] == '\n')
+       {
+         endcols = 2;
+         linebreaks[portion_len - 2] = UC_BREAK_PROHIBITED;
+         linebreaks[portion_len - 1] = UC_BREAK_PROHIBITED;
+       }
+      mbs_width_linebreaks (portion, portion_len - endcols, width,
+                           startcol, endcols, charset, linebreaks);
+
+      /* If this is the first line, and we are not using the indented
+        style, and the line would wrap, then use an empty first line
+        and restart.  */
+      if (first_line && !indent
+         && portion_len > 0
+         && (*es != '\0'
+             || startcol > width
+             || memchr (linebreaks, UC_BREAK_POSSIBLE, portion_len) != NULL))
+       {
+         if (line_prefix != NULL)
+           fputs (line_prefix, fp);
+         fputs (name, fp);
+         fputs (" \"\"\n", fp);
+         first_line = 0;
+         /* Recompute startcol and linebreaks.  */
+         goto recompute;
+       }
+
+      /* Print the beginning of the line.  This will depend on whether
+        this is the first line, and if the indented style is being
+        used.  INDENT-F.  */
+      if (line_prefix != NULL)
+        fputs (line_prefix, fp);
+      if (first_line)
+       {
+         fputs (name, fp);
+         putc (indent ? '\t' : ' ', fp);
+         first_line = 0;
+       }
+      else
+       {
+         if (indent)
+           putc ('\t', fp);
+       }
+
+      /* Print the portion itself, with linebreaks where necessary.  */
+      putc ('"', fp);
+      for (i = 0; i < portion_len; i++)
+       {
+         if (linebreaks[i] == UC_BREAK_POSSIBLE)
+           {
+             fputs ("\"\n", fp);
+             /* INDENT-S.  */
+             if (line_prefix != NULL)
+               fputs (line_prefix, fp);
+             if (indent)
+               putc ('\t', fp);
+             putc ('"', fp);
+           }
+         putc (portion[i], fp);
+       }
+      fputs ("\"\n", fp);
+
+      free (linebreaks);
+      free (portion);
+
+      s = es;
+    }
+  while (*s);
+}
+
+
+static void
+print_blank_line (fp)
+     FILE *fp;
+{
+  if (uniforum)
+    fputs ("#\n", fp);
+  else
+    putc ('\n', fp);
+}
+
+
+static void
+message_print (mp, fp, domain, charset, blank_line, debug)
+     const message_ty *mp;
+     FILE *fp;
+     const char *domain;
+     const char *charset;
+     int blank_line;
+     int debug;
+{
+  message_variant_ty *mvp;
+  int first;
+  size_t j;
+
+  /* Find the relevant message variant.  If there isn't one, remember
+     this using a NULL pointer.  */
+  mvp = NULL;
+  first = 0;
+
+  for (j = 0; j < mp->variant_count; ++j)
+    {
+      if (strcmp (domain, mp->variant[j].domain) == 0)
+       {
+         mvp = &mp->variant[j];
+         first = (j == 0);
+         break;
+       }
+    }
+
+  /* Separate messages with a blank line.  Uniforum doesn't like blank
+     lines, so use an empty comment (unless there already is one).  */
+  if (blank_line && (!uniforum
+                    || mp->comment == NULL
+                    || mp->comment->nitems == 0
+                    || mp->comment->item[0][0] != '\0'))
+    print_blank_line (fp);
+
+  /* The first variant of a message will have the comments attached to
+     it.  We can't attach them to all variants in case we are read in
+     again, multiplying the number of comment lines.  Usually there is
+     only one variant.  */
+  if (first)
+    {
+      if (mp->comment != NULL)
+       for (j = 0; j < mp->comment->nitems; ++j)
+         {
+           const char *s = mp->comment->item[j];
+           do
+             {
+               const char *e;
+               putc ('#', fp);
+               if (*s != '\0' && *s != ' ')
+                 putc (' ', fp);
+               e = strchr (s, '\n');
+               if (e == NULL)
+                 {
+                   fputs (s, fp);
+                   s = NULL;
+                 }
+               else
+                 {
+                   fwrite (s, 1, e - s, fp);
+                   s = e + 1;
+                 }
+               putc ('\n', fp);
+             }
+           while (s != NULL);
+         }
+
+      if (mp->comment_dot != NULL)
+       for (j = 0; j < mp->comment_dot->nitems; ++j)
+         {
+           const char *s = mp->comment_dot->item[j];
+           putc ('#', fp);
+           putc ('.', fp);
+           if (*s != '\0' && *s != ' ')
+             putc (' ', fp);
+           fputs (s, fp);
+           putc ('\n', fp);
+         }
+    }
+
+  /* Print the file position comments for every domain.  This will
+     help a human who is trying to navigate the sources.  There is no
+     problem of getting repeat positions, because duplicates are
+     checked for.  */
+  if (mp->filepos_count != 0)
+    {
+      if (uniforum)
+       for (j = 0; j < mp->filepos_count; ++j)
+         {
+           lex_pos_ty *pp = &mp->filepos[j];
+           char *cp = pp->file_name;
+           while (cp[0] == '.' && cp[1] == '/')
+             cp += 2;
+           /* There are two Sun formats to choose from: SunOS and
+              Solaris.  Use the Solaris form here.  */
+           fprintf (fp, "# File: %s, line: %ld\n",
+                    cp, (long) pp->line_number);
+         }
+      else
+       {
+         size_t column;
+
+         fputs ("#:", fp);
+         column = 2;
+         for (j = 0; j < mp->filepos_count; ++j)
+           {
+             lex_pos_ty *pp;
+             char buffer[20];
+             char *cp;
+             size_t len;
+
+             pp = &mp->filepos[j];
+             cp = pp->file_name;
+             while (cp[0] == '.' && cp[1] == '/')
+               cp += 2;
+             sprintf (buffer, "%ld", (long) pp->line_number);
+             len = strlen (cp) + strlen (buffer) + 2;
+             if (column > 2 && column + len >= page_width)
+               {
+                 fputs ("\n#:", fp);
+                 column = 2;
+               }
+             fprintf (fp, " %s:%s", cp, buffer);
+             column += len;
+           }
+         putc ('\n', fp);
+       }
+    }
+
+  /* Print flag information in special comment.  */
+  if (first && ((mp->is_fuzzy && mvp != NULL && mvp->msgstr[0] != '\0')
+               || significant_c_format_p (mp->is_c_format)
+               || mp->do_wrap == no))
+    {
+      int first_flag = 1;
+
+      putc ('#', fp);
+      putc (',', fp);
+
+      /* We don't print the fuzzy flag if the msgstr is empty.  This
+        might be introduced by the user but we want to normalize the
+        output.  */
+      if (mp->is_fuzzy && mvp != NULL && mvp->msgstr[0] != '\0')
+       {
+         fputs (" fuzzy", fp);
+         first_flag = 0;
+       }
+
+      if (significant_c_format_p (mp->is_c_format))
+       {
+         if (!first_flag)
+           putc (',', fp);
+
+         fputs (make_c_format_description_string (mp->is_c_format, debug),
+                fp);
+         first_flag = 0;
+       }
+
+      if (mp->do_wrap == no)
+       {
+         if (!first_flag)
+           putc (',', fp);
+
+         fputs (make_c_width_description_string (mp->do_wrap), fp);
+         first_flag = 0;
+       }
+
+      putc ('\n', fp);
+    }
+
+  /* Print each of the message components.  Wrap them nicely so they
+     are as readable as possible.  If there is no recorded msgstr for
+     this domain, emit an empty string.  */
+  wrap (fp, NULL, "msgid", mp->msgid, mp->do_wrap, charset);
+  if (mp->msgid_plural != NULL)
+    wrap (fp, NULL, "msgid_plural", mp->msgid_plural, mp->do_wrap, charset);
+
+  if (mp->msgid_plural == NULL)
+    wrap (fp, NULL, "msgstr", mvp ? mvp->msgstr : "", mp->do_wrap, charset);
+  else
+    {
+      char prefix_buf[20];
+      unsigned int i;
+
+      if (mvp)
+       {
+         const char *p;
+
+         for (p = mvp->msgstr, i = 0;
+              p < mvp->msgstr + mvp->msgstr_len;
+              p += strlen (p) + 1, i++)
+           {
+             sprintf (prefix_buf, "msgstr[%u]", i);
+             wrap (fp, NULL, prefix_buf, p, mp->do_wrap, charset);
+           }
+       }
+      else
+       {
+         for (i = 0; i < 2; i++)
+           {
+             sprintf (prefix_buf, "msgstr[%u]", i);
+             wrap (fp, NULL, prefix_buf, "", mp->do_wrap, charset);
+           }
+       }
+    }
+}
+
+
+static void
+message_print_obsolete (mp, fp, domain, charset, blank_line)
+     const message_ty *mp;
+     FILE *fp;
+     const char *domain;
+     const char *charset;
+     int blank_line;
+{
+  message_variant_ty *mvp;
+  size_t j;
+
+  /* Find the relevant message variant.  If there isn't one, remember
+     this using a NULL pointer.  */
+  mvp = NULL;
+
+  for (j = 0; j < mp->variant_count; ++j)
+    {
+      if (strcmp (domain, mp->variant[j].domain) == 0)
+       {
+         mvp = &mp->variant[j];
+         break;
+       }
+    }
+
+  /* If no msgstr is found or it is the empty string we print nothing.  */
+  if (mvp == NULL || mvp->msgstr[0] == '\0')
+    return;
+
+  /* Separate messages with a blank line.  Uniforum doesn't like blank
+     lines, so use an empty comment (unless there already is one).  */
+  if (blank_line)
+    print_blank_line (fp);
+
+  /* Print translator comment if available.  */
+  if (mp->comment)
+    for (j = 0; j < mp->comment->nitems; ++j)
+      {
+       const char *s = mp->comment->item[j];
+       do
+         {
+           const char *e;
+           putc ('#', fp);
+           if (*s != '\0' && *s != ' ')
+             putc (' ', fp);
+           e = strchr (s, '\n');
+           if (e == NULL)
+             {
+               fputs (s, fp);
+               s = NULL;
+             }
+           else
+             {
+               fwrite (s, 1, e - s, fp);
+               s = e + 1;
+             }
+           putc ('\n', fp);
+         }
+       while (s != NULL);
+      }
+
+  /* Print flag information in special comment.  */
+  if (mp->is_fuzzy)
+    {
+      int first = 1;
+
+      putc ('#', fp);
+      putc (',', fp);
+
+      if (mp->is_fuzzy)
+       {
+         fputs (" fuzzy", fp);
+         first = 0;
+       }
+
+      putc ('\n', fp);
+    }
+
+  /* Print each of the message components.  Wrap them nicely so they
+     are as readable as possible.  */
+  wrap (fp, "#~ ", "msgid", mp->msgid, mp->do_wrap, charset);
+  if (mp->msgid_plural != NULL)
+    wrap (fp, "#~ ", "msgid_plural", mp->msgid_plural, mp->do_wrap, charset);
+
+  if (mp->msgid_plural == NULL)
+    wrap (fp, "#~ ", "msgstr", mvp->msgstr, mp->do_wrap, charset);
+  else
+    {
+      char prefix_buf[20];
+      unsigned int i;
+      const char *p;
+
+      for (p = mvp->msgstr, i = 0;
+          p < mvp->msgstr + mvp->msgstr_len;
+          p += strlen (p) + 1, i++)
+       {
+         sprintf (prefix_buf, "msgstr[%u]", i);
+         wrap (fp, "#~ ", prefix_buf, p, mp->do_wrap, charset);
+       }
+    }
+}
+
+
+void
+message_list_print (mlp, filename, force, debug)
+     message_list_ty *mlp;
+     const char *filename;
+     int force;
+     int debug;
+{
+  FILE *fp;
+  size_t i, j, k;
+  string_list_ty *dl;
+  int blank_line;
+
+  /* We will not write anything if we have no message or only the
+     header entry.  */
+  if (force == 0
+      && (mlp->nitems == 0
+         || (mlp->nitems == 1 && *mlp->item[0]->msgid == '\0')))
+    return;
+
+  /* Build the list of domains.  */
+  dl = string_list_alloc ();
+  for (j = 0; j < mlp->nitems; ++j)
+    {
+      message_ty *mp = mlp->item[j];
+      for (k = 0; k < mp->variant_count; ++k)
+       string_list_append_unique (dl, mp->variant[k].domain);
+    }
+
+  /* Open the output file.  */
+  if (filename != NULL && strcmp (filename, "-") != 0
+      && strcmp (filename, "/dev/stdout") != 0)
+    {
+      fp = fopen (filename, "w");
+      if (fp == NULL)
+       error (EXIT_FAILURE, errno, _("cannot create output file \"%s\""),
+              filename);
+    }
+  else
+    {
+      fp = stdout;
+      /* xgettext:no-c-format */
+      filename = _("standard output");
+    }
+
+  /* Write out the messages for each domain.  */
+  blank_line = 0;
+  for (k = 0; k < dl->nitems; ++k)
+    {
+      const char *header;
+      char *charset;
+
+      /* If there is only one domain, and that domain is the default,
+        don't bother emitting the domain name, because it is the
+        default.  */
+      if (dl->nitems != 1 || strcmp (dl->item[0], MESSAGE_DOMAIN_DEFAULT) != 0)
+       {
+         if (blank_line)
+           print_blank_line (fp);
+         fprintf (fp, "domain \"%s\"\n", dl->item[k]);
+         blank_line = 1;
+       }
+
+      /* Search the header entry.  */
+      header = NULL;
+      for (j = 0; j < mlp->nitems; ++j)
+       if (*mlp->item[j]->msgid == '\0' && mlp->item[j]->obsolete == 0)
+         {
+           for (i = 0; i < mlp->item[j]->variant_count; i++)
+             if (strcmp (dl->item[k], mlp->item[j]->variant[i].domain) == 0)
+               {
+                 header = mlp->item[j]->variant[i].msgstr;
+                 break;
+               }
+           break;
+         }
+
+      /* Extract the charset name.  */
+      charset = "ASCII";
+      if (header != NULL)
+       {
+         const char *charsetstr = strstr (header, "charset=");
+
+         if (charsetstr != NULL)
+           {
+             size_t len;
+
+             charsetstr += strlen ("charset=");
+             len = strcspn (charsetstr, " \t\n");
+             charset = (char *) alloca (len + 1);
+             memcpy (charset, charsetstr, len);
+             charset[len] = '\0';
+           }
+       }
+
+      /* Write out each of the messages for this domain.  */
+      for (j = 0; j < mlp->nitems; ++j)
+       if (mlp->item[j]->obsolete == 0)
+         {
+           message_print (mlp->item[j], fp, dl->item[k], charset,
+                          blank_line, debug);
+           blank_line = 1;
+         }
+
+      /* Write out each of the obsolete messages for this domain.  */
+      for (j = 0; j < mlp->nitems; ++j)
+       if (mlp->item[j]->obsolete != 0)
+         {
+           message_print_obsolete (mlp->item[j], fp, dl->item[k], charset,
+                                   blank_line);
+           blank_line = 1;
+         }
+    }
+  string_list_free (dl);
+
+  /* Make sure nothing went wrong.  */
+  if (fflush (fp))
+    error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"),
+          filename);
+  fclose (fp);
+}
+
+
+static int
+msgid_cmp (va, vb)
+     const void *va;
+     const void *vb;
+{
+  const message_ty *a = *(const message_ty **) va;
+  const message_ty *b = *(const message_ty **) vb;
+  /* Because msgids normally contain only ASCII characters, it is OK to
+     sort them as if we were in the C locale. And strcoll() in the C locale
+     is the same as strcmp().  */
+  return strcmp (a->msgid, b->msgid);
+}
+
+
+void
+message_list_sort_by_msgid (mlp)
+     message_list_ty *mlp;
+{
+  qsort (mlp->item, mlp->nitems, sizeof (mlp->item[0]), msgid_cmp);
+}
+
+
+static int
+filepos_cmp (va, vb)
+     const void *va;
+     const void *vb;
+{
+  const message_ty *a = *(const message_ty **) va;
+  const message_ty *b = *(const message_ty **) vb;
+  int cmp;
+
+  /* No filepos is smaller than any other filepos.  */
+  if (a->filepos_count == 0)
+    {
+      if (b->filepos_count != 0)
+       return -1;
+    }
+  if (b->filepos_count == 0)
+    return 1;
+
+  /* Compare on the file names...  */
+  cmp = strcmp (a->filepos[0].file_name, b->filepos[0].file_name);
+  if (cmp != 0)
+    return cmp;
+
+  /* If they are equal, compare on the line numbers...  */
+  cmp = a->filepos[0].line_number - b->filepos[0].line_number;
+  if (cmp != 0)
+    return cmp;
+
+  /* If they are equal, compare on the msgid strings.  */
+  /* Because msgids normally contain only ASCII characters, it is OK to
+     sort them as if we were in the C locale. And strcoll() in the C locale
+     is the same as strcmp().  */
+  return strcmp (a->msgid, b->msgid);
+}
+
+
+void
+message_list_sort_by_filepos (mlp)
+    message_list_ty *mlp;
+{
+  qsort (mlp->item, mlp->nitems, sizeof (mlp->item[0]), filepos_cmp);
+}
diff --git a/src/write-po.h b/src/write-po.h
new file mode 100644 (file)
index 0000000..e71f107
--- /dev/null
@@ -0,0 +1,35 @@
+/* GNU gettext - internationalization aids
+   Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+
+   This file was written by Peter Miller <millerp@canb.auug.org.au>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free SoftwareFoundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _WRITE_PO_H
+#define _WRITE_PO_H
+
+#include "message.h"
+
+extern void message_page_width_set PARAMS ((size_t width));
+
+extern void message_print_style_indent PARAMS ((void));
+extern void message_print_style_uniforum PARAMS ((void));
+extern void message_print_style_escape PARAMS ((int));
+
+extern void message_list_print PARAMS ((message_list_ty *, const char *, int, int));
+extern void message_list_sort_by_msgid PARAMS ((message_list_ty *));
+extern void message_list_sort_by_filepos PARAMS ((message_list_ty *));
+
+#endif /* _WRITE_PO_H */
index 611100d39d0e2ebf59186a3596e72f8366f92a7f..16ea418bc19507563a7b66cec40dc041eebbb6ed 100644 (file)
@@ -46,6 +46,7 @@ extern int errno;
 #include "system.h"
 #include "po.h"
 #include "message.h"
+#include "write-po.h"
 #include "xget-lex.h"
 #include "printf-parse.h"