From: Bruno Haible Date: Tue, 6 Mar 2001 15:09:27 +0000 (+0000) Subject: Fix the --width option to not split multibyte characters, and respect the X-Git-Tag: v0.10.36~138 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8f746ca065b2d9c1d77012cf0d7fbc26542da620;p=thirdparty%2Fgettext.git Fix the --width option to not split multibyte characters, and respect the wcwidth of the characters. --- diff --git a/lib/.cvsignore b/lib/.cvsignore new file mode 100644 index 000000000..55e86d867 --- /dev/null +++ b/lib/.cvsignore @@ -0,0 +1 @@ +lbrkprop.txt diff --git a/lib/3level.h b/lib/3level.h new file mode 100644 index 000000000..e9f08ef94 --- /dev/null +++ b/lib/3level.h @@ -0,0 +1,322 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Bruno Haible , 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 diff --git a/lib/ChangeLog b/lib/ChangeLog index c61c22549..973a85eb6 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,35 @@ +2001-03-03 Bruno Haible + + * 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 * printf.h (PARAMS): GNU C always supports prototypes. diff --git a/lib/Makefile.am b/lib/Makefile.am index 3cab0b02f..9059a5aad 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 index 000000000..476c2168a --- /dev/null +++ b/lib/c-ctype.c @@ -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 index 000000000..919710262 --- /dev/null +++ b/lib/c-ctype.h @@ -0,0 +1,229 @@ +/* Character handling in C locale. + + These functions work like the corresponding functions in , + except that they have the C (POSIX) locale hardwired, whereas the + 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 index 000000000..bf21d99e2 --- /dev/null +++ b/lib/config.charset @@ -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 index 000000000..52a28e107 --- /dev/null +++ b/lib/gen-lbrkprop.c @@ -0,0 +1,981 @@ +/* Generate a Unicode conforming Line Break Properties tables from a + UnicodeData file. + Written by Bruno Haible , 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 +#include +#include +#include +#include +#include + +/* 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 index 000000000..1a9a220ca --- /dev/null +++ b/lib/lbrkprop.h @@ -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 index 000000000..bd15abf18 --- /dev/null +++ b/lib/linebreak.c @@ -0,0 +1,1956 @@ +/* linebreak.c - line breaking of Unicode strings + Copyright (C) 2001 Free Software Foundation, Inc. + Written by Bruno Haible , 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 +#endif + +#include +#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 + +/* 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 +#include + +/* 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 +#include + +/* 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 index 000000000..d0367eff1 --- /dev/null +++ b/lib/linebreak.h @@ -0,0 +1,82 @@ +/* linebreak.h - line breaking of Unicode strings + Copyright (C) 2001 Free Software Foundation, Inc. + Written by Bruno Haible , 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 + + +/* 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 index 000000000..12214b79b --- /dev/null +++ b/lib/localcharset.c @@ -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 . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if HAVE_STDDEF_H +# include +#endif + +#include +#if HAVE_STRING_H +# include +#else +# include +#endif +#if HAVE_STDLIB_H +# include +#endif + +#if defined _WIN32 || defined __WIN32__ +# undef WIN32 /* avoid warning on mingw32 */ +# define WIN32 +#endif + +#ifndef WIN32 +# if HAVE_LANGINFO_CODESET +# include +# else +# if HAVE_SETLOCALE +# include +# endif +# endif +#else /* WIN32 */ +# define WIN32_LEAN_AND_MEAN +# include +#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 index 000000000..167374e3c --- /dev/null +++ b/lib/ref-add.sin @@ -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 . +# +/^# 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 index 000000000..613cf37f3 --- /dev/null +++ b/lib/ref-del.sin @@ -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 . +# +/^# Packages using this file: / { + s/# Packages using this file:// + s/ @PACKAGE@ / / + s/^/# Packages using this file:/ +} diff --git a/src/ChangeLog b/src/ChangeLog index 7f4d64581..ca1a4cf94 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,45 @@ +2001-03-03 Bruno Haible + + * 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 + + * msgcmp.c (compare): Internationalize error message. + 2001-02-10 Bruno Haible * msgunfmt.c (main): Accept -e and -E options. diff --git a/src/FILES b/src/FILES index cb8d47ce6..0dd327f03 100644 --- 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 diff --git a/src/Makefile.am b/src/Makefile.am index 4db82f169..eab2f5360 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/message.c b/src/message.c index 4d527422b..b819f825a 100644 --- a/src/message.c +++ b/src/message.c @@ -21,58 +21,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ # include #endif -#include -#include -#include - -#ifdef HAVE_LIMITS_H -# include -#endif - -#include #include +#include #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; -} diff --git a/src/message.h b/src/message.h index 95e6e3db9..af5da2702 100644 --- a/src/message.h +++ b/src/message.h @@ -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 @@ -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; diff --git a/src/msgcomm.c b/src/msgcomm.c index f932ac7e4..7804a59ad 100644 --- a/src/msgcomm.c +++ b/src/msgcomm.c @@ -42,6 +42,7 @@ #include "getline.h" #include "libgettext.h" #include "message.h" +#include "write-po.h" #include "po.h" #include "system.h" diff --git a/src/msgmerge.c b/src/msgmerge.c index c70e6b464..b2be1cb8f 100644 --- a/src/msgmerge.c +++ b/src/msgmerge.c @@ -30,6 +30,7 @@ #include "dir-list.h" #include "error.h" #include "message.h" +#include "write-po.h" #include #include "libgettext.h" #include "po.h" diff --git a/src/msgunfmt.c b/src/msgunfmt.c index 89ce45033..90f91cda7 100644 --- a/src/msgunfmt.c +++ b/src/msgunfmt.c @@ -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 index 000000000..28eb1fbec --- /dev/null +++ b/src/write-po.c @@ -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 + +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 +#endif + +#include +#include +#include +#include + +#ifdef HAVE_LIMITS_H +# include +#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 index 000000000..e71f107b9 --- /dev/null +++ b/src/write-po.h @@ -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 + + 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 */ diff --git a/src/xgettext.c b/src/xgettext.c index 611100d39..16ea418bc 100644 --- a/src/xgettext.c +++ b/src/xgettext.c @@ -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"