summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--Rules.mak5
-rw-r--r--extra/locale/.cvsignore14
-rw-r--r--extra/locale/LOCALES288
-rw-r--r--extra/locale/README86
-rw-r--r--extra/locale/charmaps/ASCII.pairs128
-rw-r--r--extra/locale/charmaps/CP1251.pairs255
-rw-r--r--extra/locale/charmaps/ISO-8859-1.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-10.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-13.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-14.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-15.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-16.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-2.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-3.pairs249
-rw-r--r--extra/locale/charmaps/ISO-8859-4.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-5.pairs256
-rw-r--r--extra/locale/charmaps/ISO-8859-6.pairs211
-rw-r--r--extra/locale/charmaps/ISO-8859-7.pairs250
-rw-r--r--extra/locale/charmaps/ISO-8859-8.pairs220
-rw-r--r--extra/locale/charmaps/ISO-8859-9.pairs256
-rw-r--r--extra/locale/charmaps/KOI8-R.pairs256
-rw-r--r--extra/locale/charmaps/KOI8-U.pairs256
-rw-r--r--extra/locale/charmaps/TIS-620.pairs215
-rw-r--r--extra/locale/gen_collate_from_glibc.c207
-rw-r--r--extra/locale/gen_ctype_from_glibc.c277
-rw-r--r--extra/locale/gen_locale.c1254
-rw-r--r--extra/locale/gen_mmap.c237
-rw-r--r--extra/locale/gen_wc8bit.c729
-rw-r--r--extra/locale/gen_wctype.c833
-rw-r--r--extra/locale/lmmtolso.c72
-rw-r--r--extra/locale/locale_mmap.h89
-rw-r--r--include/ctype.h176
-rw-r--r--include/inttypes.h4
-rw-r--r--include/langinfo.h36
-rw-r--r--include/libgen.h2
-rw-r--r--include/locale.h120
-rw-r--r--include/stdint.h12
-rw-r--r--include/stdlib.h12
-rw-r--r--libc/misc/Makefile3
-rw-r--r--libc/misc/ctype/Makefile5
-rw-r--r--libc/misc/ctype/ctype.c486
-rw-r--r--libc/misc/ctype/ctype_C.c517
-rw-r--r--libc/misc/internals/__uClibc_main.c12
-rw-r--r--libc/misc/locale/Makefile15
-rw-r--r--libc/misc/locale/_locale.h22
-rw-r--r--libc/misc/locale/locale.c719
-rw-r--r--libc/misc/locale/localeconv.c52
-rw-r--r--libc/misc/wctype/Makefile47
-rw-r--r--libc/misc/wctype/wctype.c480
-rw-r--r--libc/stdlib/Makefile5
-rw-r--r--libc/stdlib/stdlib.c181
-rw-r--r--libc/string/Makefile55
-rw-r--r--libc/string/wstring.c1273
-rw-r--r--libc/sysdeps/linux/common/bits/.cvsignore1
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_ctype.h250
-rw-r--r--libc/sysdeps/linux/common/bits/uClibc_locale.h261
57 files changed, 11677 insertions, 1766 deletions
diff --git a/Makefile b/Makefile
index ef10162d0..ca5938839 100644
--- a/Makefile
+++ b/Makefile
@@ -174,10 +174,14 @@ uClibc_config: Makefile Config
fi
@if [ "$(HAS_LOCALE)" = "true" ] ; then \
echo "#define __UCLIBC_HAS_LOCALE__ 1" >> include/bits/uClibc_config.h ; \
- echo "#define __UCLIBC_LOCALE_DIR \""$(LOCALE_DIR)"\"" >> include/bits/uClibc_config.h ; \
else \
echo "#undef __UCLIBC_HAS_LOCALE__" >> include/bits/uClibc_config.h ; \
fi
+ @if [ "$(HAS_WCHAR)" = "true" ] ; then \
+ echo "#define __UCLIBC_HAS_WCHAR__ 1" >> include/bits/uClibc_config.h ; \
+ else \
+ echo "#undef __UCLIBC_HAS_WCHAR__" >> include/bits/uClibc_config.h ; \
+ fi
@if [ "$(HAVE_ELF)" = "false" ] ; then \
echo "#undef HAVE_ELF" >> include/bits/uClibc_config.h ; \
else \
diff --git a/Rules.mak b/Rules.mak
index 79f2628ee..ccf8dfeee 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -117,6 +117,11 @@ ifeq ($(strip $(INCLUDE_THREADS)),true)
CFLAGS += -D_LIBC_REENTRANT
endif
+# Locale support is required for wide char support.
+ifneq ($(strip $(HAS_LOCALE)),true)
+ HAS_WCHAR:=false
+endif
+
# TARGET_PREFIX is the directory under which which the uClibc runtime
# environment will be installed and used on the target system. The
# result will look something like the following:
diff --git a/extra/locale/.cvsignore b/extra/locale/.cvsignore
new file mode 100644
index 000000000..e020fa9e3
--- /dev/null
+++ b/extra/locale/.cvsignore
@@ -0,0 +1,14 @@
+lmmtolso
+gen_wctype
+wctables.h
+gen_wc8bit
+c8tables.h
+gen_locale
+locale_tables.h
+locale.mmap
+gen_mmap
+lt_defines.h
+locale_data.c
+uClibc_locale_data.h
+codesets.txt
+locales.txt
diff --git a/extra/locale/LOCALES b/extra/locale/LOCALES
new file mode 100644
index 000000000..739ecb95a
--- /dev/null
+++ b/extra/locale/LOCALES
@@ -0,0 +1,288 @@
+# First some @modifier mappings. Internally, the modifier is signaled by
+# replacing '_' in the locale name with a unique identifying character.
+# For example, internally we map "ca_ES@euro" to "caeES". This allows for
+# smaller code and easier processing of locale names.
+
+@euro e
+@cyrillic c
+
+#---------------------------------------------------------------------------
+# Next, set to {y}es to enable and {n}o to disable the UTF-8 and the 8-bit
+# codeset locales. Of course, you must have built the c8tables.h and
+# the wctables.h files appropriately.
+
+
+UTF-8 yes
+8-BIT yes
+
+#---------------------------------------------------------------------------
+# Now the locales
+
+af_ZA ISO-8859-1
+ar_AE ISO-8859-6
+ar_BH ISO-8859-6
+ar_DZ ISO-8859-6
+ar_EG ISO-8859-6
+ar_IN UTF-8
+ar_IQ ISO-8859-6
+ar_JO ISO-8859-6
+ar_KW ISO-8859-6
+ar_LB ISO-8859-6
+ar_LY ISO-8859-6
+ar_MA ISO-8859-6
+ar_OM ISO-8859-6
+ar_QA ISO-8859-6
+ar_SA ISO-8859-6
+ar_SD ISO-8859-6
+ar_SY ISO-8859-6
+ar_TN ISO-8859-6
+ar_YE ISO-8859-6
+be_BY CP1251
+bg_BG CP1251
+ca_ES ISO-8859-1
+ca_ES@euro ISO-8859-15
+cs_CZ ISO-8859-2
+da_DK ISO-8859-1
+de_AT ISO-8859-1
+de_AT@euro ISO-8859-15
+de_BE ISO-8859-1
+de_BE@euro ISO-8859-15
+de_CH ISO-8859-1
+de_DE ISO-8859-1
+de_DE@euro ISO-8859-15
+de_LU ISO-8859-1
+de_LU@euro ISO-8859-15
+el_GR ISO-8859-7
+en_AU ISO-8859-1
+en_BW ISO-8859-1
+en_CA ISO-8859-1
+en_DK ISO-8859-1
+en_GB ISO-8859-1
+en_HK ISO-8859-1
+en_IE ISO-8859-1
+en_IE@euro ISO-8859-15
+en_IN UTF-8
+en_NZ ISO-8859-1
+en_PH ISO-8859-1
+en_SG ISO-8859-1
+en_US ISO-8859-1
+en_ZA ISO-8859-1
+en_ZW ISO-8859-1
+es_AR ISO-8859-1
+es_BO ISO-8859-1
+es_CL ISO-8859-1
+es_CO ISO-8859-1
+es_CR ISO-8859-1
+es_DO ISO-8859-1
+es_EC ISO-8859-1
+es_ES ISO-8859-1
+es_ES@euro ISO-8859-15
+es_GT ISO-8859-1
+es_HN ISO-8859-1
+es_MX ISO-8859-1
+es_NI ISO-8859-1
+es_PA ISO-8859-1
+es_PE ISO-8859-1
+es_PR ISO-8859-1
+es_PY ISO-8859-1
+es_SV ISO-8859-1
+es_US ISO-8859-1
+es_UY ISO-8859-1
+es_VE ISO-8859-1
+et_EE ISO-8859-1
+eu_ES ISO-8859-1
+eu_ES@euro ISO-8859-15
+fa_IR UTF-8
+fi_FI ISO-8859-1
+fi_FI@euro ISO-8859-15
+fo_FO ISO-8859-1
+fr_BE ISO-8859-1
+fr_BE@euro ISO-8859-15
+fr_CA ISO-8859-1
+fr_CH ISO-8859-1
+fr_FR ISO-8859-1
+fr_FR@euro ISO-8859-15
+fr_LU ISO-8859-1
+fr_LU@euro ISO-8859-15
+ga_IE ISO-8859-1
+ga_IE@euro ISO-8859-15
+gl_ES ISO-8859-1
+gl_ES@euro ISO-8859-15
+gv_GB ISO-8859-1
+he_IL ISO-8859-8
+hi_IN UTF-8
+hr_HR ISO-8859-2
+hu_HU ISO-8859-2
+id_ID ISO-8859-1
+is_IS ISO-8859-1
+it_CH ISO-8859-1
+it_IT ISO-8859-1
+it_IT@euro ISO-8859-15
+iw_IL ISO-8859-8
+kl_GL ISO-8859-1
+ko_KR.UTF-8 UTF-8
+kw_GB ISO-8859-1
+lt_LT ISO-8859-13
+lv_LV ISO-8859-13
+mk_MK ISO-8859-5
+mr_IN UTF-8
+ms_MY ISO-8859-1
+mt_MT ISO-8859-3
+nl_BE ISO-8859-1
+nl_BE@euro ISO-8859-15
+nl_NL ISO-8859-1
+nl_NL@euro ISO-8859-15
+nn_NO ISO-8859-1
+no_NO ISO-8859-1
+pl_PL ISO-8859-2
+pt_BR ISO-8859-1
+pt_PT ISO-8859-1
+pt_PT@euro ISO-8859-15
+ro_RO ISO-8859-2
+ru_RU ISO-8859-5
+ru_RU.KOI8-R KOI8-R
+ru_UA KOI8-U
+sk_SK ISO-8859-2
+sl_SI ISO-8859-2
+sq_AL ISO-8859-1
+sr_YU ISO-8859-2
+sr_YU@cyrillic ISO-8859-5
+sv_FI ISO-8859-1
+sv_FI@euro ISO-8859-15
+sv_SE ISO-8859-1
+ta_IN UTF-8
+te_IN UTF-8
+th_TH TIS-620
+tr_TR ISO-8859-9
+uk_UA KOI8-U
+vi_VN UTF-8
+ar_AE.UTF-8 UTF-8
+ar_BH.UTF-8 UTF-8
+ar_DZ.UTF-8 UTF-8
+ar_EG.UTF-8 UTF-8
+ar_IQ.UTF-8 UTF-8
+ar_JO.UTF-8 UTF-8
+ar_KW.UTF-8 UTF-8
+ar_LB.UTF-8 UTF-8
+ar_LY.UTF-8 UTF-8
+ar_MA.UTF-8 UTF-8
+ar_OM.UTF-8 UTF-8
+ar_QA.UTF-8 UTF-8
+ar_SA.UTF-8 UTF-8
+ar_SD.UTF-8 UTF-8
+ar_SY.UTF-8 UTF-8
+ar_TN.UTF-8 UTF-8
+ar_YE.UTF-8 UTF-8
+be_BY.UTF-8 UTF-8
+bg_BG.UTF-8 UTF-8
+ca_ES.UTF-8 UTF-8
+ca_ES.UTF-8@euro UTF-8
+cs_CZ.UTF-8 UTF-8
+da_DK.UTF-8 UTF-8
+de_AT.UTF-8 UTF-8
+de_AT.UTF-8@euro UTF-8
+de_BE.UTF-8 UTF-8
+de_BE.UTF-8@euro UTF-8
+de_CH.UTF-8 UTF-8
+de_DE.UTF-8 UTF-8
+de_DE.UTF-8@euro UTF-8
+de_LU.UTF-8 UTF-8
+de_LU.UTF-8@euro UTF-8
+el_GR.UTF-8 UTF-8
+en_AU.UTF-8 UTF-8
+en_BW.UTF-8 UTF-8
+en_CA.UTF-8 UTF-8
+en_DK.UTF-8 UTF-8
+en_GB.UTF-8 UTF-8
+en_HK.UTF-8 UTF-8
+en_IE.UTF-8 UTF-8
+en_IE.UTF-8@euro UTF-8
+en_NZ.UTF-8 UTF-8
+en_PH.UTF-8 UTF-8
+en_SG.UTF-8 UTF-8
+en_US.UTF-8 UTF-8
+en_ZA.UTF-8 UTF-8
+en_ZW.UTF-8 UTF-8
+es_AR.UTF-8 UTF-8
+es_BO.UTF-8 UTF-8
+es_CL.UTF-8 UTF-8
+es_CO.UTF-8 UTF-8
+es_CR.UTF-8 UTF-8
+es_DO.UTF-8 UTF-8
+es_EC.UTF-8 UTF-8
+es_ES.UTF-8 UTF-8
+es_ES.UTF-8@euro UTF-8
+es_GT.UTF-8 UTF-8
+es_HN.UTF-8 UTF-8
+es_MX.UTF-8 UTF-8
+es_NI.UTF-8 UTF-8
+es_PA.UTF-8 UTF-8
+es_PE.UTF-8 UTF-8
+es_PR.UTF-8 UTF-8
+es_PY.UTF-8 UTF-8
+es_SV.UTF-8 UTF-8
+es_US.UTF-8 UTF-8
+es_UY.UTF-8 UTF-8
+es_VE.UTF-8 UTF-8
+et_EE.UTF-8 UTF-8
+eu_ES.UTF-8 UTF-8
+eu_ES.UTF-8@euro UTF-8
+fi_FI.UTF-8 UTF-8
+fi_FI.UTF-8@euro UTF-8
+fo_FO.UTF-8 UTF-8
+fr_BE.UTF-8 UTF-8
+fr_BE.UTF-8@euro UTF-8
+fr_CA.UTF-8 UTF-8
+fr_CH.UTF-8 UTF-8
+fr_FR.UTF-8 UTF-8
+fr_FR.UTF-8@euro UTF-8
+fr_LU.UTF-8 UTF-8
+fr_LU.UTF-8@euro UTF-8
+ga_IE.UTF-8 UTF-8
+ga_IE.UTF-8@euro UTF-8
+gl_ES.UTF-8 UTF-8
+gl_ES.UTF-8@euro UTF-8
+gv_GB.UTF-8 UTF-8
+he_IL.UTF-8 UTF-8
+hr_HR.UTF-8 UTF-8
+hu_HU.UTF-8 UTF-8
+id_ID.UTF-8 UTF-8
+is_IS.UTF-8 UTF-8
+it_CH.UTF-8 UTF-8
+it_IT.UTF-8 UTF-8
+it_IT.UTF-8@euro UTF-8
+iw_IL.UTF-8 UTF-8
+kl_GL.UTF-8 UTF-8
+kw_GB.UTF-8 UTF-8
+lt_LT.UTF-8 UTF-8
+lv_LV.UTF-8 UTF-8
+mk_MK.UTF-8 UTF-8
+ms_MY.UTF-8 UTF-8
+mt_MT.UTF-8 UTF-8
+nl_BE.UTF-8 UTF-8
+nl_BE.UTF-8@euro UTF-8
+nl_NL.UTF-8 UTF-8
+nl_NL.UTF-8@euro UTF-8
+nn_NO.UTF-8 UTF-8
+no_NO.UTF-8 UTF-8
+pl_PL.UTF-8 UTF-8
+pt_BR.UTF-8 UTF-8
+pt_PT.UTF-8 UTF-8
+pt_PT.UTF-8@euro UTF-8
+ro_RO.UTF-8 UTF-8
+ru_RU.UTF-8 UTF-8
+ru_UA.UTF-8 UTF-8
+sk_SK.UTF-8 UTF-8
+sl_SI.UTF-8 UTF-8
+sq_AL.UTF-8 UTF-8
+sr_YU.UTF-8 UTF-8
+sr_YU.UTF-8@cyrillic UTF-8
+sv_FI.UTF-8 UTF-8
+sv_FI.UTF-8@euro UTF-8
+sv_SE.UTF-8 UTF-8
+th_TH.UTF-8 UTF-8
+tr_TR.UTF-8 UTF-8
+uk_UA.UTF-8 UTF-8
+zh_CN.UTF-8 UTF-8
+zh_HK.UTF-8 UTF-8
+zh_TW.UTF-8 UTF-8
diff --git a/extra/locale/README b/extra/locale/README
index 6ac487c9a..63723f97f 100644
--- a/extra/locale/README
+++ b/extra/locale/README
@@ -1,29 +1,71 @@
+Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!!
+Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!!
-The programs gen_ctype_from_glibc.c and gen_collate_from_glibc.c
-will generate data files which can be
-used by uClibc ctype, strcoll and setlocale functions to support locales.
-From the comments:
+The programs in this directory are strictly cut-and-paste hack jobs to
+extract the data I needed from glibc's locale database. I'm ashamed to
+even let them into the light of day, and I consider them complete garbage.
-/*
- * Generator locale ctype tables
- * You must have already setuped locale for worked libc (libc5 or glibc)
- *
- * This programm scan /usr/share/locale directories and write
- * ./LOCALE/LC_CTYPE files for system with uclibc
- *
- * Written by Vladimir Oleynik <vodz@usa.net> 2001
- */
+However, they are currently necessary to build the data needed for the
+locale support I've implemented, so I'm forced to include them here.
+NOTE: While its possible to use this stuff for native != target arch,
+you'll have to either write a converter to account for endianess and
+struct padding issues, or run the mmap file generator on your target
+arch. But all these programs will be rewritten at some point.
-Sample usage to dump all the data files in a tmp directory:
+All that being said, LC_CTYPE support has been added and supports the
+ctype.h and wctype.h function. Also, LC_TIME, LC_MONETARY, LC_NUMERIC,
+and LC_MESSAGES are supported wrt SUSv3. localeconv() works in both
+real and stub locale modes. nl_langinfo() currently only works with
+real locales enabled. That will be fixed though. wc->mb unsupported
+char replacement and basic translit support is on the way as well.
+Finally, some basic 8-bit codeset LC_COLLATE support should be in place
+in the next week or two (similar to what was in the previous locale
+implementation).
-gcc gen_ctype_from_glibc.c -o gen_ctype_from_glibc
-gcc gen_collate_from_glibc.c -o gen_ctype_from_glibc
+Also, as one can probably guess, I'm working towards having the locale
+data accessed via a shared mmap. That will allow non-mmu platforms
+to use this without the current bloat.
-mkdir tmp
-cd tmp
-../gen_ctype_from_glibc -d /usr/share/locale -c
-../gen_collate_from_glibc
+Currently, the output of size for my locale_data.o file is
+ text data bss dec hex filename
+ 59072 4 0 59076 e6c4 extra/locale/locale_data.o
+which is for the C locale (automatic of course) + all codesets in
+charmaps/ and all 268 locales in LOCALES. I estimate that the
+translit support for those 8-bit codesets will add another 7-10k.
-Then just move the directory or directories you need (not the .c files)
-to the uClibc locale file directory you set in Config.
+One difference of note is that the special case upper/lower mappings
+in the turkish locale are currently not implemented. That will be
+fixed.
+
+Manuel
+
+Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!!
+Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!!
+
+
+1) In the toplevel dir, 'make headers uClibc_config' .
+
+2) Create a codesets.txt file in this dir listing the codesets you want
+ to support. The easiest way to do this is to edit the output of
+ 'find ./charmaps -name "*.pairs" > codesets.txt'.
+ NOTE: UTF-8 support is always included if you build with wide chars enabled.
+ NOTE: The files in charmaps/ were created from glibc's charmap files
+ with the awk script at the end of this file. You can add others
+ but only single byte codesets are supported.
+
+3) Create a locales.txt file to select the locales you want to support.
+ You can copy and edit the LOCALES file for example. Other locales could
+ added provided you've included the appropriate codesets in step 2.
+ NOTE: You have to have the approprite locales available for glibc!
+
+4) Run make here.
+
+5) Continue building uClibc from the toplevel dir.
+
+
+
+
+Script used to generate the charmaps/*.pairs files:
+
+cat $1 | awk 'BEGIN { i = 0 } ; { if ($1 == "CHARMAP") i=1 ; else if ($1 == "END") i=0 ; else if (i==1) { sub("/","0",$2) ; sub("<U","0x",$1) ; sub(">","",$1) ; print "{", $2, ",", $1, "}," } }'
diff --git a/extra/locale/charmaps/ASCII.pairs b/extra/locale/charmaps/ASCII.pairs
new file mode 100644
index 000000000..038314d1f
--- /dev/null
+++ b/extra/locale/charmaps/ASCII.pairs
@@ -0,0 +1,128 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
diff --git a/extra/locale/charmaps/CP1251.pairs b/extra/locale/charmaps/CP1251.pairs
new file mode 100644
index 000000000..a5a80d61d
--- /dev/null
+++ b/extra/locale/charmaps/CP1251.pairs
@@ -0,0 +1,255 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0402 },
+{ 0x81 , 0x0403 },
+{ 0x82 , 0x201A },
+{ 0x83 , 0x0453 },
+{ 0x84 , 0x201E },
+{ 0x85 , 0x2026 },
+{ 0x86 , 0x2020 },
+{ 0x87 , 0x2021 },
+{ 0x88 , 0x20AC },
+{ 0x89 , 0x2030 },
+{ 0x8a , 0x0409 },
+{ 0x8b , 0x2039 },
+{ 0x8c , 0x040A },
+{ 0x8d , 0x040C },
+{ 0x8e , 0x040B },
+{ 0x8f , 0x040F },
+{ 0x90 , 0x0452 },
+{ 0x91 , 0x2018 },
+{ 0x92 , 0x2019 },
+{ 0x93 , 0x201C },
+{ 0x94 , 0x201D },
+{ 0x95 , 0x2022 },
+{ 0x96 , 0x2013 },
+{ 0x97 , 0x2014 },
+{ 0x99 , 0x2122 },
+{ 0x9a , 0x0459 },
+{ 0x9b , 0x203A },
+{ 0x9c , 0x045A },
+{ 0x9d , 0x045C },
+{ 0x9e , 0x045B },
+{ 0x9f , 0x045F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x040E },
+{ 0xa2 , 0x045E },
+{ 0xa3 , 0x0408 },
+{ 0xa4 , 0x00A4 },
+{ 0xa5 , 0x0490 },
+{ 0xa6 , 0x00A6 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x0401 },
+{ 0xa9 , 0x00A9 },
+{ 0xaa , 0x0404 },
+{ 0xab , 0x00AB },
+{ 0xac , 0x00AC },
+{ 0xad , 0x00AD },
+{ 0xae , 0x00AE },
+{ 0xaf , 0x0407 },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x00B1 },
+{ 0xb2 , 0x0406 },
+{ 0xb3 , 0x0456 },
+{ 0xb4 , 0x0491 },
+{ 0xb5 , 0x00B5 },
+{ 0xb6 , 0x00B6 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x0451 },
+{ 0xb9 , 0x2116 },
+{ 0xba , 0x0454 },
+{ 0xbb , 0x00BB },
+{ 0xbc , 0x0458 },
+{ 0xbd , 0x0405 },
+{ 0xbe , 0x0455 },
+{ 0xbf , 0x0457 },
+{ 0xc0 , 0x0410 },
+{ 0xc1 , 0x0411 },
+{ 0xc2 , 0x0412 },
+{ 0xc3 , 0x0413 },
+{ 0xc4 , 0x0414 },
+{ 0xc5 , 0x0415 },
+{ 0xc6 , 0x0416 },
+{ 0xc7 , 0x0417 },
+{ 0xc8 , 0x0418 },
+{ 0xc9 , 0x0419 },
+{ 0xca , 0x041A },
+{ 0xcb , 0x041B },
+{ 0xcc , 0x041C },
+{ 0xcd , 0x041D },
+{ 0xce , 0x041E },
+{ 0xcf , 0x041F },
+{ 0xd0 , 0x0420 },
+{ 0xd1 , 0x0421 },
+{ 0xd2 , 0x0422 },
+{ 0xd3 , 0x0423 },
+{ 0xd4 , 0x0424 },
+{ 0xd5 , 0x0425 },
+{ 0xd6 , 0x0426 },
+{ 0xd7 , 0x0427 },
+{ 0xd8 , 0x0428 },
+{ 0xd9 , 0x0429 },
+{ 0xda , 0x042A },
+{ 0xdb , 0x042B },
+{ 0xdc , 0x042C },
+{ 0xdd , 0x042D },
+{ 0xde , 0x042E },
+{ 0xdf , 0x042F },
+{ 0xe0 , 0x0430 },
+{ 0xe1 , 0x0431 },
+{ 0xe2 , 0x0432 },
+{ 0xe3 , 0x0433 },
+{ 0xe4 , 0x0434 },
+{ 0xe5 , 0x0435 },
+{ 0xe6 , 0x0436 },
+{ 0xe7 , 0x0437 },
+{ 0xe8 , 0x0438 },
+{ 0xe9 , 0x0439 },
+{ 0xea , 0x043A },
+{ 0xeb , 0x043B },
+{ 0xec , 0x043C },
+{ 0xed , 0x043D },
+{ 0xee , 0x043E },
+{ 0xef , 0x043F },
+{ 0xf0 , 0x0440 },
+{ 0xf1 , 0x0441 },
+{ 0xf2 , 0x0442 },
+{ 0xf3 , 0x0443 },
+{ 0xf4 , 0x0444 },
+{ 0xf5 , 0x0445 },
+{ 0xf6 , 0x0446 },
+{ 0xf7 , 0x0447 },
+{ 0xf8 , 0x0448 },
+{ 0xf9 , 0x0449 },
+{ 0xfa , 0x044A },
+{ 0xfb , 0x044B },
+{ 0xfc , 0x044C },
+{ 0xfd , 0x044D },
+{ 0xfe , 0x044E },
+{ 0xff , 0x044F },
diff --git a/extra/locale/charmaps/ISO-8859-1.pairs b/extra/locale/charmaps/ISO-8859-1.pairs
new file mode 100644
index 000000000..97812a0d5
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-1.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x00A1 },
+{ 0xa2 , 0x00A2 },
+{ 0xa3 , 0x00A3 },
+{ 0xa4 , 0x00A4 },
+{ 0xa5 , 0x00A5 },
+{ 0xa6 , 0x00A6 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x00A8 },
+{ 0xa9 , 0x00A9 },
+{ 0xaa , 0x00AA },
+{ 0xab , 0x00AB },
+{ 0xac , 0x00AC },
+{ 0xad , 0x00AD },
+{ 0xae , 0x00AE },
+{ 0xaf , 0x00AF },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x00B1 },
+{ 0xb2 , 0x00B2 },
+{ 0xb3 , 0x00B3 },
+{ 0xb4 , 0x00B4 },
+{ 0xb5 , 0x00B5 },
+{ 0xb6 , 0x00B6 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x00B8 },
+{ 0xb9 , 0x00B9 },
+{ 0xba , 0x00BA },
+{ 0xbb , 0x00BB },
+{ 0xbc , 0x00BC },
+{ 0xbd , 0x00BD },
+{ 0xbe , 0x00BE },
+{ 0xbf , 0x00BF },
+{ 0xc0 , 0x00C0 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc3 , 0x00C3 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x00C5 },
+{ 0xc6 , 0x00C6 },
+{ 0xc7 , 0x00C7 },
+{ 0xc8 , 0x00C8 },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x00CA },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x00CC },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x00CF },
+{ 0xd0 , 0x00D0 },
+{ 0xd1 , 0x00D1 },
+{ 0xd2 , 0x00D2 },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x00D5 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x00D7 },
+{ 0xd8 , 0x00D8 },
+{ 0xd9 , 0x00D9 },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x00DB },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x00DD },
+{ 0xde , 0x00DE },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x00E0 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe3 , 0x00E3 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x00E5 },
+{ 0xe6 , 0x00E6 },
+{ 0xe7 , 0x00E7 },
+{ 0xe8 , 0x00E8 },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x00EA },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x00EC },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x00EF },
+{ 0xf0 , 0x00F0 },
+{ 0xf1 , 0x00F1 },
+{ 0xf2 , 0x00F2 },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x00F5 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x00F7 },
+{ 0xf8 , 0x00F8 },
+{ 0xf9 , 0x00F9 },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x00FB },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x00FD },
+{ 0xfe , 0x00FE },
+{ 0xff , 0x00FF },
diff --git a/extra/locale/charmaps/ISO-8859-10.pairs b/extra/locale/charmaps/ISO-8859-10.pairs
new file mode 100644
index 000000000..a39892fcc
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-10.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x0104 },
+{ 0xa2 , 0x0112 },
+{ 0xa3 , 0x0122 },
+{ 0xa4 , 0x012A },
+{ 0xa5 , 0x0128 },
+{ 0xa6 , 0x0136 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x013B },
+{ 0xa9 , 0x0110 },
+{ 0xaa , 0x0160 },
+{ 0xab , 0x0166 },
+{ 0xac , 0x017D },
+{ 0xad , 0x00AD },
+{ 0xae , 0x016A },
+{ 0xaf , 0x014A },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x0105 },
+{ 0xb2 , 0x0113 },
+{ 0xb3 , 0x0123 },
+{ 0xb4 , 0x012B },
+{ 0xb5 , 0x0129 },
+{ 0xb6 , 0x0137 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x013C },
+{ 0xb9 , 0x0111 },
+{ 0xba , 0x0161 },
+{ 0xbb , 0x0167 },
+{ 0xbc , 0x017E },
+{ 0xbd , 0x2015 },
+{ 0xbe , 0x016B },
+{ 0xbf , 0x014B },
+{ 0xc0 , 0x0100 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc3 , 0x00C3 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x00C5 },
+{ 0xc6 , 0x00C6 },
+{ 0xc7 , 0x012E },
+{ 0xc8 , 0x010C },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x0118 },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x0116 },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x00CF },
+{ 0xd0 , 0x00D0 },
+{ 0xd1 , 0x0145 },
+{ 0xd2 , 0x014C },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x00D5 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x0168 },
+{ 0xd8 , 0x00D8 },
+{ 0xd9 , 0x0172 },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x00DB },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x00DD },
+{ 0xde , 0x00DE },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x0101 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe3 , 0x00E3 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x00E5 },
+{ 0xe6 , 0x00E6 },
+{ 0xe7 , 0x012F },
+{ 0xe8 , 0x010D },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x0119 },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x0117 },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x00EF },
+{ 0xf0 , 0x00F0 },
+{ 0xf1 , 0x0146 },
+{ 0xf2 , 0x014D },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x00F5 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x0169 },
+{ 0xf8 , 0x00F8 },
+{ 0xf9 , 0x0173 },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x00FB },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x00FD },
+{ 0xfe , 0x00FE },
+{ 0xff , 0x0138 },
diff --git a/extra/locale/charmaps/ISO-8859-13.pairs b/extra/locale/charmaps/ISO-8859-13.pairs
new file mode 100644
index 000000000..ff95fb449
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-13.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x201D },
+{ 0xa2 , 0x00A2 },
+{ 0xa3 , 0x00A3 },
+{ 0xa4 , 0x00A4 },
+{ 0xa5 , 0x201E },
+{ 0xa6 , 0x00A6 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x00D8 },
+{ 0xa9 , 0x00A9 },
+{ 0xaa , 0x0156 },
+{ 0xab , 0x00AB },
+{ 0xac , 0x00AC },
+{ 0xad , 0x00AD },
+{ 0xae , 0x00AE },
+{ 0xaf , 0x00C6 },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x00B1 },
+{ 0xb2 , 0x00B2 },
+{ 0xb3 , 0x00B3 },
+{ 0xb4 , 0x201C },
+{ 0xb5 , 0x00B5 },
+{ 0xb6 , 0x00B6 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x00F8 },
+{ 0xb9 , 0x00B9 },
+{ 0xba , 0x0157 },
+{ 0xbb , 0x00BB },
+{ 0xbc , 0x00BC },
+{ 0xbd , 0x00BD },
+{ 0xbe , 0x00BE },
+{ 0xbf , 0x00E6 },
+{ 0xc0 , 0x0104 },
+{ 0xc1 , 0x012E },
+{ 0xc2 , 0x0100 },
+{ 0xc3 , 0x0106 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x00C5 },
+{ 0xc6 , 0x0118 },
+{ 0xc7 , 0x0112 },
+{ 0xc8 , 0x010C },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x0179 },
+{ 0xcb , 0x0116 },
+{ 0xcc , 0x0122 },
+{ 0xcd , 0x0136 },
+{ 0xce , 0x012A },
+{ 0xcf , 0x013B },
+{ 0xd0 , 0x0160 },
+{ 0xd1 , 0x0143 },
+{ 0xd2 , 0x0145 },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x014C },
+{ 0xd5 , 0x00D5 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x00D7 },
+{ 0xd8 , 0x0172 },
+{ 0xd9 , 0x0141 },
+{ 0xda , 0x015A },
+{ 0xdb , 0x016A },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x017B },
+{ 0xde , 0x017D },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x0105 },
+{ 0xe1 , 0x012F },
+{ 0xe2 , 0x0101 },
+{ 0xe3 , 0x0107 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x00E5 },
+{ 0xe6 , 0x0119 },
+{ 0xe7 , 0x0113 },
+{ 0xe8 , 0x010D },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x017A },
+{ 0xeb , 0x0117 },
+{ 0xec , 0x0123 },
+{ 0xed , 0x0137 },
+{ 0xee , 0x012B },
+{ 0xef , 0x013C },
+{ 0xf0 , 0x0161 },
+{ 0xf1 , 0x0144 },
+{ 0xf2 , 0x0146 },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x014D },
+{ 0xf5 , 0x00F5 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x00F7 },
+{ 0xf8 , 0x0173 },
+{ 0xf9 , 0x0142 },
+{ 0xfa , 0x015B },
+{ 0xfb , 0x016B },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x017C },
+{ 0xfe , 0x017E },
+{ 0xff , 0x2019 },
diff --git a/extra/locale/charmaps/ISO-8859-14.pairs b/extra/locale/charmaps/ISO-8859-14.pairs
new file mode 100644
index 000000000..8a8f06ec0
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-14.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x1E02 },
+{ 0xa2 , 0x1E03 },
+{ 0xa3 , 0x00A3 },
+{ 0xa4 , 0x010A },
+{ 0xa5 , 0x010B },
+{ 0xa6 , 0x1E0A },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x1E80 },
+{ 0xa9 , 0x00A9 },
+{ 0xaa , 0x1E82 },
+{ 0xab , 0x1E0B },
+{ 0xac , 0x1EF2 },
+{ 0xad , 0x00AD },
+{ 0xae , 0x00AE },
+{ 0xaf , 0x0178 },
+{ 0xb0 , 0x1E1E },
+{ 0xb1 , 0x1E1F },
+{ 0xb2 , 0x0120 },
+{ 0xb3 , 0x0121 },
+{ 0xb4 , 0x1E40 },
+{ 0xb5 , 0x1E41 },
+{ 0xb6 , 0x00B6 },
+{ 0xb7 , 0x1E56 },
+{ 0xb8 , 0x1E81 },
+{ 0xb9 , 0x1E57 },
+{ 0xba , 0x1E83 },
+{ 0xbb , 0x1E60 },
+{ 0xbc , 0x1EF3 },
+{ 0xbd , 0x1E84 },
+{ 0xbe , 0x1E85 },
+{ 0xbf , 0x1E61 },
+{ 0xc0 , 0x00C0 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc3 , 0x00C3 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x00C5 },
+{ 0xc6 , 0x00C6 },
+{ 0xc7 , 0x00C7 },
+{ 0xc8 , 0x00C8 },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x00CA },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x00CC },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x00CF },
+{ 0xd0 , 0x0174 },
+{ 0xd1 , 0x00D1 },
+{ 0xd2 , 0x00D2 },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x00D5 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x1E6A },
+{ 0xd8 , 0x00D8 },
+{ 0xd9 , 0x00D9 },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x00DB },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x00DD },
+{ 0xde , 0x0176 },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x00E0 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe3 , 0x00E3 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x00E5 },
+{ 0xe6 , 0x00E6 },
+{ 0xe7 , 0x00E7 },
+{ 0xe8 , 0x00E8 },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x00EA },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x00EC },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x00EF },
+{ 0xf0 , 0x0175 },
+{ 0xf1 , 0x00F1 },
+{ 0xf2 , 0x00F2 },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x00F5 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x1E6B },
+{ 0xf8 , 0x00F8 },
+{ 0xf9 , 0x00F9 },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x00FB },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x00FD },
+{ 0xfe , 0x0177 },
+{ 0xff , 0x00FF },
diff --git a/extra/locale/charmaps/ISO-8859-15.pairs b/extra/locale/charmaps/ISO-8859-15.pairs
new file mode 100644
index 000000000..ca50e22bd
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-15.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x00A1 },
+{ 0xa2 , 0x00A2 },
+{ 0xa3 , 0x00A3 },
+{ 0xa4 , 0x20AC },
+{ 0xa5 , 0x00A5 },
+{ 0xa6 , 0x0160 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x0161 },
+{ 0xa9 , 0x00A9 },
+{ 0xaa , 0x00AA },
+{ 0xab , 0x00AB },
+{ 0xac , 0x00AC },
+{ 0xad , 0x00AD },
+{ 0xae , 0x00AE },
+{ 0xaf , 0x00AF },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x00B1 },
+{ 0xb2 , 0x00B2 },
+{ 0xb3 , 0x00B3 },
+{ 0xb4 , 0x017D },
+{ 0xb5 , 0x00B5 },
+{ 0xb6 , 0x00B6 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x017E },
+{ 0xb9 , 0x00B9 },
+{ 0xba , 0x00BA },
+{ 0xbb , 0x00BB },
+{ 0xbc , 0x0152 },
+{ 0xbd , 0x0153 },
+{ 0xbe , 0x0178 },
+{ 0xbf , 0x00BF },
+{ 0xc0 , 0x00C0 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc3 , 0x00C3 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x00C5 },
+{ 0xc6 , 0x00C6 },
+{ 0xc7 , 0x00C7 },
+{ 0xc8 , 0x00C8 },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x00CA },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x00CC },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x00CF },
+{ 0xd0 , 0x00D0 },
+{ 0xd1 , 0x00D1 },
+{ 0xd2 , 0x00D2 },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x00D5 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x00D7 },
+{ 0xd8 , 0x00D8 },
+{ 0xd9 , 0x00D9 },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x00DB },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x00DD },
+{ 0xde , 0x00DE },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x00E0 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe3 , 0x00E3 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x00E5 },
+{ 0xe6 , 0x00E6 },
+{ 0xe7 , 0x00E7 },
+{ 0xe8 , 0x00E8 },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x00EA },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x00EC },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x00EF },
+{ 0xf0 , 0x00F0 },
+{ 0xf1 , 0x00F1 },
+{ 0xf2 , 0x00F2 },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x00F5 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x00F7 },
+{ 0xf8 , 0x00F8 },
+{ 0xf9 , 0x00F9 },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x00FB },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x00FD },
+{ 0xfe , 0x00FE },
+{ 0xff , 0x00FF },
diff --git a/extra/locale/charmaps/ISO-8859-16.pairs b/extra/locale/charmaps/ISO-8859-16.pairs
new file mode 100644
index 000000000..6b749639e
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-16.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x0104 },
+{ 0xa2 , 0x0105 },
+{ 0xa3 , 0x0141 },
+{ 0xa4 , 0x20AC },
+{ 0xa5 , 0x00AB },
+{ 0xa6 , 0x0160 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x0161 },
+{ 0xa9 , 0x00A9 },
+{ 0xaa , 0x0218 },
+{ 0xab , 0x201E },
+{ 0xac , 0x0179 },
+{ 0xad , 0x00AD },
+{ 0xae , 0x017A },
+{ 0xaf , 0x017B },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x00B1 },
+{ 0xb2 , 0x010C },
+{ 0xb3 , 0x0142 },
+{ 0xb4 , 0x017D },
+{ 0xb5 , 0x201D },
+{ 0xb6 , 0x00B6 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x017E },
+{ 0xb9 , 0x010D },
+{ 0xba , 0x0219 },
+{ 0xbb , 0x00BB },
+{ 0xbc , 0x0152 },
+{ 0xbd , 0x0153 },
+{ 0xbe , 0x0178 },
+{ 0xbf , 0x017C },
+{ 0xc0 , 0x00C0 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc3 , 0x0102 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x0106 },
+{ 0xc6 , 0x00C6 },
+{ 0xc7 , 0x00C7 },
+{ 0xc8 , 0x00C8 },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x00CA },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x00CC },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x00CF },
+{ 0xd0 , 0x0110 },
+{ 0xd1 , 0x0143 },
+{ 0xd2 , 0x00D2 },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x0150 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x015A },
+{ 0xd8 , 0x0170 },
+{ 0xd9 , 0x00D9 },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x00DB },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x0118 },
+{ 0xde , 0x021A },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x00E0 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe3 , 0x0103 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x0107 },
+{ 0xe6 , 0x00E6 },
+{ 0xe7 , 0x00E7 },
+{ 0xe8 , 0x00E8 },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x00EA },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x00EC },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x00EF },
+{ 0xf0 , 0x0111 },
+{ 0xf1 , 0x0144 },
+{ 0xf2 , 0x00F2 },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x0151 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x015B },
+{ 0xf8 , 0x0171 },
+{ 0xf9 , 0x00F9 },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x00FB },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x0119 },
+{ 0xfe , 0x021B },
+{ 0xff , 0x00FF },
diff --git a/extra/locale/charmaps/ISO-8859-2.pairs b/extra/locale/charmaps/ISO-8859-2.pairs
new file mode 100644
index 000000000..4e92f9432
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-2.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x0104 },
+{ 0xa2 , 0x02D8 },
+{ 0xa3 , 0x0141 },
+{ 0xa4 , 0x00A4 },
+{ 0xa5 , 0x013D },
+{ 0xa6 , 0x015A },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x00A8 },
+{ 0xa9 , 0x0160 },
+{ 0xaa , 0x015E },
+{ 0xab , 0x0164 },
+{ 0xac , 0x0179 },
+{ 0xad , 0x00AD },
+{ 0xae , 0x017D },
+{ 0xaf , 0x017B },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x0105 },
+{ 0xb2 , 0x02DB },
+{ 0xb3 , 0x0142 },
+{ 0xb4 , 0x00B4 },
+{ 0xb5 , 0x013E },
+{ 0xb6 , 0x015B },
+{ 0xb7 , 0x02C7 },
+{ 0xb8 , 0x00B8 },
+{ 0xb9 , 0x0161 },
+{ 0xba , 0x015F },
+{ 0xbb , 0x0165 },
+{ 0xbc , 0x017A },
+{ 0xbd , 0x02DD },
+{ 0xbe , 0x017E },
+{ 0xbf , 0x017C },
+{ 0xc0 , 0x0154 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc3 , 0x0102 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x0139 },
+{ 0xc6 , 0x0106 },
+{ 0xc7 , 0x00C7 },
+{ 0xc8 , 0x010C },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x0118 },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x011A },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x010E },
+{ 0xd0 , 0x0110 },
+{ 0xd1 , 0x0143 },
+{ 0xd2 , 0x0147 },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x0150 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x00D7 },
+{ 0xd8 , 0x0158 },
+{ 0xd9 , 0x016E },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x0170 },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x00DD },
+{ 0xde , 0x0162 },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x0155 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe3 , 0x0103 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x013A },
+{ 0xe6 , 0x0107 },
+{ 0xe7 , 0x00E7 },
+{ 0xe8 , 0x010D },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x0119 },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x011B },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x010F },
+{ 0xf0 , 0x0111 },
+{ 0xf1 , 0x0144 },
+{ 0xf2 , 0x0148 },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x0151 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x00F7 },
+{ 0xf8 , 0x0159 },
+{ 0xf9 , 0x016F },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x0171 },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x00FD },
+{ 0xfe , 0x0163 },
+{ 0xff , 0x02D9 },
diff --git a/extra/locale/charmaps/ISO-8859-3.pairs b/extra/locale/charmaps/ISO-8859-3.pairs
new file mode 100644
index 000000000..3a8814cde
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-3.pairs
@@ -0,0 +1,249 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x0126 },
+{ 0xa2 , 0x02D8 },
+{ 0xa3 , 0x00A3 },
+{ 0xa4 , 0x00A4 },
+{ 0xa6 , 0x0124 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x00A8 },
+{ 0xa9 , 0x0130 },
+{ 0xaa , 0x015E },
+{ 0xab , 0x011E },
+{ 0xac , 0x0134 },
+{ 0xad , 0x00AD },
+{ 0xaf , 0x017B },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x0127 },
+{ 0xb2 , 0x00B2 },
+{ 0xb3 , 0x00B3 },
+{ 0xb4 , 0x00B4 },
+{ 0xb5 , 0x00B5 },
+{ 0xb6 , 0x0125 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x00B8 },
+{ 0xb9 , 0x0131 },
+{ 0xba , 0x015F },
+{ 0xbb , 0x011F },
+{ 0xbc , 0x0135 },
+{ 0xbd , 0x00BD },
+{ 0xbf , 0x017C },
+{ 0xc0 , 0x00C0 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x010A },
+{ 0xc6 , 0x0108 },
+{ 0xc7 , 0x00C7 },
+{ 0xc8 , 0x00C8 },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x00CA },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x00CC },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x00CF },
+{ 0xd1 , 0x00D1 },
+{ 0xd2 , 0x00D2 },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x0120 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x00D7 },
+{ 0xd8 , 0x011C },
+{ 0xd9 , 0x00D9 },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x00DB },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x016C },
+{ 0xde , 0x015C },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x00E0 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x010B },
+{ 0xe6 , 0x0109 },
+{ 0xe7 , 0x00E7 },
+{ 0xe8 , 0x00E8 },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x00EA },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x00EC },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x00EF },
+{ 0xf1 , 0x00F1 },
+{ 0xf2 , 0x00F2 },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x0121 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x00F7 },
+{ 0xf8 , 0x011D },
+{ 0xf9 , 0x00F9 },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x00FB },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x016D },
+{ 0xfe , 0x015D },
+{ 0xff , 0x02D9 },
diff --git a/extra/locale/charmaps/ISO-8859-4.pairs b/extra/locale/charmaps/ISO-8859-4.pairs
new file mode 100644
index 000000000..dda865c3c
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-4.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x0104 },
+{ 0xa2 , 0x0138 },
+{ 0xa3 , 0x0156 },
+{ 0xa4 , 0x00A4 },
+{ 0xa5 , 0x0128 },
+{ 0xa6 , 0x013B },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x00A8 },
+{ 0xa9 , 0x0160 },
+{ 0xaa , 0x0112 },
+{ 0xab , 0x0122 },
+{ 0xac , 0x0166 },
+{ 0xad , 0x00AD },
+{ 0xae , 0x017D },
+{ 0xaf , 0x00AF },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x0105 },
+{ 0xb2 , 0x02DB },
+{ 0xb3 , 0x0157 },
+{ 0xb4 , 0x00B4 },
+{ 0xb5 , 0x0129 },
+{ 0xb6 , 0x013C },
+{ 0xb7 , 0x02C7 },
+{ 0xb8 , 0x00B8 },
+{ 0xb9 , 0x0161 },
+{ 0xba , 0x0113 },
+{ 0xbb , 0x0123 },
+{ 0xbc , 0x0167 },
+{ 0xbd , 0x014A },
+{ 0xbe , 0x017E },
+{ 0xbf , 0x014B },
+{ 0xc0 , 0x0100 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc3 , 0x00C3 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x00C5 },
+{ 0xc6 , 0x00C6 },
+{ 0xc7 , 0x012E },
+{ 0xc8 , 0x010C },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x0118 },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x0116 },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x012A },
+{ 0xd0 , 0x0110 },
+{ 0xd1 , 0x0145 },
+{ 0xd2 , 0x014C },
+{ 0xd3 , 0x0136 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x00D5 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x00D7 },
+{ 0xd8 , 0x00D8 },
+{ 0xd9 , 0x0172 },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x00DB },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x0168 },
+{ 0xde , 0x016A },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x0101 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe3 , 0x00E3 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x00E5 },
+{ 0xe6 , 0x00E6 },
+{ 0xe7 , 0x012F },
+{ 0xe8 , 0x010D },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x0119 },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x0117 },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x012B },
+{ 0xf0 , 0x0111 },
+{ 0xf1 , 0x0146 },
+{ 0xf2 , 0x014D },
+{ 0xf3 , 0x0137 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x00F5 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x00F7 },
+{ 0xf8 , 0x00F8 },
+{ 0xf9 , 0x0173 },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x00FB },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x0169 },
+{ 0xfe , 0x016B },
+{ 0xff , 0x02D9 },
diff --git a/extra/locale/charmaps/ISO-8859-5.pairs b/extra/locale/charmaps/ISO-8859-5.pairs
new file mode 100644
index 000000000..08ebcae49
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-5.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x0401 },
+{ 0xa2 , 0x0402 },
+{ 0xa3 , 0x0403 },
+{ 0xa4 , 0x0404 },
+{ 0xa5 , 0x0405 },
+{ 0xa6 , 0x0406 },
+{ 0xa7 , 0x0407 },
+{ 0xa8 , 0x0408 },
+{ 0xa9 , 0x0409 },
+{ 0xaa , 0x040A },
+{ 0xab , 0x040B },
+{ 0xac , 0x040C },
+{ 0xad , 0x00AD },
+{ 0xae , 0x040E },
+{ 0xaf , 0x040F },
+{ 0xb0 , 0x0410 },
+{ 0xb1 , 0x0411 },
+{ 0xb2 , 0x0412 },
+{ 0xb3 , 0x0413 },
+{ 0xb4 , 0x0414 },
+{ 0xb5 , 0x0415 },
+{ 0xb6 , 0x0416 },
+{ 0xb7 , 0x0417 },
+{ 0xb8 , 0x0418 },
+{ 0xb9 , 0x0419 },
+{ 0xba , 0x041A },
+{ 0xbb , 0x041B },
+{ 0xbc , 0x041C },
+{ 0xbd , 0x041D },
+{ 0xbe , 0x041E },
+{ 0xbf , 0x041F },
+{ 0xc0 , 0x0420 },
+{ 0xc1 , 0x0421 },
+{ 0xc2 , 0x0422 },
+{ 0xc3 , 0x0423 },
+{ 0xc4 , 0x0424 },
+{ 0xc5 , 0x0425 },
+{ 0xc6 , 0x0426 },
+{ 0xc7 , 0x0427 },
+{ 0xc8 , 0x0428 },
+{ 0xc9 , 0x0429 },
+{ 0xca , 0x042A },
+{ 0xcb , 0x042B },
+{ 0xcc , 0x042C },
+{ 0xcd , 0x042D },
+{ 0xce , 0x042E },
+{ 0xcf , 0x042F },
+{ 0xd0 , 0x0430 },
+{ 0xd1 , 0x0431 },
+{ 0xd2 , 0x0432 },
+{ 0xd3 , 0x0433 },
+{ 0xd4 , 0x0434 },
+{ 0xd5 , 0x0435 },
+{ 0xd6 , 0x0436 },
+{ 0xd7 , 0x0437 },
+{ 0xd8 , 0x0438 },
+{ 0xd9 , 0x0439 },
+{ 0xda , 0x043A },
+{ 0xdb , 0x043B },
+{ 0xdc , 0x043C },
+{ 0xdd , 0x043D },
+{ 0xde , 0x043E },
+{ 0xdf , 0x043F },
+{ 0xe0 , 0x0440 },
+{ 0xe1 , 0x0441 },
+{ 0xe2 , 0x0442 },
+{ 0xe3 , 0x0443 },
+{ 0xe4 , 0x0444 },
+{ 0xe5 , 0x0445 },
+{ 0xe6 , 0x0446 },
+{ 0xe7 , 0x0447 },
+{ 0xe8 , 0x0448 },
+{ 0xe9 , 0x0449 },
+{ 0xea , 0x044A },
+{ 0xeb , 0x044B },
+{ 0xec , 0x044C },
+{ 0xed , 0x044D },
+{ 0xee , 0x044E },
+{ 0xef , 0x044F },
+{ 0xf0 , 0x2116 },
+{ 0xf1 , 0x0451 },
+{ 0xf2 , 0x0452 },
+{ 0xf3 , 0x0453 },
+{ 0xf4 , 0x0454 },
+{ 0xf5 , 0x0455 },
+{ 0xf6 , 0x0456 },
+{ 0xf7 , 0x0457 },
+{ 0xf8 , 0x0458 },
+{ 0xf9 , 0x0459 },
+{ 0xfa , 0x045A },
+{ 0xfb , 0x045B },
+{ 0xfc , 0x045C },
+{ 0xfd , 0x00A7 },
+{ 0xfe , 0x045E },
+{ 0xff , 0x045F },
diff --git a/extra/locale/charmaps/ISO-8859-6.pairs b/extra/locale/charmaps/ISO-8859-6.pairs
new file mode 100644
index 000000000..ccba9f907
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-6.pairs
@@ -0,0 +1,211 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa4 , 0x00A4 },
+{ 0xac , 0x060C },
+{ 0xad , 0x00AD },
+{ 0xbb , 0x061B },
+{ 0xbf , 0x061F },
+{ 0xc1 , 0x0621 },
+{ 0xc2 , 0x0622 },
+{ 0xc3 , 0x0623 },
+{ 0xc4 , 0x0624 },
+{ 0xc5 , 0x0625 },
+{ 0xc6 , 0x0626 },
+{ 0xc7 , 0x0627 },
+{ 0xc8 , 0x0628 },
+{ 0xc9 , 0x0629 },
+{ 0xca , 0x062A },
+{ 0xcb , 0x062B },
+{ 0xcc , 0x062C },
+{ 0xcd , 0x062D },
+{ 0xce , 0x062E },
+{ 0xcf , 0x062F },
+{ 0xd0 , 0x0630 },
+{ 0xd1 , 0x0631 },
+{ 0xd2 , 0x0632 },
+{ 0xd3 , 0x0633 },
+{ 0xd4 , 0x0634 },
+{ 0xd5 , 0x0635 },
+{ 0xd6 , 0x0636 },
+{ 0xd7 , 0x0637 },
+{ 0xd8 , 0x0638 },
+{ 0xd9 , 0x0639 },
+{ 0xda , 0x063A },
+{ 0xe0 , 0x0640 },
+{ 0xe1 , 0x0641 },
+{ 0xe2 , 0x0642 },
+{ 0xe3 , 0x0643 },
+{ 0xe4 , 0x0644 },
+{ 0xe5 , 0x0645 },
+{ 0xe6 , 0x0646 },
+{ 0xe7 , 0x0647 },
+{ 0xe8 , 0x0648 },
+{ 0xe9 , 0x0649 },
+{ 0xea , 0x064A },
+{ 0xeb , 0x064B },
+{ 0xec , 0x064C },
+{ 0xed , 0x064D },
+{ 0xee , 0x064E },
+{ 0xef , 0x064F },
+{ 0xf0 , 0x0650 },
+{ 0xf1 , 0x0651 },
+{ 0xf2 , 0x0652 },
diff --git a/extra/locale/charmaps/ISO-8859-7.pairs b/extra/locale/charmaps/ISO-8859-7.pairs
new file mode 100644
index 000000000..36b8ba24c
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-7.pairs
@@ -0,0 +1,250 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x2018 },
+{ 0xa2 , 0x2019 },
+{ 0xa3 , 0x00A3 },
+{ 0xa6 , 0x00A6 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x00A8 },
+{ 0xa9 , 0x00A9 },
+{ 0xab , 0x00AB },
+{ 0xac , 0x00AC },
+{ 0xad , 0x00AD },
+{ 0xaf , 0x2015 },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x00B1 },
+{ 0xb2 , 0x00B2 },
+{ 0xb3 , 0x00B3 },
+{ 0xb4 , 0x0384 },
+{ 0xb5 , 0x0385 },
+{ 0xb6 , 0x0386 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x0388 },
+{ 0xb9 , 0x0389 },
+{ 0xba , 0x038A },
+{ 0xbb , 0x00BB },
+{ 0xbc , 0x038C },
+{ 0xbd , 0x00BD },
+{ 0xbe , 0x038E },
+{ 0xbf , 0x038F },
+{ 0xc0 , 0x0390 },
+{ 0xc1 , 0x0391 },
+{ 0xc2 , 0x0392 },
+{ 0xc3 , 0x0393 },
+{ 0xc4 , 0x0394 },
+{ 0xc5 , 0x0395 },
+{ 0xc6 , 0x0396 },
+{ 0xc7 , 0x0397 },
+{ 0xc8 , 0x0398 },
+{ 0xc9 , 0x0399 },
+{ 0xca , 0x039A },
+{ 0xcb , 0x039B },
+{ 0xcc , 0x039C },
+{ 0xcd , 0x039D },
+{ 0xce , 0x039E },
+{ 0xcf , 0x039F },
+{ 0xd0 , 0x03A0 },
+{ 0xd1 , 0x03A1 },
+{ 0xd3 , 0x03A3 },
+{ 0xd4 , 0x03A4 },
+{ 0xd5 , 0x03A5 },
+{ 0xd6 , 0x03A6 },
+{ 0xd7 , 0x03A7 },
+{ 0xd8 , 0x03A8 },
+{ 0xd9 , 0x03A9 },
+{ 0xda , 0x03AA },
+{ 0xdb , 0x03AB },
+{ 0xdc , 0x03AC },
+{ 0xdd , 0x03AD },
+{ 0xde , 0x03AE },
+{ 0xdf , 0x03AF },
+{ 0xe0 , 0x03B0 },
+{ 0xe1 , 0x03B1 },
+{ 0xe2 , 0x03B2 },
+{ 0xe3 , 0x03B3 },
+{ 0xe4 , 0x03B4 },
+{ 0xe5 , 0x03B5 },
+{ 0xe6 , 0x03B6 },
+{ 0xe7 , 0x03B7 },
+{ 0xe8 , 0x03B8 },
+{ 0xe9 , 0x03B9 },
+{ 0xea , 0x03BA },
+{ 0xeb , 0x03BB },
+{ 0xec , 0x03BC },
+{ 0xed , 0x03BD },
+{ 0xee , 0x03BE },
+{ 0xef , 0x03BF },
+{ 0xf0 , 0x03C0 },
+{ 0xf1 , 0x03C1 },
+{ 0xf2 , 0x03C2 },
+{ 0xf3 , 0x03C3 },
+{ 0xf4 , 0x03C4 },
+{ 0xf5 , 0x03C5 },
+{ 0xf6 , 0x03C6 },
+{ 0xf7 , 0x03C7 },
+{ 0xf8 , 0x03C8 },
+{ 0xf9 , 0x03C9 },
+{ 0xfa , 0x03CA },
+{ 0xfb , 0x03CB },
+{ 0xfc , 0x03CC },
+{ 0xfd , 0x03CD },
+{ 0xfe , 0x03CE },
diff --git a/extra/locale/charmaps/ISO-8859-8.pairs b/extra/locale/charmaps/ISO-8859-8.pairs
new file mode 100644
index 000000000..8d32dd859
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-8.pairs
@@ -0,0 +1,220 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa2 , 0x00A2 },
+{ 0xa3 , 0x00A3 },
+{ 0xa4 , 0x00A4 },
+{ 0xa5 , 0x00A5 },
+{ 0xa6 , 0x00A6 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x00A8 },
+{ 0xa9 , 0x00A9 },
+{ 0xaa , 0x00D7 },
+{ 0xab , 0x00AB },
+{ 0xac , 0x00AC },
+{ 0xad , 0x00AD },
+{ 0xae , 0x00AE },
+{ 0xaf , 0x00AF },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x00B1 },
+{ 0xb2 , 0x00B2 },
+{ 0xb3 , 0x00B3 },
+{ 0xb4 , 0x00B4 },
+{ 0xb5 , 0x00B5 },
+{ 0xb6 , 0x00B6 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x00B8 },
+{ 0xb9 , 0x00B9 },
+{ 0xba , 0x00F7 },
+{ 0xbb , 0x00BB },
+{ 0xbc , 0x00BC },
+{ 0xbd , 0x00BD },
+{ 0xbe , 0x00BE },
+{ 0xdf , 0x2017 },
+{ 0xe0 , 0x05D0 },
+{ 0xe1 , 0x05D1 },
+{ 0xe2 , 0x05D2 },
+{ 0xe3 , 0x05D3 },
+{ 0xe4 , 0x05D4 },
+{ 0xe5 , 0x05D5 },
+{ 0xe6 , 0x05D6 },
+{ 0xe7 , 0x05D7 },
+{ 0xe8 , 0x05D8 },
+{ 0xe9 , 0x05D9 },
+{ 0xea , 0x05DA },
+{ 0xeb , 0x05DB },
+{ 0xec , 0x05DC },
+{ 0xed , 0x05DD },
+{ 0xee , 0x05DE },
+{ 0xef , 0x05DF },
+{ 0xf0 , 0x05E0 },
+{ 0xf1 , 0x05E1 },
+{ 0xf2 , 0x05E2 },
+{ 0xf3 , 0x05E3 },
+{ 0xf4 , 0x05E4 },
+{ 0xf5 , 0x05E5 },
+{ 0xf6 , 0x05E6 },
+{ 0xf7 , 0x05E7 },
+{ 0xf8 , 0x05E8 },
+{ 0xf9 , 0x05E9 },
+{ 0xfa , 0x05EA },
+{ 0xfd , 0x200E },
+{ 0xfe , 0x200F },
diff --git a/extra/locale/charmaps/ISO-8859-9.pairs b/extra/locale/charmaps/ISO-8859-9.pairs
new file mode 100644
index 000000000..a5748cda7
--- /dev/null
+++ b/extra/locale/charmaps/ISO-8859-9.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x0080 },
+{ 0x81 , 0x0081 },
+{ 0x82 , 0x0082 },
+{ 0x83 , 0x0083 },
+{ 0x84 , 0x0084 },
+{ 0x85 , 0x0085 },
+{ 0x86 , 0x0086 },
+{ 0x87 , 0x0087 },
+{ 0x88 , 0x0088 },
+{ 0x89 , 0x0089 },
+{ 0x8a , 0x008A },
+{ 0x8b , 0x008B },
+{ 0x8c , 0x008C },
+{ 0x8d , 0x008D },
+{ 0x8e , 0x008E },
+{ 0x8f , 0x008F },
+{ 0x90 , 0x0090 },
+{ 0x91 , 0x0091 },
+{ 0x92 , 0x0092 },
+{ 0x93 , 0x0093 },
+{ 0x94 , 0x0094 },
+{ 0x95 , 0x0095 },
+{ 0x96 , 0x0096 },
+{ 0x97 , 0x0097 },
+{ 0x98 , 0x0098 },
+{ 0x99 , 0x0099 },
+{ 0x9a , 0x009A },
+{ 0x9b , 0x009B },
+{ 0x9c , 0x009C },
+{ 0x9d , 0x009D },
+{ 0x9e , 0x009E },
+{ 0x9f , 0x009F },
+{ 0xa0 , 0x00A0 },
+{ 0xa1 , 0x00A1 },
+{ 0xa2 , 0x00A2 },
+{ 0xa3 , 0x00A3 },
+{ 0xa4 , 0x00A4 },
+{ 0xa5 , 0x00A5 },
+{ 0xa6 , 0x00A6 },
+{ 0xa7 , 0x00A7 },
+{ 0xa8 , 0x00A8 },
+{ 0xa9 , 0x00A9 },
+{ 0xaa , 0x00AA },
+{ 0xab , 0x00AB },
+{ 0xac , 0x00AC },
+{ 0xad , 0x00AD },
+{ 0xae , 0x00AE },
+{ 0xaf , 0x00AF },
+{ 0xb0 , 0x00B0 },
+{ 0xb1 , 0x00B1 },
+{ 0xb2 , 0x00B2 },
+{ 0xb3 , 0x00B3 },
+{ 0xb4 , 0x00B4 },
+{ 0xb5 , 0x00B5 },
+{ 0xb6 , 0x00B6 },
+{ 0xb7 , 0x00B7 },
+{ 0xb8 , 0x00B8 },
+{ 0xb9 , 0x00B9 },
+{ 0xba , 0x00BA },
+{ 0xbb , 0x00BB },
+{ 0xbc , 0x00BC },
+{ 0xbd , 0x00BD },
+{ 0xbe , 0x00BE },
+{ 0xbf , 0x00BF },
+{ 0xc0 , 0x00C0 },
+{ 0xc1 , 0x00C1 },
+{ 0xc2 , 0x00C2 },
+{ 0xc3 , 0x00C3 },
+{ 0xc4 , 0x00C4 },
+{ 0xc5 , 0x00C5 },
+{ 0xc6 , 0x00C6 },
+{ 0xc7 , 0x00C7 },
+{ 0xc8 , 0x00C8 },
+{ 0xc9 , 0x00C9 },
+{ 0xca , 0x00CA },
+{ 0xcb , 0x00CB },
+{ 0xcc , 0x00CC },
+{ 0xcd , 0x00CD },
+{ 0xce , 0x00CE },
+{ 0xcf , 0x00CF },
+{ 0xd0 , 0x011E },
+{ 0xd1 , 0x00D1 },
+{ 0xd2 , 0x00D2 },
+{ 0xd3 , 0x00D3 },
+{ 0xd4 , 0x00D4 },
+{ 0xd5 , 0x00D5 },
+{ 0xd6 , 0x00D6 },
+{ 0xd7 , 0x00D7 },
+{ 0xd8 , 0x00D8 },
+{ 0xd9 , 0x00D9 },
+{ 0xda , 0x00DA },
+{ 0xdb , 0x00DB },
+{ 0xdc , 0x00DC },
+{ 0xdd , 0x0130 },
+{ 0xde , 0x015E },
+{ 0xdf , 0x00DF },
+{ 0xe0 , 0x00E0 },
+{ 0xe1 , 0x00E1 },
+{ 0xe2 , 0x00E2 },
+{ 0xe3 , 0x00E3 },
+{ 0xe4 , 0x00E4 },
+{ 0xe5 , 0x00E5 },
+{ 0xe6 , 0x00E6 },
+{ 0xe7 , 0x00E7 },
+{ 0xe8 , 0x00E8 },
+{ 0xe9 , 0x00E9 },
+{ 0xea , 0x00EA },
+{ 0xeb , 0x00EB },
+{ 0xec , 0x00EC },
+{ 0xed , 0x00ED },
+{ 0xee , 0x00EE },
+{ 0xef , 0x00EF },
+{ 0xf0 , 0x011F },
+{ 0xf1 , 0x00F1 },
+{ 0xf2 , 0x00F2 },
+{ 0xf3 , 0x00F3 },
+{ 0xf4 , 0x00F4 },
+{ 0xf5 , 0x00F5 },
+{ 0xf6 , 0x00F6 },
+{ 0xf7 , 0x00F7 },
+{ 0xf8 , 0x00F8 },
+{ 0xf9 , 0x00F9 },
+{ 0xfa , 0x00FA },
+{ 0xfb , 0x00FB },
+{ 0xfc , 0x00FC },
+{ 0xfd , 0x0131 },
+{ 0xfe , 0x015F },
+{ 0xff , 0x00FF },
diff --git a/extra/locale/charmaps/KOI8-R.pairs b/extra/locale/charmaps/KOI8-R.pairs
new file mode 100644
index 000000000..f34053d95
--- /dev/null
+++ b/extra/locale/charmaps/KOI8-R.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x2500 },
+{ 0x81 , 0x2502 },
+{ 0x82 , 0x250C },
+{ 0x83 , 0x2510 },
+{ 0x84 , 0x2514 },
+{ 0x85 , 0x2518 },
+{ 0x86 , 0x251C },
+{ 0x87 , 0x2524 },
+{ 0x88 , 0x252C },
+{ 0x89 , 0x2534 },
+{ 0x8a , 0x253C },
+{ 0x8b , 0x2580 },
+{ 0x8c , 0x2584 },
+{ 0x8d , 0x2588 },
+{ 0x8e , 0x258C },
+{ 0x8f , 0x2590 },
+{ 0x90 , 0x2591 },
+{ 0x91 , 0x2592 },
+{ 0x92 , 0x2593 },
+{ 0x93 , 0x2320 },
+{ 0x94 , 0x25A0 },
+{ 0x95 , 0x2219 },
+{ 0x96 , 0x221A },
+{ 0x97 , 0x2248 },
+{ 0x98 , 0x2264 },
+{ 0x99 , 0x2265 },
+{ 0x9a , 0x00A0 },
+{ 0x9b , 0x2321 },
+{ 0x9c , 0x00B0 },
+{ 0x9d , 0x00B2 },
+{ 0x9e , 0x00B7 },
+{ 0x9f , 0x00F7 },
+{ 0xa0 , 0x2550 },
+{ 0xa1 , 0x2551 },
+{ 0xa2 , 0x2552 },
+{ 0xa3 , 0x0451 },
+{ 0xa4 , 0x2553 },
+{ 0xa5 , 0x2554 },
+{ 0xa6 , 0x2555 },
+{ 0xa7 , 0x2556 },
+{ 0xa8 , 0x2557 },
+{ 0xa9 , 0x2558 },
+{ 0xaa , 0x2559 },
+{ 0xab , 0x255A },
+{ 0xac , 0x255B },
+{ 0xad , 0x255C },
+{ 0xae , 0x255D },
+{ 0xaf , 0x255E },
+{ 0xb0 , 0x255F },
+{ 0xb1 , 0x2560 },
+{ 0xb2 , 0x2561 },
+{ 0xb3 , 0x0401 },
+{ 0xb4 , 0x2562 },
+{ 0xb5 , 0x2563 },
+{ 0xb6 , 0x2564 },
+{ 0xb7 , 0x2565 },
+{ 0xb8 , 0x2566 },
+{ 0xb9 , 0x2567 },
+{ 0xba , 0x2568 },
+{ 0xbb , 0x2569 },
+{ 0xbc , 0x256A },
+{ 0xbd , 0x256B },
+{ 0xbe , 0x256C },
+{ 0xbf , 0x00A9 },
+{ 0xc0 , 0x044E },
+{ 0xc1 , 0x0430 },
+{ 0xc2 , 0x0431 },
+{ 0xc3 , 0x0446 },
+{ 0xc4 , 0x0434 },
+{ 0xc5 , 0x0435 },
+{ 0xc6 , 0x0444 },
+{ 0xc7 , 0x0433 },
+{ 0xc8 , 0x0445 },
+{ 0xc9 , 0x0438 },
+{ 0xca , 0x0439 },
+{ 0xcb , 0x043A },
+{ 0xcc , 0x043B },
+{ 0xcd , 0x043C },
+{ 0xce , 0x043D },
+{ 0xcf , 0x043E },
+{ 0xd0 , 0x043F },
+{ 0xd1 , 0x044F },
+{ 0xd2 , 0x0440 },
+{ 0xd3 , 0x0441 },
+{ 0xd4 , 0x0442 },
+{ 0xd5 , 0x0443 },
+{ 0xd6 , 0x0436 },
+{ 0xd7 , 0x0432 },
+{ 0xd8 , 0x044C },
+{ 0xd9 , 0x044B },
+{ 0xda , 0x0437 },
+{ 0xdb , 0x0448 },
+{ 0xdc , 0x044D },
+{ 0xdd , 0x0449 },
+{ 0xde , 0x0447 },
+{ 0xdf , 0x044A },
+{ 0xe0 , 0x042E },
+{ 0xe1 , 0x0410 },
+{ 0xe2 , 0x0411 },
+{ 0xe3 , 0x0426 },
+{ 0xe4 , 0x0414 },
+{ 0xe5 , 0x0415 },
+{ 0xe6 , 0x0424 },
+{ 0xe7 , 0x0413 },
+{ 0xe8 , 0x0425 },
+{ 0xe9 , 0x0418 },
+{ 0xea , 0x0419 },
+{ 0xeb , 0x041A },
+{ 0xec , 0x041B },
+{ 0xed , 0x041C },
+{ 0xee , 0x041D },
+{ 0xef , 0x041E },
+{ 0xf0 , 0x041F },
+{ 0xf1 , 0x042F },
+{ 0xf2 , 0x0420 },
+{ 0xf3 , 0x0421 },
+{ 0xf4 , 0x0422 },
+{ 0xf5 , 0x0423 },
+{ 0xf6 , 0x0416 },
+{ 0xf7 , 0x0412 },
+{ 0xf8 , 0x042C },
+{ 0xf9 , 0x042B },
+{ 0xfa , 0x0417 },
+{ 0xfb , 0x0428 },
+{ 0xfc , 0x042D },
+{ 0xfd , 0x0429 },
+{ 0xfe , 0x0427 },
+{ 0xff , 0x042A },
diff --git a/extra/locale/charmaps/KOI8-U.pairs b/extra/locale/charmaps/KOI8-U.pairs
new file mode 100644
index 000000000..ff05ed24f
--- /dev/null
+++ b/extra/locale/charmaps/KOI8-U.pairs
@@ -0,0 +1,256 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0x80 , 0x2500 },
+{ 0x81 , 0x2502 },
+{ 0x82 , 0x250C },
+{ 0x83 , 0x2510 },
+{ 0x84 , 0x2514 },
+{ 0x85 , 0x2518 },
+{ 0x86 , 0x251C },
+{ 0x87 , 0x2524 },
+{ 0x88 , 0x252C },
+{ 0x89 , 0x2534 },
+{ 0x8a , 0x253C },
+{ 0x8b , 0x2580 },
+{ 0x8c , 0x2584 },
+{ 0x8d , 0x2588 },
+{ 0x8e , 0x258C },
+{ 0x8f , 0x2590 },
+{ 0x90 , 0x2591 },
+{ 0x91 , 0x2592 },
+{ 0x92 , 0x2593 },
+{ 0x93 , 0x2320 },
+{ 0x94 , 0x25A0 },
+{ 0x95 , 0x2219 },
+{ 0x96 , 0x221A },
+{ 0x97 , 0x2248 },
+{ 0x98 , 0x2264 },
+{ 0x99 , 0x2265 },
+{ 0x9a , 0x00A0 },
+{ 0x9b , 0x2321 },
+{ 0x9c , 0x00B0 },
+{ 0x9d , 0x00B2 },
+{ 0x9e , 0x00B7 },
+{ 0x9f , 0x00F7 },
+{ 0xa0 , 0x2550 },
+{ 0xa1 , 0x2551 },
+{ 0xa2 , 0x2552 },
+{ 0xa3 , 0x0451 },
+{ 0xa4 , 0x0454 },
+{ 0xa5 , 0x2554 },
+{ 0xa6 , 0x0456 },
+{ 0xa7 , 0x0457 },
+{ 0xa8 , 0x2557 },
+{ 0xa9 , 0x2558 },
+{ 0xaa , 0x2559 },
+{ 0xab , 0x255A },
+{ 0xac , 0x255B },
+{ 0xad , 0x0491 },
+{ 0xae , 0x255D },
+{ 0xaf , 0x255E },
+{ 0xb0 , 0x255F },
+{ 0xb1 , 0x2560 },
+{ 0xb2 , 0x2561 },
+{ 0xb3 , 0x0401 },
+{ 0xb4 , 0x0404 },
+{ 0xb5 , 0x2563 },
+{ 0xb6 , 0x0406 },
+{ 0xb7 , 0x0407 },
+{ 0xb8 , 0x2566 },
+{ 0xb9 , 0x2567 },
+{ 0xba , 0x2568 },
+{ 0xbb , 0x2569 },
+{ 0xbc , 0x256A },
+{ 0xbd , 0x0490 },
+{ 0xbe , 0x256C },
+{ 0xbf , 0x00A9 },
+{ 0xc0 , 0x044E },
+{ 0xc1 , 0x0430 },
+{ 0xc2 , 0x0431 },
+{ 0xc3 , 0x0446 },
+{ 0xc4 , 0x0434 },
+{ 0xc5 , 0x0435 },
+{ 0xc6 , 0x0444 },
+{ 0xc7 , 0x0433 },
+{ 0xc8 , 0x0445 },
+{ 0xc9 , 0x0438 },
+{ 0xca , 0x0439 },
+{ 0xcb , 0x043A },
+{ 0xcc , 0x043B },
+{ 0xcd , 0x043C },
+{ 0xce , 0x043D },
+{ 0xcf , 0x043E },
+{ 0xd0 , 0x043F },
+{ 0xd1 , 0x044F },
+{ 0xd2 , 0x0440 },
+{ 0xd3 , 0x0441 },
+{ 0xd4 , 0x0442 },
+{ 0xd5 , 0x0443 },
+{ 0xd6 , 0x0436 },
+{ 0xd7 , 0x0432 },
+{ 0xd8 , 0x044C },
+{ 0xd9 , 0x044B },
+{ 0xda , 0x0437 },
+{ 0xdb , 0x0448 },
+{ 0xdc , 0x044D },
+{ 0xdd , 0x0449 },
+{ 0xde , 0x0447 },
+{ 0xdf , 0x044A },
+{ 0xe0 , 0x042E },
+{ 0xe1 , 0x0410 },
+{ 0xe2 , 0x0411 },
+{ 0xe3 , 0x0426 },
+{ 0xe4 , 0x0414 },
+{ 0xe5 , 0x0415 },
+{ 0xe6 , 0x0424 },
+{ 0xe7 , 0x0413 },
+{ 0xe8 , 0x0425 },
+{ 0xe9 , 0x0418 },
+{ 0xea , 0x0419 },
+{ 0xeb , 0x041A },
+{ 0xec , 0x041B },
+{ 0xed , 0x041C },
+{ 0xee , 0x041D },
+{ 0xef , 0x041E },
+{ 0xf0 , 0x041F },
+{ 0xf1 , 0x042F },
+{ 0xf2 , 0x0420 },
+{ 0xf3 , 0x0421 },
+{ 0xf4 , 0x0422 },
+{ 0xf5 , 0x0423 },
+{ 0xf6 , 0x0416 },
+{ 0xf7 , 0x0412 },
+{ 0xf8 , 0x042C },
+{ 0xf9 , 0x042B },
+{ 0xfa , 0x0417 },
+{ 0xfb , 0x0428 },
+{ 0xfc , 0x042D },
+{ 0xfd , 0x0429 },
+{ 0xfe , 0x0427 },
+{ 0xff , 0x042A },
diff --git a/extra/locale/charmaps/TIS-620.pairs b/extra/locale/charmaps/TIS-620.pairs
new file mode 100644
index 000000000..618a3be98
--- /dev/null
+++ b/extra/locale/charmaps/TIS-620.pairs
@@ -0,0 +1,215 @@
+{ 0x00 , 0x0000 },
+{ 0x01 , 0x0001 },
+{ 0x02 , 0x0002 },
+{ 0x03 , 0x0003 },
+{ 0x04 , 0x0004 },
+{ 0x05 , 0x0005 },
+{ 0x06 , 0x0006 },
+{ 0x07 , 0x0007 },
+{ 0x08 , 0x0008 },
+{ 0x09 , 0x0009 },
+{ 0x0a , 0x000A },
+{ 0x0b , 0x000B },
+{ 0x0c , 0x000C },
+{ 0x0d , 0x000D },
+{ 0x0e , 0x000E },
+{ 0x0f , 0x000F },
+{ 0x10 , 0x0010 },
+{ 0x11 , 0x0011 },
+{ 0x12 , 0x0012 },
+{ 0x13 , 0x0013 },
+{ 0x14 , 0x0014 },
+{ 0x15 , 0x0015 },
+{ 0x16 , 0x0016 },
+{ 0x17 , 0x0017 },
+{ 0x18 , 0x0018 },
+{ 0x19 , 0x0019 },
+{ 0x1a , 0x001A },
+{ 0x1b , 0x001B },
+{ 0x1c , 0x001C },
+{ 0x1d , 0x001D },
+{ 0x1e , 0x001E },
+{ 0x1f , 0x001F },
+{ 0x20 , 0x0020 },
+{ 0x21 , 0x0021 },
+{ 0x22 , 0x0022 },
+{ 0x23 , 0x0023 },
+{ 0x24 , 0x0024 },
+{ 0x25 , 0x0025 },
+{ 0x26 , 0x0026 },
+{ 0x27 , 0x0027 },
+{ 0x28 , 0x0028 },
+{ 0x29 , 0x0029 },
+{ 0x2a , 0x002A },
+{ 0x2b , 0x002B },
+{ 0x2c , 0x002C },
+{ 0x2d , 0x002D },
+{ 0x2e , 0x002E },
+{ 0x2f , 0x002F },
+{ 0x30 , 0x0030 },
+{ 0x31 , 0x0031 },
+{ 0x32 , 0x0032 },
+{ 0x33 , 0x0033 },
+{ 0x34 , 0x0034 },
+{ 0x35 , 0x0035 },
+{ 0x36 , 0x0036 },
+{ 0x37 , 0x0037 },
+{ 0x38 , 0x0038 },
+{ 0x39 , 0x0039 },
+{ 0x3a , 0x003A },
+{ 0x3b , 0x003B },
+{ 0x3c , 0x003C },
+{ 0x3d , 0x003D },
+{ 0x3e , 0x003E },
+{ 0x3f , 0x003F },
+{ 0x40 , 0x0040 },
+{ 0x41 , 0x0041 },
+{ 0x42 , 0x0042 },
+{ 0x43 , 0x0043 },
+{ 0x44 , 0x0044 },
+{ 0x45 , 0x0045 },
+{ 0x46 , 0x0046 },
+{ 0x47 , 0x0047 },
+{ 0x48 , 0x0048 },
+{ 0x49 , 0x0049 },
+{ 0x4a , 0x004A },
+{ 0x4b , 0x004B },
+{ 0x4c , 0x004C },
+{ 0x4d , 0x004D },
+{ 0x4e , 0x004E },
+{ 0x4f , 0x004F },
+{ 0x50 , 0x0050 },
+{ 0x51 , 0x0051 },
+{ 0x52 , 0x0052 },
+{ 0x53 , 0x0053 },
+{ 0x54 , 0x0054 },
+{ 0x55 , 0x0055 },
+{ 0x56 , 0x0056 },
+{ 0x57 , 0x0057 },
+{ 0x58 , 0x0058 },
+{ 0x59 , 0x0059 },
+{ 0x5a , 0x005A },
+{ 0x5b , 0x005B },
+{ 0x5c , 0x005C },
+{ 0x5d , 0x005D },
+{ 0x5e , 0x005E },
+{ 0x5f , 0x005F },
+{ 0x60 , 0x0060 },
+{ 0x61 , 0x0061 },
+{ 0x62 , 0x0062 },
+{ 0x63 , 0x0063 },
+{ 0x64 , 0x0064 },
+{ 0x65 , 0x0065 },
+{ 0x66 , 0x0066 },
+{ 0x67 , 0x0067 },
+{ 0x68 , 0x0068 },
+{ 0x69 , 0x0069 },
+{ 0x6a , 0x006A },
+{ 0x6b , 0x006B },
+{ 0x6c , 0x006C },
+{ 0x6d , 0x006D },
+{ 0x6e , 0x006E },
+{ 0x6f , 0x006F },
+{ 0x70 , 0x0070 },
+{ 0x71 , 0x0071 },
+{ 0x72 , 0x0072 },
+{ 0x73 , 0x0073 },
+{ 0x74 , 0x0074 },
+{ 0x75 , 0x0075 },
+{ 0x76 , 0x0076 },
+{ 0x77 , 0x0077 },
+{ 0x78 , 0x0078 },
+{ 0x79 , 0x0079 },
+{ 0x7a , 0x007A },
+{ 0x7b , 0x007B },
+{ 0x7c , 0x007C },
+{ 0x7d , 0x007D },
+{ 0x7e , 0x007E },
+{ 0x7f , 0x007F },
+{ 0xa1 , 0x0E01 },
+{ 0xa2 , 0x0E02 },
+{ 0xa3 , 0x0E03 },
+{ 0xa4 , 0x0E04 },
+{ 0xa5 , 0x0E05 },
+{ 0xa6 , 0x0E06 },
+{ 0xa7 , 0x0E07 },
+{ 0xa8 , 0x0E08 },
+{ 0xa9 , 0x0E09 },
+{ 0xaa , 0x0E0A },
+{ 0xab , 0x0E0B },
+{ 0xac , 0x0E0C },
+{ 0xad , 0x0E0D },
+{ 0xae , 0x0E0E },
+{ 0xaf , 0x0E0F },
+{ 0xb0 , 0x0E10 },
+{ 0xb1 , 0x0E11 },
+{ 0xb2 , 0x0E12 },
+{ 0xb3 , 0x0E13 },
+{ 0xb4 , 0x0E14 },
+{ 0xb5 , 0x0E15 },
+{ 0xb6 , 0x0E16 },
+{ 0xb7 , 0x0E17 },
+{ 0xb8 , 0x0E18 },
+{ 0xb9 , 0x0E19 },
+{ 0xba , 0x0E1A },
+{ 0xbb , 0x0E1B },
+{ 0xbc , 0x0E1C },
+{ 0xbd , 0x0E1D },
+{ 0xbe , 0x0E1E },
+{ 0xbf , 0x0E1F },
+{ 0xc0 , 0x0E20 },
+{ 0xc1 , 0x0E21 },
+{ 0xc2 , 0x0E22 },
+{ 0xc3 , 0x0E23 },
+{ 0xc4 , 0x0E24 },
+{ 0xc5 , 0x0E25 },
+{ 0xc6 , 0x0E26 },
+{ 0xc7 , 0x0E27 },
+{ 0xc8 , 0x0E28 },
+{ 0xc9 , 0x0E29 },
+{ 0xca , 0x0E2A },
+{ 0xcb , 0x0E2B },
+{ 0xcc , 0x0E2C },
+{ 0xcd , 0x0E2D },
+{ 0xce , 0x0E2E },
+{ 0xcf , 0x0E2F },
+{ 0xd0 , 0x0E30 },
+{ 0xd1 , 0x0E31 },
+{ 0xd2 , 0x0E32 },
+{ 0xd3 , 0x0E33 },
+{ 0xd4 , 0x0E34 },
+{ 0xd5 , 0x0E35 },
+{ 0xd6 , 0x0E36 },
+{ 0xd7 , 0x0E37 },
+{ 0xd8 , 0x0E38 },
+{ 0xd9 , 0x0E39 },
+{ 0xda , 0x0E3A },
+{ 0xdf , 0x0E3F },
+{ 0xe0 , 0x0E40 },
+{ 0xe1 , 0x0E41 },
+{ 0xe2 , 0x0E42 },
+{ 0xe3 , 0x0E43 },
+{ 0xe4 , 0x0E44 },
+{ 0xe5 , 0x0E45 },
+{ 0xe6 , 0x0E46 },
+{ 0xe7 , 0x0E47 },
+{ 0xe8 , 0x0E48 },
+{ 0xe9 , 0x0E49 },
+{ 0xea , 0x0E4A },
+{ 0xeb , 0x0E4B },
+{ 0xec , 0x0E4C },
+{ 0xed , 0x0E4D },
+{ 0xee , 0x0E4E },
+{ 0xef , 0x0E4F },
+{ 0xf0 , 0x0E50 },
+{ 0xf1 , 0x0E51 },
+{ 0xf2 , 0x0E52 },
+{ 0xf3 , 0x0E53 },
+{ 0xf4 , 0x0E54 },
+{ 0xf5 , 0x0E55 },
+{ 0xf6 , 0x0E56 },
+{ 0xf7 , 0x0E57 },
+{ 0xf8 , 0x0E58 },
+{ 0xf9 , 0x0E59 },
+{ 0xfa , 0x0E5A },
+{ 0xfb , 0x0E5B },
diff --git a/extra/locale/gen_collate_from_glibc.c b/extra/locale/gen_collate_from_glibc.c
deleted file mode 100644
index f6d12ba9c..000000000
--- a/extra/locale/gen_collate_from_glibc.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Generator collate table from glibc special for Uclibc.
- * Author Vladimir Oleynik. vodz@usa.net (c) 2001
- *
- * Require setuped work non-C LC_COLLATE
- * This programm created ./LOCALE/LC_COLLATE file for Uclibc
- * setlocale() and strcoll().
- * Without argument this programm used setlocale(LC_COLLATE, "") -
- * equivalent result setlocale(LC_COLLATE, getenv("LC_XXX"))
- *
- * Also, this programm have russian koi8 collate for test
- * working Uclibc ;-)
- *
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <locale.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/stat.h> /* mkdir() */
-#include <errno.h>
-
-
-/* For strong test russian locale LC_COLLATE="ru_RU.KOI8-R" */
-static const unsigned char koi8_weights[256] = {
- 0, 99, 100, 101, 102, 103, 104, 105,
-106, 2, 5, 3, 6, 4, 107, 108,
-109, 110, 111, 112, 113, 114, 115, 116,
-117, 118, 119, 120, 121, 122, 123, 124,
- 1, 12, 21, 34, 30, 35, 33, 20,
- 22, 23, 31, 36, 9, 8, 15, 14,
-127, 128, 129, 131, 132, 133, 134, 135,
-136, 137, 11, 10, 38, 40, 42, 13,
- 29, 138, 140, 142, 144, 146, 148, 150,
-152, 154, 156, 158, 160, 162, 164, 166,
-168, 170, 172, 174, 176, 178, 180, 182,
-184, 186, 188, 24, 32, 25, 17, 7,
- 16, 139, 141, 143, 145, 147, 149, 151,
-153, 155, 157, 159, 161, 163, 165, 167,
-169, 171, 173, 175, 177, 179, 181, 183,
-185, 187, 189, 26, 43, 27, 18, 125,
- 50, 52, 54, 58, 62, 66, 70, 74,
- 78, 82, 86, 90, 91, 92, 93, 94,
- 95, 96, 97, 48, 98, 45, 46, 47,
- 39, 41, 126, 49, 44, 130, 19, 37,
- 51, 53, 55, 203, 56, 57, 59, 60,
- 61, 63, 64, 65, 67, 68, 69, 71,
- 72, 73, 75, 202, 76, 77, 79, 80,
- 81, 83, 84, 85, 87, 88, 89, 28,
-253, 191, 193, 237, 199, 201, 233, 197,
-235, 209, 211, 213, 215, 217, 219, 221,
-223, 255, 225, 227, 229, 231, 205, 195,
-249, 247, 207, 241, 251, 243, 239, 245,
-252, 190, 192, 236, 198, 200, 232, 196,
-234, 208, 210, 212, 214, 216, 218, 220,
-222, 254, 224, 226, 228, 230, 204, 194,
-248, 246, 206, 240, 250, 242, 238, 244
-};
-
-int gen_weights(const char *collate)
-{
- int weights[256];
- int i,j;
- char probe_str1[2];
- char probe_str2[2];
- char print_buf[16];
- int retcode = 0;
- unsigned char out_weights[256];
- FILE *out;
-
- memset(weights, 0, sizeof(weights));
- probe_str1[1]=probe_str2[1]=0;
-
- for(i=0; i<256; i++) {
- probe_str1[0] = i;
- for(j=0; j<256; j++) {
- probe_str2[0] = j;
- if(strcoll(probe_str1, probe_str2)>0) {
- weights[i]++;
- if(i==j) {
- fprintf(stderr, "\
-\nWarning! c1=%d == c2, but strcoll returned greater zero\n", i);
- retcode++;
- }
- }
- }
- }
- for(i=0; i<256; ) {
- if(isprint(i))
- sprintf(print_buf, " '%c'", i);
- else {
- if(i=='\0')
- strcpy(print_buf, "'\\0'");
- else if(i=='\a')
- strcpy(print_buf, "'\\a'");
- else if(i=='\b')
- strcpy(print_buf, "'\\b'");
- else if(i=='\f')
- strcpy(print_buf, "'\\f'");
- else if(i=='\r')
- strcpy(print_buf, "'\\r'");
- else if(i=='\t')
- strcpy(print_buf, "'\\t'");
- else sprintf(print_buf, " x%02X", i);
- }
- printf("weights[%s] = %3d ", print_buf, weights[i]);
- i++;
- if( (i%4) == 0)
- printf("\n");
- }
-
- for(i=0; i<256; i++) {
- if(weights[i]<0 || weights[i]>=256) {
- fprintf(stderr, "Hmm, weights[%d]=%d\n", i, weights[i]);
- retcode++;
- }
- for(j=0; j<256; j++) {
- if(i==j)
- continue;
- if(weights[i]==weights[j]) {
- fprintf(stderr, "\
-Warning! c1=%d c2=%d and strcoll returned equivalent weight\n", i, j);
- retcode++;
- }
- }
- }
- if(retcode)
- return 1;
-
- if(strcasecmp(collate, "ru_RU.KOI8-R")==0 ||
- strcmp(collate, "ru_RU")==0 ||
- strcmp(collate, "koi8-r")==0) {
- for(i=0; i<256; i++)
- if(weights[i]!=koi8_weights[i]) {
- fprintf(stderr, "\
-Error koi8-r collate compare, glibc weights[%d]=%d but current generation %d\n",
- i, koi8_weights[i], weights[i]);
- retcode++;
- }
- if(retcode)
- return 5;
- }
- for(i=0; i<256; i++)
- out_weights[i] = weights[i];
- out = fopen("LC_COLLATE", "w");
- if(out == NULL) {
- fprintf(stderr, "Can`t create ./%s/LC_COLLATE file\n", collate);
- return 10;
- }
- if(fwrite(out_weights, 1, 256, out)!=256) {
- fprintf(stderr, "IO error in process write ./%s/LC_COLLATE file\n", collate);
- return 11;
- }
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- char *locale;
- char *slr;
- char *collate;
-
- if(argc<1 || argc>2) {
- fprintf(stderr, "Usage: %s [locale]\n", argv[0]);
- }
- locale = argc==1 ? "" : argv[1];
-
- collate = setlocale(LC_COLLATE, locale);
- fprintf(stderr, "setlocale(LC_COLLATE, \"%s\") returned %s\n", locale, collate);
- if(collate==0) {
- fprintf(stderr, "Can`t set LC_COLLATE\n");
- return 2;
- }
- if(strcmp(collate, "C")==0) {
- fprintf(stderr, "\
-LC_COLLATE=\"C\" is trivial and not interesting for this programm\n");
- return 3;
- }
- slr = setlocale(LC_CTYPE, locale);
- fprintf(stderr, "setlocale(LC_CTYPE, \"%s\") returned %s\n", locale, slr);
- if(slr==0) {
- slr = setlocale(LC_CTYPE, "POSIX");
- if(slr==0) {
- fprintf(stderr, "Hmm, can`t set setlocale(LC_CTYPE, \"POSIX\")\n");
- return 4;
- }
- }
- if(mkdir(collate, 0755)!=0 && errno!=EEXIST) {
- fprintf(stderr, "Can`t make directory %s\n", collate);
- return 6;
- }
- if(chdir(collate)) {
- fprintf(stderr, "Hmm, can`t change directory to %s\n", collate);
- return 7;
- }
- if(gen_weights(collate)) {
- if(chdir("..")) {
- fprintf(stderr, "Hmm, can`t change to current directory\n");
- return 7;
- }
- rmdir(collate);
- return 1;
- }
- return 0;
-}
diff --git a/extra/locale/gen_ctype_from_glibc.c b/extra/locale/gen_ctype_from_glibc.c
deleted file mode 100644
index 0488048cd..000000000
--- a/extra/locale/gen_ctype_from_glibc.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Generator locale ctype tables
- * You must have already setuped locale for worked libc (libc5 or glibc)
- *
- * This programm scan /usr/share/locale directories and write
- * ./LOCALE/LC_CTYPE files for system with uclibc
- *
- * Written by Vladimir Oleynik <vodz@usa.net> 2001
- * Base on ideas Nickolay Saukh <nms@ussr.EU.net>
- *
- */
-
-#include <locale.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "../../libc/misc/locale/_locale.h"
-
-
-#define DEFAULT_LOCALE_DIR "/usr/share/locale/"
-
-#define DEF_OUT_NAME "LC_CTYPE"
-
-#define CURRENT_SUPPORT_MAX (LOCALE_BUF_SIZE/2)
-
-
-unsigned char x2type[CURRENT_SUPPORT_MAX];
-
-unsigned char x2trans[CURRENT_SUPPORT_MAX];
-
-
-
-int
-write_out (outname)
- unsigned char *outname;
-{
- FILE *ofp = fopen (outname, "w");
-
- if (ofp == NULL) {
- fprintf (stderr, "Can`t write `%s\n", outname);
- return 1;
- }
-
- fwrite (x2type, sizeof (x2type), 1, ofp);
- fwrite (x2trans, sizeof (x2trans), 1, ofp);
- fclose (ofp);
- return 0;
-}
-
-
-typedef struct bbits_ {
- int bbits;
- char *bb_name;
- } bbits_t;
-
-
-bbits_t basic_bits[] =
-{
- {ISprint , "ISprint" },
- {ISupper , "ISupper" },
- {ISlower , "ISlower" },
- {IScntrl , "IScntrl" },
- {ISspace , "ISspace" },
- {ISpunct , "ISpunct" },
- {ISalpha , "ISalpha" },
- {ISxdigit, "ISxdigit"},
- {0, NULL}
-};
-
-
-void
-ctab_out (char *oun)
-{
- int i;
- char *outname;
- FILE *fout;
-
- outname = alloca(strlen(oun)+strlen("ctype_.c")+1);
- if(outname==0) {
- perror("");
- exit(1);
- }
- strcpy(outname, "ctype_");
- strcat(outname, oun);
- strcat(outname, ".c");
-
- fout = fopen (outname, "w");
-
- if (fout == NULL)
- {
- perror ("");
- return;
- }
-
- fprintf (fout, "const unsigned char _uc_ctype_b_C[LOCALE_BUF_SIZE] = {\n");
-
- for (i = 0; i < CURRENT_SUPPORT_MAX; i++)
- {
- if(i)
- fprintf (fout, ",\n");
- fprintf (fout, "\t/* 0x%02x, %d, 0%o */\t", i, i, i);
- if (x2type[i])
- {
- int dirty = 0;
- bbits_t *tb = basic_bits;
-
- while (tb->bbits)
- {
- if (x2type[i] & tb->bbits)
- {
- if (dirty)
- fputs ("|", fout);
- fputs (tb->bb_name, fout);
- dirty = 1;
- }
- tb++;
- }
- }
- else
- fputs ("0", fout);
- }
-
- fputs (",\n\n", fout);
-
- fprintf (fout, "/* _uc_ctype_trans_C */\n\n");
-
- for (i = 0; i < CURRENT_SUPPORT_MAX; i++)
- {
- if(i)
- fprintf (fout, ",\n");
- fprintf (fout, "\t/* 0x%02x, %d, 0%o */\t0x%02x", i, i, i, x2trans[i]);
- }
- fputs ("\n};\n", fout);
-
- (void) fclose (fout);
-}
-
-
-int
-main (int argc, char *argv[])
-{
- int i,l;
- char *outname = DEF_OUT_NAME;
- char *search_dir = DEFAULT_LOCALE_DIR;
- char *full_path = 0;
- DIR *dir;
- struct dirent *next;
- char *t;
- int err=0;
- char *ln;
- int generate_c_code = 1;
-
- while ((i = getopt (argc, argv, "d:o:c")) != EOF) {
- switch (i) {
- case 'o':
- outname = optarg;
- break;
- case 'd':
- search_dir = optarg;
- break;
- case 'c':
- generate_c_code = 0;
- break;
- default:
- optind = i = -1;
- break;
- }
- if(i<0)
- break;
- }
-
- if (argc > optind) {
- fprintf (stderr,
-"Usage: %s [-d search_dir] [-o output_name] [-c]\n\
-Defaults:\n\
- search_dir : " DEFAULT_LOCALE_DIR "\n\
- output_name : " DEF_OUT_NAME "\n\
- -c : no generate c-code for other locale exept C-locale.\n"
- , argv[0]);
- return 3;
- }
-
- l = strlen(search_dir);
- if(l == 0) {
- search_dir = "./";
- l = 2;
- } else {
- if(search_dir[l-1]!='/') {
-
- t = malloc(l+2);
- if(t==0) {
- fprintf (stderr, "Can`t get %d bytes memory\n", l+2);
- return 4;
- }
- search_dir = strcat(strcpy(t, search_dir), "/");
- l++;
- }
- }
-
- dir = opendir(search_dir);
- if (!dir) {
- fprintf (stderr, "Can`t open directory `%s' load all locales\n", search_dir);
- return 2;
- }
-
- while ((next = readdir(dir)) != NULL) {
-
- struct stat st;
- if(strcmp(next->d_name, ".")==0)
- ln = "C";
- else if(strcmp(next->d_name, "..")==0)
- continue;
- else {
- ln = next->d_name;
- full_path = realloc(full_path, l+strlen(ln)+1);
- strcat(strcpy(full_path, search_dir), ln);
- if (lstat(full_path, &st) < 0)
- continue;
- if(S_ISDIR(st.st_mode)==0)
- continue;
- }
- t = setlocale(LC_CTYPE, ln);
- printf("setlocale(LC_CTYPE, %s) returned %s\n", ln, t);
- if(t==0)
- continue;
- if(mkdir(ln, 0755)!=0 && errno!=EEXIST) {
- fprintf(stderr, "Can`t create directory `%s'\n", ln);
- continue;
- }
- if(chdir(ln)) {
- fprintf(stderr, "Can`t change directory to `%s'\n", ln);
- continue;
- }
-
- for (i = 0; i < CURRENT_SUPPORT_MAX; i++) {
-
- if(isprint(i))
- x2type[i] |= ISprint;
- if(isupper(i))
- x2type[i] |= ISupper;
- if(islower(i))
- x2type[i] |= ISlower;
- if(isspace(i))
- x2type[i] |= ISspace;
- if(isalpha(i))
- x2type[i] |= ISalpha;
- if(iscntrl(i))
- x2type[i] |= IScntrl;
- if(ispunct(i))
- x2type[i] |= ISpunct;
- if(isxdigit(i))
- x2type[i] |= ISxdigit;
- x2trans[i] = i;
- if(toupper(x2trans[i]) != x2trans[i])
- x2trans[i] = toupper(x2trans[i]);
- else if(tolower(x2trans[i]) != x2trans[i])
- x2trans[i] = tolower(x2trans[i]);
- }
- err += write_out(outname);
- if(chdir("..")) {
- fprintf(stderr, "Can`t change directory to `..'\n");
- return 1;
- }
- if(strcmp(ln, "C")==0 || generate_c_code!=0)
- ctab_out(ln);
- for (i = 0; i < CURRENT_SUPPORT_MAX; i++)
- x2type[i] = x2trans[i] = 0;
- }
- return err ? 1 : 0;
-}
diff --git a/extra/locale/gen_locale.c b/extra/locale/gen_locale.c
new file mode 100644
index 000000000..9b2576e50
--- /dev/null
+++ b/extra/locale/gen_locale.c
@@ -0,0 +1,1254 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <nl_types.h>
+#include <stdint.h>
+
+#define __CTYPE_HAS_8_BIT_LOCALES
+#include "c8tables.h"
+
+
+#define CATEGORIES 6
+
+/* must agree with ordering of gen_mmap! */
+static const unsigned char *lc_names[] = {
+ "LC_CTYPE",
+ "LC_NUMERIC",
+ "LC_MONETARY",
+ "LC_TIME",
+ "LC_COLLATE",
+ "LC_MESSAGES",
+#if CATEGORIES == 12
+ "LC_PAPER",
+ "LC_NAME",
+ "LC_ADDRESS",
+ "LC_TELEPHONE",
+ "LC_MEASUREMENT",
+ "LC_IDENTIFICATION",
+#elif CATEGORIES != 6
+#error unsupported CATEGORIES value!
+#endif
+};
+
+
+
+typedef struct {
+ char *glibc_name;
+ char name[5];
+ char dot_cs; /* 0 if no codeset specified */
+ char cs;
+ unsigned char idx_name;
+ unsigned char lc_time_row;
+ unsigned char lc_numeric_row;
+ unsigned char lc_monetary_row;
+ unsigned char lc_messages_row;
+#if CATEGORIES != 6
+#error unsupported CATEGORIES value
+#endif
+} locale_entry;
+
+static void read_at_mappings(void);
+static void read_enable_disable(void);
+static void read_locale_list(void);
+
+static int find_codeset_num(const char *cs);
+static int find_at_string_num(const char *as);
+static int le_cmp(const void *, const void *);
+static void dump_table8(const char *name, const char *tbl, int len);
+static void dump_table8c(const char *name, const char *tbl, int len);
+static void dump_table16(const char *name, const int *tbl, int len);
+
+static void do_lc_time(void);
+static void do_lc_numeric(void);
+static void do_lc_monetary(void);
+
+static void do_lc_messages(void);
+
+
+static FILE *fp;
+static FILE *ofp;
+static char line_buf[80];
+static char at_mappings[256];
+static char at_mapto[256];
+static char at_strings[1024];
+static char *at_strings_end;
+static locale_entry locales[700];
+static char glibc_locale_names[60000];
+
+static int num_locales;
+
+static int default_utf8;
+static int default_8bit;
+
+static int total_size;
+static int null_count;
+
+static void do_locale_names(void)
+{
+ /* "C" locale name is handled specially by the setlocale code. */
+ int uniq = 0;
+ int i;
+
+ if (num_locales <= 1) {
+/* printf("error - only C locale?\n"); */
+/* exit(EXIT_FAILURE); */
+ fprintf(ofp, "static const unsigned char __locales[%d];\n", (3 + CATEGORIES));
+ fprintf(ofp, "static const unsigned char __locale_names5[5];\n");
+ } else {
+ fprintf(ofp, "#define CATEGORIES\t\t\t%d\n", CATEGORIES);
+ fprintf(ofp, "#define WIDTH_LOCALES\t\t\t%d\n", 3+CATEGORIES);
+ fprintf(ofp, "#define NUM_LOCALES\t\t\t%d\n", num_locales);
+ fprintf(ofp, "static const unsigned char __locales[%d] = {\n",
+ (num_locales) * (3 + CATEGORIES));
+ for (i=0 ; i < num_locales ; i++) {
+ if (memcmp(locales[i].name, locales[i-1].name, 5) != 0) {
+ locales[i].idx_name = uniq;
+ ++uniq;
+ } else {
+ locales[i].idx_name = uniq - 1;
+ }
+ fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].idx_name));
+ fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].dot_cs));
+ fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].cs));
+ /* lc_ctype would store translit flags and turkish up/low flag. */
+ fprintf(ofp, "%#4x, ", 0); /* place holder for lc_ctype */
+ fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_numeric_row));
+ fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_monetary_row));
+ fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_time_row));
+ fprintf(ofp, "%#4x, ", 0); /* place holder for lc_collate */
+ fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_messages_row));
+ fprintf(ofp, "\t/* %s */\n", locales[i].glibc_name);
+ }
+ fprintf(ofp, "};\n\n");
+
+ fprintf(ofp, "#define NUM_LOCALE_NAMES\t\t%d\n", uniq );
+ fprintf(ofp, "static const unsigned char __locale_names5[%d] = \n\t", uniq * 5);
+ uniq = 0;
+ for (i=1 ; i < num_locales ; i++) {
+ if (memcmp(locales[i].name, locales[i-1].name, 5) != 0) {
+ fprintf(ofp, "\"%5.5s\" ", locales[i].name);
+ ++uniq;
+ if ((uniq % 8) == 0) {
+ fprintf(ofp, "\n\t");
+ }
+ }
+ }
+ fprintf(ofp,";\n\n");
+
+ if (at_strings_end > at_strings) {
+ int i, j;
+ char *p;
+ i = 0;
+ p = at_strings;
+ while (*p) {
+ ++i;
+ p += 1 + (unsigned char) *p;
+ }
+ /* len, char, string\0 */
+ fprintf(ofp, "#define LOCALE_AT_MODIFIERS_LENGTH\t\t%d\n",
+ i + (at_strings_end - at_strings));
+ fprintf(ofp, "static const unsigned char __locale_at_modifiers[%d] = {",
+ i + (at_strings_end - at_strings));
+ i = 0;
+ p = at_strings;
+ while (*p) {
+ fprintf(ofp, "\n\t%4d, '%c',",
+ (unsigned char) *p, /* len of string\0 */
+ at_mapto[i]);
+ for (j=1 ; j < ((unsigned char) *p) ; j++) {
+ fprintf(ofp, " '%c',", p[j]);
+ }
+ fprintf(ofp, " 0,");
+ ++i;
+ p += 1 + (unsigned char) *p;
+ }
+ fprintf(ofp, "\n};\n\n");
+ }
+
+ {
+ int pos[CATEGORIES];
+ pos[0] = CATEGORIES;
+ for (i=0 ; i < CATEGORIES ; i++) {
+ fprintf(ofp, "#define __%s\t\t%d\n", lc_names[i], i);
+ if (i + 1 < CATEGORIES) {
+ pos[i+1] = 1 + strlen(lc_names[i]) + pos[i];
+ }
+ }
+ if (pos[CATEGORIES-1] > 255) {
+ printf("error - lc_names is too big (%d)\n", pos[CATEGORIES-1]);
+ exit(EXIT_FAILURE);
+ }
+ fprintf(ofp, "#define __LC_ALL\t\t%d\n\n", i);
+
+ fprintf(ofp, "#define lc_names_LEN\t\t%d\n",
+ pos[CATEGORIES-1] + strlen(lc_names[CATEGORIES-1]) + 1);
+ total_size += pos[CATEGORIES-1] + strlen(lc_names[CATEGORIES-1]) + 1;
+
+ fprintf(ofp, "static unsigned const char lc_names[%d] =\n",
+ pos[CATEGORIES-1] + strlen(lc_names[CATEGORIES-1]) + 1);
+ fprintf(ofp, "\t\"");
+ for (i=0 ; i < CATEGORIES ; i++) {
+ fprintf(ofp, "\\x%02x", (unsigned char) pos[i]);
+ }
+ fprintf(ofp, "\"");
+ for (i=0 ; i < CATEGORIES ; i++) {
+ fprintf(ofp, "\n\t\"%s\\0\"", lc_names[i]);
+ }
+ fprintf(ofp, ";\n\n");
+ }
+
+ printf("locale data = %d name data = %d for %d uniq\n",
+ num_locales * (3 + CATEGORIES), uniq * 5, uniq);
+
+ total_size += num_locales * (3 + CATEGORIES) + uniq * 5;
+ }
+
+}
+
+int main(int argc, char **argv)
+{
+ if ((argc != 2) || (!(fp = fopen(*++argv, "r")))) {
+ printf("error: missing filename or file!\n");
+ return EXIT_FAILURE;
+ }
+
+ at_strings_end = at_strings;
+
+ read_at_mappings();
+ read_enable_disable();
+ read_locale_list();
+
+ fclose(fp);
+
+ /* handle C locale specially */
+ qsort(locales+1, num_locales-1, sizeof(locale_entry), le_cmp);
+
+#if 0
+ for (i=0 ; i < num_locales ; i++) {
+ printf("locale: %5.5s %2d %2d %s\n",
+ locales[i].name,
+ locales[i].cs,
+ locales[i].dot_cs,
+ locales[i].glibc_name
+ );
+ }
+#endif
+
+ if (!(ofp = fopen("locale_tables.h", "w"))) {
+ printf("error: can not open locale_tables.h for writing!\n");
+ return EXIT_FAILURE;
+ }
+
+ do_lc_time();
+ do_lc_numeric();
+ do_lc_monetary();
+ do_lc_messages();
+
+ do_locale_names();
+
+ fclose(ofp);
+
+ printf("total data size = %d\n", total_size);
+ printf("null count = %d\n", null_count);
+
+ return EXIT_SUCCESS;
+}
+
+static char *idx[10000];
+static char buf[100000];
+static char *last;
+static int uniq;
+
+static int addstring(const char *s)
+{
+ int j;
+ size_t l;
+
+ if (!s) {
+ ++null_count;
+ return 0;
+ }
+
+ for (j=0 ; j < uniq ; j++) {
+ if (!strcmp(s, idx[j])) {
+ return idx[j] - buf;
+ }
+ }
+ if (uniq >= sizeof(idx)) {
+ printf("too many uniq strings!\n");
+ exit(EXIT_FAILURE);
+ }
+ l = strlen(s) + 1;
+ if (last + l >= buf + sizeof(buf)) {
+ printf("need to increase size of buf!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ idx[uniq] = last;
+ ++uniq;
+ strcpy(last, s);
+ last += l;
+ return idx[uniq - 1] - buf;
+}
+
+static int buf16[50*256];
+
+
+static int lc_time_item[50][256];
+static int lc_time_count[50];
+static unsigned char lc_time_uniq_50[700][50];
+static int lc_time_uniq;
+
+#define DO_NL_S(X) lc_time_S(X, k++)
+
+static void lc_time_S(int X, int k)
+{
+ int j, m;
+ j = addstring(nl_langinfo(X));
+ for (m=0 ; m < lc_time_count[k] ; m++) {
+ if (lc_time_item[k][m] == j) {
+ break;
+ }
+ }
+ if (m == lc_time_count[k]) { /* new for this nl_item */
+ if (m > 255) {
+ printf("too many nl_item %d entries in lc_time\n", k);
+ exit(EXIT_FAILURE);
+ }
+ lc_time_item[k][m] = j;
+ ++lc_time_count[k];
+ }
+/* printf("\\x%02x", m); */
+ lc_time_uniq_50[lc_time_uniq][k] = m;
+}
+
+static void do_lc_time(void)
+{
+ int i, k, m;
+
+ last = buf+1;
+ uniq = 1;
+ *buf = 0;
+ *idx = buf;
+
+/* printf("processing lc_time..."); */
+ for (i=0 ; i < num_locales ; i++) {
+ k = 0;
+
+/* printf(" %d", i); fflush(stdout); */
+ if (!setlocale(LC_ALL, locales[i].glibc_name)) {
+ printf("setlocale(LC_ALL,%s) failed!\n",
+ locales[i].glibc_name);
+ }
+
+ DO_NL_S(ABDAY_1);
+ DO_NL_S(ABDAY_2);
+ DO_NL_S(ABDAY_3);
+ DO_NL_S(ABDAY_4);
+ DO_NL_S(ABDAY_5);
+ DO_NL_S(ABDAY_6);
+ DO_NL_S(ABDAY_7);
+
+ DO_NL_S(DAY_1);
+ DO_NL_S(DAY_2);
+ DO_NL_S(DAY_3);
+ DO_NL_S(DAY_4);
+ DO_NL_S(DAY_5);
+ DO_NL_S(DAY_6);
+ DO_NL_S(DAY_7);
+
+ DO_NL_S(ABMON_1);
+ DO_NL_S(ABMON_2);
+ DO_NL_S(ABMON_3);
+ DO_NL_S(ABMON_4);
+ DO_NL_S(ABMON_5);
+ DO_NL_S(ABMON_6);
+ DO_NL_S(ABMON_7);
+ DO_NL_S(ABMON_8);
+ DO_NL_S(ABMON_9);
+ DO_NL_S(ABMON_10);
+ DO_NL_S(ABMON_11);
+ DO_NL_S(ABMON_12);
+
+ DO_NL_S(MON_1);
+ DO_NL_S(MON_2);
+ DO_NL_S(MON_3);
+ DO_NL_S(MON_4);
+ DO_NL_S(MON_5);
+ DO_NL_S(MON_6);
+ DO_NL_S(MON_7);
+ DO_NL_S(MON_8);
+ DO_NL_S(MON_9);
+ DO_NL_S(MON_10);
+ DO_NL_S(MON_11);
+ DO_NL_S(MON_12);
+
+ DO_NL_S(AM_STR);
+ DO_NL_S(PM_STR);
+
+ DO_NL_S(D_T_FMT);
+ DO_NL_S(D_FMT);
+ DO_NL_S(T_FMT);
+ DO_NL_S(T_FMT_AMPM);
+ DO_NL_S(ERA);
+
+ DO_NL_S(ERA_YEAR); /* non SuSv3 */
+ DO_NL_S(ERA_D_FMT);
+ DO_NL_S(ALT_DIGITS);
+ DO_NL_S(ERA_D_T_FMT);
+ DO_NL_S(ERA_T_FMT);
+
+ if (k > 50) {
+ printf("error -- lc_time nl_item count > 50!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ {
+ int r;
+ for (r=0 ; r < lc_time_uniq ; r++) {
+ if (!memcmp(lc_time_uniq_50[lc_time_uniq],
+ lc_time_uniq_50[r], 50)) {
+ break;
+ }
+ }
+ if (r == lc_time_uniq) { /* new locale row */
+ ++lc_time_uniq;
+ if (lc_time_uniq > 255) {
+ printf("too many unique lc_time rows!\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ locales[i].lc_time_row = r;
+ }
+/* printf("\n"); */
+ }
+/* printf(" done\n"); */
+
+ m = k = 0;
+ for (i=0 ; i < 50 ; i++) {
+ k += lc_time_count[i];
+ if (m < lc_time_count[i]) {
+ m = lc_time_count[i];
+ }
+ }
+ printf("buf-size=%d uniq=%d item_offsets=%d max=%d rows=%d\n",
+ (int)(last - buf), uniq, k, m, lc_time_uniq);
+/* printf("total = %d * 50 + 2 * (50 + %d) + %d = %d\n", */
+/* num_locales, k, (int)(last - buf), */
+/* num_locales*50 + 2*(50 + k) + (int)(last - buf)); */
+ printf("total = %d + %d * 50 + 2 * (50 + %d) + %d = %d\n",
+ num_locales, lc_time_uniq, k, (int)(last - buf),
+ i = num_locales + lc_time_uniq*50 + 2*(50 + k) + (int)(last - buf));
+ total_size += i;
+
+ dump_table8c("__lc_time_data", buf, (int)(last - buf));
+
+ for (i=0 ; i < lc_time_uniq ; i++) {
+ m = locales[i].lc_time_row;
+ for (k=0 ; k < 50 ; k++) {
+ buf[50*i + k] = (char)((unsigned char) lc_time_uniq_50[i][k]);
+ }
+ }
+ dump_table8("__lc_time_rows", buf, lc_time_uniq * 50);
+
+ buf16[0] =0;
+ for (i=0 ; i < 50 - 1 ; i++) {
+ buf16[i+1] = buf16[i] + lc_time_count[i];
+ }
+ dump_table16("__lc_time_item_offsets", buf16, 50);
+
+ m = 0;
+ for (k=0 ; k < 50 ; k++) {
+ for (i=0 ; i < lc_time_count[k] ; i++) {
+ buf16[m] = lc_time_item[k][i];
+ ++m;
+ }
+ }
+ dump_table16("__lc_time_item_idx", buf16, m);
+}
+
+static void dump_table8(const char *name, const char *tbl, int len)
+{
+ int i;
+
+ fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len);
+ fprintf(ofp, "static const unsigned char %s[%d] = {", name, len);
+ for (i=0 ; i < len ; i++) {
+ if ((i % 12) == 0) {
+ fprintf(ofp, "\n\t");
+ }
+ fprintf(ofp, "%#4x, ", (int)((unsigned char) tbl[i]));
+ }
+ fprintf(ofp, "\n};\n\n");
+}
+
+#define __C_isdigit(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)((c) - '0')) < 10) \
+ : (((unsigned int)((c) - '0')) < 10))
+#define __C_isalpha(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)(((c) | 0x20) - 'a')) < 26) \
+ : (((unsigned int)(((c) | 0x20) - 'a')) < 26))
+#define __C_isalnum(c) (__C_isalpha(c) || __C_isdigit(c))
+
+static void dump_table8c(const char *name, const char *tbl, int len)
+{
+ int i;
+
+ fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len);
+ fprintf(ofp, "static const unsigned char %s[%d] = {", name, len);
+ for (i=0 ; i < len ; i++) {
+ if ((i % 12) == 0) {
+ fprintf(ofp, "\n\t");
+ }
+ if (__C_isalnum(tbl[i]) || (tbl[i] == ' ')) {
+ fprintf(ofp, " '%c', ", (int)((unsigned char) tbl[i]));
+ } else {
+ fprintf(ofp, "%#4x, ", (int)((unsigned char) tbl[i]));
+ }
+ }
+ fprintf(ofp, "\n};\n\n");
+}
+
+static void dump_table16(const char *name, const int *tbl, int len)
+{
+ int i;
+
+ fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len);
+ fprintf(ofp, "static const uint16_t %s[%d] = {", name, len);
+ for (i=0 ; i < len ; i++) {
+ if ((i % 8) == 0) {
+ fprintf(ofp, "\n\t");
+ }
+ if (tbl[i] != (uint16_t) tbl[i]) {
+ printf("error - falls outside uint16 range!\n");
+ exit(EXIT_FAILURE);
+ }
+ fprintf(ofp, "%#6x, ", tbl[i]);
+ }
+ fprintf(ofp, "\n};\n\n");
+}
+
+#undef DO_NL_S
+
+static int lc_numeric_item[3][256];
+static int lc_numeric_count[3];
+static unsigned char lc_numeric_uniq_3[700][3];
+static int lc_numeric_uniq;
+
+#define DO_NL_S(X) lc_numeric_S(X, k++)
+
+static void lc_numeric_S(int X, int k)
+{
+ int j, m;
+ j = addstring(nl_langinfo(X));
+ for (m=0 ; m < lc_numeric_count[k] ; m++) {
+ if (lc_numeric_item[k][m] == j) {
+ break;
+ }
+ }
+ if (m == lc_numeric_count[k]) { /* new for this nl_item */
+ if (m > 255) {
+ printf("too many nl_item %d entries in lc_numeric\n", k);
+ exit(EXIT_FAILURE);
+ }
+ lc_numeric_item[k][m] = j;
+ ++lc_numeric_count[k];
+ }
+/* printf("\\x%02x", m); */
+ lc_numeric_uniq_3[lc_numeric_uniq][k] = m;
+}
+
+static void do_lc_numeric(void)
+{
+ int i, k, m;
+
+ last = buf+1;
+ uniq = 1;
+ *buf = 0;
+ *idx = buf;
+
+ for (i=0 ; i < num_locales ; i++) {
+ k = 0;
+
+ if (!setlocale(LC_ALL, locales[i].glibc_name)) {
+ printf("setlocale(LC_ALL,%s) failed!\n",
+ locales[i].glibc_name);
+ }
+
+ DO_NL_S(RADIXCHAR); /* DECIMAL_POINT */
+ DO_NL_S(THOUSEP); /* THOUSANDS_SEP */
+ DO_NL_S(GROUPING);
+
+ if (k > 3) {
+ printf("error -- lc_numeric nl_item count > 3!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ {
+ int r;
+ for (r=0 ; r < lc_numeric_uniq ; r++) {
+ if (!memcmp(lc_numeric_uniq_3[lc_numeric_uniq],
+ lc_numeric_uniq_3[r], 3)) {
+ break;
+ }
+ }
+ if (r == lc_numeric_uniq) { /* new locale row */
+ ++lc_numeric_uniq;
+ if (lc_numeric_uniq > 255) {
+ printf("too many unique lc_numeric rows!\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ locales[i].lc_numeric_row = r;
+ }
+ }
+
+ printf("buf-size=%d uniq=%d rows=%d\n",
+ (int)(last - buf), uniq, lc_numeric_uniq);
+ printf("total = %d + %d * 3 + %d = %d\n",
+ num_locales, lc_numeric_uniq, (int)(last - buf),
+ i = num_locales + lc_numeric_uniq*3 + (int)(last - buf));
+ total_size += i;
+
+/* printf("buf-size=%d uniq=%d\n", (int)(last - buf), uniq); */
+
+ dump_table8c("__lc_numeric_data", buf, (int)(last - buf));
+
+
+ for (i=0 ; i < lc_numeric_uniq ; i++) {
+ m = locales[i].lc_numeric_row;
+ for (k=0 ; k < 3 ; k++) {
+ buf[3*i + k] = (char)((unsigned char) lc_numeric_uniq_3[i][k]);
+ }
+ }
+ dump_table8("__lc_numeric_rows", buf, lc_numeric_uniq * 3);
+
+ buf16[0] =0;
+ for (i=0 ; i < 3 - 1 ; i++) {
+ buf16[i+1] = buf16[i] + lc_numeric_count[i];
+ }
+ dump_table16("__lc_numeric_item_offsets", buf16, 3);
+
+ m = 0;
+ for (k=0 ; k < 3 ; k++) {
+ for (i=0 ; i < lc_numeric_count[k] ; i++) {
+ buf16[m] = lc_numeric_item[k][i];
+ ++m;
+ }
+ }
+ dump_table16("__lc_numeric_item_idx", buf16, m);
+}
+
+#undef DO_NL_S
+
+/* #define NUM_NL_MONETARY 7 */
+#define NUM_NL_MONETARY (7+14+1)
+
+static int lc_monetary_item[NUM_NL_MONETARY][256];
+static int lc_monetary_count[NUM_NL_MONETARY];
+static unsigned char lc_monetary_uniq_X[700][NUM_NL_MONETARY];
+static int lc_monetary_uniq;
+
+#define DO_NL_S(X) lc_monetary_S(X, k++)
+
+/* #define DO_NL_C(X) printf("%#02x", (int)(unsigned char)(*nl_langinfo(X))); */
+#define DO_NL_C(X) lc_monetary_C(X, k++)
+
+static void lc_monetary_C(int X, int k)
+{
+ int j, m;
+ char c_buf[2];
+
+#warning fix the char entries for monetary... target signedness of char may be different!
+
+ c_buf[1] = 0;
+ c_buf[0] = *nl_langinfo(X);
+ j = addstring(c_buf);
+ for (m=0 ; m < lc_monetary_count[k] ; m++) {
+ if (lc_monetary_item[k][m] == j) {
+ break;
+ }
+ }
+ if (m == lc_monetary_count[k]) { /* new for this nl_item */
+ if (m > 255) {
+ printf("too many nl_item %d entries in lc_monetary\n", k);
+ exit(EXIT_FAILURE);
+ }
+ lc_monetary_item[k][m] = j;
+ ++lc_monetary_count[k];
+ }
+/* printf("\\x%02x", m); */
+ lc_monetary_uniq_X[lc_monetary_uniq][k] = m;
+}
+
+
+static void lc_monetary_S(int X, int k)
+{
+ int j, m;
+ j = addstring(nl_langinfo(X));
+ for (m=0 ; m < lc_monetary_count[k] ; m++) {
+ if (lc_monetary_item[k][m] == j) {
+ break;
+ }
+ }
+ if (m == lc_monetary_count[k]) { /* new for this nl_item */
+ if (m > 255) {
+ printf("too many nl_item %d entries in lc_monetary\n", k);
+ exit(EXIT_FAILURE);
+ }
+ lc_monetary_item[k][m] = j;
+ ++lc_monetary_count[k];
+ }
+/* printf("\\x%02x", m); */
+ lc_monetary_uniq_X[lc_monetary_uniq][k] = m;
+}
+
+static void do_lc_monetary(void)
+{
+ int i, k, m;
+
+ last = buf+1;
+ uniq = 1;
+ *buf = 0;
+ *idx = buf;
+
+ for (i=0 ; i < num_locales ; i++) {
+ k = 0;
+
+ if (!setlocale(LC_ALL, locales[i].glibc_name)) {
+ printf("setlocale(LC_ALL,%s) failed!\n",
+ locales[i].glibc_name);
+ }
+
+
+ /* non SUSv3 */
+ DO_NL_S(INT_CURR_SYMBOL);
+ DO_NL_S(CURRENCY_SYMBOL);
+ DO_NL_S(MON_DECIMAL_POINT);
+ DO_NL_S(MON_THOUSANDS_SEP);
+ DO_NL_S(MON_GROUPING);
+ DO_NL_S(POSITIVE_SIGN);
+ DO_NL_S(NEGATIVE_SIGN);
+ DO_NL_C(INT_FRAC_DIGITS);
+ DO_NL_C(FRAC_DIGITS);
+ DO_NL_C(P_CS_PRECEDES);
+ DO_NL_C(P_SEP_BY_SPACE);
+ DO_NL_C(N_CS_PRECEDES);
+ DO_NL_C(N_SEP_BY_SPACE);
+ DO_NL_C(P_SIGN_POSN);
+ DO_NL_C(N_SIGN_POSN);
+ DO_NL_C(INT_P_CS_PRECEDES);
+ DO_NL_C(INT_P_SEP_BY_SPACE);
+ DO_NL_C(INT_N_CS_PRECEDES);
+ DO_NL_C(INT_N_SEP_BY_SPACE);
+ DO_NL_C(INT_P_SIGN_POSN);
+ DO_NL_C(INT_N_SIGN_POSN);
+
+ DO_NL_S(CRNCYSTR); /* CURRENCY_SYMBOL */
+
+/* printf("\n"); */
+
+ if (k > NUM_NL_MONETARY) {
+ printf("error -- lc_monetary nl_item count > %d!\n", NUM_NL_MONETARY);
+ exit(EXIT_FAILURE);
+ }
+
+ {
+ int r;
+ for (r=0 ; r < lc_monetary_uniq ; r++) {
+ if (!memcmp(lc_monetary_uniq_X[lc_monetary_uniq],
+ lc_monetary_uniq_X[r], NUM_NL_MONETARY)) {
+ break;
+ }
+ }
+ if (r == lc_monetary_uniq) { /* new locale row */
+ ++lc_monetary_uniq;
+ if (lc_monetary_uniq > 255) {
+ printf("too many unique lc_monetary rows!\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ locales[i].lc_monetary_row = r;
+ }
+ }
+
+ printf("buf-size=%d uniq=%d rows=%d\n",
+ (int)(last - buf), uniq, lc_monetary_uniq);
+ printf("total = %d + %d * %d + %d = %d\n",
+ num_locales, lc_monetary_uniq, NUM_NL_MONETARY, (int)(last - buf),
+ i = num_locales + lc_monetary_uniq*NUM_NL_MONETARY + (int)(last - buf));
+ total_size += i;
+
+ dump_table8c("__lc_monetary_data", buf, (int)(last - buf));
+
+ for (i=0 ; i < lc_monetary_uniq ; i++) {
+ m = locales[i].lc_monetary_row;
+ for (k=0 ; k < NUM_NL_MONETARY ; k++) {
+ buf[NUM_NL_MONETARY*i + k] = (char)((unsigned char) lc_monetary_uniq_X[i][k]);
+ }
+ }
+ dump_table8("__lc_monetary_rows", buf, lc_monetary_uniq * NUM_NL_MONETARY);
+
+ buf16[0] =0;
+ for (i=0 ; i < NUM_NL_MONETARY - 1 ; i++) {
+ buf16[i+1] = buf16[i] + lc_monetary_count[i];
+ }
+ dump_table16("__lc_monetary_item_offsets", buf16, NUM_NL_MONETARY);
+
+ m = 0;
+ for (k=0 ; k < NUM_NL_MONETARY ; k++) {
+ for (i=0 ; i < lc_monetary_count[k] ; i++) {
+ buf16[m] = lc_monetary_item[k][i];
+ ++m;
+ }
+ }
+ dump_table16("__lc_monetary_item_idx", buf16, m);
+}
+
+
+#undef DO_NL_S
+
+static int lc_messages_item[2][256];
+static int lc_messages_count[2];
+static unsigned char lc_messages_uniq_2[700][2];
+static int lc_messages_uniq;
+
+#define DO_NL_S(X) lc_messages_S(X, k++)
+
+static void lc_messages_S(int X, int k)
+{
+ int j, m;
+ j = addstring(nl_langinfo(X));
+ for (m=0 ; m < lc_messages_count[k] ; m++) {
+ if (lc_messages_item[k][m] == j) {
+ break;
+ }
+ }
+ if (m == lc_messages_count[k]) { /* new for this nl_item */
+ if (m > 255) {
+ printf("too many nl_item %d entries in lc_messages\n", k);
+ exit(EXIT_FAILURE);
+ }
+ lc_messages_item[k][m] = j;
+ ++lc_messages_count[k];
+ }
+/* printf("\\x%02x", m); */
+ lc_messages_uniq_2[lc_messages_uniq][k] = m;
+}
+
+static void do_lc_messages(void)
+{
+ int i, k, m;
+
+ last = buf+1;
+ uniq = 1;
+ *buf = 0;
+ *idx = buf;
+
+ for (i=0 ; i < num_locales ; i++) {
+ k = 0;
+
+ if (!setlocale(LC_ALL, locales[i].glibc_name)) {
+ printf("setlocale(LC_ALL,%s) failed!\n",
+ locales[i].glibc_name);
+ }
+
+ DO_NL_S(YESEXPR);
+ DO_NL_S(NOEXPR);
+
+ if (k > 2) {
+ printf("error -- lc_messages nl_item count > 2!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ {
+ int r;
+ for (r=0 ; r < lc_messages_uniq ; r++) {
+ if (!memcmp(lc_messages_uniq_2[lc_messages_uniq],
+ lc_messages_uniq_2[r], 2)) {
+ break;
+ }
+ }
+ if (r == lc_messages_uniq) { /* new locale row */
+ ++lc_messages_uniq;
+ if (lc_messages_uniq > 255) {
+ printf("too many unique lc_messages rows!\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ locales[i].lc_messages_row = r;
+ }
+ }
+
+ printf("buf-size=%d uniq=%d rows=%d\n",
+ (int)(last - buf), uniq, lc_messages_uniq);
+ printf("total = %d + %d * 2 + %d = %d\n",
+ num_locales, lc_messages_uniq, (int)(last - buf),
+ i = num_locales + lc_messages_uniq*2 + (int)(last - buf));
+ total_size += i;
+
+/* printf("buf-size=%d uniq=%d\n", (int)(last - buf), uniq); */
+
+ dump_table8c("__lc_messages_data", buf, (int)(last - buf));
+
+ for (i=0 ; i < lc_messages_uniq ; i++) {
+ m = locales[i].lc_messages_row;
+ for (k=0 ; k < 2 ; k++) {
+ buf[2*i + k] = (char)((unsigned char) lc_messages_uniq_2[i][k]);
+ }
+ }
+ dump_table8("__lc_messages_rows", buf, lc_messages_uniq * 2);
+
+ buf16[0] =0;
+ for (i=0 ; i < 2 - 1 ; i++) {
+ buf16[i+1] = buf16[i] + lc_messages_count[i];
+ }
+ dump_table16("__lc_messages_item_offsets", buf16, 2);
+
+ m = 0;
+ for (k=0 ; k < 2 ; k++) {
+ for (i=0 ; i < lc_messages_count[k] ; i++) {
+ buf16[m] = lc_messages_item[k][i];
+ ++m;
+ }
+ }
+ dump_table16("__lc_messages_item_idx", buf16, m);
+}
+
+
+
+
+
+static void read_at_mappings(void)
+{
+ char *p;
+ char *m;
+ int mc = 0;
+
+ do {
+ if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) {
+ if (!fgets(line_buf, sizeof(line_buf), fp)) {
+ if (ferror(fp)) {
+ printf("error reading file\n");
+ exit(EXIT_FAILURE);
+ }
+ return; /* EOF */
+ }
+ if ((*line_buf == '#') && (line_buf[1] == '-')) {
+ break;
+ }
+ continue;
+ }
+ if (*p == '@') {
+ if (p[1] == 0) {
+ printf("error: missing @modifier name\n");
+ exit(EXIT_FAILURE);
+ }
+ m = p; /* save the modifier name */
+ if (!(p = strtok(NULL, " \t\n")) || p[1] || (((unsigned char) *p) > 0x7f)) {
+ printf("error: missing or illegal @modifier mapping char\n");
+ exit(EXIT_FAILURE);
+ }
+ if (at_mappings[(int)((unsigned char) *p)]) {
+ printf("error: reused @modifier mapping char\n");
+ exit(EXIT_FAILURE);
+ }
+ at_mappings[(int)((unsigned char) *p)] = 1;
+ at_mapto[mc] = *p;
+ ++mc;
+ *at_strings_end = (char)( (unsigned char) (strlen(m)) );
+ strcpy(++at_strings_end, m+1);
+ at_strings_end += (unsigned char) at_strings_end[-1];
+
+ printf("@mapping: \"%s\" to '%c'\n", m, *p);
+
+ if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
+ printf("ignoring trailing text: %s...\n", p);
+ }
+ *line_buf = 0;
+ continue;
+ }
+ break;
+ } while (1);
+
+#if 0
+ {
+ p = at_strings;
+
+ if (!*p) {
+ printf("no @ strings\n");
+ return;
+ }
+
+ do {
+ printf("%s\n", p+1);
+ p += 1 + (unsigned char) *p;
+ } while (*p);
+ }
+#endif
+}
+
+static void read_enable_disable(void)
+{
+ char *p;
+
+ do {
+ if (!(p = strtok(line_buf, " =\t\n")) || (*p == '#')) {
+ if (!fgets(line_buf, sizeof(line_buf), fp)) {
+ if (ferror(fp)) {
+ printf("error reading file\n");
+ exit(EXIT_FAILURE);
+ }
+ return; /* EOF */
+ }
+ if ((*line_buf == '#') && (line_buf[1] == '-')) {
+ break;
+ }
+ continue;
+ }
+ if (!strcmp(p, "UTF-8")) {
+ if (!(p = strtok(NULL, " =\t\n"))
+ || ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) {
+ printf("error: missing or illegal UTF-8 setting\n");
+ exit(EXIT_FAILURE);
+ }
+ default_utf8 = (toupper(*p) == 'Y');
+ printf("UTF-8 locales are %sabled\n", "dis\0en"+ (default_utf8 << 2));
+ } else if (!strcmp(p, "8-BIT")) {
+ if (!(p = strtok(NULL, " =\t\n"))
+ || ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) {
+ printf("error: missing or illegal 8-BIT setting\n");
+ exit(EXIT_FAILURE);
+ }
+ default_8bit = (toupper(*p) == 'Y');
+ printf("8-BIT locales are %sabled\n", "dis\0en" + (default_8bit << 2));
+ } else {
+ break;
+ }
+
+ if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
+ printf("ignoring trailing text: %s...\n", p);
+ }
+ *line_buf = 0;
+ continue;
+
+ } while (1);
+}
+
+#ifdef CODESET_LIST
+
+static int find_codeset_num(const char *cs)
+{
+ int r = 2;
+ char *s = CODESET_LIST;
+
+ /* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */
+
+ if (strcmp(cs, "UTF-8") != 0) {
+ ++r;
+ while (*s && strcmp(CODESET_LIST+ ((unsigned char) *s), cs)) {
+/* printf("tried %s\n", CODESET_LIST + ((unsigned char) *s)); */
+ ++r;
+ ++s;
+ }
+ if (!*s) {
+ printf("error: unsupported codeset %s\n", cs);
+ exit(EXIT_FAILURE);
+ }
+ }
+ return r;
+}
+
+#else
+
+static int find_codeset_num(const char *cs)
+{
+ int r = 2;
+
+ /* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */
+
+ if (strcmp(cs, "UTF-8") != 0) {
+ printf("error: unsupported codeset %s\n", cs);
+ exit(EXIT_FAILURE);
+ }
+ return r;
+}
+
+#endif
+
+static int find_at_string_num(const char *as)
+{
+ int i = 0;
+ char *p = at_strings;
+
+ while (*p) {
+ if (!strcmp(p+1, as)) {
+ return i;
+ }
+ ++i;
+ p += 1 + (unsigned char) *p;
+ }
+
+ printf("error: unmapped @string %s\n", as);
+ exit(EXIT_FAILURE);
+}
+
+static void read_locale_list(void)
+{
+ char *p;
+ char *s;
+ char *ln; /* locale name */
+ char *ls; /* locale name ll_CC */
+ char *as; /* at string */
+ char *ds; /* dot string */
+ char *cs; /* codeset */
+ int i;
+
+ typedef struct {
+ char *glibc_name;
+ char name[5];
+ char dot_cs; /* 0 if no codeset specified */
+ char cs;
+ } locale_entry;
+
+ /* First the C locale. */
+ locales[0].glibc_name = locales[0].name;
+ strncpy(locales[0].name,"C",5);
+ locales[0].dot_cs = 0;
+ locales[0].cs = 1; /* 7-bit encoding */
+ ++num_locales;
+
+ do {
+ if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) {
+ if (!fgets(line_buf, sizeof(line_buf), fp)) {
+ if (ferror(fp)) {
+ printf("error reading file\n");
+ exit(EXIT_FAILURE);
+ }
+ return; /* EOF */
+ }
+ if ((*line_buf == '#') && (line_buf[1] == '-')) {
+ break;
+ }
+ continue;
+ }
+
+ s = glibc_locale_names;
+ for (i=0 ; i < num_locales ; i++) {
+ if (!strcmp(s+1, p)) {
+ break;
+ }
+ s += 1 + ((unsigned char) *s);
+ }
+ if (i < num_locales) {
+ printf("ignoring dulplicate locale name: %s", p);
+ *line_buf = 0;
+ continue;
+ }
+
+ /* New locale, but don't increment num until codeset verified! */
+ *s = (char)((unsigned char) (strlen(p) + 1));
+ strcpy(s+1, p);
+ locales[num_locales].glibc_name = s+1;
+ ln = p; /* save locale name */
+
+ if (!(p = strtok(NULL, " \t\n"))) {
+ printf("error: missing codeset for locale %s\n", ln);
+ exit(EXIT_FAILURE);
+ }
+ cs = p;
+ i = find_codeset_num(p);
+ if ((i == 2) && !default_utf8) {
+ printf("ignoring UTF-8 locale %s\n", ln);
+ *line_buf = 0;
+ continue;
+ } else if ((i > 2) && !default_8bit) {
+ printf("ignoring 8-bit codeset locale %s\n", ln);
+ *line_buf = 0;
+ continue;
+ }
+ locales[num_locales].cs = (char)((unsigned char) i);
+
+ if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
+ printf("ignoring trailing text: %s...\n", p);
+ }
+
+ /* Now go back to locale string for .codeset and @modifier */
+ as = strtok(ln, "@");
+ if (as) {
+ as = strtok(NULL, "@");
+ }
+ ds = strtok(ln, ".");
+ if (ds) {
+ ds = strtok(NULL, ".");
+ }
+ ls = ln;
+
+ if ((strlen(ls) != 5) || (ls[2] != '_')) {
+ printf("error: illegal locale name %s\n", ls);
+ exit(EXIT_FAILURE);
+ }
+
+ i = 0; /* value for unspecified codeset */
+ if (ds) {
+ i = find_codeset_num(ds);
+ if ((i == 2) && !default_utf8) {
+ printf("ignoring UTF-8 locale %s\n", ln);
+ *line_buf = 0;
+ continue;
+ } else if ((i > 2) && !default_8bit) {
+ printf("ignoring 8-bit codeset locale %s\n", ln);
+ *line_buf = 0;
+ continue;
+ }
+ }
+ locales[num_locales].dot_cs = (char)((unsigned char) i);
+
+ if (as) {
+ i = find_at_string_num(as);
+ ls[2] = at_mapto[i];
+ }
+ memcpy(locales[num_locales].name, ls, 5);
+/* printf("locale: %5.5s %2d %2d %s\n", */
+/* locales[num_locales].name, */
+/* locales[num_locales].cs, */
+/* locales[num_locales].dot_cs, */
+/* locales[num_locales].glibc_name */
+/* ); */
+ ++num_locales;
+ *line_buf = 0;
+ } while (1);
+}
+
+static int le_cmp(const void *a, const void *b)
+{
+ const locale_entry *p;
+ const locale_entry *q;
+ int r;
+
+ p = (const locale_entry *) a;
+ q = (const locale_entry *) b;
+
+ if (!(r = p->name[0] - q->name[0])
+ && !(r = p->name[1] - q->name[1])
+ && !(r = p->name[3] - q->name[3])
+ && !(r = p->name[4] - q->name[4])
+ && !(r = p->name[2] - q->name[2])
+ && !(r = -(p->cs - q->cs))
+ ) {
+ r = -(p->dot_cs - q->dot_cs);
+ /* Reverse the ordering of the codesets so UTF-8 comes last.
+ * Work-around (hopefully) for glibc bug affecting at least
+ * the euro currency symbol. */
+ }
+
+ return r;
+}
+
diff --git a/extra/locale/gen_mmap.c b/extra/locale/gen_mmap.c
new file mode 100644
index 000000000..ae5d4dff6
--- /dev/null
+++ b/extra/locale/gen_mmap.c
@@ -0,0 +1,237 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#define WANT_DATA
+#include "c8tables.h"
+
+/* #define Cctype_TBL_LEN 328 */
+/* #define Cuplow_TBL_LEN 400 */
+/* #define Cc2wc_TBL_LEN 1448 */
+/* #define Cwc2c_TBL_LEN 3744 */
+
+#define WANT_WCctype_data
+#define WANT_WCuplow_data
+#define WANT_WCuplow_diff_data
+#define WANT_WCcomb_data
+/* #define WANT_WCwidth_data */
+#include "wctables.h"
+#undef WANT_WCctype_data
+#undef WANT_WCuplow_data
+#undef WANT_WCuplow_diff_data
+#undef WANT_WCcomb_data
+/* #undef WANT_WCwidth_data */
+
+/* #define WCctype_TBL_LEN (WCctype_II_LEN + WCctype_TI_LEN + WCctype_UT_LEN) */
+/* #define WCuplow_TBL_LEN (WCuplow_II_LEN + WCuplow_TI_LEN + WCuplow_UT_LEN) */
+/* #define WCuplow_diff_TBL_LEN (2 * WCuplow_diffs) */
+/* #define WCcomb_TBL_LEN (WCcomb_II_LEN + WCcomb_TI_LEN + WCcomb_UT_LEN) */
+
+#include "locale_tables.h"
+
+#include "locale_mmap.h"
+
+/* #undef __PASTE2 */
+/* #define __PASTE2(A,B) A ## B */
+/* #undef __PASTE3 */
+/* #define __PASTE3(A,B,C) A ## B ## C */
+
+
+/* #define MAGIC_SIZE 64 */
+
+/* #define COMMON_MMAP(X) \ */
+/* unsigned char __PASTE3(lc_,X,_data)[__PASTE3(__lc_,X,_data_LEN)]; */
+
+/* #define COMMON_MMIDX(X) \ */
+/* unsigned char __PASTE3(lc_,X,_rows)[__PASTE3(__lc_,X,_rows_LEN)]; \ */
+/* uint16_t __PASTE3(lc_,X,_item_offsets)[__PASTE3(__lc_,X,_item_offsets_LEN)]; \ */
+/* uint16_t __PASTE3(lc_,X,_item_idx)[__PASTE3(__lc_,X,_item_idx_LEN)]; \ */
+
+#define WRITE_COMMON_MMAP(X) \
+ fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_data)), SEEK_SET); \
+ for (i=0 ; i < __PASTE3(__lc_,X,_data_LEN) ; i++) { \
+ putc(__PASTE3(__lc_,X,_data)[i], fp); \
+ }
+
+#define WRITE_COMMON_MMIDX(X) \
+ fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_rows)), SEEK_SET); \
+ for (i=0 ; i < __PASTE3(__lc_,X,_rows_LEN) ; i++) { \
+ putc(__PASTE3(__lc_,X,_rows)[i], fp); \
+ } \
+ fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_offsets)), SEEK_SET); \
+ for (i=0 ; i < __PASTE3(__lc_,X,_item_offsets_LEN) ; i++) { \
+ putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_offsets)[i]))[0], fp); \
+ putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_offsets)[i]))[1], fp); \
+ } \
+ fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_idx)), SEEK_SET); \
+ for (i=0 ; i < __PASTE3(__lc_,X,_item_idx_LEN) ; i++) { \
+ putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_idx)[i]))[0], fp); \
+ putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_idx)[i]))[1], fp); \
+ }
+
+#define WRITE_WC_DATA(X) \
+ fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tblw,X)), SEEK_SET); \
+ for (i=0 ; i < __PASTE3(WC,X,_TBL_LEN) ; i++) { \
+ putc(__PASTE3(WC,X,_data)[i], fp); \
+ }
+
+#define WRITE_WC_I16_DATA(X) \
+ fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tblw,X)), SEEK_SET); \
+ for (i=0 ; i < __PASTE3(WC,X,_TBL_LEN) ; i++) { \
+ putc( ((unsigned char *) &(__PASTE3(WC,X,_data)[i]))[0], fp); \
+ putc( ((unsigned char *) &(__PASTE3(WC,X,_data)[i]))[1], fp); \
+ }
+
+#define WRITE_C_DATA(X) \
+ fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tbl8,X)), SEEK_SET); \
+ for (i=0 ; i < __PASTE3(C,X,_TBL_LEN) ; i++) { \
+ putc(__PASTE3(C,X,_data)[i], fp); \
+ }
+
+#define WRITE_C_U16_DATA(X) \
+ fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tbl8,X)), SEEK_SET); \
+ for (i=0 ; i < __PASTE3(C,X,_TBL_LEN) ; i++) { \
+ putc( ((unsigned char *) &(__PASTE3(C,X,_data)[i]))[0], fp); \
+ putc( ((unsigned char *) &(__PASTE3(C,X,_data)[i]))[1], fp); \
+ }
+
+/**********************************************************************/
+
+#define COMMON_OFFSETS(X) \
+ offsetof(__locale_mmap_t, __PASTE3(lc_,X,_rows)), \
+ offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_offsets)), \
+ offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_idx)), \
+ offsetof(__locale_mmap_t, __PASTE3(lc_,X,_data)) \
+
+
+static const size_t common_tbl_offsets[CATEGORIES*4] = {
+ 0, 0, 0, 0, /* ctype */
+ COMMON_OFFSETS(numeric),
+ COMMON_OFFSETS(monetary),
+ COMMON_OFFSETS(time),
+ 0, 0, 0, 0, /* collate */
+ COMMON_OFFSETS(messages),
+};
+
+
+
+
+
+int main(void)
+{
+ FILE *fp;
+ size_t i;
+ unsigned char *p;
+
+ if (!(fp = fopen("locale.mmap", "w"))) {
+ printf("error - can't open locale.mmap for writing!");
+ return EXIT_FAILURE;
+ }
+
+ for (i=0 ; i < sizeof(__locale_mmap_t) ; i++) {
+ putc(0, fp); /* Zero out the file. */
+ }
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ WRITE_C_DATA(ctype);
+ WRITE_C_DATA(uplow);
+#ifdef __WCHAR_ENABLED
+ WRITE_C_U16_DATA(c2wc);
+ WRITE_C_DATA(wc2c);
+ /* translit */
+#endif /* __WCHAR_ENABLED */
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+
+#ifdef __WCHAR_ENABLED
+ WRITE_WC_DATA(ctype);
+ WRITE_WC_DATA(uplow);
+ WRITE_WC_I16_DATA(uplow_diff);
+ WRITE_WC_DATA(comb);
+ /* width?? */
+#endif /* __WCHAR_ENABLED */
+
+ WRITE_COMMON_MMAP(numeric);
+ WRITE_COMMON_MMAP(monetary);
+ WRITE_COMMON_MMAP(time);
+ /* TODO -- collate*/
+ WRITE_COMMON_MMAP(messages);
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ fseek(fp, (long) offsetof(__locale_mmap_t, codeset_8_bit), SEEK_SET); \
+ p = (unsigned char *) codeset_8_bit;
+ for (i=0 ; i < sizeof(codeset_8_bit) ; i++) {
+ putc(p[i], fp);
+ }
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+
+ WRITE_COMMON_MMIDX(numeric);
+ WRITE_COMMON_MMIDX(monetary);
+ WRITE_COMMON_MMIDX(time);
+ /* TODO -- collate*/
+ WRITE_COMMON_MMIDX(messages);
+
+ fseek(fp, (long) offsetof(__locale_mmap_t, lc_common_item_offsets_LEN), SEEK_SET);
+ putc(1, fp); /* ctype -- (codeset) handled specially */
+ putc(__lc_numeric_item_offsets_LEN, fp);
+ putc(__lc_monetary_item_offsets_LEN, fp);
+ putc(__lc_time_item_offsets_LEN, fp);
+ putc(0, fp); /* collate */
+ putc(__lc_messages_item_offsets_LEN, fp);
+
+ fseek(fp, (long) offsetof(__locale_mmap_t, lc_common_tbl_offsets), SEEK_SET);
+ for (i=0 ; i < sizeof(common_tbl_offsets) ; i++) {
+ putc(((unsigned char *)common_tbl_offsets)[i], fp);
+ }
+
+#ifdef NUM_LOCALES
+ fseek(fp, (long) offsetof(__locale_mmap_t, locales), SEEK_SET);
+ for (i=0 ; i < (NUM_LOCALES * WIDTH_LOCALES) ; i++) {
+ putc(__locales[i], fp);
+ }
+
+ fseek(fp, (long) offsetof(__locale_mmap_t, locale_names5), SEEK_SET);
+ for (i=0 ; i < 5 * NUM_LOCALE_NAMES ; i++) {
+ putc(__locale_names5[i], fp);
+ }
+
+#ifdef LOCALE_AT_MODIFIERS_LENGTH
+ fseek(fp, (long) offsetof(__locale_mmap_t, locale_at_modifiers), SEEK_SET);
+ for (i=0 ; i < LOCALE_AT_MODIFIERS_LENGTH ; i++) {
+ putc(__locale_at_modifiers[i], fp);
+ }
+#endif /* LOCALE_AT_MODIFIERS_LENGTH */
+#endif /* NUM_LOCALES */
+
+ fseek(fp, (long) offsetof(__locale_mmap_t, lc_names), SEEK_SET);
+ for (i=0 ; i < lc_names_LEN ; i++) {
+ putc(lc_names[i], fp);
+ }
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ fseek(fp, (long) offsetof(__locale_mmap_t, codeset_list), SEEK_SET);
+ for (i=0 ; i < sizeof(CODESET_LIST) ; i++) {
+ putc((unsigned char)(CODESET_LIST[i]), fp);
+ }
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+
+
+ if (ferror(fp) || (fclose(fp) == EOF)) {
+ printf("error - stream in error state or fclose failed!");
+ return EXIT_FAILURE;
+ }
+
+ printf("sizeof(__locale_mmap_t) = %zd\n", sizeof(__locale_mmap_t));
+
+ return EXIT_SUCCESS;
+}
+
+/* TODO:
+ * collate data (8-bit weighted single char only)
+ * @ mappings!
+ * codeset list? yes, since we'll want to be able to inspect them...
+ * that means putting some header stuff in magic
+ * fix ctype LEN defines in gen_c8tables
+ */
diff --git a/extra/locale/gen_wc8bit.c b/extra/locale/gen_wc8bit.c
new file mode 100644
index 000000000..785c3f4c0
--- /dev/null
+++ b/extra/locale/gen_wc8bit.c
@@ -0,0 +1,729 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <stddef.h>
+#include <wctype.h>
+#include <limits.h>
+
+/* #define CTYPE_PACKED */
+#define UPLOW_IDX_SHIFT 3
+/* best if 2 unpacked or 3 packed */
+#define CTYPE_IDX_SHIFT 3
+/* 3 or 4 are very similar */
+#define C2WC_IDX_SHIFT 3
+
+#define CTYPE_IDX_LEN (128 >> (CTYPE_IDX_SHIFT))
+#define UPLOW_IDX_LEN (128 >> (UPLOW_IDX_SHIFT))
+#define C2WC_IDX_LEN (128 >> (C2WC_IDX_SHIFT))
+
+/* #ifdef CTYPE_PACKED */
+/* #define CTYPE_ROW_LEN (1 << ((CTYPE_IDX_SHIFT)-1)) */
+/* #else */
+#define CTYPE_ROW_LEN (1 << (CTYPE_IDX_SHIFT))
+/* #endif */
+#define UPLOW_ROW_LEN (1 << (UPLOW_IDX_SHIFT))
+#define C2WC_ROW_LEN (1 << (C2WC_IDX_SHIFT))
+
+
+
+#define MAX_WCHAR (0x2600-1)
+
+static unsigned char ctype_tbl[256 * CTYPE_ROW_LEN];
+static unsigned char uplow_tbl[256 * UPLOW_ROW_LEN];
+#ifdef DO_WIDE_CHAR
+static unsigned short c2wc_tbl[256 * C2WC_ROW_LEN];
+#endif
+static unsigned char tt[MAX_WCHAR+1];
+static unsigned char ti[MAX_WCHAR+1];
+static unsigned char xi[MAX_WCHAR+1];
+
+static int n_ctype_rows;
+static int n_uplow_rows;
+#ifdef DO_WIDE_CHAR
+static int n_c2wc_rows;
+#endif
+static int tt_num;
+static int ti_num;
+
+#define RANGE MAX_WCHAR
+
+#define TT_SHIFT 4
+#define TI_SHIFT 4
+
+#define II_LEN ((MAX_WCHAR+1) >> (TT_SHIFT+TI_SHIFT))
+
+typedef struct {
+ unsigned long c2w[256];
+ unsigned char w2c[MAX_WCHAR];
+ unsigned char ii[II_LEN];
+ unsigned char ctype_idx[CTYPE_IDX_LEN];
+ unsigned char uplow_idx[UPLOW_IDX_LEN];
+ unsigned char c2wc_idx[C2WC_IDX_LEN];
+} charset_data;
+
+/* Taking advantage of the C99 mutual-exclusion guarantees for the various
+ * (w)ctype classes, including the descriptions of printing and control
+ * (w)chars, we can place each in one of the following mutually-exlusive
+ * subsets. Since there are less than 16, we can store the data for
+ * each (w)chars in a nibble. In contrast, glibc uses an unsigned int
+ * per (w)char, with one bit flag for each is* type. While this allows
+ * a simple '&' operation to determine the type vs. a range test and a
+ * little special handling for the "blank" and "xdigit" types in my
+ * approach, it also uses 8 times the space for the tables on the typical
+ * 32-bit archs we supported.*/
+enum {
+ __CTYPE_unclassified = 0,
+ __CTYPE_alpha_nonupper_nonlower,
+ __CTYPE_alpha_lower,
+ __CTYPE_alpha_upper_lower,
+ __CTYPE_alpha_upper,
+ __CTYPE_digit,
+ __CTYPE_punct,
+ __CTYPE_graph,
+ __CTYPE_print_space_nonblank,
+ __CTYPE_print_space_blank,
+ __CTYPE_space_nonblank_noncntrl,
+ __CTYPE_space_blank_noncntrl,
+ __CTYPE_cntrl_space_nonblank,
+ __CTYPE_cntrl_space_blank,
+ __CTYPE_cntrl_nonspace,
+};
+
+int main(int argc, char **argv)
+{
+ FILE *fp;
+ FILE *out;
+ charset_data csd[20];
+ unsigned long max_wchar;
+ unsigned char *p;
+ int numsets;
+ int i;
+ int j;
+ char buf[80];
+ unsigned char row[256];
+#ifdef DO_WIDE_CHAR
+ unsigned short wrow[256];
+#endif
+ char codeset_list[500];
+ char codeset_index[30];
+ int codeset_list_end = 0;
+ int total_size = 0;
+
+ if (!setlocale(LC_CTYPE, "en_US.UTF-8")) {
+ printf("setlocale(LC_CTYPE,\"en_US.UTF-8\") failed!\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!(out = fopen("c8tables.h","w"))) {
+ printf("error: couldn't open file \"c8tables.h\"\n");
+ return EXIT_FAILURE;
+ }
+
+#if 0
+ if (argc == 1) {
+ /* User requested 8-bit codesets, but didn't list any... */
+ /* Allow to build, just so this feature can be left on in config. */
+ fprintf(out, "#ifdef __CTYPE_HAS_8_BIT_LOCALES\n");
+ fprintf(out, "#warning ignoring 8 bit codesets request"
+ " as no codesets specified.\n");
+ fprintf(out, "#endif\n");
+ fprintf(out, "#undef __CTYPE_HAS_8_BIT_LOCALES\n\n");
+
+ fprintf(out, "#define NUM_CODESETS\t\t0\n");
+ fprintf(out, "#define CODESET_LIST\t\t\"\"\n");
+ fclose(out);
+ return EXIT_SUCCESS;
+ }
+
+/* fprintf(out, "#define __CTYPE_HAS_8_BIT_LOCALES\t1\n\n"); */
+ fprintf(out, "#ifdef __CTYPE_HAS_8_BIT_LOCALES\n\n");
+#endif
+
+ if (argc == 1) {
+ fprintf(out, "#undef __CTYPE_HAS_8_BIT_LOCALES\n\n");
+
+ fprintf(out, "#define NUM_CODESETS\t\t0\n");
+ fprintf(out, "#define CODESET_LIST\t\t\"\"\n");
+ } else {
+ fprintf(out, "#define __CTYPE_HAS_8_BIT_LOCALES\t\t1\n\n");
+ }
+
+ fprintf(out, "#define Cctype_IDX_SHIFT\t%d\n", CTYPE_IDX_SHIFT);
+ fprintf(out, "#define Cctype_IDX_LEN\t\t%d\n", CTYPE_IDX_LEN);
+#ifdef CTYPE_PACKED
+ fprintf(out, "#define Cctype_ROW_LEN\t\t%d\n", CTYPE_ROW_LEN >> 1);
+ fprintf(out, "#define Cctype_PACKED\t\t1\n");
+#else
+ fprintf(out, "#define Cctype_ROW_LEN\t\t%d\n", CTYPE_ROW_LEN);
+ fprintf(out, "#undef Cctype_PACKED\n");
+#endif
+
+ fprintf(out, "\n#define Cuplow_IDX_SHIFT\t%d\n", UPLOW_IDX_SHIFT);
+ fprintf(out, "#define Cuplow_IDX_LEN\t\t%d\n", UPLOW_IDX_LEN);
+ fprintf(out, "#define Cuplow_ROW_LEN\t\t%d\n", UPLOW_ROW_LEN);
+
+#ifdef DO_WIDE_CHAR
+ fprintf(out, "\n#define Cc2wc_IDX_LEN\t\t%d\n", C2WC_IDX_LEN);
+ fprintf(out, "#define Cc2wc_IDX_SHIFT\t\t%d\n", C2WC_IDX_SHIFT);
+ fprintf(out, "#define Cc2wc_ROW_LEN\t\t%d\n", C2WC_ROW_LEN);
+#endif
+
+ fprintf(out, "\ntypedef struct {\n");
+ fprintf(out, "\tunsigned char idx8ctype[%d];\n", CTYPE_IDX_LEN);
+ fprintf(out, "\tunsigned char idx8uplow[%d];\n", UPLOW_IDX_LEN);
+#ifdef DO_WIDE_CHAR
+ fprintf(out, "\tunsigned char idx8c2wc[%d];\n", C2WC_IDX_LEN);
+ fprintf(out, "\tunsigned char idx8wc2c[%d];\n", II_LEN);
+#endif
+ fprintf(out, "} codeset_8_bit_t;\n\n");
+
+ fprintf(out, "#ifdef WANT_DATA\n\n");
+ fprintf(out, "static const codeset_8_bit_t codeset_8_bit[%d] = {\n", argc-1);
+
+ max_wchar = 0x7f;
+ numsets = 0;
+ codeset_index[0] = 0;
+ while (--argc) {
+ if (!(fp = fopen(*++argv,"r"))) {
+ printf("error: couldn't open file \"%s\"\n", *argv);
+ return EXIT_FAILURE;
+ }
+ printf("processing %s... ", *argv);
+
+ {
+ char *s0;
+ char *s1;
+ int n;
+
+ s0 = strrchr(*argv, '/');
+ if (!s0) {
+ s0 = *argv;
+ } else {
+ ++s0;
+ }
+ s1 = strchr(s0, '.');
+ if (!s1) {
+ n = strlen(s0);
+ } else {
+ n = s1 - s0;
+ }
+
+/* if ((numsets == 0) && strncmp("ASCII", s0, n)) { */
+/* printf("error - first codeset isn't ASCII!\n"); */
+/* return EXIT_FAILURE; */
+/* } */
+
+ if (numsets >= sizeof(codeset_index)) {
+ printf("error - too many codesets!\n");
+ return EXIT_FAILURE;
+ }
+
+ if (codeset_list_end + n + 1 + numsets + 1 + 1 >= 256) {
+ printf("error - codeset list to big!\n");
+ return EXIT_FAILURE;
+ }
+
+ codeset_index[numsets+1] = codeset_index[numsets] + n+1;
+ strncpy(codeset_list + codeset_list_end, s0, n);
+ codeset_list_end += (n+1);
+ codeset_list[codeset_list_end - 1] = 0;
+
+ fprintf(out, "\t{ /* %.*s */", n, s0);
+ }
+
+ memset(&csd[numsets],sizeof(charset_data),0);
+ memset(xi, sizeof(xi), 0);
+ {
+ unsigned long c, wc;
+ int lines;
+ lines = 0;
+ while (fgets(buf,sizeof(buf),fp)) {
+ if ((2 != sscanf(buf, "{ %lx , %lx", &c, &wc))
+ || (c >= 256) || (wc > MAX_WCHAR)) {
+ printf("error: scanf failure! \"%s\"\n", buf);
+ return EXIT_FAILURE;
+ }
+
+ /* don't put in w2c... dynamicly build tt instead. */
+
+ if (c <= 0x7f) { /* check the 7bit entries but don't store */
+ if (c != wc) {
+ printf("error: c != wc in %s\n", buf);
+ return EXIT_FAILURE;
+ }
+ csd[numsets].c2w[c] = wc;
+ csd[numsets].w2c[wc] = 0; /* ignore */
+ if (wc > max_wchar) {
+ max_wchar = wc;
+ }
+ } else {
+ csd[numsets].c2w[c] = wc;
+ csd[numsets].w2c[wc] = c;
+ if (wc > max_wchar) {
+ max_wchar = wc;
+ }
+ }
+ ++lines;
+ }
+ printf("%d lines ", lines);
+
+ for (i = 0 ; i <= MAX_WCHAR ; i += (1 << TT_SHIFT)) {
+ p = &csd[numsets].w2c[i];
+ for (j = 0 ; j < tt_num ; j++) {
+ if (!memcmp(p, &tt[j << TT_SHIFT], (1 << TT_SHIFT))) {
+ break;
+ }
+ }
+ if (j == tt_num) { /* new entry */
+ memcpy(&tt[j << TT_SHIFT], p, (1 << TT_SHIFT));
+ ++tt_num;
+ }
+ xi[i >> TT_SHIFT] = j;
+ }
+
+ for (i = 0 ; i <= (MAX_WCHAR >> TT_SHIFT) ; i += (1 << TI_SHIFT)) {
+ p = &xi[i];
+ for (j = 0 ; j < ti_num ; j++) {
+ if (!memcmp(p, &ti[j << TI_SHIFT], (1 << TI_SHIFT))) {
+ break;
+ }
+ }
+ if (j == ti_num) { /* new entry */
+ memcpy(&ti[j << TI_SHIFT], p, (1 << TI_SHIFT));
+ ++ti_num;
+ }
+ csd[numsets].ii[i >> TI_SHIFT] = j;
+/* printf("%d ", i >> TI_SHIFT); */
+ }
+
+#if 1
+ fprintf(out, "\n\t\t/* idx8ctype data */\n\t\t{");
+ for (i = 128 ; i < 256 ; i++) {
+ wchar_t c;
+ unsigned int d;
+
+/* if (!(i & 0x7)) { */
+/* fprintf(out, "\n"); */
+/* } */
+
+ c = csd[numsets].c2w[i];
+
+ if (c == 0) { /* non-existant char in codeset */
+ d = __CTYPE_unclassified;
+ } else if (iswdigit(c)) {
+ d = __CTYPE_digit;
+ } else if (iswalpha(c)) {
+ d = __CTYPE_alpha_nonupper_nonlower;
+ if (iswlower(c)) {
+ d = __CTYPE_alpha_lower;
+ if (iswupper(c)) {
+ d = __CTYPE_alpha_upper_lower;
+ }
+ } else if (iswupper(c)) {
+ d = __CTYPE_alpha_upper;
+ }
+ } else if (iswpunct(c)) {
+ d = __CTYPE_punct;
+ } else if (iswgraph(c)) {
+ d = __CTYPE_graph;
+ } else if (iswprint(c)) {
+ d = __CTYPE_print_space_nonblank;
+ if (iswblank(c)) {
+ d = __CTYPE_print_space_blank;
+ }
+ } else if (iswspace(c) && !iswcntrl(c)) {
+ d = __CTYPE_space_nonblank_noncntrl;
+ if (iswblank(c)) {
+ d = __CTYPE_space_blank_noncntrl;
+ }
+ } else if (iswcntrl(c)) {
+ d = __CTYPE_cntrl_nonspace;
+ if (iswspace(c)) {
+ d = __CTYPE_cntrl_space_nonblank;
+ if (iswblank(c)) {
+ d = __CTYPE_cntrl_space_blank;
+ }
+ }
+ } else {
+ d = __CTYPE_unclassified;
+ }
+
+#if 1
+ row[i & (CTYPE_ROW_LEN-1)] = d;
+ if ((i & (CTYPE_ROW_LEN-1)) == (CTYPE_ROW_LEN-1)) {
+ p = ctype_tbl;
+ for (j=0 ; j < n_ctype_rows ; j++) {
+ if (!memcmp(p, row, CTYPE_ROW_LEN)) {
+ break;
+ }
+ p += CTYPE_ROW_LEN;
+ }
+ if (j == n_ctype_rows) { /* new entry */
+ if (++n_ctype_rows > 256) {
+ printf("error -- to many ctype rows!\n");
+ return EXIT_FAILURE;
+ }
+ memcpy(p, row, CTYPE_ROW_LEN);
+ }
+ csd[numsets].ctype_idx[i >> CTYPE_IDX_SHIFT] = j;
+ if (!((i >> CTYPE_IDX_SHIFT) & 0x7)
+ && (i != (127 + CTYPE_ROW_LEN))
+ ) {
+ fprintf(out, "\n\t\t ");
+ }
+ fprintf(out, " %#4x,", j);
+ }
+#else
+ fprintf(out, " %#4x,", d);
+#endif
+ }
+#endif
+ fprintf(out, " }");
+
+#if 1
+ fprintf(out, ",\n\t\t/* idx8uplow data */\n\t\t{");
+ for (i = 128 ; i < 256 ; i++) {
+ wchar_t c, u, l;
+/* if (!(i & 0x7)) { */
+/* fprintf(out, "\n"); */
+/* } */
+ c = csd[numsets].c2w[i];
+ if ((c != 0) || 1) {
+ u = towupper(c);
+ l = towlower(c);
+
+ if (u >= 0x80) u = csd[numsets].w2c[u];
+ if (l >= 0x80) l = csd[numsets].w2c[l];
+
+ if (u == 0) u = i; /* upper is missing, so ignore */
+ if (l == 0) l = i; /* lower is missing, so ignore */
+
+#if 1
+ /* store as unsigned char and let overflow handle it. */
+/* if ((((u-i) < CHAR_MIN) || ((u-i) > CHAR_MAX)) */
+/* || (((i-l) < CHAR_MIN) || ((i-l) > CHAR_MAX)) */
+/* ) { */
+/* printf("error - uplow diff out of range! %d %ld %ld\n", */
+/* i, u, l); */
+/* return EXIT_FAILURE; */
+/* } */
+
+ row[i & (UPLOW_ROW_LEN-1)] = ((l==i) ? (u-i) : (i-l));
+ if ((i & (UPLOW_ROW_LEN-1)) == (UPLOW_ROW_LEN-1)) {
+ p = uplow_tbl;
+ for (j=0 ; j < n_uplow_rows ; j++) {
+ if (!memcmp(p, row, UPLOW_ROW_LEN)) {
+ break;
+ }
+ p += UPLOW_ROW_LEN;
+ }
+ if (j == n_uplow_rows) { /* new entry */
+ if (++n_uplow_rows > 256) {
+ printf("error -- to many uplow rows!\n");
+ return EXIT_FAILURE;
+ }
+ memcpy(p, row, UPLOW_ROW_LEN);
+ }
+ csd[numsets].uplow_idx[i >> UPLOW_IDX_SHIFT] = j;
+ if (!((i >> UPLOW_IDX_SHIFT) & 0x7)
+ && (i != (127 + UPLOW_ROW_LEN))
+ ) {
+ fprintf(out, "\n\t\t ");
+ }
+ fprintf(out, " %#4x,", j);
+ }
+
+#elif 0
+ if (!(i & 0x7) && i) {
+ fprintf(out, "\n");
+ }
+ fprintf(out, " %4ld,", (l==i) ? (u-i) : (i-l));
+/* fprintf(out, " %4ld,", (l==i) ? u : l); */
+#else
+ if ((u != i) || (l != i)) {
+#if 0
+ fprintf(out, " %#08lx, %#08lx, %#08lx, %#08lx, %#08lx, %#08lx, \n",
+ (unsigned long) i,
+ (unsigned long) c,
+ (unsigned long) l,
+ (unsigned long) towlower(c),
+ (unsigned long) u,
+ (unsigned long) towupper(c));
+
+#else
+ fprintf(out, " %#08lx, %8ld, %d, %8ld, %d, %#08lx\n",
+ (unsigned long) i,
+ (long) (l - i),
+ iswupper(c),
+ (long) (i - u),
+ iswlower(c),
+ (unsigned long) c);
+#endif
+ }
+#endif
+ }
+ }
+ fprintf(out, " }");
+#endif
+
+#ifndef DO_WIDE_CHAR
+ fprintf(out,"\n");
+#else /* DO_WIDE_CHAR */
+
+#if 1
+ fprintf(out, ",\n\t\t/* idx8c2wc data */\n\t\t{");
+ for (i = 128 ; i < 256 ; i++) {
+#if 1
+ wrow[i & (C2WC_ROW_LEN-1)] = csd[numsets].c2w[i];
+ if ((i & (C2WC_ROW_LEN-1)) == (C2WC_ROW_LEN-1)) {
+ p = (char *) c2wc_tbl;
+ for (j=0 ; j < n_c2wc_rows ; j++) {
+ if (!memcmp(p, (char *) wrow, 2*C2WC_ROW_LEN)) {
+ break;
+ }
+ p += 2*C2WC_ROW_LEN;
+ }
+ if (j == n_c2wc_rows) { /* new entry */
+ if (++n_c2wc_rows > 256) {
+ printf("error -- to many c2wc rows!\n");
+ return EXIT_FAILURE;
+ }
+ memcpy(p, (char *) wrow, 2*C2WC_ROW_LEN);
+ }
+ csd[numsets].c2wc_idx[i >> C2WC_IDX_SHIFT] = j;
+ if (!((i >> C2WC_IDX_SHIFT) & 0x7)
+ && (i != (127 + C2WC_ROW_LEN))
+ ) {
+ fprintf(out, "\n\t\t ");
+ }
+ fprintf(out, " %#4x,", j);
+ }
+#else
+ if (!(i & 0x7) && i) {
+ fprintf(out, "\n");
+ }
+ fprintf(out, " %#6lx,", csd[numsets].c2w[i]);
+#endif
+ }
+ fprintf(out, " },\n");
+#endif
+
+#if 1
+/* fprintf(out, "\nII_LEN = %d\n", II_LEN); */
+ fprintf(out, "\t\t/* idx8wc2c data */\n\t\t{");
+ for (i = 0 ; i < II_LEN ; i++) {
+ if (!(i & 0x7) && i) {
+ fprintf(out, "\n\t\t ");
+ }
+ fprintf(out, " %#4x,", csd[numsets].ii[i]);
+ }
+ fprintf(out, " }\n");
+#endif
+
+#endif /* DO_WIDE_CHAR */
+ fprintf(out, "\t},\n");
+
+ }
+ ++numsets;
+ printf("done\n");
+ }
+ fprintf(out, "};\n");
+ fprintf(out, "\n#endif /* WANT_DATA */\n");
+
+#ifdef DO_WIDE_CHAR
+ fprintf(out, "\n");
+ fprintf(out, "#define Cwc2c_DOMAIN_MAX\t%#x\n", RANGE);
+ fprintf(out, "#define Cwc2c_TI_SHIFT\t\t%d\n", TI_SHIFT);
+ fprintf(out, "#define Cwc2c_TT_SHIFT\t\t%d\n", TT_SHIFT);
+ fprintf(out, "#define Cwc2c_II_LEN\t\t%d\n", II_LEN);
+ fprintf(out, "#define Cwc2c_TI_LEN\t\t%d\n", ti_num << TI_SHIFT);
+ fprintf(out, "#define Cwc2c_TT_LEN\t\t%d\n", tt_num << TT_SHIFT);
+ fprintf(out, "\n");
+
+ fprintf(out, "\n#define Cwc2c_TBL_LEN\t\t%d\n",
+ (ti_num << TI_SHIFT) + (tt_num << TT_SHIFT));
+
+ fprintf(out, "#ifdef WANT_DATA\n\n");
+ fprintf(out, "static const unsigned char Cwc2c_data[%d] = {\n",
+ (ti_num << TI_SHIFT) + (tt_num << TT_SHIFT));
+ fprintf(out, "\t/* ti_table */\n\t");
+ for (i=0 ; i < ti_num << TI_SHIFT ; i++) {
+ if (!(i & 7) && i) {
+ fprintf(out, "\n\t");
+ }
+ fprintf(out, " %#4x,", ti[i]);
+ }
+ fprintf(out, "\n");
+ fprintf(out, "\t/* tt_table */\n\t");
+ for (i=0 ; i < tt_num << TT_SHIFT ; i++) {
+ if (!(i & 7) && i) {
+ fprintf(out, "\n\t");
+ }
+ fprintf(out, " %#4x,", tt[i]);
+ }
+ fprintf(out, "\n};\n");
+
+ fprintf(out, "\n#endif /* WANT_DATA */\n");
+#endif /* DO_WIDE_CHAR */
+
+ fprintf(out, "\n#define Cuplow_TBL_LEN\t\t%d\n",
+ n_uplow_rows * UPLOW_ROW_LEN);
+ fprintf(out, "\n#ifdef WANT_DATA\n\n");
+
+ fprintf(out, "\nstatic const unsigned char Cuplow_data[%d] = {\n",
+ n_uplow_rows * UPLOW_ROW_LEN);
+ p = uplow_tbl;
+ for (j=0 ; j < n_uplow_rows ; j++) {
+ fprintf(out, "\t");
+ for (i=0 ; i < UPLOW_ROW_LEN ; i++) {
+ fprintf(out, " %#4x,", (unsigned int)((unsigned char) p[i]));
+ }
+ fprintf(out, "\n");
+ p += UPLOW_ROW_LEN;
+ }
+ fprintf(out, "};\n");
+
+ fprintf(out, "\n#endif /* WANT_DATA */\n");
+ fprintf(out, "\n#define Cctype_TBL_LEN\t\t%d\n",
+#ifdef CTYPE_PACKED
+ n_ctype_rows * CTYPE_ROW_LEN / 2
+#else
+ n_ctype_rows * CTYPE_ROW_LEN
+#endif
+ );
+ fprintf(out, "\n#ifdef WANT_DATA\n\n");
+
+
+ fprintf(out, "\nstatic const unsigned char Cctype_data[%d] = {\n",
+#ifdef CTYPE_PACKED
+ n_ctype_rows * CTYPE_ROW_LEN / 2
+#else
+ n_ctype_rows * CTYPE_ROW_LEN
+#endif
+ );
+ p = ctype_tbl;
+ for (j=0 ; j < n_ctype_rows ; j++) {
+ fprintf(out, "\t");
+ for (i=0 ; i < CTYPE_ROW_LEN ; i++) {
+#ifdef CTYPE_PACKED
+ fprintf(out, " %#4x,", (unsigned int)(p[i] + (p[i+1] << 4)));
+ ++i;
+#else
+ fprintf(out, " %#4x,", (unsigned int)p[i]);
+#endif
+ }
+ fprintf(out, "\n");
+ p += CTYPE_ROW_LEN;
+ }
+ fprintf(out, "};\n");
+
+ fprintf(out, "\n#endif /* WANT_DATA */\n");
+
+#ifdef DO_WIDE_CHAR
+
+ fprintf(out, "\n#define Cc2wc_TBL_LEN\t\t%d\n",
+ n_c2wc_rows * C2WC_ROW_LEN);
+ fprintf(out, "\n#ifdef WANT_DATA\n\n");
+
+ fprintf(out, "\nstatic const unsigned short Cc2wc_data[%d] = {\n",
+ n_c2wc_rows * C2WC_ROW_LEN);
+ p = (char *) c2wc_tbl;
+ for (j=0 ; j < n_c2wc_rows ; j++) {
+ fprintf(out, "\t");
+ for (i=0 ; i < C2WC_ROW_LEN ; i++) {
+ fprintf(out, " %#6x,", (unsigned int)(((unsigned short *)p)[i]));
+ }
+ fprintf(out, "\n");
+ p += 2*C2WC_ROW_LEN;
+ }
+ fprintf(out, "};\n");
+ fprintf(out, "\n#endif /* WANT_DATA */\n");
+#endif /* DO_WIDE_CHAR */
+ fprintf(out, "\n\n");
+
+ fprintf(out, "#define NUM_CODESETS\t\t%d\n", numsets);
+ fprintf(out, "#define CODESET_LIST \\\n\t\"");
+ for (i=0 ; i < numsets ; i++) {
+ fprintf(out, "\\x%02x", numsets + 1 + (unsigned char) codeset_index[i]);
+ if (((i & 7) == 7) && (i + 1 < numsets)) {
+ fprintf(out, "\" \\\n\t\"");
+ }
+ }
+ fprintf(out, "\" \\\n\t\"\\0\"");
+ for (i=0 ; i < numsets ; i++) {
+ fprintf(out, " \\\n\t\"%s\\0\"",
+ codeset_list + ((unsigned char)codeset_index[i]));
+ }
+
+ fprintf(out, "\n\n");
+ for (i=0 ; i < numsets ; i++) {
+ char buf[30];
+ char *z;
+ strcpy(buf, codeset_list + ((unsigned char)codeset_index[i]));
+ for (z=buf ; *z ; z++) {
+ if (*z == '-') {
+ *z = '_';
+ }
+ }
+ fprintf(out, "#define __CTYPE_HAS_CODESET_%s\n", buf);
+ }
+#ifdef DO_WIDE_CHAR
+ fprintf(out, "#define __CTYPE_HAS_CODESET_UTF_8\n");
+#endif /* DO_WIDE_CHAR */
+
+#if 0
+ fprintf(out, "\n#endif /* __CTYPE_HAS_8_BIT_LOCALES */\n\n");
+#endif
+
+ fclose(out);
+
+ total_size = 0;
+#ifdef DO_WIDE_CHAR
+ printf("tt_num = %d ti_num = %d\n", tt_num, ti_num);
+ printf("max_wchar = %#lx\n", max_wchar);
+
+ printf("size is %d * %d + %d * %d + %d * %d = %d\n",
+ tt_num, 1 << TT_SHIFT, ti_num, 1 << TI_SHIFT,
+ ((MAX_WCHAR >> (TT_SHIFT + TI_SHIFT)) + 1), numsets,
+ j = tt_num * (1 << TT_SHIFT) + ti_num * (1 << TI_SHIFT)
+ + ((MAX_WCHAR >> (TT_SHIFT + TI_SHIFT)) + 1) * numsets);
+ total_size += j;
+#endif /* DO_WIDE_CHAR */
+
+#ifdef CTYPE_PACKED
+ i = 2;
+#else
+ i = 1;
+#endif
+
+ printf("ctype - CTYPE_IDX_SHIFT = %d -- %d * %d + %d * %d = %d\n",
+ CTYPE_IDX_SHIFT, numsets, CTYPE_IDX_LEN, n_ctype_rows, CTYPE_ROW_LEN / i,
+ j = numsets * CTYPE_IDX_LEN + n_ctype_rows * CTYPE_ROW_LEN / i);
+ total_size += j;
+
+ printf("uplow - UPLOW_IDX_SHIFT = %d -- %d * %d + %d * %d = %d\n",
+ UPLOW_IDX_SHIFT, numsets, UPLOW_IDX_LEN, n_uplow_rows, UPLOW_ROW_LEN,
+ j = numsets * UPLOW_IDX_LEN + n_uplow_rows * UPLOW_ROW_LEN);
+ total_size += j;
+
+#ifdef DO_WIDE_CHAR
+
+ printf("c2wc - C2WC_IDX_SHIFT = %d -- %d * %d + 2 * %d * %d = %d\n",
+ C2WC_IDX_SHIFT, numsets, C2WC_IDX_LEN, n_c2wc_rows, C2WC_ROW_LEN,
+ j = numsets * C2WC_IDX_LEN + 2 * n_c2wc_rows * C2WC_ROW_LEN);
+ total_size += j;
+
+#endif /* DO_WIDE_CHAR */
+
+ printf("total size = %d\n", total_size);
+
+/* for (i=0 ; i < numsets ; i++) { */
+/* printf("codeset_index[i] = %d codeset_list[ci[i]] = \"%s\"\n", */
+/* (unsigned char) codeset_index[i], */
+/* codeset_list + ((unsigned char)codeset_index[i])); */
+/* } */
+
+ return EXIT_SUCCESS;
+}
diff --git a/extra/locale/gen_wctype.c b/extra/locale/gen_wctype.c
new file mode 100644
index 000000000..9508a3bbf
--- /dev/null
+++ b/extra/locale/gen_wctype.c
@@ -0,0 +1,833 @@
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <wctype.h>
+#include <limits.h>
+#include <stdint.h>
+#include <wchar.h>
+#include <ctype.h>
+
+
+/* 0x9 : space blank */
+/* 0xa : space */
+/* 0xb : space */
+/* 0xc : space */
+/* 0xd : space */
+/* 0x20 : space blank */
+/* 0x1680 : space blank */
+/* 0x2000 : space blank */
+/* 0x2001 : space blank */
+/* 0x2002 : space blank */
+/* 0x2003 : space blank */
+/* 0x2004 : space blank */
+/* 0x2005 : space blank */
+/* 0x2006 : space blank */
+/* 0x2008 : space blank */
+/* 0x2009 : space blank */
+/* 0x200a : space blank */
+/* 0x200b : space blank */
+/* 0x2028 : space */
+/* 0x2029 : space */
+/* 0x3000 : space blank */
+
+/* typecount[ 0] = 88670 C_alpha_nonupper_nonlower */
+/* typecount[ 1] = 742 C_alpha_lower */
+/* typecount[ 2] = 4 C_alpha_upper_lower */
+/* typecount[ 3] = 731 C_alpha_upper */
+/* typecount[ 4] = 10 C_digit */
+/* typecount[ 5] = 10270 C_punct */
+/* typecount[ 6] = 0 C_graph */
+/* typecount[ 7] = 0 C_print_space_nonblank */
+/* typecount[ 8] = 14 C_print_space_blank */
+/* typecount[ 9] = 0 C_space_nonblank_noncntrl */
+/* typecount[10] = 0 C_space_blank_noncntrl */
+/* typecount[11] = 6 C_cntrl_space_nonblank */
+/* typecount[12] = 1 C_cntrl_space_blank */
+/* typecount[13] = 60 C_cntrl_nonspace */
+/* typecount[14] = 96100 C_unclassified */
+/* typecount[15] = 0 empty_slot */
+
+
+
+/* Set to #if 0 to restrict wchars to 16 bits. */
+#if 1
+#define RANGE 0x2ffffUL
+#elif 0
+#define RANGE 0x1ffffUL
+#else
+#define RANGE 0xffffUL /* Restrict for 16-bit wchar_t... */
+#endif
+
+/* Classification codes. */
+
+static const char *typename[] = {
+ "C_unclassified",
+ "C_alpha_nonupper_nonlower",
+ "C_alpha_lower",
+ "C_alpha_upper_lower",
+ "C_alpha_upper",
+ "C_digit",
+ "C_punct",
+ "C_graph",
+ "C_print_space_nonblank",
+ "C_print_space_blank",
+ "C_space_nonblank_noncntrl",
+ "C_space_blank_noncntrl",
+ "C_cntrl_space_nonblank",
+ "C_cntrl_space_blank",
+ "C_cntrl_nonspace",
+ "empty_slot"
+};
+
+/* Taking advantage of the C99 mutual-exclusion guarantees for the various
+ * (w)ctype classes, including the descriptions of printing and control
+ * (w)chars, we can place each in one of the following mutually-exlusive
+ * subsets. Since there are less than 16, we can store the data for
+ * each (w)chars in a nibble. In contrast, glibc uses an unsigned int
+ * per (w)char, with one bit flag for each is* type. While this allows
+ * a simple '&' operation to determine the type vs. a range test and a
+ * little special handling for the "blank" and "xdigit" types in my
+ * approach, it also uses 8 times the space for the tables on the typical
+ * 32-bit archs we supported.*/
+enum {
+ __CTYPE_unclassified = 0,
+ __CTYPE_alpha_nonupper_nonlower,
+ __CTYPE_alpha_lower,
+ __CTYPE_alpha_upper_lower,
+ __CTYPE_alpha_upper,
+ __CTYPE_digit,
+ __CTYPE_punct,
+ __CTYPE_graph,
+ __CTYPE_print_space_nonblank,
+ __CTYPE_print_space_blank,
+ __CTYPE_space_nonblank_noncntrl,
+ __CTYPE_space_blank_noncntrl,
+ __CTYPE_cntrl_space_nonblank,
+ __CTYPE_cntrl_space_blank,
+ __CTYPE_cntrl_nonspace,
+};
+
+/* Some macros that test for various (w)ctype classes when passed one of the
+ * designator values enumerated above. */
+#define __CTYPE_isalnum(D) ((unsigned int)(D-1) <= (__CTYPE_digit-1))
+#define __CTYPE_isalpha(D) ((unsigned int)(D-1) <= (__CTYPE_alpha_upper-1))
+#define __CTYPE_isblank(D) \
+ ((((unsigned int)(D - __CTYPE_print_space_nonblank)) <= 5) && (D & 1))
+#define __CTYPE_iscntrl(D) (((unsigned int)(D - __CTYPE_cntrl_space_nonblank)) <= 2)
+#define __CTYPE_isdigit(D) (D == __CTYPE_digit)
+#define __CTYPE_isgraph(D) ((unsigned int)(D-1) <= (__CTYPE_graph-1))
+#define __CTYPE_islower(D) (((unsigned int)(D - __CTYPE_alpha_lower)) <= 1)
+#define __CTYPE_isprint(D) ((unsigned int)(D-1) <= (__CTYPE_print_space_blank-1))
+#define __CTYPE_ispunct(D) (D == __CTYPE_punct)
+#define __CTYPE_isspace(D) (((unsigned int)(D - __CTYPE_print_space_nonblank)) <= 5)
+#define __CTYPE_isupper(D) (((unsigned int)(D - __CTYPE_alpha_upper_lower)) <= 1)
+#define __CTYPE_isxdigit(D,X) \
+ (__CTYPE_isdigit(D) || (((unsigned int)(((X)|0x20) - 'a')) <= 5))
+
+#define mywalnum(x) __CTYPE_isalnum(d)
+#define mywalpha(x) __CTYPE_isalpha(d)
+#define mywblank(x) __CTYPE_isblank(d)
+#define mywcntrl(x) __CTYPE_iscntrl(d)
+#define mywdigit(x) __CTYPE_isdigit(d)
+#define mywgraph(x) __CTYPE_isgraph(d)
+#define mywlower(x) __CTYPE_islower(d)
+#define mywprint(x) __CTYPE_isprint(d)
+#define mywpunct(x) __CTYPE_ispunct(d)
+#define mywspace(x) __CTYPE_isspace(d)
+#define mywupper(x) __CTYPE_isupper(d)
+#define mywxdigit(x) __CTYPE_isxdigit(d,x)
+
+typedef struct {
+ short l;
+ short u;
+} uldiff_entry;
+
+typedef struct {
+ uint16_t ii_len;
+ uint16_t ti_len;
+ uint16_t ut_len;
+
+ unsigned char ii_shift;
+ unsigned char ti_shift;
+
+ unsigned char *ii;
+ unsigned char *ti;
+ unsigned char *ut;
+} table_data;
+
+
+void output_table(FILE *fp, const char *name, table_data *tbl)
+{
+ size_t i;
+
+ fprintf(fp, "#define WC%s_II_LEN %7u\n", name, tbl->ii_len);
+ fprintf(fp, "#define WC%s_TI_LEN %7u\n", name, tbl->ti_len);
+ fprintf(fp, "#define WC%s_UT_LEN %7u\n", name, tbl->ut_len);
+
+ fprintf(fp, "#define WC%s_II_SHIFT %7u\n", name, tbl->ii_shift);
+ fprintf(fp, "#define WC%s_TI_SHIFT %7u\n", name, tbl->ti_shift);
+
+ fprintf(fp, "\n#ifdef WANT_WC%s_data\n", name);
+
+ i = tbl->ii_len + tbl->ti_len + tbl->ut_len;
+ fprintf(fp, "\nstatic const unsigned char WC%s_data[%zu] = {", name, i);
+ for (i=0 ; i < tbl->ii_len ; i++) {
+ if (i % 12 == 0) {
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, " %#04x,", tbl->ii[i]);
+ }
+ for (i=0 ; i < tbl->ti_len ; i++) {
+ if (i % 12 == 0) {
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, " %#04x,", tbl->ti[i]);
+ }
+ for (i=0 ; i < tbl->ut_len ; i++) {
+ if (i % 12 == 0) {
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, " %#04x,", tbl->ut[i]);
+ }
+ fprintf(fp, "\n};\n\n");
+
+ fprintf(fp, "#endif /* WANT_WC%s_data */\n\n", name);
+}
+
+static void dump_table_data(table_data *tbl)
+{
+ printf("ii_shift = %d ti_shift = %d\n"
+ "ii_len = %d ti_len = %d ut_len = %d\n"
+ "total = %d\n",
+ tbl->ii_shift, tbl->ti_shift,
+ tbl->ii_len, tbl->ti_len, tbl->ut_len,
+ (int) tbl->ii_len + (int) tbl->ti_len + (int) tbl->ut_len);
+}
+
+/* For sorting the blocks of unsigned chars. */
+static size_t nu_val;
+
+int nu_memcmp(const void *a, const void *b)
+{
+ return memcmp(*(unsigned char**)a, *(unsigned char**)b, nu_val);
+}
+
+static size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl);
+
+#define MAXTO 255 /* Restrict to minimal unsigned char max. */
+
+int main(int argc, char **argv)
+{
+ long int u, l, tt;
+ size_t smallest, t;
+ unsigned int c;
+ unsigned int d;
+ int i, n;
+ int ul_count = 0;
+ uldiff_entry uldiff[MAXTO];
+ table_data cttable;
+ table_data ultable;
+ table_data combtable;
+ table_data widthtable;
+
+ unsigned char wct[(RANGE/2)+1]; /* wctype table (nibble per wchar) */
+ unsigned char ult[RANGE+1]; /* upper/lower table */
+ unsigned char combt[(RANGE/4)+1]; /* combining */
+ unsigned char widtht[(RANGE/4)+1]; /* width */
+ wctrans_t totitle;
+ wctype_t is_comb, is_comb3;
+
+ long int typecount[16];
+ int built = 0;
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ while (--argc) {
+ if (!setlocale(LC_CTYPE, *++argv)) {
+ printf("setlocale(LC_CTYPE,%s) failed!\n", *argv);
+ continue;
+ }
+
+ if (!(totitle = wctrans("totitle"))) {
+ printf("no totitle transformation.\n");
+ }
+ if (!(is_comb = wctype("combining"))) {
+ printf("no combining wctype.\n");
+ }
+ if (!(is_comb3 = wctype("combining_level3"))) {
+ printf("no combining_level3 wctype.\n");
+ }
+
+ if (!built) {
+ built = 1;
+ ul_count = 1;
+ uldiff[0].u = uldiff[0].l = 0;
+
+ memset(wct, 0, sizeof(wct));
+ memset(combt, 0, sizeof(combt));
+ memset(widtht, 0, sizeof(widtht));
+
+ for (i = 0 ; i < 16 ; i++) {
+ typecount[i] = 0;
+ }
+
+ for (c=0 ; c <= RANGE ; c++) {
+ if (iswdigit(c)) {
+ d = __CTYPE_digit;
+ } else if (iswalpha(c)) {
+ d = __CTYPE_alpha_nonupper_nonlower;
+ if (iswlower(c)) {
+ d = __CTYPE_alpha_lower;
+ if (iswupper(c)) {
+ d = __CTYPE_alpha_upper_lower;
+ }
+ } else if (iswupper(c)) {
+ d = __CTYPE_alpha_upper;
+ }
+ } else if (iswpunct(c)) {
+ d = __CTYPE_punct;
+ } else if (iswgraph(c)) {
+ d = __CTYPE_graph;
+ } else if (iswprint(c)) {
+ d = __CTYPE_print_space_nonblank;
+ if (iswblank(c)) {
+ d = __CTYPE_print_space_blank;
+ }
+ } else if (iswspace(c) && !iswcntrl(c)) {
+ d = __CTYPE_space_nonblank_noncntrl;
+ if (iswblank(c)) {
+ d = __CTYPE_space_blank_noncntrl;
+ }
+ } else if (iswcntrl(c)) {
+ d = __CTYPE_cntrl_nonspace;
+ if (iswspace(c)) {
+ d = __CTYPE_cntrl_space_nonblank;
+ if (iswblank(c)) {
+ d = __CTYPE_cntrl_space_blank;
+ }
+ }
+ } else {
+ d = __CTYPE_unclassified;
+ }
+
+ ++typecount[d];
+
+#if 0
+ if (iswspace(c)) {
+ if (iswblank(c)) {
+ printf("%#8x : space blank\n", c);
+ } else {
+ printf("%#8x : space\n", c);
+ }
+ }
+#endif
+
+#if 0
+ if (c < 256) {
+ unsigned int glibc;
+
+ glibc = 0;
+ if (isalnum(c)) ++glibc; glibc <<= 1;
+ if (isalpha(c)) ++glibc; glibc <<= 1;
+ if (isblank(c)) ++glibc; glibc <<= 1;
+ if (iscntrl(c)) ++glibc; glibc <<= 1;
+ if (isdigit(c)) ++glibc; glibc <<= 1;
+ if (isgraph(c)) ++glibc; glibc <<= 1;
+ if (islower(c)) ++glibc; glibc <<= 1;
+ if (isprint(c)) ++glibc; glibc <<= 1;
+ if (ispunct(c)) ++glibc; glibc <<= 1;
+ if (isspace(c)) ++glibc; glibc <<= 1;
+ if (isupper(c)) ++glibc; glibc <<= 1;
+ if (isxdigit(c)) ++glibc;
+ printf("%#8x : ctype %#4x\n", c, glibc);
+ }
+#endif
+
+#if 1
+ /* Paranoid checking... */
+ {
+ unsigned int glibc;
+ unsigned int mine;
+
+ glibc = 0;
+ if (iswalnum(c)) ++glibc; glibc <<= 1;
+ if (iswalpha(c)) ++glibc; glibc <<= 1;
+ if (iswblank(c)) ++glibc; glibc <<= 1;
+ if (iswcntrl(c)) ++glibc; glibc <<= 1;
+ if (iswdigit(c)) ++glibc; glibc <<= 1;
+ if (iswgraph(c)) ++glibc; glibc <<= 1;
+ if (iswlower(c)) ++glibc; glibc <<= 1;
+ if (iswprint(c)) ++glibc; glibc <<= 1;
+ if (iswpunct(c)) ++glibc; glibc <<= 1;
+ if (iswspace(c)) ++glibc; glibc <<= 1;
+ if (iswupper(c)) ++glibc; glibc <<= 1;
+ if (iswxdigit(c)) ++glibc;
+
+ mine = 0;
+ if (mywalnum(c)) ++mine; mine <<= 1;
+ if (mywalpha(c)) ++mine; mine <<= 1;
+ if (mywblank(c)) ++mine; mine <<= 1;
+ if (mywcntrl(c)) ++mine; mine <<= 1;
+ if (mywdigit(c)) ++mine; mine <<= 1;
+ if (mywgraph(c)) ++mine; mine <<= 1;
+ if (mywlower(c)) ++mine; mine <<= 1;
+ if (mywprint(c)) ++mine; mine <<= 1;
+ if (mywpunct(c)) ++mine; mine <<= 1;
+ if (mywspace(c)) ++mine; mine <<= 1;
+ if (mywupper(c)) ++mine; mine <<= 1;
+ if (mywxdigit(c)) ++mine;
+
+ if (glibc != mine) {
+ printf("%#8x : glibc %#4x != %#4x mine %u\n", c, glibc, mine, d);
+ return EXIT_FAILURE;
+ }
+
+#if 0
+ if (iswctype(c,is_comb) || iswctype(c,is_comb3)) {
+/* if (!iswpunct(c)) { */
+ printf("%#8x : %d %d %#4x\n",
+ c, iswctype(c,is_comb),iswctype(c,is_comb3), glibc);
+/* } */
+ }
+#endif
+
+ }
+#endif
+
+ combt[c/4] |= ((((!!iswctype(c,is_comb)) << 1) | !!iswctype(c,is_comb3))
+ << ((c & 3) << 1));
+/* comb3t[c/8] |= ((!!iswctype(c,is_comb3)) << (c & 7)); */
+ widtht[c/4] |= (wcwidth(c) << ((c & 3) << 1));
+
+ if (c & 1) { /* Use the high nibble for odd numbered wchars. */
+ d <<= 4;
+ }
+ wct[c/2] |= d;
+
+ l = towlower(c) - c;
+ u = towupper(c) - c;
+ ult[c] = 0;
+ if (l || u) {
+ if ((l != (short)l) || (u != (short)u)) {
+ printf("range assumption error! %x %ld %ld\n", c, l, u);
+ return EXIT_FAILURE;
+ }
+ for (i=0 ; i < ul_count ; i++) {
+ if ((l == uldiff[i].l) && (u == uldiff[i].u)) {
+ goto found;
+ }
+ }
+ uldiff[ul_count].l = l;
+ uldiff[ul_count].u = u;
+ ++ul_count;
+ if (ul_count > MAXTO) {
+ printf("too many touppers/tolowers!\n");
+ return EXIT_FAILURE;
+ }
+ found:
+ ult[c] = i;
+ }
+ }
+
+ for (i = 0 ; i < 16 ; i++) {
+ printf("typecount[%2d] = %8ld %s\n", i, typecount[i], typename[i]);
+ }
+
+ printf("optimizing is* table..\n");
+ n = -1;
+ smallest = SIZE_MAX;
+ cttable.ii = NULL;
+ for (i=0 ; i < 14 ; i++) {
+ t = newopt(wct, (RANGE/2)+1, i, &cttable);
+ if (smallest >= t) {
+ n = i;
+ smallest = t;
+/* } else { */
+/* break; */
+ }
+ }
+ printf("smallest = %zu\n", smallest);
+ if (!(cttable.ii = malloc(smallest))) {
+ printf("couldn't allocate space!\n");
+ return EXIT_FAILURE;
+ }
+ smallest = SIZE_MAX;
+ newopt(wct, (RANGE/2)+1, n, &cttable);
+ ++cttable.ti_shift; /* correct for nibble mode */
+
+
+
+ printf("optimizing u/l-to table..\n");
+ smallest = SIZE_MAX;
+ ultable.ii = NULL;
+ for (i=0 ; i < 14 ; i++) {
+ t = newopt(ult, RANGE+1, i, &ultable);
+ if (smallest >= t) {
+ n = i;
+ smallest = t;
+/* } else { */
+/* break; */
+ }
+ }
+ printf("%zu (smallest) + %zu (u/l diffs) = %zu\n",
+ smallest, 4 * ul_count, smallest + 4 * ul_count);
+ printf("smallest = %zu\n", smallest);
+ if (!(ultable.ii = malloc(smallest))) {
+ printf("couldn't allocate space!\n");
+ return EXIT_FAILURE;
+ }
+ smallest = SIZE_MAX;
+ newopt(ult, RANGE+1, n, &ultable);
+
+
+ printf("optimizing comb table..\n");
+ smallest = SIZE_MAX;
+ combtable.ii = NULL;
+ for (i=0 ; i < 14 ; i++) {
+ t = newopt(combt, sizeof(combt), i, &combtable);
+ if (smallest >= t) {
+ n = i;
+ smallest = t;
+/* } else { */
+/* break; */
+ }
+ }
+ printf("smallest = %zu\n", smallest);
+ if (!(combtable.ii = malloc(smallest))) {
+ printf("couldn't allocate space!\n");
+ return EXIT_FAILURE;
+ }
+ smallest = SIZE_MAX;
+ newopt(combt, sizeof(combt), n, &combtable);
+ combtable.ti_shift += 4; /* correct for 4 entries per */
+
+
+ printf("optimizing width table..\n");
+ smallest = SIZE_MAX;
+ widthtable.ii = NULL;
+ for (i=0 ; i < 14 ; i++) {
+ t = newopt(widtht, sizeof(widtht), i, &widthtable);
+ if (smallest >= t) {
+ n = i;
+ smallest = t;
+/* } else { */
+/* break; */
+ }
+ }
+ printf("smallest = %zu\n", smallest);
+ if (!(widthtable.ii = malloc(smallest))) {
+ printf("couldn't allocate space!\n");
+ return EXIT_FAILURE;
+ }
+ smallest = SIZE_MAX;
+ newopt(widtht, sizeof(widtht), n, &widthtable);
+ widthtable.ti_shift += 4; /* correct for 4 entries per */
+
+
+#if 0
+ printf("optimizing comb3 table..\n");
+ smallest = SIZE_MAX;
+ comb3table.ii = NULL;
+ for (i=0 ; i < 14 ; i++) {
+ t = newopt(comb3t, sizeof(comb3t), i, &comb3table);
+ if (smallest >= t) {
+ n = i;
+ smallest = t;
+/* } else { */
+/* break; */
+ }
+ }
+ printf("smallest = %zu\n", smallest);
+ if (!(comb3table.ii = malloc(smallest))) {
+ printf("couldn't allocate space!\n");
+ return EXIT_FAILURE;
+ }
+ smallest = SIZE_MAX;
+ newopt(comb3t, sizeof(comb3t), n, &comb3table);
+ comb3table.ti_shift += 8; /* correct for 4 entries per */
+#endif
+
+ dump_table_data(&cttable);
+ dump_table_data(&ultable);
+ dump_table_data(&combtable);
+ dump_table_data(&widthtable);
+ }
+
+ printf("verifying for %s...\n", *argv);
+#if RANGE == 0xffffU
+ for (c=0 ; c <= 0xffffUL ; c++)
+#else
+ for (c=0 ; c <= 0x10ffffUL ; c++)
+#endif
+ {
+ unsigned int glibc;
+ unsigned int mine;
+ unsigned int upper, lower;
+
+#if 0
+#if RANGE < 0x10000UL
+ if (c == 0x10000UL) {
+ c = 0x30000UL; /* skip 1st and 2nd sup planes */
+ }
+#elif RANGE < 0x20000UL
+ if (c == 0x20000UL) {
+ c = 0x30000UL; /* skip 2nd sup planes */
+ }
+#endif
+#endif
+
+ glibc = 0;
+ if (iswalnum(c)) ++glibc; glibc <<= 1;
+ if (iswalpha(c)) ++glibc; glibc <<= 1;
+ if (iswblank(c)) ++glibc; glibc <<= 1;
+ if (iswcntrl(c)) ++glibc; glibc <<= 1;
+ if (iswdigit(c)) ++glibc; glibc <<= 1;
+ if (iswgraph(c)) ++glibc; glibc <<= 1;
+ if (iswlower(c)) ++glibc; glibc <<= 1;
+ if (iswprint(c)) ++glibc; glibc <<= 1;
+ if (iswpunct(c)) ++glibc; glibc <<= 1;
+ if (iswspace(c)) ++glibc; glibc <<= 1;
+ if (iswupper(c)) ++glibc; glibc <<= 1;
+ if (iswxdigit(c)) ++glibc;
+
+ {
+ unsigned int u;
+ int n, sc;
+ int i0, i1;
+
+ u = c;
+ if (u <= RANGE) {
+ sc = u & ((1 << cttable.ti_shift) - 1);
+ u >>= cttable.ti_shift;
+ n = u & ((1 << cttable.ii_shift) - 1);
+ u >>= cttable.ii_shift;
+
+ i0 = cttable.ii[u];
+ i0 <<= cttable.ii_shift;
+ i1 = cttable.ti[i0 + n];
+ i1 <<= (cttable.ti_shift-1);
+ d = cttable.ut[i1 + (sc >> 1)];
+
+ if (sc & 1) {
+ d >>= 4;
+ }
+ d &= 0x0f;
+ } else if ((((unsigned int)(c - 0xe0020UL)) <= 0x5f) || (c == 0xe0001UL)){
+ d = __CTYPE_punct;
+ } else if (((unsigned int)(c - 0xf0000UL)) < 0x20000UL) {
+ if ((c & 0xffffU) <= 0xfffdU) {
+ d = __CTYPE_punct;
+ } else {
+ d = __CTYPE_unclassified;
+ }
+ } else {
+ d = __CTYPE_unclassified;
+ }
+
+ mine = 0;
+ if (mywalnum(c)) ++mine; mine <<= 1;
+ if (mywalpha(c)) ++mine; mine <<= 1;
+ if (mywblank(c)) ++mine; mine <<= 1;
+ if (mywcntrl(c)) ++mine; mine <<= 1;
+ if (mywdigit(c)) ++mine; mine <<= 1;
+ if (mywgraph(c)) ++mine; mine <<= 1;
+ if (mywlower(c)) ++mine; mine <<= 1;
+ if (mywprint(c)) ++mine; mine <<= 1;
+ if (mywpunct(c)) ++mine; mine <<= 1;
+ if (mywspace(c)) ++mine; mine <<= 1;
+ if (mywupper(c)) ++mine; mine <<= 1;
+ if (mywxdigit(c)) ++mine;
+
+ if (glibc != mine) {
+ printf("%#8x : glibc %#4x != %#4x mine %d\n", c, glibc, mine, d);
+ if (c < 0x30000UL) {
+ printf("sc=%#x u=%#x n=%#x i0=%#x i1=%#x\n", sc, u, n, i0, i1);
+ }
+ }
+ upper = lower = u = c;
+ if (u <= RANGE) {
+ sc = u & ((1 << ultable.ti_shift) - 1);
+ u >>= ultable.ti_shift;
+ n = u & ((1 << ultable.ii_shift) - 1);
+ u >>= ultable.ii_shift;
+
+ i0 = ultable.ii[u];
+ i0 <<= ultable.ii_shift;
+ i1 = ultable.ti[i0 + n];
+ i1 <<= (ultable.ti_shift);
+ i1 += sc;
+ i0 = ultable.ut[i1];
+ upper = c + uldiff[i0].u;
+ lower = c + uldiff[i0].l;
+ }
+
+ if (towupper(c) != upper) {
+ printf("%#8x : towupper glibc %#4x != %#4x mine\n",
+ c, towupper(c), upper);
+ }
+
+ if (towlower(c) != lower) {
+ printf("%#8x : towlower glibc %#4x != %#4x mine i0 = %d\n",
+ c, towlower(c), lower, i0);
+ }
+
+ if (totitle && ((tt = towctrans(c, totitle)) != upper)) {
+ printf("%#8x : totitle glibc %#4lx != %#4x mine i0 = %d\n",
+ c, tt, upper, i0);
+ }
+ }
+
+
+ if ((c & 0xfff) == 0xfff) printf(".");
+ }
+ printf("done\n");
+ }
+
+ if (1) {
+ FILE *fp;
+
+ if (!(fp = fopen("wctables.h", "w"))) {
+ printf("couldn't open wctables.h!\n");
+ return EXIT_FAILURE;
+ }
+
+ fprintf(fp, "#define WC_TABLE_DOMAIN_MAX %#8lx\n\n",
+ (unsigned long) RANGE);
+ output_table(fp, "ctype", &cttable);
+ output_table(fp, "uplow", &ultable);
+
+
+#warning fix the upper bound on the upper/lower tables... save 200 bytes or so
+ fprintf(fp, "#define WCuplow_diffs %7u\n", ul_count);
+ fprintf(fp, "\n#ifdef WANT_WCuplow_diff_data\n\n");
+ fprintf(fp, "\nstatic const short WCuplow_diff_data[%zu] = {",
+ 2 * (size_t) ul_count);
+ for (i=0 ; i < ul_count ; i++) {
+ if (i % 4 == 0) {
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, " %6d, %6d,", uldiff[i].u, uldiff[i].l);
+ }
+ fprintf(fp, "\n};\n\n");
+ fprintf(fp, "#endif /* WANT_WCuplow_diff_data */\n\n");
+
+
+ output_table(fp, "comb", &combtable);
+ output_table(fp, "width", &widthtable);
+
+ fclose(fp);
+ }
+
+ return EXIT_SUCCESS;
+}
+
+size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl)
+{
+ static int recurse = 0;
+ unsigned char *ti[RANGE+1]; /* table index */
+ size_t numblocks;
+ size_t blocksize;
+ size_t uniq;
+ size_t i, j;
+ size_t smallest, t;
+ unsigned char *ii_save;
+ int uniqblock[256];
+ unsigned char uit[RANGE+1];
+ int shift2;
+
+ ii_save = NULL;
+ blocksize = 1 << shift;
+ numblocks = usize >> shift;
+
+ /* init table index */
+ for (i=j=0 ; i < numblocks ; i++) {
+ ti[i] = ut + j;
+ j += blocksize;
+ }
+
+ /* sort */
+ nu_val = blocksize;
+ qsort(ti, numblocks, sizeof(unsigned char *), nu_memcmp);
+
+ uniq = 1;
+ uit[(ti[0]-ut)/blocksize] = 0;
+ for (i=1 ; i < numblocks ; i++) {
+ if (memcmp(ti[i-1], ti[i], blocksize) < 0) {
+ if (++uniq > 255) {
+ break;
+ }
+ uniqblock[uniq - 1] = i;
+ }
+#if 1
+ else if (memcmp(ti[i-1], ti[i], blocksize) > 0) {
+ printf("bad sort %i!\n", i);
+ abort();
+ }
+#endif
+ uit[(ti[i]-ut)/blocksize] = uniq - 1;
+ }
+
+ smallest = SIZE_MAX;
+ shift2 = -1;
+ if (uniq <= 255) {
+ smallest = numblocks + uniq * blocksize;
+ if (!recurse) {
+ ++recurse;
+ for (j=1 ; j < 14 ; j++) {
+ if ((numblocks >> j) < 2) break;
+ if (tbl) {
+ ii_save = tbl->ii;
+ tbl->ii = NULL;
+ }
+ if ((t = newopt(uit, numblocks, j, tbl)) < SIZE_MAX) {
+ t += uniq * blocksize;
+ }
+ if (tbl) {
+ tbl->ii = ii_save;
+ }
+ if (smallest >= t) {
+ shift2 = j;
+ smallest = t;
+ if (!tbl->ii) {
+ printf("ishift %zu tshift %zu size %zu\n",
+ shift2, shift, t);
+ }
+/* } else { */
+/* break; */
+ }
+ }
+ --recurse;
+ }
+ } else {
+ return SIZE_MAX;
+ }
+
+ if (tbl->ii) {
+ if (recurse) {
+ tbl->ii_shift = shift;
+ tbl->ii_len = numblocks;
+ memcpy(tbl->ii, uit, numblocks);
+ tbl->ti = tbl->ii + tbl->ii_len;
+ tbl->ti_len = uniq * blocksize;
+ for (i=0 ; i < uniq ; i++) {
+ memcpy(tbl->ti + i * blocksize, ti[uniqblock[i]], blocksize);
+ }
+ } else {
+ ++recurse;
+ printf("setting ishift %zu tshift %zu\n",
+ shift2, shift);
+ newopt(uit, numblocks, shift2, tbl);
+ --recurse;
+ tbl->ti_shift = shift;
+ tbl->ut_len = uniq * blocksize;
+ tbl->ut = tbl->ti + tbl->ti_len;
+ for (i=0 ; i < uniq ; i++) {
+ memcpy(tbl->ut + i * blocksize, ti[uniqblock[i]], blocksize);
+ }
+ }
+ }
+ return smallest;
+}
diff --git a/extra/locale/lmmtolso.c b/extra/locale/lmmtolso.c
new file mode 100644
index 000000000..a1876a7dc
--- /dev/null
+++ b/extra/locale/lmmtolso.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int main(void)
+{
+ FILE *lmm; /* mmap-able file */
+ FILE *lso; /* static object */
+ struct stat fd_stat;
+ int c;
+ size_t i;
+
+ if (!(lmm = fopen("locale.mmap", "r"))) {
+ printf("can't open locale.mmap!\n");
+ return EXIT_FAILURE;
+ }
+
+ if (fstat(fileno(lmm), &fd_stat)) {
+ printf("can't stat locale.mmap!\n");
+ fclose(lmm);
+ return EXIT_FAILURE;
+ }
+
+ if (!(lso = fopen("locale_data.c", "w"))) {
+ printf("can't open locale_data.c!\n");
+ fclose(lmm);
+ return EXIT_FAILURE;
+ }
+
+ fprintf(lso,
+ "#include <stddef.h>\n"
+ "#include <stdint.h>\n"
+ "#include \"lt_defines.h\"\n"
+ "#include \"locale_mmap.h\"\n\n"
+ "typedef union {\n"
+ "\tunsigned char buf[%zu];\n"
+ "\t__locale_mmap_t lmm;\n"
+ "} locale_union_t;\n\n"
+ "static const locale_union_t locale_union = { {",
+ (size_t) fd_stat.st_size
+ );
+
+ i = 0;
+ while ((c = getc(lmm)) != EOF) {
+ if (!(i & 0x7)) {
+ fprintf(lso, "\n\t");
+ }
+ fprintf(lso, "%#04x, ", c);
+ ++i;
+ }
+ fprintf(lso,
+ "\n} };\n\n"
+ "const __locale_mmap_t *__locale_mmap = &locale_union.lmm;\n\n"
+ );
+
+ if (ferror(lmm)) {
+ printf("error reading!\n");
+ return EXIT_FAILURE;
+ }
+
+ if (ferror(lso) || fclose(lso)) {
+ printf("error writing!\n");
+ return EXIT_FAILURE;
+ }
+
+ fclose(lmm);
+
+ return EXIT_SUCCESS;
+}
diff --git a/extra/locale/locale_mmap.h b/extra/locale/locale_mmap.h
new file mode 100644
index 000000000..1ed7a2094
--- /dev/null
+++ b/extra/locale/locale_mmap.h
@@ -0,0 +1,89 @@
+/* #include "lt_defines.h" */
+
+/* TODO - fix */
+#define MAGIC_SIZE 64
+
+/* TODO - fix */
+#ifdef __WCHAR_ENABLED
+#define WCctype_TBL_LEN (WCctype_II_LEN + WCctype_TI_LEN + WCctype_UT_LEN)
+#define WCuplow_TBL_LEN (WCuplow_II_LEN + WCuplow_TI_LEN + WCuplow_UT_LEN)
+#define WCuplow_diff_TBL_LEN (2 * WCuplow_diffs)
+#define WCcomb_TBL_LEN (WCcomb_II_LEN + WCcomb_TI_LEN + WCcomb_UT_LEN)
+#endif
+
+#undef __PASTE2
+#define __PASTE2(A,B) A ## B
+#undef __PASTE3
+#define __PASTE3(A,B,C) A ## B ## C
+
+#define COMMON_MMAP(X) \
+ unsigned char __PASTE3(lc_,X,_data)[__PASTE3(__lc_,X,_data_LEN)];
+
+#define COMMON_MMIDX(X) \
+ unsigned char __PASTE3(lc_,X,_rows)[__PASTE3(__lc_,X,_rows_LEN)]; \
+ uint16_t __PASTE3(lc_,X,_item_offsets)[__PASTE3(__lc_,X,_item_offsets_LEN)]; \
+ uint16_t __PASTE3(lc_,X,_item_idx)[__PASTE3(__lc_,X,_item_idx_LEN)]; \
+
+
+typedef struct {
+ unsigned char magic[MAGIC_SIZE];
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ const unsigned char tbl8ctype[Cctype_TBL_LEN];
+ const unsigned char tbl8uplow[Cuplow_TBL_LEN];
+#ifdef __WCHAR_ENABLED
+ const uint16_t tbl8c2wc[Cc2wc_TBL_LEN]; /* char > 0x7f to wide char */
+ const unsigned char tbl8wc2c[Cwc2c_TBL_LEN];
+ /* translit */
+#endif /* __WCHAR_ENABLED */
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+#ifdef __WCHAR_ENABLED
+ const unsigned char tblwctype[WCctype_TBL_LEN];
+ const unsigned char tblwuplow[WCuplow_TBL_LEN];
+ const int16_t tblwuplow_diff[WCuplow_diff_TBL_LEN];
+ const unsigned char tblwcomb[WCcomb_TBL_LEN];
+ /* width?? */
+#endif /* __WCHAR_ENABLED */
+
+ COMMON_MMAP(numeric);
+ COMMON_MMAP(monetary);
+ COMMON_MMAP(time);
+
+ /* TODO -- collate*/
+
+ COMMON_MMAP(messages);
+
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ const codeset_8_bit_t codeset_8_bit[NUM_CODESETS];
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+
+ COMMON_MMIDX(numeric);
+ COMMON_MMIDX(monetary);
+ COMMON_MMIDX(time);
+
+ /* TODO -- collate*/
+
+ COMMON_MMIDX(messages);
+
+
+ unsigned char lc_common_item_offsets_LEN[CATEGORIES];
+ size_t lc_common_tbl_offsets[CATEGORIES * 4];
+ /* offsets from start of locale_mmap_t */
+ /* rows, item_offsets, item_idx, data */
+
+#ifdef NUM_LOCALES
+ unsigned char locales[NUM_LOCALES * WIDTH_LOCALES];
+ unsigned char locale_names5[5*NUM_LOCALE_NAMES];
+ unsigned char locale_at_modifiers[LOCALE_AT_MODIFIERS_LENGTH];
+#endif /* NUM_LOCALES */
+
+ unsigned char lc_names[lc_names_LEN];
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ unsigned char codeset_list[sizeof(CODESET_LIST)]; /* TODO - fix */
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+
+
+} __locale_mmap_t;
+
+extern const __locale_mmap_t *__locale_mmap;
diff --git a/include/ctype.h b/include/ctype.h
index a7e397e3d..c39bd3ccd 100644
--- a/include/ctype.h
+++ b/include/ctype.h
@@ -1,82 +1,126 @@
-/* vi: set sw=4 ts=4: */
-/*
- * ctype.h
- * Character classification and conversion
+/* Copyright (C) 2002 Manuel Novoa III
*
- * Copyright (C) 2000 by Lineo, inc.
- * Copyright (C) 2000,2001 Erik Andersen <andersee@debian.org>
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
*
- * 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 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 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
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
*
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef __CTYPE_H
-#define __CTYPE_H
+/* NOTE: It is assumed here and throughout the library that the underlying
+ * char encoding for the portable C character set is ASCII (host & target). */
+
+#ifndef _CTYPE_H
+#define _CTYPE_H
#include <features.h>
+#include <bits/uClibc_ctype.h>
__BEGIN_DECLS
+extern int isalnum(int c) __THROW;
+extern int isalpha(int c) __THROW;
+#ifdef __USE_ISOC99
+extern int isblank(int c) __THROW;
+#endif
+extern int iscntrl(int c) __THROW;
+extern int isdigit(int c) __THROW;
+extern int isgraph(int c) __THROW;
+extern int islower(int c) __THROW;
+extern int isprint(int c) __THROW;
+extern int ispunct(int c) __THROW;
+extern int isspace(int c) __THROW;
+extern int isupper(int c) __THROW;
+extern int isxdigit(int c) __THROW;
-/* function prototpes */
-extern int isalnum(int c);
-extern int isalpha(int c);
-extern int isascii(int c);
-extern int isblank(int c);
-extern int iscntrl(int c);
-extern int isdigit(int c);
-extern int isgraph(int c);
-extern int islower(int c);
-extern int isprint(int c);
-extern int ispunct(int c);
-extern int isspace(int c);
-extern int isupper(int c);
-extern int isxdigit(int c);
-extern int isxlower(int c);
-extern int isxupper(int c);
-extern int toascii(int c);
-extern int tolower(int c);
-extern int toupper(int c);
-
-
-/* Locale-compatible macros/inlines have yet to be implemented. */
-#if defined(__USE_CTYPE_MACROS) && !defined __UCLIBC_HAS_LOCALE__
-
-/* macro definitions */
-#define isalnum(c) (isalpha(c) || isdigit(c))
-#define isalpha(c) (isupper(c) || islower(c))
-#define isascii(c) (c > 0 && c <= 0x7f)
-#define isblank(c) (c == ' ' || c == '\t')
-#define iscntrl(c) ((c >= 0) && ((c <= 0x1F) || (c == 0x7f)))
-#define isdigit(c) (c >= '0' && c <= '9')
-#define isgraph(c) (c != ' ' && isprint(c))
-#define islower(c) (c >= 'a' && c <= 'z')
-#define isprint(c) (c >= ' ' && c <= '~')
-#define ispunct(c) ((c > ' ' && c <= '~') && !isalnum(c))
-#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' ||\
- c == '\t' || c == '\v')
-#define isupper(c) (c >= 'A' && c <= 'Z')
-#define isxdigit(c) (isxupper(c) || isxlower(c))
-#define isxlower(c) (isdigit(c) || (c >= 'a' && c <= 'f'))
-#define isxupper(c) (isdigit(c) || (c >= 'A' && c <= 'F'))
-#define toascii(c) (c & 0x7f)
-#define tolower(c) (isupper(c) ? ( c - 'A' + 'a') : (c))
-#define toupper(c) (islower(c) ? (c - 'a' + 'A') : (c))
+extern int tolower(int c) __THROW;
+extern int toupper(int c) __THROW;
+#if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN
+extern int isascii(int c) __THROW;
+extern int toascii(int c) __THROW;
#endif
+/* The following are included for compatibility with older versions of
+ * uClibc; but now they're only visible if MISC funcctionality is requested.
+ * However, as they are locale-independent, the hidden macro versions are
+ * always present. */
+#ifdef __USE_MISC
+extern int isxlower(int c) __THROW; /* uClibc-specific. */
+extern int isxupper(int c) __THROW; /* uClibc-specific. */
+#endif
+
+/* Next, some ctype macros which are valid for all supported locales. */
+/* WARNING: isspace and isblank need to be reverified if more 8-bit codesets
+ * are added!!! But isdigit and isxdigit are always valid. */
+
+#define __isspace(c) __C_isspace(c)
+#define __isblank(c) __C_isblank(c)
+
+#define __isdigit(c) __C_isdigit(c)
+#define __isxdigit(c) __C_isxdigit(c)
+
+/* Now some non-ansi/iso c99 macros. */
+
+#define __isascii(c) (((unsigned int)(c)) <= 0x7f)
+#define __toascii(c) ((c) & 0x7f)
+
+#define _toupper(c) ((c) | 0x20)
+#define _tolower(c) ((c) ^ 0x20)
+
+/* For compatibility with older versions of uClibc. Are these ever used? */
+#define __isxlower(c) __C_isxlower(c) /* uClibc-specific. */
+#define __isxupper(c) __C_isxupper(c) /* uClibc-specific. */
+
+/* Apparently, glibc implements things as macros if __NO_CTYPE isn't defined.
+ * If we don't have locale support, we'll do the same. Otherwise, we'll
+ * only use macros for the supported-locale-invariant cases. */
+#ifndef __NO_CTYPE
+
+#define isdigit(c) __isdigit(c)
+#define isxdigit(c) __isxdigit(c)
+#define isspace(c) __isspace(c)
+#ifdef __USE_ISOC99
+#define isblank(c) __isblank(c)
+#endif
+
+#if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN
+#define isascii(c) __isascii(c)
+#define toascii(c) __toascii(c)
+#endif
+
+#ifdef __USE_MISC
+#define isxlower(c) __C_isxlower(c) /* uClibc-specific. */
+#define isxupper(c) __C_isxupper(c) /* uClibc-specific. */
+#endif
+
+/* TODO - Should test for 8-bit codesets instead, but currently impossible. */
+#ifndef __UCLIBC_HAS_LOCALE__
+
+#define isalnum(c) __C_isalnum(c)
+#define isalpha(c) __C_isalpha(c)
+#define iscntrl(c) __C_iscntrl(c)
+#define isgraph(c) __C_isgraph(c)
+#define islower(c) __C_islower(c)
+#define isprint(c) __C_isprint(c)
+#define ispunct(c) __C_ispunct(c)
+#define isupper(c) __C_isupper(c)
+
+#define tolower(c) __C_tolower(c)
+#define toupper(c) __C_toupper(c)
+
+#endif /* __UCLIBC_HAS_LOCALE__ */
+
+#endif /* __NO_CTYPE */
+
__END_DECLS
-#endif /* __CTYPE_H */
+#endif /* _CTYPE_H */
diff --git a/include/inttypes.h b/include/inttypes.h
index 6c1553f58..b81e73179 100644
--- a/include/inttypes.h
+++ b/include/inttypes.h
@@ -27,7 +27,7 @@
/* Get the type definitions. */
#include <stdint.h>
-#if 0
+#if __UCLIBC_HAS_WCHAR__
/* Get a definition for wchar_t. But we must not define wchar_t itself. */
#ifndef ____gwchar_t_defined
# ifdef __cplusplus
@@ -311,7 +311,7 @@ extern intmax_t strtoimax (__const char *__restrict __nptr,
extern uintmax_t strtoumax (__const char *__restrict __nptr,
char ** __restrict __endptr, int __base) __THROW;
-#if 0
+#if __UCLIBC_HAS_WCHAR__
/* Like `wcstol' but convert to `intmax_t'. */
extern intmax_t wcstoimax (__const __gwchar_t *__restrict __nptr,
__gwchar_t **__restrict __endptr, int __base)
diff --git a/include/langinfo.h b/include/langinfo.h
index 3d0e7e8f0..109923ff5 100644
--- a/include/langinfo.h
+++ b/include/langinfo.h
@@ -23,7 +23,7 @@
/* Get the type definition. */
#include <nl_types.h>
-#include <bits/locale.h> /* Define the __LC_* category names. */
+#include <bits/uClibc_locale.h> /* Define the __LC_* category names. */
__BEGIN_DECLS
@@ -32,11 +32,12 @@ __BEGIN_DECLS
(LC_*) and an item index within the category. Some code may depend on
the item values within a category increasing monotonically with the
indices. */
-#define _NL_ITEM(category, index) (((category) << 16) | (index))
+#define _NL_ITEM(category, index) \
+ (((category) << __NL_ITEM_CATEGORY_SHIFT) | (index))
/* Extract the category and item index from a constructed `nl_item' value. */
-#define _NL_ITEM_CATEGORY(item) ((int) (item) >> 16)
-#define _NL_ITEM_INDEX(item) ((int) (item) & 0xffff)
+#define _NL_ITEM_CATEGORY(item) ((int) (item) >> __NL_ITEM_CATEGORY_SHIFT)
+#define _NL_ITEM_INDEX(item) ((int) (item) & __NL_ITEM_INDEX_MASK)
/* Enumeration of locale items that can be queried with `nl_langinfo'. */
@@ -157,6 +158,7 @@ enum
ERA_T_FMT, /* Time in alternate era format. */
#define ERA_T_FMT ERA_T_FMT
+#if 0
_NL_TIME_ERA_NUM_ENTRIES, /* Number entries in the era arrays. */
_NL_TIME_ERA_ENTRIES, /* Structure with era entries in usable form.*/
@@ -232,12 +234,14 @@ enum
_NL_W_DATE_FMT,
_NL_TIME_CODESET,
+#endif /* 0 */
_NL_NUM_LC_TIME, /* Number of indices in LC_TIME category. */
/* LC_COLLATE category: text sorting.
This information is accessed by the strcoll and strxfrm functions.
These `nl_langinfo' names are used only internally. */
+#if 0
_NL_COLLATE_NRULES = _NL_ITEM (__LC_COLLATE, 0),
_NL_COLLATE_RULESETS,
_NL_COLLATE_TABLEMB,
@@ -258,10 +262,12 @@ enum
_NL_COLLATE_COLLSEQWC,
_NL_COLLATE_CODESET,
_NL_NUM_LC_COLLATE,
+#endif
/* LC_CTYPE category: character classification.
This information is accessed by the functions in <ctype.h>.
These `nl_langinfo' names are used only internally. */
+#if 0
_NL_CTYPE_CLASS = _NL_ITEM (__LC_CTYPE, 0),
_NL_CTYPE_TOUPPER,
_NL_CTYPE_GAP1,
@@ -349,6 +355,11 @@ enum
_NL_CTYPE_EXTRA_MAP_13,
_NL_CTYPE_EXTRA_MAP_14,
_NL_NUM_LC_CTYPE,
+#else /* 0 */
+ _NL_CTYPE_CODESET_NAME = _NL_ITEM (__LC_CTYPE, 0),
+ CODESET = _NL_CTYPE_CODESET_NAME,
+#define CODESET CODESET
+#endif /* 0 */
/* LC_MONETARY category: formatting of monetary quantities.
These items each correspond to a member of `struct lconv',
@@ -413,8 +424,6 @@ enum
#ifdef __USE_GNU
# define N_SIGN_POSN __N_SIGN_POSN
#endif
- _NL_MONETARY_CRNCYSTR,
-#define CRNCYSTR _NL_MONETARY_CRNCYSTR
__INT_P_CS_PRECEDES,
#ifdef __USE_GNU
# define INT_P_CS_PRECEDES __INT_P_CS_PRECEDES
@@ -439,6 +448,11 @@ enum
#ifdef __USE_GNU
# define INT_N_SIGN_POSN __INT_N_SIGN_POSN
#endif
+
+ _NL_MONETARY_CRNCYSTR,
+#define CRNCYSTR _NL_MONETARY_CRNCYSTR
+
+#if 0
_NL_MONETARY_DUO_INT_CURR_SYMBOL,
_NL_MONETARY_DUO_CURRENCY_SYMBOL,
_NL_MONETARY_DUO_INT_FRAC_DIGITS,
@@ -463,6 +477,7 @@ enum
_NL_MONETARY_DECIMAL_POINT_WC,
_NL_MONETARY_THOUSANDS_SEP_WC,
_NL_MONETARY_CODESET,
+#endif /* 0 */
_NL_NUM_LC_MONETARY,
/* LC_NUMERIC category: formatting of numbers.
@@ -483,15 +498,18 @@ enum
#ifdef __USE_GNU
# define GROUPING __GROUPING
#endif
+#if 0
_NL_NUMERIC_DECIMAL_POINT_WC,
_NL_NUMERIC_THOUSANDS_SEP_WC,
_NL_NUMERIC_CODESET,
+#endif
_NL_NUM_LC_NUMERIC,
__YESEXPR = _NL_ITEM (__LC_MESSAGES, 0), /* Regex matching ``yes'' input. */
#define YESEXPR __YESEXPR
__NOEXPR, /* Regex matching ``no'' input. */
#define NOEXPR __NOEXPR
+#if 0
__YESSTR, /* Output string for ``yes''. */
#if defined __USE_GNU || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
# define YESSTR __YESSTR
@@ -501,8 +519,10 @@ enum
# define NOSTR __NOSTR
#endif
_NL_MESSAGES_CODESET,
+#endif
_NL_NUM_LC_MESSAGES,
+#if 0
_NL_PAPER_HEIGHT = _NL_ITEM (__LC_PAPER, 0),
_NL_PAPER_WIDTH,
_NL_PAPER_CODESET,
@@ -560,7 +580,7 @@ enum
_NL_IDENTIFICATION_CATEGORY,
_NL_IDENTIFICATION_CODESET,
_NL_NUM_LC_IDENTIFICATION,
-
+#endif
/* This marks the highest value used. */
_NL_NUM
};
@@ -585,7 +605,7 @@ extern char *nl_langinfo (nl_item __item) __THROW;
/* Just like nl_langinfo but get the information from the locale object L. */
extern char *__nl_langinfo_l (nl_item __item, __locale_t l);
-#endif
+#endif /* 0 */
__END_DECLS
diff --git a/include/libgen.h b/include/libgen.h
index dc3f064d3..b25254357 100644
--- a/include/libgen.h
+++ b/include/libgen.h
@@ -26,7 +26,6 @@ __BEGIN_DECLS
/* Return directory part of PATH or "." if none is available. */
extern char *dirname (char *__path) __THROW;
-#if 0
/* Return final component of PATH.
This is the weird XPG version of this function. It sometimes will
@@ -35,7 +34,6 @@ extern char *dirname (char *__path) __THROW;
version available under the real name. */
extern char *__xpg_basename (char *__path) __THROW;
#define basename __xpg_basename
-#endif
__END_DECLS
diff --git a/include/locale.h b/include/locale.h
index b3736dd11..1101bb15a 100644
--- a/include/locale.h
+++ b/include/locale.h
@@ -1,30 +1,51 @@
-/* locale.h
- * Support international type specific characters.
+/* Copyright (C) 1991,92,1995-1999,2000,2001 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/*
+ * ISO C99 Standard: 7.11 Localization <locale.h>
*/
-#ifndef _LOCALE_H
-#define _LOCALE_H 1
+
+#ifndef _LOCALE_H
+#define _LOCALE_H 1
#include <features.h>
-__BEGIN_DECLS
+#define __need_NULL
+#include <stddef.h>
+#include <bits/uClibc_locale.h>
-#ifndef NULL
-#ifdef __cplusplus
-#define NULL 0
-#else
-#define NULL ((void *) 0)
-#endif
-#endif
+__BEGIN_DECLS
/* These are the possibilities for the first argument to setlocale.
- The code assumes that LC_ALL is the highest value, and zero the lowest. */
-#define LC_CTYPE 0
-#define LC_NUMERIC 1
-#define LC_TIME 2
-#define LC_COLLATE 3
-#define LC_MONETARY 4
-#define LC_MESSAGES 5
-#define LC_ALL 6
+ The code assumes that the lowest LC_* symbol has the value zero. */
+#define LC_CTYPE __LC_CTYPE
+#define LC_NUMERIC __LC_NUMERIC
+#define LC_TIME __LC_TIME
+#define LC_COLLATE __LC_COLLATE
+#define LC_MONETARY __LC_MONETARY
+#define LC_MESSAGES __LC_MESSAGES
+/* #define LC_PAPER __LC_PAPER */
+/* #define LC_NAME __LC_NAME */
+/* #define LC_ADDRESS __LC_ADDRESS */
+/* #define LC_TELEPHONE __LC_TELEPHONE */
+/* #define LC_MEASUREMENT __LC_MEASUREMENT */
+/* #define LC_IDENTIFICATION __LC_IDENTIFICATION */
+#define LC_ALL __LC_ALL
/* Structure giving information about numeric and monetary notation. */
@@ -70,6 +91,31 @@ struct lconv
4 The sign string immediately follows the currency_symbol. */
char p_sign_posn;
char n_sign_posn;
+#ifdef __USE_ISOC99
+ /* 1 if int_curr_symbol precedes a positive value, 0 if succeeds. */
+ char int_p_cs_precedes;
+ /* 1 iff a space separates int_curr_symbol from a positive value. */
+ char int_p_sep_by_space;
+ /* 1 if int_curr_symbol precedes a negative value, 0 if succeeds. */
+ char int_n_cs_precedes;
+ /* 1 iff a space separates int_curr_symbol from a negative value. */
+ char int_n_sep_by_space;
+ /* Positive and negative sign positions:
+ 0 Parentheses surround the quantity and int_curr_symbol.
+ 1 The sign string precedes the quantity and int_curr_symbol.
+ 2 The sign string follows the quantity and int_curr_symbol.
+ 3 The sign string immediately precedes the int_curr_symbol.
+ 4 The sign string immediately follows the int_curr_symbol. */
+ char int_p_sign_posn;
+ char int_n_sign_posn;
+#else
+ char __int_p_cs_precedes;
+ char __int_p_sep_by_space;
+ char __int_n_cs_precedes;
+ char __int_n_sep_by_space;
+ char __int_p_sign_posn;
+ char __int_n_sign_posn;
+#endif
};
@@ -79,6 +125,40 @@ extern char *setlocale (int __category, __const char *__locale) __THROW;
/* Return the numeric/monetary information for the current locale. */
extern struct lconv *localeconv (void) __THROW;
+#if 0
+/* #ifdef __USE_GNU */
+/* The concept of one static locale per category is not very well
+ thought out. Many applications will need to process its data using
+ information from several different locales. Another application is
+ the implementation of the internationalization handling in the
+ upcoming ISO C++ standard library. To support this another set of
+ the functions using locale data exist which have an additional
+ argument.
+
+ Attention: all these functions are *not* standardized in any form.
+ This is a proof-of-concept implementation. */
+
+/* Get locale datatype definition. */
+# include <xlocale.h>
+
+/* Return a reference to a data structure representing a set of locale
+ datasets. Unlike for the CATEGORY parameter for `setlocale' the
+ CATEGORY_MASK parameter here uses a single bit for each category.
+ I.e., 1 << LC_CTYPE means to load data for this category. If
+ BASE is non-null the appropriate category information in the BASE
+ record is replaced. */
+extern __locale_t __newlocale (int __category_mask, __const char *__locale,
+ __locale_t __base) __THROW;
+
+/* Return a duplicate of the set of locale in DATASET. All usage
+ counters are increased if necessary. */
+extern __locale_t __duplocale (__locale_t __dataset) __THROW;
+
+/* Free the data associated with a locale dataset previously returned
+ by a call to `setlocale_r'. */
+extern void __freelocale (__locale_t __dataset) __THROW;
+#endif
+
__END_DECLS
#endif /* locale.h */
diff --git a/include/stdint.h b/include/stdint.h
index cfd11d4f2..ba0a79037 100644
--- a/include/stdint.h
+++ b/include/stdint.h
@@ -24,11 +24,9 @@
#define _STDINT_H 1
#include <features.h>
-#if 0
-/*#define __need_wchar_t*/
-#include <stddef.h>
-#endif
-/*#include <bits/wchar.h>*/
+#ifdef __UCLIBC_HAS_WCHAR__
+#include <bits/wchar.h>
+#endif /* __UCLIBC_HAS_WCHAR__ */
#include <bits/wordsize.h>
/* Exact integral types. */
@@ -280,18 +278,18 @@ typedef unsigned long long int uintmax_t;
# define SIZE_MAX (4294967295U)
# endif
-#if 0
+#ifdef __UCLIBC_HAS_WCHAR__
/* Limits of `wchar_t'. */
# ifndef WCHAR_MIN
/* These constants might also be defined in <wchar.h>. */
# define WCHAR_MIN __WCHAR_MIN
# define WCHAR_MAX __WCHAR_MAX
# endif
-#endif
/* Limits of `wint_t'. */
# define WINT_MIN (0u)
# define WINT_MAX (4294967295u)
+#endif /* __UCLIBC_HAS_WCHAR__ */
#endif /* C++ && limit macros */
diff --git a/include/stdlib.h b/include/stdlib.h
index 302f2819a..1920e418a 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -27,7 +27,7 @@
/* Get size_t, wchar_t and NULL from <stddef.h>. */
#define __need_size_t
#ifndef __need_malloc_and_calloc
-#if 0
+#ifdef __UCLIBC_HAS_WCHAR__
# define __need_wchar_t
#endif
# define __need_NULL
@@ -130,10 +130,10 @@ __extension__ typedef struct
#define EXIT_SUCCESS 0 /* Successful exit status. */
-#if 0
+#ifdef __UCLIBC_HAS_WCHAR__
/* Maximum length of a multibyte character in the current locale. */
-#define MB_CUR_MAX (__ctype_get_mb_cur_max ())
-extern size_t __ctype_get_mb_cur_max (void) __THROW;
+#define MB_CUR_MAX (_stdlib_mb_cur_max ())
+extern size_t _stdlib_mb_cur_max (void) __THROW;
#endif
/* Convert a string to a floating-point number. */
@@ -776,7 +776,7 @@ extern int qfcvt_r (long double __value, int __ndigit,
# endif /* misc */
#endif /* use MISC || use X/Open Unix */
-#if 0
+#ifdef __UCLIBC_HAS_WCHAR__
/* Return the length of the multibyte character
in S, which is no longer than N. */
extern int mblen (__const char *__s, size_t __n) __THROW;
@@ -796,7 +796,7 @@ extern size_t mbstowcs (wchar_t *__restrict __pwcs,
extern size_t wcstombs (char *__restrict __s,
__const wchar_t *__restrict __pwcs, size_t __n)
__THROW;
-#endif
+#endif /* def __UCLIBC_HAS_WCHAR__ */
#ifdef __USE_SVID
/* Determine whether the string value of RESPONSE matches the affirmation
diff --git a/libc/misc/Makefile b/libc/misc/Makefile
index 9040e7e0b..8dcf5486a 100644
--- a/libc/misc/Makefile
+++ b/libc/misc/Makefile
@@ -34,6 +34,9 @@ endif
ifeq ($(strip $(INCLUDE_THREADS)),true)
DIRS += pthread
endif
+ifeq ($(strip $(HAS_WCHAR)),true)
+DIRS += wctype # wchar
+endif
all: libc.a
diff --git a/libc/misc/ctype/Makefile b/libc/misc/ctype/Makefile
index fb099012a..1d7c24535 100644
--- a/libc/misc/ctype/Makefile
+++ b/libc/misc/ctype/Makefile
@@ -28,10 +28,7 @@ MSRC=ctype.c
MOBJ= isalnum.o isalpha.o isascii.o iscntrl.o isdigit.o isgraph.o \
islower.o isprint.o ispunct.o isspace.o isupper.o isxdigit.o \
isxlower.o isxupper.o toascii.o tolower.o toupper.o isblank.o \
-
-ifeq ($(HAS_LOCALE),true)
- MOBJ += ctype_C.o
-endif
+ __isctype_loc.o
CSRC=junk.c
COBJS=$(patsubst %.c,%.o, $(CSRC))
diff --git a/libc/misc/ctype/ctype.c b/libc/misc/ctype/ctype.c
index a3d3d4354..dedd5c00a 100644
--- a/libc/misc/ctype/ctype.c
+++ b/libc/misc/ctype/ctype.c
@@ -1,341 +1,329 @@
-/* ctype.c
- * Character classification and conversion
- * Copyright (C) 2000 Lineo, Inc.
- * Written by Erik Andersen
- * This file is part of the uClibc C library and is distributed
- * under the GNU Library General Public License.
+/* Copyright (C) 2002 Manuel Novoa III
*
- * not C-locale only code
- * written by Vladimir Oleynik (c) vodz@usa.net
- * and Manuel Novoa III <mnovoa3@bellsouth.net>
- * used ideas is part of the GNU C Library.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#define __USE_CTYPE_MACROS
+/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
+ *
+ * Besides uClibc, I'm using this code in my libc for elks, which is
+ * a 16-bit environment with a fairly limited compiler. It would make
+ * things much easier for me if this file isn't modified unnecessarily.
+ * In particular, please put any new or replacement functions somewhere
+ * else, and modify the makefile to use your version instead.
+ * Thanks. Manuel
+ *
+ * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
+
+#define _GNU_SOURCE
+#define __NO_CTYPE
+
#include <ctype.h>
+#include <stdio.h>
+#include <limits.h>
+#include <assert.h>
+#include <locale.h>
-#ifdef L_isascii
-#undef isascii
-int
-isascii( int c )
-{
- return (c > 0 && c <= 0x7f);
-}
-#endif
+/**********************************************************************/
-#ifdef L_isdigit
-#undef isdigit
-int
-isdigit( int c )
-{
- return (c >= '0' && c <= '9');
-}
-#endif
+extern int __isctype_loc(int c, int ct);
-#ifdef L_toascii
-#undef toascii
-int
-toascii( int c )
-{
- return (c & 0x7f);
-}
-#endif
+/* Some macros used throughout the file. */
+#define U ((unsigned char)c)
+/* #define LCT (__cur_locale->ctype) */
+#define LCT (&__global_locale)
-#ifdef L_isblank
-#undef isblank
-int
-isblank( int c )
-{
- return ((c == ' ') || (c == '\t'));
-}
+/**********************************************************************/
+
+#ifndef __PASTE
+#define __PASTE(X,Y) X ## Y
#endif
-/* locale depended */
-#ifndef __UCLIBC_HAS_LOCALE__
+#define C_MACRO(X) __PASTE(__C_,X)(c)
-#ifdef L_isalpha
-#undef isalpha
-int
-isalpha( int c )
-{
- return (isupper(c) || islower(c));
-}
-#endif
+#define CT_MACRO(X) __PASTE(__ctype_,X)(c)
-#ifdef L_isalnum
-#undef isalnum
-int
-isalnum( int c )
-{
- return (isalpha(c) || isdigit(c));
-}
-#endif
+/**********************************************************************/
-#ifdef L_iscntrl
-#undef iscntrl
-int
-iscntrl( int c )
-{
- return ((c >= 0) && ((c <= 0x1f) || (c == 0x7f)));
-}
-#endif
+#ifndef __CTYPE_HAS_8_BIT_LOCALES
-#ifdef L_isgraph
-#undef isgraph
-int
-isgraph( int c )
-{
- return (c > ' ' && isprint(c));
+#define IS_FUNC_BODY(NAME) \
+int NAME (int c) \
+{ \
+ return C_MACRO(NAME); \
}
-#endif
-#ifdef L_islower
-#undef islower
-int
-islower( int c )
-{
- return (c >= 'a' && c <= 'z');
-}
-#endif
+#else
-#ifdef L_isprint
-#undef isprint
-int
-isprint( int c )
-{
- return (c >= ' ' && c <= '~');
-}
-#endif
+/* It may be worth defining __isctype_loc over the whole range of char. */
+/* #define IS_FUNC_BODY(NAME) \ */
+/* int NAME (int c) \ */
+/* { \ */
+/* return __isctype_loc(c, __PASTE(_CTYPE_,NAME)); \ */
+/* } */
-#ifdef L_ispunct
-#undef ispunct
-int
-ispunct( int c )
-{
- return ((c > ' ' && c <= '~') && !isalnum(c));
+#define IS_FUNC_BODY(NAME) \
+int NAME (int c) \
+{ \
+ if (((unsigned int) c) <= 0x7f) { \
+ return C_MACRO(NAME); \
+ } \
+ return __isctype_loc(c, __PASTE(_CTYPE_,NAME)); \
}
-#endif
-#ifdef L_isspace
-#undef isspace
-int
-isspace( int c )
-{
- return (c == ' ' || c == '\f' || c == '\n' || c == '\r' ||
- c == '\t' || c == '\v');
-}
-#endif
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
-#ifdef L_isupper
-#undef isupper
-int
-isupper( int c )
-{
- return (c >= 'A' && c <= 'Z');
-}
-#endif
+/**********************************************************************/
+#ifdef L_isalnum
+
+IS_FUNC_BODY(isalnum);
-#ifdef L_isxdigit
-#undef isxdigit
-int
-isxdigit( int c )
-{
- return (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
-}
#endif
+/**********************************************************************/
+#ifdef L_isalpha
+
+IS_FUNC_BODY(isalpha);
-#ifdef L_isxlower
-#undef isxlower
-int
-isxlower( int c )
-{
- return (isdigit(c) || (c >= 'a' && c <= 'f'));
-}
#endif
+/**********************************************************************/
+#ifdef L_isblank
-#ifdef L_isxupper
-#undef isxupper
-int
-isxupper( int c )
+/* Warning!!! This is correct for all the currently supported 8-bit locales.
+ * If any are added though, this will need to be verified. */
+
+int isblank(int c)
{
- return (isdigit(c) || (c >= 'A' && c <= 'F'));
+ return __isblank(c);
}
+
#endif
+/**********************************************************************/
+#ifdef L_iscntrl
+
+IS_FUNC_BODY(iscntrl);
-#ifdef L_tolower
-#undef tolower
-int
-tolower( int c )
-{
- return (isupper(c) ? (c - 'A' + 'a') : (c));
-}
#endif
+/**********************************************************************/
+#ifdef L_isdigit
-#ifdef L_toupper
-#undef toupper
-int
-toupper( int c )
+int isdigit(int c)
{
- return (islower(c) ? (c - 'a' + 'A') : (c));
+ return __isdigit(c);
}
+
#endif
+/**********************************************************************/
+#ifdef L_isgraph
-#else /* __UCLIBC_HAS_LOCALE__ */
+IS_FUNC_BODY(isgraph);
-#include <limits.h>
-#include "../locale/_locale.h"
+#endif
+/**********************************************************************/
+#ifdef L_islower
-#define _UC_ISCTYPE(c, type) \
-((c != -1) && ((_uc_ctype_b[(int)((unsigned char)c)] & type) != 0))
+IS_FUNC_BODY(islower);
-#define _UC_ISCTYPE2(c, type, type2) \
-((c != -1) && ((_uc_ctype_b[(int)((unsigned char)c)] & type) == type2))
+#endif
+/**********************************************************************/
+#ifdef L_isprint
+IS_FUNC_BODY(isprint);
-#ifdef L_ctype_C
+#endif
+/**********************************************************************/
+#ifdef L_ispunct
-/* startup setlocale(LC_TYPE, "C"); */
-#include "ctype_C.c"
+IS_FUNC_BODY(ispunct);
-const unsigned char *_uc_ctype_b = _uc_ctype_b_C;
-const unsigned char *_uc_ctype_trans = _uc_ctype_b_C+LOCALE_BUF_SIZE/2;
+#endif
+/**********************************************************************/
+#ifdef L_isspace
-#endif /* L_ctype_C */
+/* Warning!!! This is correct for all the currently supported 8-bit locales.
+ * If any are added though, this will need to be verified. */
-#ifdef L_isalpha
-#undef isalpha
-int
-isalpha( int c )
+int isspace(int c)
{
- return _UC_ISCTYPE(c, ISalpha);
+ return __isspace(c);
}
-#endif
-#ifdef L_isalnum
-#undef isalnum
-int
-isalnum( int c )
-{
- return _UC_ISCTYPE(c, (ISalpha|ISxdigit));
-}
#endif
+/**********************************************************************/
+#ifdef L_isupper
+
+IS_FUNC_BODY(isupper);
-#ifdef L_iscntrl
-#undef iscntrl
-int
-iscntrl( int c )
-{
- return _UC_ISCTYPE(c, IScntrl);
-}
#endif
+/**********************************************************************/
+#ifdef L_isxdigit
-#ifdef L_isgraph
-#undef isgraph
-int
-isgraph( int c )
+int isxdigit(int c)
{
- return _UC_ISCTYPE2(c, (ISprint|ISspace), ISprint);
+ return __isxdigit(c);
}
+
#endif
+/**********************************************************************/
+#ifdef L_tolower
-#ifdef L_islower
-#undef islower
-int
-islower( int c )
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+
+int tolower(int c)
{
- return _UC_ISCTYPE(c, ISlower);
+ return ((((unsigned int) c) <= 0x7f)
+ || (LCT->encoding != __ctype_encoding_8_bit))
+ ? __C_tolower(c)
+ : ( __isctype_loc(c, _CTYPE_isupper)
+ ? (unsigned char)
+ ( U - LCT->tbl8uplow[ ((int)
+ (LCT->idx8uplow[(U & 0x7f)
+ >> Cuplow_IDX_SHIFT])
+ << Cuplow_IDX_SHIFT)
+ + (U & ((1 << Cuplow_IDX_SHIFT) - 1)) ])
+ : c );
}
-#endif
-#ifdef L_isprint
-#undef isprint
-int
-isprint( int c )
+#else /* __CTYPE_HAS_8_BIT_LOCALES */
+
+int tolower(int c)
{
- return _UC_ISCTYPE(c, ISprint);
+ return __C_tolower(c);
}
+
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+
#endif
+/**********************************************************************/
+#ifdef L_toupper
-#ifdef L_ispunct
-#undef ispunct
-int
-ispunct( int c )
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+
+int toupper(int c)
{
- return _UC_ISCTYPE(c, ISpunct);
+ return ((((unsigned int) c) <= 0x7f)
+ || (LCT->encoding != __ctype_encoding_8_bit))
+ ? __C_toupper(c)
+ : ( __isctype_loc(c, _CTYPE_islower)
+ ? (unsigned char)
+ ( U + LCT->tbl8uplow[ ((int)
+ (LCT->idx8uplow[(U & 0x7f)
+ >> Cuplow_IDX_SHIFT])
+ << Cuplow_IDX_SHIFT)
+ + (U & ((1 << Cuplow_IDX_SHIFT) - 1)) ])
+ : c );
}
-#endif
-#ifdef L_isspace
-#undef isspace
-int
-isspace( int c )
+#else /* __CTYPE_HAS_8_BIT_LOCALES */
+
+int toupper(int c)
{
- return _UC_ISCTYPE(c, ISspace);
+ return __C_toupper(c);
}
+
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+
#endif
+/**********************************************************************/
+#ifdef L_isascii
-#ifdef L_isupper
-#undef isupper
-int
-isupper( int c )
+int isascii(int c)
{
- return _UC_ISCTYPE(c, ISupper);
+ return __isascii(c);
}
+
#endif
+/**********************************************************************/
+#ifdef L_toascii
-#ifdef L_isxdigit
-#undef isxdigit
-int
-isxdigit( int c )
+int toascii(int c)
{
- return _UC_ISCTYPE(c, ISxdigit);
+ return __toascii(c);
}
-#endif
+#endif
+/**********************************************************************/
#ifdef L_isxlower
-#undef isxlower
-int
-isxlower( int c )
+
+int isxlower(int c)
{
- return _UC_ISCTYPE2(c, (ISxdigit|ISupper), ISxdigit);
+ return __isxlower(c);
}
-#endif
+#endif
+/**********************************************************************/
#ifdef L_isxupper
-#undef isxupper
-int
-isxupper( int c )
+
+int isxupper(int c)
{
- return _UC_ISCTYPE2(c, (ISxdigit|ISlower), ISxdigit);
+ return __isxupper(c);
}
+
#endif
+/**********************************************************************/
+#ifdef L___isctype_loc
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
-#ifdef L_tolower
-#undef tolower
-int
-tolower( int c )
+/* This internal routine is similar to iswctype(), but it doesn't
+ * work for any non-standard types, itdoesn't work for "xdigit"s,
+ * and it doesn't work for chars between 0 and 0x7f (although that
+ * may change). */
+
+static const char ctype_range[] = {
+ __CTYPE_RANGES
+};
+
+int __isctype_loc(int c, int ct)
{
- if((c < CHAR_MIN) || (c > UCHAR_MAX))
- return c;
- if(isupper(c))
- return _uc_ctype_trans[(int)((unsigned char)c)];
- else
- return c;
-}
+ unsigned char d;
+
+ assert(((unsigned int)ct) < _CTYPE_isxdigit);
+ assert(((unsigned int)c) > 0x7f);
+
+#if (CHAR_MIN == 0) /* We don't have signed chars... */
+ if ((LCT->encoding != __ctype_encoding_8_bit)
+ || (((unsigned int) c) > UCHAR_MAX)
+ ) {
+ return 0;
+ }
+#else
+ /* Allow non-EOF negative char values for glibc compatiblity. */
+ if ((LCT->encoding != __ctype_encoding_8_bit) || (c == EOF)
+ || ( ((unsigned int)(c - CHAR_MIN)) > (UCHAR_MAX - CHAR_MIN))
+ ) {
+ return 0;
+ }
#endif
-#ifdef L_toupper
-#undef toupper
-int
-toupper( int c )
-{
- if((c < CHAR_MIN) || (c > UCHAR_MAX))
- return c;
- if(islower(c))
- return _uc_ctype_trans[(int)((unsigned char)c)];
- else
- return c;
-}
+ /* TODO - test assumptions??? 8-bit chars -- or ensure in generator. */
+
+#define Cctype_TBL_MASK ((1 << Cctype_IDX_SHIFT) - 1)
+#define Cctype_IDX_OFFSET (128 >> Cctype_IDX_SHIFT)
+
+ c &= 0x7f;
+#ifdef Cctype_PACKED
+ d = LCT->tbl8ctype[ ((int)(LCT->idx8ctype[(U >> Cctype_IDX_SHIFT) ])
+ << (Cctype_IDX_SHIFT - 1))
+ + ((U & Cctype_TBL_MASK) >> 1)];
+ d = (U & 1) ? (d >> 4) : (d & 0xf);
+#else
+ d = LCT->tbl8ctype[ ((int)(LCT->idx8ctype[(U >> Cctype_IDX_SHIFT) ])
+ << Cctype_IDX_SHIFT)
+ + (U & Cctype_TBL_MASK) ];
#endif
+ return ( ((unsigned char)(d - ctype_range[2*ct])) <= ctype_range[2*ct+1] );
+}
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
#endif
+/**********************************************************************/
diff --git a/libc/misc/ctype/ctype_C.c b/libc/misc/ctype/ctype_C.c
deleted file mode 100644
index 2aa2690b6..000000000
--- a/libc/misc/ctype/ctype_C.c
+++ /dev/null
@@ -1,517 +0,0 @@
-const unsigned char _uc_ctype_b_C[LOCALE_BUF_SIZE] = {
- /* 0x00, 0, 00 */ IScntrl,
- /* 0x01, 1, 01 */ IScntrl,
- /* 0x02, 2, 02 */ IScntrl,
- /* 0x03, 3, 03 */ IScntrl,
- /* 0x04, 4, 04 */ IScntrl,
- /* 0x05, 5, 05 */ IScntrl,
- /* 0x06, 6, 06 */ IScntrl,
- /* 0x07, 7, 07 */ IScntrl,
- /* 0x08, 8, 010 */ IScntrl,
- /* 0x09, 9, 011 */ IScntrl|ISspace,
- /* 0x0a, 10, 012 */ IScntrl|ISspace,
- /* 0x0b, 11, 013 */ IScntrl|ISspace,
- /* 0x0c, 12, 014 */ IScntrl|ISspace,
- /* 0x0d, 13, 015 */ IScntrl|ISspace,
- /* 0x0e, 14, 016 */ IScntrl,
- /* 0x0f, 15, 017 */ IScntrl,
- /* 0x10, 16, 020 */ IScntrl,
- /* 0x11, 17, 021 */ IScntrl,
- /* 0x12, 18, 022 */ IScntrl,
- /* 0x13, 19, 023 */ IScntrl,
- /* 0x14, 20, 024 */ IScntrl,
- /* 0x15, 21, 025 */ IScntrl,
- /* 0x16, 22, 026 */ IScntrl,
- /* 0x17, 23, 027 */ IScntrl,
- /* 0x18, 24, 030 */ IScntrl,
- /* 0x19, 25, 031 */ IScntrl,
- /* 0x1a, 26, 032 */ IScntrl,
- /* 0x1b, 27, 033 */ IScntrl,
- /* 0x1c, 28, 034 */ IScntrl,
- /* 0x1d, 29, 035 */ IScntrl,
- /* 0x1e, 30, 036 */ IScntrl,
- /* 0x1f, 31, 037 */ IScntrl,
- /* 0x20, 32, 040 */ ISprint|ISspace,
- /* 0x21, 33, 041 */ ISprint|ISpunct,
- /* 0x22, 34, 042 */ ISprint|ISpunct,
- /* 0x23, 35, 043 */ ISprint|ISpunct,
- /* 0x24, 36, 044 */ ISprint|ISpunct,
- /* 0x25, 37, 045 */ ISprint|ISpunct,
- /* 0x26, 38, 046 */ ISprint|ISpunct,
- /* 0x27, 39, 047 */ ISprint|ISpunct,
- /* 0x28, 40, 050 */ ISprint|ISpunct,
- /* 0x29, 41, 051 */ ISprint|ISpunct,
- /* 0x2a, 42, 052 */ ISprint|ISpunct,
- /* 0x2b, 43, 053 */ ISprint|ISpunct,
- /* 0x2c, 44, 054 */ ISprint|ISpunct,
- /* 0x2d, 45, 055 */ ISprint|ISpunct,
- /* 0x2e, 46, 056 */ ISprint|ISpunct,
- /* 0x2f, 47, 057 */ ISprint|ISpunct,
- /* 0x30, 48, 060 */ ISprint|ISxdigit,
- /* 0x31, 49, 061 */ ISprint|ISxdigit,
- /* 0x32, 50, 062 */ ISprint|ISxdigit,
- /* 0x33, 51, 063 */ ISprint|ISxdigit,
- /* 0x34, 52, 064 */ ISprint|ISxdigit,
- /* 0x35, 53, 065 */ ISprint|ISxdigit,
- /* 0x36, 54, 066 */ ISprint|ISxdigit,
- /* 0x37, 55, 067 */ ISprint|ISxdigit,
- /* 0x38, 56, 070 */ ISprint|ISxdigit,
- /* 0x39, 57, 071 */ ISprint|ISxdigit,
- /* 0x3a, 58, 072 */ ISprint|ISpunct,
- /* 0x3b, 59, 073 */ ISprint|ISpunct,
- /* 0x3c, 60, 074 */ ISprint|ISpunct,
- /* 0x3d, 61, 075 */ ISprint|ISpunct,
- /* 0x3e, 62, 076 */ ISprint|ISpunct,
- /* 0x3f, 63, 077 */ ISprint|ISpunct,
- /* 0x40, 64, 0100 */ ISprint|ISpunct,
- /* 0x41, 65, 0101 */ ISprint|ISupper|ISalpha|ISxdigit,
- /* 0x42, 66, 0102 */ ISprint|ISupper|ISalpha|ISxdigit,
- /* 0x43, 67, 0103 */ ISprint|ISupper|ISalpha|ISxdigit,
- /* 0x44, 68, 0104 */ ISprint|ISupper|ISalpha|ISxdigit,
- /* 0x45, 69, 0105 */ ISprint|ISupper|ISalpha|ISxdigit,
- /* 0x46, 70, 0106 */ ISprint|ISupper|ISalpha|ISxdigit,
- /* 0x47, 71, 0107 */ ISprint|ISupper|ISalpha,
- /* 0x48, 72, 0110 */ ISprint|ISupper|ISalpha,
- /* 0x49, 73, 0111 */ ISprint|ISupper|ISalpha,
- /* 0x4a, 74, 0112 */ ISprint|ISupper|ISalpha,
- /* 0x4b, 75, 0113 */ ISprint|ISupper|ISalpha,
- /* 0x4c, 76, 0114 */ ISprint|ISupper|ISalpha,
- /* 0x4d, 77, 0115 */ ISprint|ISupper|ISalpha,
- /* 0x4e, 78, 0116 */ ISprint|ISupper|ISalpha,
- /* 0x4f, 79, 0117 */ ISprint|ISupper|ISalpha,
- /* 0x50, 80, 0120 */ ISprint|ISupper|ISalpha,
- /* 0x51, 81, 0121 */ ISprint|ISupper|ISalpha,
- /* 0x52, 82, 0122 */ ISprint|ISupper|ISalpha,
- /* 0x53, 83, 0123 */ ISprint|ISupper|ISalpha,
- /* 0x54, 84, 0124 */ ISprint|ISupper|ISalpha,
- /* 0x55, 85, 0125 */ ISprint|ISupper|ISalpha,
- /* 0x56, 86, 0126 */ ISprint|ISupper|ISalpha,
- /* 0x57, 87, 0127 */ ISprint|ISupper|ISalpha,
- /* 0x58, 88, 0130 */ ISprint|ISupper|ISalpha,
- /* 0x59, 89, 0131 */ ISprint|ISupper|ISalpha,
- /* 0x5a, 90, 0132 */ ISprint|ISupper|ISalpha,
- /* 0x5b, 91, 0133 */ ISprint|ISpunct,
- /* 0x5c, 92, 0134 */ ISprint|ISpunct,
- /* 0x5d, 93, 0135 */ ISprint|ISpunct,
- /* 0x5e, 94, 0136 */ ISprint|ISpunct,
- /* 0x5f, 95, 0137 */ ISprint|ISpunct,
- /* 0x60, 96, 0140 */ ISprint|ISpunct,
- /* 0x61, 97, 0141 */ ISprint|ISlower|ISalpha|ISxdigit,
- /* 0x62, 98, 0142 */ ISprint|ISlower|ISalpha|ISxdigit,
- /* 0x63, 99, 0143 */ ISprint|ISlower|ISalpha|ISxdigit,
- /* 0x64, 100, 0144 */ ISprint|ISlower|ISalpha|ISxdigit,
- /* 0x65, 101, 0145 */ ISprint|ISlower|ISalpha|ISxdigit,
- /* 0x66, 102, 0146 */ ISprint|ISlower|ISalpha|ISxdigit,
- /* 0x67, 103, 0147 */ ISprint|ISlower|ISalpha,
- /* 0x68, 104, 0150 */ ISprint|ISlower|ISalpha,
- /* 0x69, 105, 0151 */ ISprint|ISlower|ISalpha,
- /* 0x6a, 106, 0152 */ ISprint|ISlower|ISalpha,
- /* 0x6b, 107, 0153 */ ISprint|ISlower|ISalpha,
- /* 0x6c, 108, 0154 */ ISprint|ISlower|ISalpha,
- /* 0x6d, 109, 0155 */ ISprint|ISlower|ISalpha,
- /* 0x6e, 110, 0156 */ ISprint|ISlower|ISalpha,
- /* 0x6f, 111, 0157 */ ISprint|ISlower|ISalpha,
- /* 0x70, 112, 0160 */ ISprint|ISlower|ISalpha,
- /* 0x71, 113, 0161 */ ISprint|ISlower|ISalpha,
- /* 0x72, 114, 0162 */ ISprint|ISlower|ISalpha,
- /* 0x73, 115, 0163 */ ISprint|ISlower|ISalpha,
- /* 0x74, 116, 0164 */ ISprint|ISlower|ISalpha,
- /* 0x75, 117, 0165 */ ISprint|ISlower|ISalpha,
- /* 0x76, 118, 0166 */ ISprint|ISlower|ISalpha,
- /* 0x77, 119, 0167 */ ISprint|ISlower|ISalpha,
- /* 0x78, 120, 0170 */ ISprint|ISlower|ISalpha,
- /* 0x79, 121, 0171 */ ISprint|ISlower|ISalpha,
- /* 0x7a, 122, 0172 */ ISprint|ISlower|ISalpha,
- /* 0x7b, 123, 0173 */ ISprint|ISpunct,
- /* 0x7c, 124, 0174 */ ISprint|ISpunct,
- /* 0x7d, 125, 0175 */ ISprint|ISpunct,
- /* 0x7e, 126, 0176 */ ISprint|ISpunct,
- /* 0x7f, 127, 0177 */ IScntrl,
- /* 0x80, 128, 0200 */ 0,
- /* 0x81, 129, 0201 */ 0,
- /* 0x82, 130, 0202 */ 0,
- /* 0x83, 131, 0203 */ 0,
- /* 0x84, 132, 0204 */ 0,
- /* 0x85, 133, 0205 */ 0,
- /* 0x86, 134, 0206 */ 0,
- /* 0x87, 135, 0207 */ 0,
- /* 0x88, 136, 0210 */ 0,
- /* 0x89, 137, 0211 */ 0,
- /* 0x8a, 138, 0212 */ 0,
- /* 0x8b, 139, 0213 */ 0,
- /* 0x8c, 140, 0214 */ 0,
- /* 0x8d, 141, 0215 */ 0,
- /* 0x8e, 142, 0216 */ 0,
- /* 0x8f, 143, 0217 */ 0,
- /* 0x90, 144, 0220 */ 0,
- /* 0x91, 145, 0221 */ 0,
- /* 0x92, 146, 0222 */ 0,
- /* 0x93, 147, 0223 */ 0,
- /* 0x94, 148, 0224 */ 0,
- /* 0x95, 149, 0225 */ 0,
- /* 0x96, 150, 0226 */ 0,
- /* 0x97, 151, 0227 */ 0,
- /* 0x98, 152, 0230 */ 0,
- /* 0x99, 153, 0231 */ 0,
- /* 0x9a, 154, 0232 */ 0,
- /* 0x9b, 155, 0233 */ 0,
- /* 0x9c, 156, 0234 */ 0,
- /* 0x9d, 157, 0235 */ 0,
- /* 0x9e, 158, 0236 */ 0,
- /* 0x9f, 159, 0237 */ 0,
- /* 0xa0, 160, 0240 */ 0,
- /* 0xa1, 161, 0241 */ 0,
- /* 0xa2, 162, 0242 */ 0,
- /* 0xa3, 163, 0243 */ 0,
- /* 0xa4, 164, 0244 */ 0,
- /* 0xa5, 165, 0245 */ 0,
- /* 0xa6, 166, 0246 */ 0,
- /* 0xa7, 167, 0247 */ 0,
- /* 0xa8, 168, 0250 */ 0,
- /* 0xa9, 169, 0251 */ 0,
- /* 0xaa, 170, 0252 */ 0,
- /* 0xab, 171, 0253 */ 0,
- /* 0xac, 172, 0254 */ 0,
- /* 0xad, 173, 0255 */ 0,
- /* 0xae, 174, 0256 */ 0,
- /* 0xaf, 175, 0257 */ 0,
- /* 0xb0, 176, 0260 */ 0,
- /* 0xb1, 177, 0261 */ 0,
- /* 0xb2, 178, 0262 */ 0,
- /* 0xb3, 179, 0263 */ 0,
- /* 0xb4, 180, 0264 */ 0,
- /* 0xb5, 181, 0265 */ 0,
- /* 0xb6, 182, 0266 */ 0,
- /* 0xb7, 183, 0267 */ 0,
- /* 0xb8, 184, 0270 */ 0,
- /* 0xb9, 185, 0271 */ 0,
- /* 0xba, 186, 0272 */ 0,
- /* 0xbb, 187, 0273 */ 0,
- /* 0xbc, 188, 0274 */ 0,
- /* 0xbd, 189, 0275 */ 0,
- /* 0xbe, 190, 0276 */ 0,
- /* 0xbf, 191, 0277 */ 0,
- /* 0xc0, 192, 0300 */ 0,
- /* 0xc1, 193, 0301 */ 0,
- /* 0xc2, 194, 0302 */ 0,
- /* 0xc3, 195, 0303 */ 0,
- /* 0xc4, 196, 0304 */ 0,
- /* 0xc5, 197, 0305 */ 0,
- /* 0xc6, 198, 0306 */ 0,
- /* 0xc7, 199, 0307 */ 0,
- /* 0xc8, 200, 0310 */ 0,
- /* 0xc9, 201, 0311 */ 0,
- /* 0xca, 202, 0312 */ 0,
- /* 0xcb, 203, 0313 */ 0,
- /* 0xcc, 204, 0314 */ 0,
- /* 0xcd, 205, 0315 */ 0,
- /* 0xce, 206, 0316 */ 0,
- /* 0xcf, 207, 0317 */ 0,
- /* 0xd0, 208, 0320 */ 0,
- /* 0xd1, 209, 0321 */ 0,
- /* 0xd2, 210, 0322 */ 0,
- /* 0xd3, 211, 0323 */ 0,
- /* 0xd4, 212, 0324 */ 0,
- /* 0xd5, 213, 0325 */ 0,
- /* 0xd6, 214, 0326 */ 0,
- /* 0xd7, 215, 0327 */ 0,
- /* 0xd8, 216, 0330 */ 0,
- /* 0xd9, 217, 0331 */ 0,
- /* 0xda, 218, 0332 */ 0,
- /* 0xdb, 219, 0333 */ 0,
- /* 0xdc, 220, 0334 */ 0,
- /* 0xdd, 221, 0335 */ 0,
- /* 0xde, 222, 0336 */ 0,
- /* 0xdf, 223, 0337 */ 0,
- /* 0xe0, 224, 0340 */ 0,
- /* 0xe1, 225, 0341 */ 0,
- /* 0xe2, 226, 0342 */ 0,
- /* 0xe3, 227, 0343 */ 0,
- /* 0xe4, 228, 0344 */ 0,
- /* 0xe5, 229, 0345 */ 0,
- /* 0xe6, 230, 0346 */ 0,
- /* 0xe7, 231, 0347 */ 0,
- /* 0xe8, 232, 0350 */ 0,
- /* 0xe9, 233, 0351 */ 0,
- /* 0xea, 234, 0352 */ 0,
- /* 0xeb, 235, 0353 */ 0,
- /* 0xec, 236, 0354 */ 0,
- /* 0xed, 237, 0355 */ 0,
- /* 0xee, 238, 0356 */ 0,
- /* 0xef, 239, 0357 */ 0,
- /* 0xf0, 240, 0360 */ 0,
- /* 0xf1, 241, 0361 */ 0,
- /* 0xf2, 242, 0362 */ 0,
- /* 0xf3, 243, 0363 */ 0,
- /* 0xf4, 244, 0364 */ 0,
- /* 0xf5, 245, 0365 */ 0,
- /* 0xf6, 246, 0366 */ 0,
- /* 0xf7, 247, 0367 */ 0,
- /* 0xf8, 248, 0370 */ 0,
- /* 0xf9, 249, 0371 */ 0,
- /* 0xfa, 250, 0372 */ 0,
- /* 0xfb, 251, 0373 */ 0,
- /* 0xfc, 252, 0374 */ 0,
- /* 0xfd, 253, 0375 */ 0,
- /* 0xfe, 254, 0376 */ 0,
- /* 0xff, 255, 0377 */ 0,
-
-/* _uc_ctype_trans_C */
-
- /* 0x00, 0, 00 */ 0x00,
- /* 0x01, 1, 01 */ 0x01,
- /* 0x02, 2, 02 */ 0x02,
- /* 0x03, 3, 03 */ 0x03,
- /* 0x04, 4, 04 */ 0x04,
- /* 0x05, 5, 05 */ 0x05,
- /* 0x06, 6, 06 */ 0x06,
- /* 0x07, 7, 07 */ 0x07,
- /* 0x08, 8, 010 */ 0x08,
- /* 0x09, 9, 011 */ 0x09,
- /* 0x0a, 10, 012 */ 0x0a,
- /* 0x0b, 11, 013 */ 0x0b,
- /* 0x0c, 12, 014 */ 0x0c,
- /* 0x0d, 13, 015 */ 0x0d,
- /* 0x0e, 14, 016 */ 0x0e,
- /* 0x0f, 15, 017 */ 0x0f,
- /* 0x10, 16, 020 */ 0x10,
- /* 0x11, 17, 021 */ 0x11,
- /* 0x12, 18, 022 */ 0x12,
- /* 0x13, 19, 023 */ 0x13,
- /* 0x14, 20, 024 */ 0x14,
- /* 0x15, 21, 025 */ 0x15,
- /* 0x16, 22, 026 */ 0x16,
- /* 0x17, 23, 027 */ 0x17,
- /* 0x18, 24, 030 */ 0x18,
- /* 0x19, 25, 031 */ 0x19,
- /* 0x1a, 26, 032 */ 0x1a,
- /* 0x1b, 27, 033 */ 0x1b,
- /* 0x1c, 28, 034 */ 0x1c,
- /* 0x1d, 29, 035 */ 0x1d,
- /* 0x1e, 30, 036 */ 0x1e,
- /* 0x1f, 31, 037 */ 0x1f,
- /* 0x20, 32, 040 */ 0x20,
- /* 0x21, 33, 041 */ 0x21,
- /* 0x22, 34, 042 */ 0x22,
- /* 0x23, 35, 043 */ 0x23,
- /* 0x24, 36, 044 */ 0x24,
- /* 0x25, 37, 045 */ 0x25,
- /* 0x26, 38, 046 */ 0x26,
- /* 0x27, 39, 047 */ 0x27,
- /* 0x28, 40, 050 */ 0x28,
- /* 0x29, 41, 051 */ 0x29,
- /* 0x2a, 42, 052 */ 0x2a,
- /* 0x2b, 43, 053 */ 0x2b,
- /* 0x2c, 44, 054 */ 0x2c,
- /* 0x2d, 45, 055 */ 0x2d,
- /* 0x2e, 46, 056 */ 0x2e,
- /* 0x2f, 47, 057 */ 0x2f,
- /* 0x30, 48, 060 */ 0x30,
- /* 0x31, 49, 061 */ 0x31,
- /* 0x32, 50, 062 */ 0x32,
- /* 0x33, 51, 063 */ 0x33,
- /* 0x34, 52, 064 */ 0x34,
- /* 0x35, 53, 065 */ 0x35,
- /* 0x36, 54, 066 */ 0x36,
- /* 0x37, 55, 067 */ 0x37,
- /* 0x38, 56, 070 */ 0x38,
- /* 0x39, 57, 071 */ 0x39,
- /* 0x3a, 58, 072 */ 0x3a,
- /* 0x3b, 59, 073 */ 0x3b,
- /* 0x3c, 60, 074 */ 0x3c,
- /* 0x3d, 61, 075 */ 0x3d,
- /* 0x3e, 62, 076 */ 0x3e,
- /* 0x3f, 63, 077 */ 0x3f,
- /* 0x40, 64, 0100 */ 0x40,
- /* 0x41, 65, 0101 */ 0x61,
- /* 0x42, 66, 0102 */ 0x62,
- /* 0x43, 67, 0103 */ 0x63,
- /* 0x44, 68, 0104 */ 0x64,
- /* 0x45, 69, 0105 */ 0x65,
- /* 0x46, 70, 0106 */ 0x66,
- /* 0x47, 71, 0107 */ 0x67,
- /* 0x48, 72, 0110 */ 0x68,
- /* 0x49, 73, 0111 */ 0x69,
- /* 0x4a, 74, 0112 */ 0x6a,
- /* 0x4b, 75, 0113 */ 0x6b,
- /* 0x4c, 76, 0114 */ 0x6c,
- /* 0x4d, 77, 0115 */ 0x6d,
- /* 0x4e, 78, 0116 */ 0x6e,
- /* 0x4f, 79, 0117 */ 0x6f,
- /* 0x50, 80, 0120 */ 0x70,
- /* 0x51, 81, 0121 */ 0x71,
- /* 0x52, 82, 0122 */ 0x72,
- /* 0x53, 83, 0123 */ 0x73,
- /* 0x54, 84, 0124 */ 0x74,
- /* 0x55, 85, 0125 */ 0x75,
- /* 0x56, 86, 0126 */ 0x76,
- /* 0x57, 87, 0127 */ 0x77,
- /* 0x58, 88, 0130 */ 0x78,
- /* 0x59, 89, 0131 */ 0x79,
- /* 0x5a, 90, 0132 */ 0x7a,
- /* 0x5b, 91, 0133 */ 0x5b,
- /* 0x5c, 92, 0134 */ 0x5c,
- /* 0x5d, 93, 0135 */ 0x5d,
- /* 0x5e, 94, 0136 */ 0x5e,
- /* 0x5f, 95, 0137 */ 0x5f,
- /* 0x60, 96, 0140 */ 0x60,
- /* 0x61, 97, 0141 */ 0x41,
- /* 0x62, 98, 0142 */ 0x42,
- /* 0x63, 99, 0143 */ 0x43,
- /* 0x64, 100, 0144 */ 0x44,
- /* 0x65, 101, 0145 */ 0x45,
- /* 0x66, 102, 0146 */ 0x46,
- /* 0x67, 103, 0147 */ 0x47,
- /* 0x68, 104, 0150 */ 0x48,
- /* 0x69, 105, 0151 */ 0x49,
- /* 0x6a, 106, 0152 */ 0x4a,
- /* 0x6b, 107, 0153 */ 0x4b,
- /* 0x6c, 108, 0154 */ 0x4c,
- /* 0x6d, 109, 0155 */ 0x4d,
- /* 0x6e, 110, 0156 */ 0x4e,
- /* 0x6f, 111, 0157 */ 0x4f,
- /* 0x70, 112, 0160 */ 0x50,
- /* 0x71, 113, 0161 */ 0x51,
- /* 0x72, 114, 0162 */ 0x52,
- /* 0x73, 115, 0163 */ 0x53,
- /* 0x74, 116, 0164 */ 0x54,
- /* 0x75, 117, 0165 */ 0x55,
- /* 0x76, 118, 0166 */ 0x56,
- /* 0x77, 119, 0167 */ 0x57,
- /* 0x78, 120, 0170 */ 0x58,
- /* 0x79, 121, 0171 */ 0x59,
- /* 0x7a, 122, 0172 */ 0x5a,
- /* 0x7b, 123, 0173 */ 0x7b,
- /* 0x7c, 124, 0174 */ 0x7c,
- /* 0x7d, 125, 0175 */ 0x7d,
- /* 0x7e, 126, 0176 */ 0x7e,
- /* 0x7f, 127, 0177 */ 0x7f,
- /* 0x80, 128, 0200 */ 0x80,
- /* 0x81, 129, 0201 */ 0x81,
- /* 0x82, 130, 0202 */ 0x82,
- /* 0x83, 131, 0203 */ 0x83,
- /* 0x84, 132, 0204 */ 0x84,
- /* 0x85, 133, 0205 */ 0x85,
- /* 0x86, 134, 0206 */ 0x86,
- /* 0x87, 135, 0207 */ 0x87,
- /* 0x88, 136, 0210 */ 0x88,
- /* 0x89, 137, 0211 */ 0x89,
- /* 0x8a, 138, 0212 */ 0x8a,
- /* 0x8b, 139, 0213 */ 0x8b,
- /* 0x8c, 140, 0214 */ 0x8c,
- /* 0x8d, 141, 0215 */ 0x8d,
- /* 0x8e, 142, 0216 */ 0x8e,
- /* 0x8f, 143, 0217 */ 0x8f,
- /* 0x90, 144, 0220 */ 0x90,
- /* 0x91, 145, 0221 */ 0x91,
- /* 0x92, 146, 0222 */ 0x92,
- /* 0x93, 147, 0223 */ 0x93,
- /* 0x94, 148, 0224 */ 0x94,
- /* 0x95, 149, 0225 */ 0x95,
- /* 0x96, 150, 0226 */ 0x96,
- /* 0x97, 151, 0227 */ 0x97,
- /* 0x98, 152, 0230 */ 0x98,
- /* 0x99, 153, 0231 */ 0x99,
- /* 0x9a, 154, 0232 */ 0x9a,
- /* 0x9b, 155, 0233 */ 0x9b,
- /* 0x9c, 156, 0234 */ 0x9c,
- /* 0x9d, 157, 0235 */ 0x9d,
- /* 0x9e, 158, 0236 */ 0x9e,
- /* 0x9f, 159, 0237 */ 0x9f,
- /* 0xa0, 160, 0240 */ 0xa0,
- /* 0xa1, 161, 0241 */ 0xa1,
- /* 0xa2, 162, 0242 */ 0xa2,
- /* 0xa3, 163, 0243 */ 0xa3,
- /* 0xa4, 164, 0244 */ 0xa4,
- /* 0xa5, 165, 0245 */ 0xa5,
- /* 0xa6, 166, 0246 */ 0xa6,
- /* 0xa7, 167, 0247 */ 0xa7,
- /* 0xa8, 168, 0250 */ 0xa8,
- /* 0xa9, 169, 0251 */ 0xa9,
- /* 0xaa, 170, 0252 */ 0xaa,
- /* 0xab, 171, 0253 */ 0xab,
- /* 0xac, 172, 0254 */ 0xac,
- /* 0xad, 173, 0255 */ 0xad,
- /* 0xae, 174, 0256 */ 0xae,
- /* 0xaf, 175, 0257 */ 0xaf,
- /* 0xb0, 176, 0260 */ 0xb0,
- /* 0xb1, 177, 0261 */ 0xb1,
- /* 0xb2, 178, 0262 */ 0xb2,
- /* 0xb3, 179, 0263 */ 0xb3,
- /* 0xb4, 180, 0264 */ 0xb4,
- /* 0xb5, 181, 0265 */ 0xb5,
- /* 0xb6, 182, 0266 */ 0xb6,
- /* 0xb7, 183, 0267 */ 0xb7,
- /* 0xb8, 184, 0270 */ 0xb8,
- /* 0xb9, 185, 0271 */ 0xb9,
- /* 0xba, 186, 0272 */ 0xba,
- /* 0xbb, 187, 0273 */ 0xbb,
- /* 0xbc, 188, 0274 */ 0xbc,
- /* 0xbd, 189, 0275 */ 0xbd,
- /* 0xbe, 190, 0276 */ 0xbe,
- /* 0xbf, 191, 0277 */ 0xbf,
- /* 0xc0, 192, 0300 */ 0xc0,
- /* 0xc1, 193, 0301 */ 0xc1,
- /* 0xc2, 194, 0302 */ 0xc2,
- /* 0xc3, 195, 0303 */ 0xc3,
- /* 0xc4, 196, 0304 */ 0xc4,
- /* 0xc5, 197, 0305 */ 0xc5,
- /* 0xc6, 198, 0306 */ 0xc6,
- /* 0xc7, 199, 0307 */ 0xc7,
- /* 0xc8, 200, 0310 */ 0xc8,
- /* 0xc9, 201, 0311 */ 0xc9,
- /* 0xca, 202, 0312 */ 0xca,
- /* 0xcb, 203, 0313 */ 0xcb,
- /* 0xcc, 204, 0314 */ 0xcc,
- /* 0xcd, 205, 0315 */ 0xcd,
- /* 0xce, 206, 0316 */ 0xce,
- /* 0xcf, 207, 0317 */ 0xcf,
- /* 0xd0, 208, 0320 */ 0xd0,
- /* 0xd1, 209, 0321 */ 0xd1,
- /* 0xd2, 210, 0322 */ 0xd2,
- /* 0xd3, 211, 0323 */ 0xd3,
- /* 0xd4, 212, 0324 */ 0xd4,
- /* 0xd5, 213, 0325 */ 0xd5,
- /* 0xd6, 214, 0326 */ 0xd6,
- /* 0xd7, 215, 0327 */ 0xd7,
- /* 0xd8, 216, 0330 */ 0xd8,
- /* 0xd9, 217, 0331 */ 0xd9,
- /* 0xda, 218, 0332 */ 0xda,
- /* 0xdb, 219, 0333 */ 0xdb,
- /* 0xdc, 220, 0334 */ 0xdc,
- /* 0xdd, 221, 0335 */ 0xdd,
- /* 0xde, 222, 0336 */ 0xde,
- /* 0xdf, 223, 0337 */ 0xdf,
- /* 0xe0, 224, 0340 */ 0xe0,
- /* 0xe1, 225, 0341 */ 0xe1,
- /* 0xe2, 226, 0342 */ 0xe2,
- /* 0xe3, 227, 0343 */ 0xe3,
- /* 0xe4, 228, 0344 */ 0xe4,
- /* 0xe5, 229, 0345 */ 0xe5,
- /* 0xe6, 230, 0346 */ 0xe6,
- /* 0xe7, 231, 0347 */ 0xe7,
- /* 0xe8, 232, 0350 */ 0xe8,
- /* 0xe9, 233, 0351 */ 0xe9,
- /* 0xea, 234, 0352 */ 0xea,
- /* 0xeb, 235, 0353 */ 0xeb,
- /* 0xec, 236, 0354 */ 0xec,
- /* 0xed, 237, 0355 */ 0xed,
- /* 0xee, 238, 0356 */ 0xee,
- /* 0xef, 239, 0357 */ 0xef,
- /* 0xf0, 240, 0360 */ 0xf0,
- /* 0xf1, 241, 0361 */ 0xf1,
- /* 0xf2, 242, 0362 */ 0xf2,
- /* 0xf3, 243, 0363 */ 0xf3,
- /* 0xf4, 244, 0364 */ 0xf4,
- /* 0xf5, 245, 0365 */ 0xf5,
- /* 0xf6, 246, 0366 */ 0xf6,
- /* 0xf7, 247, 0367 */ 0xf7,
- /* 0xf8, 248, 0370 */ 0xf8,
- /* 0xf9, 249, 0371 */ 0xf9,
- /* 0xfa, 250, 0372 */ 0xfa,
- /* 0xfb, 251, 0373 */ 0xfb,
- /* 0xfc, 252, 0374 */ 0xfc,
- /* 0xfd, 253, 0375 */ 0xfd,
- /* 0xfe, 254, 0376 */ 0xfe,
- /* 0xff, 255, 0377 */ 0xff
-};
diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c
index 23e024e15..ab3ee2fd7 100644
--- a/libc/misc/internals/__uClibc_main.c
+++ b/libc/misc/internals/__uClibc_main.c
@@ -34,6 +34,9 @@ extern void weak_function _stdio_init(void);
extern void weak_function _stdio_term(void);
extern int *weak_const_function __errno_location(void);
extern int *weak_const_function __h_errno_location(void);
+#ifdef __UCLIBC_HAS_LOCALE__
+extern void weak_function _locale_init(void);
+#endif
#else
/*
* Define an empty function and use it as a weak alias for the stdio
@@ -62,6 +65,9 @@ extern int atexit(void (*function)(void));
extern int *__errno_location(void);
//weak_alias(__uClibc_empty_func, __h_errno_location);
extern int *__h_errno_location(void);
+#ifdef __UCLIBC_HAS_LOCALE__
+extern void _locale_init(void);
+#endif
#endif
/*
@@ -93,6 +99,12 @@ __uClibc_main(int argc, char **argv, char **envp)
if (unlikely (__libc_enable_secure))
__libc_check_standard_fds ();
#endif
+
+#ifdef __UCLIBC_HAS_LOCALE__
+ /* Initialize the global locale structure. */
+ if (likely(_locale_init)) _locale_init();
+#endif
+
/*
* Initialize stdio here. In the static library case, this will
* be bypassed if not needed because of the weak alias above.
diff --git a/libc/misc/locale/Makefile b/libc/misc/locale/Makefile
index 77a54bdc4..393336c50 100644
--- a/libc/misc/locale/Makefile
+++ b/libc/misc/locale/Makefile
@@ -24,9 +24,14 @@
TOPDIR=../../../
include $(TOPDIR)Rules.mak
-CSRC=locale.c localeconv.c
-COBJS=$(patsubst %.c,%.o, $(CSRC))
-OBJS=$(COBJS)
+MSRC= locale.c
+MOBJ= setlocale.o localeconv.o _locale_init.o nl_langinfo.o
+
+OBJS= $(MOBJ)
+
+ifeq ($(HAS_LOCALE),true)
+ OBJS += locale_data.o
+endif
all: $(OBJS) $(LIBC)
@@ -35,8 +40,8 @@ $(LIBC): ar-target
ar-target: $(OBJS)
$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
-$(COBJS): %.o : %.c
- $(CC) $(CFLAGS) -c $< -o $@
+$(MOBJ): $(MSRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
$(OBJS): Makefile
diff --git a/libc/misc/locale/_locale.h b/libc/misc/locale/_locale.h
deleted file mode 100644
index 139a862f9..000000000
--- a/libc/misc/locale/_locale.h
+++ /dev/null
@@ -1,22 +0,0 @@
-extern const unsigned char *_uc_ctype_b;
-extern const unsigned char *_uc_ctype_trans;
-
-extern const unsigned char _uc_ctype_b_C[256+256];
-
-#define LOCALE_BUF_SIZE (sizeof(_uc_ctype_b_C))
-
-#define ISbit(bit) (1 << bit)
-
-enum
-{
- ISprint = ISbit (0), /* 1 Printable. */
- ISupper = ISbit (1), /* 2 UPPERCASE. */
- ISlower = ISbit (2), /* 4 lowercase. */
- IScntrl = ISbit (3), /* 8 Control character. */
- ISspace = ISbit (4), /* 16 Whitespace. */
- ISpunct = ISbit (5), /* 32 Punctuation. */
- ISalpha = ISbit (6), /* 64 Alphabetic. */
- ISxdigit = ISbit (7), /* 128 Hexnumeric. */
-};
-
-extern const unsigned char *_uc_collate_b;
diff --git a/libc/misc/locale/locale.c b/libc/misc/locale/locale.c
index d978ae37c..fd587429b 100644
--- a/libc/misc/locale/locale.c
+++ b/libc/misc/locale/locale.c
@@ -1,332 +1,507 @@
-/* setlocale.c
- * Load LC_CTYPE and LC_COLLATE locale only special for uclibc
+/* Copyright (C) 2002 Manuel Novoa III
*
- * Written by Vladimir Oleynik (c) vodz@usa.net
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
*
- * This file is part of the uClibc C library and is distributed
- * under the GNU Library General Public License.
- * used ideas is part of the GNU C Library.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* TODO:
+ * Implement the shared mmap code so non-mmu platforms can use this.
+ * Implement nl_langinfo() for the stub locale support.
+ * Add some basic collate functionality similar to what the previous
+ * locale support had (8-bit codesets only).
*/
+#define _GNU_SOURCE
#include <locale.h>
-#include <stdio.h> /* NULL, fopen */
-#include <stdlib.h> /* malloc */
#include <string.h>
-#include <limits.h> /* PATH_MAX */
-#include <errno.h> /* EINVAL */
-#include <unistd.h> /* get(e)[u|g]id */
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <stdint.h>
+#include <assert.h>
-#include "_locale.h"
+#ifdef __LOCALE_C_ONLY
-static char C_LOCALE_NAME []="C";
-static char POSIX_LOCALE_NAME[]="POSIX";
-static char composite_name_C []=
-"LC_CTYPE=C;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C";
+#ifdef __WCHAR_ENABLED
+#error wide char support requires full locale support
+#endif
-#ifdef __UCLIBC_HAS_LOCALE__
+#else /* __LOCALE_C_ONLY */
-#ifdef TEST_LOCALE
-static const char PATH_LOCALE[]="./";
-#else
-static const char PATH_LOCALE[]=__UCLIBC_LOCALE_DIR;
-#endif
+#define CUR_LOCALE_SPEC (__global_locale.cur_locale)
+#undef CODESET_LIST
+#define CODESET_LIST (__locale_mmap->codeset_list)
-struct SAV_LOADED_LOCALE {
- int category;
- char *locale;
- const unsigned char *buf;
- struct SAV_LOADED_LOCALE *next;
-};
+/* TODO: Optional... See below. */
+#define __LOCALE_STRICTER_SETLOCALE
-static struct SAV_LOADED_LOCALE sll_C_LC_MESSAGES = {
- LC_MESSAGES, C_LOCALE_NAME, 0, 0
-};
+#endif /* __LOCALE_C_ONLY */
-static struct SAV_LOADED_LOCALE sll_C_LC_MONETARY = {
- LC_MONETARY, C_LOCALE_NAME, 0, &sll_C_LC_MESSAGES
-};
+/**********************************************************************/
+#ifdef L_setlocale
-static struct SAV_LOADED_LOCALE sll_C_LC_COLLATE = {
- LC_COLLATE, C_LOCALE_NAME, 0, &sll_C_LC_MONETARY
-};
+#ifdef __LOCALE_C_ONLY
-static struct SAV_LOADED_LOCALE sll_C_LC_TIME = {
- LC_TIME, C_LOCALE_NAME, 0, &sll_C_LC_COLLATE
-};
+link_warning(setlocale,"the 'setlocale' function supports only C|POSIX locales");
-static struct SAV_LOADED_LOCALE sll_C_LC_NUMERIC = {
- LC_NUMERIC, C_LOCALE_NAME, 0, &sll_C_LC_TIME
-};
+static const char C_string[] = "C";
-static struct SAV_LOADED_LOCALE sll_C_LC_CTYPE = {
- LC_CTYPE, C_LOCALE_NAME, _uc_ctype_b_C, &sll_C_LC_NUMERIC
-};
+char *setlocale(int category, register const char *locale)
+{
+ return ( (((unsigned int)(category)) <= LC_ALL)
+ && ( (!locale) /* Request for locale category string. */
+ || (!*locale) /* Implementation-defined default is C. */
+ || ((*locale == 'C') && !locale[1])
+ || (!strcmp(locale, "POSIX"))) )
+ ? (char *) C_string /* Always in C/POSIX locale. */
+ : NULL;
+}
-static struct SAV_LOADED_LOCALE *sll = &sll_C_LC_CTYPE;
+#else /* ---------------------------------------------- __LOCALE_C_ONLY */
+#if !defined(NUM_LOCALES) || (NUM_LOCALES <= 1)
+#error locales enabled, but not data other than for C locale!
+#endif
-#endif /* __UCLIBC_HAS_LOCALE__ */
+static unsigned char setlocale_buf[LOCALE_STRING_SIZE];
-static char *nl_current[LC_ALL+1] = {
- C_LOCALE_NAME, C_LOCALE_NAME, C_LOCALE_NAME,
- C_LOCALE_NAME, C_LOCALE_NAME, C_LOCALE_NAME,
- composite_name_C
-};
+#define LOCALE_NAMES (__locale_mmap->locale_names5)
+#define LOCALES (__locale_mmap->locales)
+#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers)
+#define CATEGORY_NAMES (__locale_mmap->lc_names)
-static const char * const LC_strs[LC_ALL+1] = {
- "/LC_CTYPE",
- "/LC_NUMERIC",
- "/LC_TIME",
- "/LC_COLLATE",
- "/LC_MONETARY",
- "/LC_MESSAGES",
- "/LC_ALL"
-};
+static const char posix[] = "POSIX";
-static char *find_locale(int c, const char **plocale)
+static int find_locale(int category, const char *p, unsigned char *new_locale)
{
-#ifdef __UCLIBC_HAS_LOCALE__
- struct SAV_LOADED_LOCALE *cur;
+ int i;
+ const unsigned char *s;
+ uint16_t n;
+ unsigned char lang_cult, codeset;
+
+#if defined(LOCALE_AT_MODIFIERS_LENGTH) && 1
+ /* Support standard locale handling for @-modifiers. */
+ char buf[18]; /* TODO: 7+{max codeset name length} */
+ const char *q;
+
+ if ((q = strchr(p,'@')) != NULL) {
+ if ((((size_t)((q-p)-5)) > (sizeof(buf) - 5)) || (p[2] != '_')) {
+ return 0;
+ }
+ /* locale name at least 5 chars long and 3rd char is '_' */
+ s = LOCALE_AT_MODIFIERS;
+ do {
+ if (!strcmp(s+2, q+1)) {
+ break;
+ }
+ s += 2 + *s; /* TODO - fix this throughout */
+ } while (*s);
+ if (!*s) {
+ return 0;
+ }
+ memcpy(buf, p, q-p);
+ buf[q-p] = 0;
+ buf[2] = s[1];
+ p = buf;
+ }
#endif
- const char *name = *plocale;
-
- if (name[0] == '\0') {
- /* The user decides which locale to use by setting environment
- variables. */
- name = getenv (&LC_strs[LC_ALL][1]);
- if (name == NULL || name[0] == '\0')
- name = getenv (&LC_strs[c][1]);
- if (name == NULL || name[0] == '\0')
- name = getenv ("LANG");
- if (name == NULL || name[0] == '\0')
- name = C_LOCALE_NAME;
+
+ lang_cult = codeset = 0; /* Assume C and default codeset. */
+ if (((*p == 'C') && !p[1]) || !strcmp(p, posix)) {
+ goto FIND_LOCALE;
}
- if (strcmp (name, C_LOCALE_NAME) == 0 ||
- strcmp (name, POSIX_LOCALE_NAME) == 0 ||
- /* TODO! */ (c!=LC_CTYPE && c!=LC_COLLATE))
- name = C_LOCALE_NAME;
+ if (p[5] == '.') { /* Codeset specified in locale name? */
+ /* TODO: maybe CODESET_LIST + *s ??? */
+ /* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */
+ codeset = 2;
+ if (strcmp("UTF-8",p+6) != 0) {/* TODO - fix! */
+ s = CODESET_LIST;
+ do {
+ ++codeset; /* Increment codeset first. */
+ if (!strcmp(CODESET_LIST+*s, p+6)) {
+ goto FIND_LANG_CULT;
+ }
+ } while (*++s);
+ return 0; /* No matching codeset! */
+ }
+ }
- *plocale = name;
+ FIND_LANG_CULT: /* Find language_culture number. */
+ s = LOCALE_NAMES;
+ do { /* TODO -- do a binary search? */
+ /* TODO -- fix gen_mmap!*/
+ ++lang_cult; /* Increment first since C/POSIX is 0. */
+ if (!strncmp(s,p,5)) { /* Found a matching locale name; */
+ goto FIND_LOCALE;
+ }
+ s += 5;
+ } while (lang_cult < NUM_LOCALE_NAMES);
+ return 0; /* No matching language_culture! */
+
+ FIND_LOCALE: /* Find locale row matching name and codeset */
+ s = LOCALES;
+ n = 1;
+ do { /* TODO -- do a binary search? */
+ if ((lang_cult == *s) && ((codeset == s[1]) || (codeset == s[2]))) {
+ i = ((category == LC_ALL) ? 0 : category);
+ s = new_locale + 2*i;
+ do {
+ /* Encode current locale row number. */
+ *((unsigned char *) ++s) = (n >> 8) | 0x80;
+ *((unsigned char *) ++s) = n & 0xff;
+ } while (++i < category);
+
+ return i; /* Return non-zero */
+ }
+ s += WIDTH_LOCALES;
+ ++n;
+ } while (n <= NUM_LOCALES); /* We started at 1!!! */
-#ifdef __UCLIBC_HAS_LOCALE__
- for(cur = sll; cur; cur = cur->next)
- if(cur->category == c && strcmp(cur->locale, name)==0)
- return cur->locale;
-#else
- if(name == C_LOCALE_NAME)
- return C_LOCALE_NAME;
-#endif
- return NULL;
+ return 0; /* Unsupported locale. */
}
-
-#ifdef __UCLIBC_HAS_LOCALE__
-static char *load_locale(int category, const char *locale)
+char *setlocale(int category, const char *locale)
{
- FILE * fl;
- char full_path[PATH_MAX];
- char * buf = 0;
- struct SAV_LOADED_LOCALE *cur;
- struct SAV_LOADED_LOCALE *bottom;
- int bufsize;
- int l = strlen(locale);
-
- if((l+sizeof(PATH_LOCALE)+strlen(LC_strs[category]))>=PATH_MAX)
- return NULL;
-
- /* Not allow acces suid/sgid binaries to outside PATH_LOCALE */
- if((geteuid()!=getuid() || getegid()!=getgid()) &&
- strchr(locale, '/')!=NULL)
- return NULL;
-
- strcpy(full_path, PATH_LOCALE);
- strcat(full_path, locale);
- strcat(full_path, LC_strs[category]);
- fl = fopen(full_path, "r");
- if(fl==0)
- return NULL;
+ const unsigned char *p;
+ unsigned char *s;
+ int i;
+ unsigned lc_mask;
+ unsigned char new_locale[LOCALE_STRING_SIZE];
+
+ if (((unsigned int)(category)) > LC_ALL) {
+ /* TODO - set errno? SUSv3 doesn't say too. */
+ return NULL; /* Illegal/unsupported category. */
+ }
- switch(category) {
- case LC_CTYPE:
- bufsize = LOCALE_BUF_SIZE;
- break;
- case LC_COLLATE:
- bufsize = 256;
- break;
- default: /* TODO */
- bufsize = 0;
- break;
+ lc_mask = 1 << category;
+ if (category == LC_ALL) {
+ --lc_mask;
}
- cur = malloc(sizeof(struct SAV_LOADED_LOCALE)+bufsize+l+2);
- if(cur) {
- buf = (char *)(cur+1);
- if(bufsize!=0 && fread(buf, 1, bufsize+1, fl)!=(bufsize)) {
- /* broken locale file */
- free(cur);
- buf = 0;
-#ifdef TEST_LOCALE
- fprintf(stderr, "\nbroken locale file\n");
-#endif
- }
+ if (!locale) { /* Request for locale category string... */
+ DONE:
+ strcpy(setlocale_buf, CUR_LOCALE_SPEC);
+#ifdef __LOCALE_STRICTER_SETLOCALE
+ /* The standard says you can only use the string returned to restore
+ * the category (categories) requested. This could be optional.
+ * See below as well. */
+ s = setlocale_buf + 1;
+ lc_mask |= (1 << LC_ALL);
+ do {
+ if (!(lc_mask & 1)) {
+ /* Encode non-selected locale flag. */
+ s[1] = *s = 0xff;
+ }
+ s += 2;
+ } while ((lc_mask >>= 1) > 1);
+#endif /* __LOCALE_STRICTER_SETLOCALE */
+ return (char *) setlocale_buf;
}
- fclose(fl);
- if(cur==0) /* not enough memory */
+ strcpy(new_locale, CUR_LOCALE_SPEC); /* Start with current. */
+
+ if (!*locale) { /* locale == "", so check environment. */
+ i = ((category == LC_ALL) ? 0 : category);
+ do {
+ /* Note: SUSv3 doesn't define a fallback mechanism here. So,
+ * if LC_ALL is invalid, we do _not_ continue trying the other
+ * environment vars. */
+ if (!(p = getenv("LC_ALL"))) {
+ if (!(p = getenv(CATEGORY_NAMES + CATEGORY_NAMES[i]))) {
+ if (!(p = getenv("LANG"))) {
+ p = posix;
+ }
+ }
+ }
+
+ /* The user set something... is it valid? */
+ /* Note: Since we don't support user-supplied locales and
+ * alternate paths, we don't need to worry about special
+ * handling for suid/sgid apps. */
+ if (!find_locale(i, p, new_locale)) {
+ return NULL;
+ }
+ } while (++i < category);
+ } else if (*locale == '#') { /* Previsouly returned value. */
+ assert(strlen(locale) == LOCALE_STRING_SIZE - 1);
+
+ i = ((category == LC_ALL) ? 0 : category);
+ p = locale + 2*i;
+ s = new_locale + 2*i;
+ do {
+#ifdef __LOCALE_STRICTER_SETLOCALE
+ /* Only set categories that were selected in the previous
+ * return value. Could be optional. See above as well.
+ * NOTE: This still isn't quite right for non-LC_ALL
+ * as it only checks the category selected to set. */
+ if ((*p == 0xff) && (p[1] == 0xff)) {
+ return NULL;
+ }
+#endif /* __LOCALE_STRICTER_SETLOCALE */
+ /* Note: Validate settings below. */
+ *++s = *++p;
+ *++s = *++p;
+ } while (++i < category);
+ } else if (!find_locale(category, locale, new_locale)) {
return NULL;
- if(buf==0) { /* broken locale file, set to "C" */
- return C_LOCALE_NAME;
}
- cur->next = 0;
- cur->buf = buf;
- cur->category = category;
- cur->locale = buf+bufsize;
- strcpy(cur->locale, locale);
- bottom = sll;
- while(bottom->next!=0)
- bottom = bottom->next;
- bottom->next = cur;
+ /* TODO: Ok, everything checks out, so install the new locale. */
+ _locale_set(new_locale);
- return cur->locale;
+ /* Everything ok, so make a copy in setlocale_buf and return. */
+ goto DONE;
}
-static char *set_composite(int category, char *locale)
+#endif /* __LOCALE_C_ONLY */
+
+#endif
+/**********************************************************************/
+#ifdef L_localeconv
+
+/* Note: We assume here that the compiler does the sane thing regarding
+ * placement of the fields in the struct. If necessary, we could ensure
+ * this usings an array of offsets but at some size cost. */
+
+#ifdef __LOCALE_C_ONLY
+
+#warning localeconv is hardwired for C/POSIX locale only
+link_warning(localeconv,"the 'localeconv' function is hardwired for C/POSIX locale only");
+
+static struct lconv the_lconv;
+
+static const char decpt[] = ".";
+
+struct lconv *localeconv(void)
{
- int i, l;
- char *old_composite_name = nl_current[LC_ALL];
- char *new_composite_name;
- struct SAV_LOADED_LOCALE *cur;
-
- for(l=i=0; i<LC_ALL; i++) {
- new_composite_name = i == category ? locale : nl_current[i];
- /* '=' + ';' or '\0' */
- l += strlen(&LC_strs[i][1])+strlen(new_composite_name)+2;
- }
+ register char *p = (char *)(&the_lconv);
- new_composite_name = malloc(l);
- if(new_composite_name==NULL)
- return NULL;
- if(old_composite_name!=composite_name_C)
- free(old_composite_name);
- nl_current[category] = locale; /* change after malloc */
-
- *new_composite_name = 0;
- for(i=0; i<LC_ALL; i++) {
- if(i)
- strcat(new_composite_name, ";");
- strcat(new_composite_name, &LC_strs[i][1]);
- strcat(new_composite_name, "=");
- strcat(new_composite_name, nl_current[i]);
- }
- nl_current[LC_ALL] = new_composite_name;
-
- /* set locale data for ctype and strcollate functions */
- for(cur = sll; ; cur = cur->next)
- if(cur->category == category && cur->locale == locale)
- break;
-
- switch(category) {
- case LC_CTYPE:
- _uc_ctype_b = cur->buf;
- _uc_ctype_trans = cur->buf+LOCALE_BUF_SIZE/2;
- break;
- case LC_COLLATE:
- _uc_collate_b = cur->buf;
- break;
- default: /* TODO */
- break;
- }
- return locale;
+ *((char **)p) = (char *) decpt;
+ do {
+ p += sizeof(char **);
+ *((char **)p) = (char *) (decpt+1);
+ } while (p < (char *) &the_lconv.negative_sign);
+
+ p = (&the_lconv.int_frac_digits);
+ do {
+ *p = CHAR_MAX;
+ ++p;
+ } while (p <= &the_lconv.int_n_sign_posn);
+
+ return &the_lconv;
}
-#endif /* __UCLIBC_HAS_LOCALE__ */
+#else /* __LOCALE_C_ONLY */
-char *setlocale(int category, const char *locale)
+static struct lconv the_lconv;
+
+struct lconv *localeconv(void)
{
- char * tl;
-#ifdef __UCLIBC_HAS_LOCALE__
- int i;
+ register char *p = (char *) &the_lconv;
+ register char **q = (char **) &__global_locale.decimal_point;
+
+ do {
+ *((char **)p) = *q;
+ p += sizeof(char **);
+ ++q;
+ } while (p < &the_lconv.int_frac_digits);
+
+ do {
+ *p = **q;
+ ++p;
+ ++q;
+ } while (p <= &the_lconv.int_n_sign_posn);
+
+ return &the_lconv;
+}
+
+#endif /* __LOCALE_C_ONLY */
+
#endif
+/**********************************************************************/
+#ifdef L__locale_init
- if (category < 0 || category > LC_ALL) {
-#ifdef __UCLIBC_HAS_LOCALE__
-einval:
+#ifndef __LOCALE_C_ONLY
+
+#define C_LOCALE_SELECTOR "\x23\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01\x80\x01"
+#define LOCALE_INIT_FAILED "locale init failed!\n"
+
+#define CUR_LOCALE_SPEC (__global_locale.cur_locale)
+
+__locale_t __global_locale;
+
+void _locale_init(void)
+{
+ /* TODO: mmap the locale file */
+
+ /* TODO - ??? */
+ memset(CUR_LOCALE_SPEC, 0, LOCALE_STRING_SIZE);
+ CUR_LOCALE_SPEC[0] = '#';
+
+ memcpy(__global_locale.category_item_count,
+ __locale_mmap->lc_common_item_offsets_LEN,
+ LC_ALL);
+
+ __global_locale.category_offsets[0] = offsetof(__locale_t, codeset);
+ __global_locale.category_offsets[1] = offsetof(__locale_t, decimal_point);
+ __global_locale.category_offsets[2] = offsetof(__locale_t, int_curr_symbol);
+ __global_locale.category_offsets[3] = offsetof(__locale_t, abday_1);
+/* __global_locale.category_offsets[4] = offsetof(__locale_t, collate???); */
+ __global_locale.category_offsets[5] = offsetof(__locale_t, yesexpr);
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ __global_locale.tbl8ctype
+ = (const unsigned char *) &__locale_mmap->tbl8ctype;
+ __global_locale.tbl8uplow
+ = (const unsigned char *) &__locale_mmap->tbl8uplow;
+#ifdef __WCHAR_ENABLED
+ __global_locale.tbl8c2wc
+ = (const uint16_t *) &__locale_mmap->tbl8c2wc;
+ __global_locale.tbl8wc2c
+ = (const unsigned char *) &__locale_mmap->tbl8wc2c;
+ /* translit */
+#endif /* __WCHAR_ENABLED */
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+#ifdef __WCHAR_ENABLED
+ __global_locale.tblwctype
+ = (const unsigned char *) &__locale_mmap->tblwctype;
+ __global_locale.tblwuplow
+ = (const unsigned char *) &__locale_mmap->tblwuplow;
+ __global_locale.tblwuplow_diff
+ = (const uint16_t *) &__locale_mmap->tblwuplow_diff;
+ __global_locale.tblwcomb
+ = (const unsigned char *) &__locale_mmap->tblwcomb;
+ /* width?? */
+#endif /* __WCHAR_ENABLED */
+
+ _locale_set(C_LOCALE_SELECTOR);
+}
+
+static const char ascii[] = "ASCII";
+static const char utf8[] = "UTF-8";
+
+void _locale_set(const unsigned char *p)
+{
+ const char **x;
+ unsigned char *s = CUR_LOCALE_SPEC + 1;
+ const size_t *stp;
+ const unsigned char *r;
+ const uint16_t *io;
+ const uint16_t *ii;
+ const unsigned char *d;
+ int row; /* locale row */
+ int crow; /* category row */
+ int len;
+ int c;
+ int i = 0;
+
+ ++p;
+ do {
+ if ((*p != *s) || (p[1] != s[1])) {
+ row = (((int)(*p & 0x7f)) << 8) + p[1] - 1;
+#ifndef NDEBUG
+ assert(row < NUM_LOCALES);
#endif
- errno = EINVAL;
- return NULL;
- }
+ *s = *p;
+ s[1] = p[1];
+
+ if (i == LC_CTYPE) {
+ c = __locale_mmap->locales[ WIDTH_LOCALES * row + 2 ]; /* codeset */
+ if (c <= 2) {
+ if (c == 2) {
+ __global_locale.codeset = utf8;
+ __global_locale.encoding = __ctype_encoding_utf8;
+ /* TODO - fix for bcc */
+ __global_locale.mb_cur_max = 6;
+ } else {
+ assert(c==1);
+ __global_locale.codeset = ascii;
+ __global_locale.encoding = __ctype_encoding_7_bit;
+ __global_locale.mb_cur_max = 1;
+ }
+ } else {
+ const codeset_8_bit_t *c8b;
+ r = CODESET_LIST;
+ __global_locale.codeset = r + r[c -= 3];
+ __global_locale.encoding = __ctype_encoding_8_bit;
+#warning REMINDER: update 8 bit mb_cur_max when trasnlit implemented!
+ /* TODO - update when translit implemented! */
+ __global_locale.mb_cur_max = 1;
+ c8b = __locale_mmap->codeset_8_bit + c;
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ __global_locale.idx8ctype = c8b->idx8ctype;
+ __global_locale.idx8uplow = c8b->idx8uplow;
+#ifdef __WCHAR_ENABLED
+ __global_locale.idx8c2wc = c8b->idx8c2wc;
+ __global_locale.idx8wc2c = c8b->idx8wc2c;
+ /* translit */
+#endif /* __WCHAR_ENABLED */
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+ }
+
+ } else if ((len = __locale_mmap->lc_common_item_offsets_LEN[i]) != 0) {
+ crow = __locale_mmap->locales[ WIDTH_LOCALES * row + 3 + i ]
+ * len;
+ x = (const char **)(((char *) &__global_locale)
+ + __global_locale.category_offsets[i]);
+ stp = __locale_mmap->lc_common_tbl_offsets + 4*i;
+ r = (const unsigned char *)( ((char *)__locale_mmap) + *stp );
+ io = (const uint16_t *)( ((char *)__locale_mmap) + *++stp );
+ ii = (const uint16_t *)( ((char *)__locale_mmap) + *++stp );
+ d = (const unsigned char *)( ((char *)__locale_mmap) + *++stp );
+ for (c=0 ; c < len ; c++) {
+ *(x + c) = d + ii[ r[crow + c] + io[c] ];
+ }
+ }
- if(locale==NULL)
- return nl_current[category];
-
- if(category!=LC_ALL) {
- tl = find_locale(category, &locale);
-#ifdef __UCLIBC_HAS_LOCALE__
- if(tl==NULL)
- tl = load_locale(category, locale);
- if(tl) {
- if(nl_current[category] != tl)
- tl = set_composite(category, tl);
}
+ ++i;
+ p += 2;
+ s += 2;
+ } while (i < LC_ALL);
+}
+
+#endif /* __LOCALE_C_ONLY */
+
#endif
- return tl;
- }
- /* LC_ALL */
-#ifdef __UCLIBC_HAS_LOCALE__
- /* The user wants to set all categories. The desired locales
- for the individual categories can be selected by using a
- composite locale name. This is a semi-colon separated list
- of entries of the form `CATEGORY=VALUE'. */
- tl = strchr(locale, ';');
- if(tl==NULL) {
- /* This is not a composite name. Load the data for each category. */
- for(i=0; i<LC_ALL; i++)
- setlocale(i, locale); /* recursive */
- } else {
- /* This is a composite name. Make a copy and split it up. */
- const char *newnames[LC_ALL];
- char *np;
- char *cp;
-
- i = strlen(locale);
- np = alloca (i);
- if(np)
- strcpy(np, locale);
- else
- return NULL;
- for (i = 0; i < LC_ALL; ++i)
- newnames[i] = 0;
-
- while ((cp = strchr (np, '=')) != NULL) {
- for (i = 0; i < LC_ALL; ++i)
- if ((size_t) (cp - np) == strlen(&LC_strs[i][1])
- && memcmp (np, &LC_strs[i][1], (cp - np)) == 0)
- break;
-
- if (i == LC_ALL)
- /* Bogus category name. */
- goto einval;
-
- /* Found the category this clause sets. */
- newnames[i] = ++cp;
- cp = strchr (cp, ';');
- if (cp != NULL) {
- /* Examine the next clause. */
- *cp = '\0';
- np = cp + 1;
- } else
- /* This was the last clause. We are done. */
- break;
- }
-
- for (i = 0; i < LC_ALL; ++i)
- setlocale(i, newnames[i]); /* recursive */
+/**********************************************************************/
+#ifdef L_nl_langinfo
+
+#ifndef __LOCALE_C_ONLY
+
+#include <langinfo.h>
+#include <nl_types.h>
+
+static const char empty[] = "";
+
+char *nl_langinfo(nl_item item)
+{
+ unsigned int c = _NL_ITEM_CATEGORY(item);
+ unsigned int i = _NL_ITEM_INDEX(item);
+
+ if ((c < LC_ALL) && (i < __global_locale.category_item_count[c])) {
+ return ((char **)(((char *) &__global_locale)
+ + __global_locale.category_offsets[c]))[i];
+
}
+ return (char *) empty;
+}
+
+#endif /* __LOCALE_C_ONLY */
#endif
- return nl_current[LC_ALL];
-}
+/**********************************************************************/
diff --git a/libc/misc/locale/localeconv.c b/libc/misc/locale/localeconv.c
deleted file mode 100644
index ab447924a..000000000
--- a/libc/misc/locale/localeconv.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* localeconv.c
- *
- * Written by Erik Andersen <andersee@debian.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; see the file COPYING.LIB. If not,
- * write to the Free Software Foundation, Inc., 675 Mass Ave,
- * Cambridge, MA 02139, USA. */
-
-#include <string.h>
-#include <locale.h>
-
-/* Return monetary and numeric information about the current locale. */
-struct lconv * localeconv __P ((void))
-{
- static struct lconv result;
- static char *blank = "";
- static char *decimal = ".";
- char junk = '\177';
-
- result.decimal_point = decimal;
- result.thousands_sep = blank;
- result.grouping = "\177";
- result.int_curr_symbol = blank;
- result.currency_symbol = blank;
- result.mon_decimal_point = blank;
- result.mon_thousands_sep = blank;
- result.mon_grouping = blank;
- result.positive_sign = blank;
- result.negative_sign = blank;
- result.int_frac_digits = junk;
- result.frac_digits = junk;
- result.p_cs_precedes = junk;
- result.p_sep_by_space = junk;
- result.n_cs_precedes = junk;
- result.n_sep_by_space = junk;
- result.p_sign_posn = junk;
- result.n_sign_posn = junk;
-
- return &result;
-}
-
diff --git a/libc/misc/wctype/Makefile b/libc/misc/wctype/Makefile
new file mode 100644
index 000000000..875ccef56
--- /dev/null
+++ b/libc/misc/wctype/Makefile
@@ -0,0 +1,47 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000 by Lineo, inc.
+# Copyright (C) 2000,2001 Erik Andersen <andersen@uclibc.org>
+#
+# 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 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 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
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources. Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../../
+include $(TOPDIR)Rules.mak
+
+MSRC= wctype.c
+MOBJ= iswalnum.o iswalpha.o iswcntrl.o iswdigit.o iswgraph.o iswlower.o \
+ iswprint.o iswpunct.o iswspace.o iswupper.o iswxdigit.o towlower.o \
+ towupper.o iswblank.o wctype.o iswctype.o wctrans.o towctrans.o
+
+OBJS=$(MOBJ)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+ $(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(MOBJ): $(MSRC)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(STRIPTOOL) -x -R .note -R .comment $*.o
+
+clean:
+ rm -f *.[oa] *~ core
+
diff --git a/libc/misc/wctype/wctype.c b/libc/misc/wctype/wctype.c
new file mode 100644
index 000000000..39ed2cfd5
--- /dev/null
+++ b/libc/misc/wctype/wctype.c
@@ -0,0 +1,480 @@
+/* Copyright (C) 2002 Manuel Novoa III
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
+ *
+ * Besides uClibc, I'm using this code in my libc for elks, which is
+ * a 16-bit environment with a fairly limited compiler. It would make
+ * things much easier for me if this file isn't modified unnecessarily.
+ * In particular, please put any new or replacement functions somewhere
+ * else, and modify the makefile to use your version instead.
+ * Thanks. Manuel
+ *
+ * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
+
+#define _GNU_SOURCE
+#define __NO_CTYPE
+
+#include <wctype.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <locale.h>
+
+/* We know wide char support is enabled. We wouldn't be here otherwise. */
+
+/* Define this if you want to unify the towupper and towlower code in the
+ * towctrans function. */
+/* #define SMALL_UPLOW */
+
+#define __WCTYPE_WITH_LOCALE
+
+/**********************************************************************/
+
+#ifndef __PASTE
+#define __PASTE(X,Y) X ## Y
+#endif
+
+#define C_MACRO(X) __PASTE(__C_,X)(wc)
+
+#define CT_MACRO(X) __PASTE(__ctype_,X)(wc)
+
+/**********************************************************************/
+
+/* TODO: fix this! */
+#ifdef __WCTYPE_WITH_LOCALE
+
+#define WCctype (__global_locale.tblwctype)
+#define WCuplow (__global_locale.tblwuplow)
+#define WCcmob (__global_locale.tblwcomb)
+#define WCuplow_diff (__global_locale.tblwuplow_diff)
+
+#define ENCODING (__global_locale.encoding)
+
+#define ISW_FUNC_BODY(NAME) \
+int NAME (wint_t wc) \
+{ \
+ return iswctype(wc, __PASTE(_CTYPE_,NAME)); \
+}
+
+#else /* __WCTYPE_WITH_LOCALE */
+
+#define ISW_FUNC_BODY(NAME) \
+int NAME (wint_t wc) \
+{ \
+ return C_MACRO(NAME); \
+}
+
+#endif /* __WCTYPE_WITH_LOCALE */
+
+/**********************************************************************/
+#ifdef L_iswalnum
+
+ISW_FUNC_BODY(iswalnum);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswalpha
+
+ISW_FUNC_BODY(iswalpha);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswblank
+
+ISW_FUNC_BODY(iswblank);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswcntrl
+
+ISW_FUNC_BODY(iswcntrl);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswdigit
+
+int iswdigit(wint_t wc)
+{
+ return __C_iswdigit(wc);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_iswgraph
+
+ISW_FUNC_BODY(iswgraph);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswlower
+
+ISW_FUNC_BODY(iswlower);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswprint
+
+ISW_FUNC_BODY(iswprint);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswpunct
+
+ISW_FUNC_BODY(iswpunct);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswspace
+
+ISW_FUNC_BODY(iswspace);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswupper
+
+ISW_FUNC_BODY(iswupper);
+
+#endif
+/**********************************************************************/
+#ifdef L_iswxdigit
+
+int iswxdigit(wint_t wc)
+{
+ return __C_iswxdigit(wc);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_towlower
+
+#ifdef __WCTYPE_WITH_LOCALE
+
+#ifdef SMALL_UPLOW
+
+wint_t towlower(wint_t wc)
+{
+ return towctrans(wc, _CTYPE_tolower);
+}
+
+#else
+
+wint_t towlower(wint_t wc)
+{
+ unsigned int sc, n, i;
+ __uwchar_t u = wc;
+
+ if (ENCODING == __ctype_encoding_7_bit) {
+ /* We're in the C/POSIX locale, so ignore the tables. */
+ return __C_towlower(wc);
+ }
+
+ if (u <= WC_TABLE_DOMAIN_MAX) {
+ sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
+ u >>= WCuplow_TI_SHIFT;
+ n = u & ((1 << WCuplow_II_SHIFT) - 1);
+ u >>= WCuplow_II_SHIFT;
+
+ i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
+ i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
+ << WCuplow_TI_SHIFT;
+ i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
+ + i + sc]) << 1;
+ wc += WCuplow_diff[i + 1];
+ }
+ return wc;
+}
+
+#endif
+
+#else /* __WCTYPE_WITH_LOCALE */
+
+wint_t towlower(wint_t wc)
+{
+ return __C_towlower(wc);
+}
+
+#endif /* __WCTYPE_WITH_LOCALE */
+
+#endif
+/**********************************************************************/
+#ifdef L_towupper
+
+#ifdef __WCTYPE_WITH_LOCALE
+
+#ifdef SMALL_UPLOW
+
+wint_t towupper(wint_t wc)
+{
+ return towctrans(wc, _CTYPE_toupper);
+}
+
+#else
+
+wint_t towupper(wint_t wc)
+{
+ unsigned int sc, n, i;
+ __uwchar_t u = wc;
+
+ if (ENCODING == __ctype_encoding_7_bit) {
+ /* We're in the C/POSIX locale, so ignore the tables. */
+ return __C_towupper(wc);
+ }
+
+ if (u <= WC_TABLE_DOMAIN_MAX) {
+ sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
+ u >>= WCuplow_TI_SHIFT;
+ n = u & ((1 << WCuplow_II_SHIFT) - 1);
+ u >>= WCuplow_II_SHIFT;
+
+ i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
+ i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
+ << WCuplow_TI_SHIFT;
+ i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
+ + i + sc]) << 1;
+ wc += WCuplow_diff[i];
+ }
+ return wc;
+}
+
+#endif
+
+#else /* __WCTYPE_WITH_LOCALE */
+
+wint_t towupper(wint_t wc)
+{
+ return __C_towupper(wc);
+}
+
+#endif /* __WCTYPE_WITH_LOCALE */
+
+#endif
+/**********************************************************************/
+#ifdef L_wctype
+
+static const unsigned char typestring[] = __CTYPE_TYPESTRING;
+/* extern const unsigned char typestring[]; */
+
+wctype_t wctype(const char *property)
+{
+ const unsigned char *p;
+ int i;
+
+ p = typestring;
+ i = 1;
+ do {
+ if (!strcmp(property, ++p)) {
+ return i;
+ }
+ ++i;
+ p += p[-1];
+ } while (*p);
+
+ /* TODO - Add locale-specific classifications. */
+ return 0;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_iswctype
+
+#warning TODO: need to fix locale ctype table lookup stuff
+#if 0
+extern const char ctype_range[];
+#else
+static const char ctype_range[] = {
+ __CTYPE_RANGES
+};
+#endif
+
+#warning TODO: need to handle combining class!
+
+#define WCctype_TI_MASK ((1 << WCctype_TI_SHIFT) - 1)
+#define WCctype_II_MASK ((1 << WCctype_II_SHIFT) - 1)
+
+int iswctype(wint_t wc, wctype_t desc)
+{
+ unsigned int sc, n, i0, i1;
+ unsigned char d = __CTYPE_unclassified;
+
+ if ((ENCODING != __ctype_encoding_7_bit) || (((__uwchar_t) wc) <= 0x7f)){
+ if (desc < _CTYPE_iswxdigit) {
+ if (((__uwchar_t) wc) <= WC_TABLE_DOMAIN_MAX) {
+ /* From here on, we know wc > 0. */
+ sc = wc & WCctype_TI_MASK;
+ wc >>= WCctype_TI_SHIFT;
+ n = wc & WCctype_II_MASK;
+ wc >>= WCctype_II_SHIFT;
+
+ i0 = WCctype[wc];
+ i0 <<= WCctype_II_SHIFT;
+ i1 = WCctype[WCctype_II_LEN + i0 + n];
+ i1 <<= (WCctype_TI_SHIFT-1);
+ d = WCctype[WCctype_II_LEN + WCctype_TI_LEN + i1 + (sc >> 1)];
+
+ d = (sc & 1) ? (d >> 4) : (d & 0xf);
+ } else if ( ((((__uwchar_t)(wc - 0xe0020UL)) <= 0x5f)
+ || (wc == 0xe0001UL))
+ || ( (((__uwchar_t)(wc - 0xf0000UL)) < 0x20000UL)
+ && ((wc & 0xffffU) <= 0xfffdU))
+ ) {
+ d = __CTYPE_punct;
+ }
+
+ return ( ((unsigned char)(d - ctype_range[2*desc]))
+ <= ctype_range[2*desc + 1] )
+ && ((desc != _CTYPE_iswblank) || (d & 1));
+ }
+
+ /* TODO - Add locale-specific classifications. */
+ return (desc == _CTYPE_iswxdigit) ? __C_iswxdigit(wc) : 0;
+ }
+ return 0;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_towctrans
+
+#ifdef __WCTYPE_WITH_LOCALE
+
+#ifdef SMALL_UPLOW
+
+wint_t towctrans(wint_t wc, wctrans_t desc)
+{
+ unsigned int sc, n, i;
+ __uwchar_t u = wc;
+
+ /* TODO - clean up */
+ if (ENCODING == __ctype_encoding_7_bit) {
+ if ((((__uwchar_t) wc) > 0x7f)
+ || (((unsigned int)(desc - _CTYPE_tolower))
+ > (_CTYPE_toupper - _CTYPE_tolower))
+ ){
+ /* We're in the C/POSIX locale, so ignore non-ASCII values
+ * as well an any mappings other than toupper or tolower. */
+ return wc;
+ }
+ }
+
+ if (((unsigned int)(desc - _CTYPE_tolower))
+ <= (_CTYPE_totitle - _CTYPE_tolower)
+ ) {
+ if (u <= WC_TABLE_DOMAIN_MAX) {
+ sc = u & ((1 << WCuplow_TI_SHIFT) - 1);
+ u >>= WCuplow_TI_SHIFT;
+ n = u & ((1 << WCuplow_II_SHIFT) - 1);
+ u >>= WCuplow_II_SHIFT;
+
+ i = ((unsigned int) WCuplow[u]) << WCuplow_II_SHIFT;
+ i = ((unsigned int) WCuplow[WCuplow_II_LEN + i + n])
+ << WCuplow_TI_SHIFT;
+ i = ((unsigned int) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN
+ + i + sc]) << 1;
+ if (desc == _CTYPE_tolower) {
+ ++i;
+ }
+ wc += WCuplow_diff[i];
+ if (desc == _CTYPE_totitle) {
+ /* WARNING! These special cases work for glibc 2.2.4. Changes
+ * may be needed if the glibc locale tables are updated. */
+ if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4))
+ || (wc == 0x1f1)
+ ) {
+ ++wc;
+ }
+ }
+ }
+ } else {
+ /* TODO - Deal with other transliterations. */
+ __set_errno(EINVAL);
+ }
+
+ return wc;
+}
+
+#else
+
+wint_t towctrans(wint_t wc, wctrans_t desc)
+{
+ if (ENCODING == __ctype_encoding_7_bit) {
+ if ((((__uwchar_t) wc) > 0x7f)
+ || (((unsigned int)(desc - _CTYPE_tolower))
+ > (_CTYPE_toupper - _CTYPE_tolower))
+ ){
+ /* We're in the C/POSIX locale, so ignore non-ASCII values
+ * as well an any mappings other than toupper or tolower. */
+ return wc;
+ }
+ }
+
+ if (desc == _CTYPE_tolower) {
+ return towlower(wc);
+ } else if (((unsigned int)(desc - _CTYPE_toupper))
+ <= (_CTYPE_totitle - _CTYPE_toupper)
+ ) {
+ wc = towupper(wc);
+ if (desc == _CTYPE_totitle) {
+ /* WARNING! These special cases work for glibc 2.2.4. Changes
+ * may be needed if the glibc locale tables are updated. */
+ if ( (((__uwchar_t)(wc - 0x1c4)) <= (0x1cc - 0x1c4))
+ || (wc == 0x1f1)
+ ) {
+ ++wc;
+ }
+ }
+ } else {
+ /* TODO - Deal with other transliterations. */
+ __set_errno(EINVAL);
+ }
+ return wc;
+}
+
+#endif
+
+#else
+
+
+#endif
+
+#endif
+/**********************************************************************/
+#ifdef L_wctrans
+
+static const char transstring[] = __CTYPE_TRANSTRING;
+
+wctrans_t wctrans(const char *property)
+{
+ const unsigned char *p;
+ int i;
+
+ p = transstring;
+ i = 1;
+ do {
+ if (!strcmp(property, ++p)) {
+ return i;
+ }
+ ++i;
+ p += p[-1];
+ } while (*p);
+
+ /* TODO - Add locale-specific translations. */
+ return 0;
+}
+
+#endif
+/**********************************************************************/
diff --git a/libc/stdlib/Makefile b/libc/stdlib/Makefile
index 44a359434..64ae75d18 100644
--- a/libc/stdlib/Makefile
+++ b/libc/stdlib/Makefile
@@ -28,7 +28,8 @@ DIRS = $(MALLOC)
ALL_SUBDIRS = malloc malloc-930716 malloc-simple
MSRC = stdlib.c
-MOBJ = abs.o labs.o atoi.o atol.o strtol.o strtoul.o _stdlib_strto_l.o
+MOBJ = abs.o labs.o atoi.o atol.o strtol.o strtoul.o _stdlib_strto_l.o \
+ qsort.o bsearch.o
ifeq ($(HAS_LONG_LONG),true)
MOBJ += llabs.o atoll.o strtoll.o strtoull.o _stdlib_strto_ll.o
@@ -37,7 +38,7 @@ endif
MSRC2=atexit.c
MOBJ2=atexit.o on_exit.o __exit_handler.o exit.o
-CSRC = abort.c getenv.c mktemp.c qsort.c realpath.c bsearch.c \
+CSRC = abort.c getenv.c mktemp.c realpath.c \
mkstemp.c mkstemp64.c putenv.c rand.c random.c random_r.c setenv.c \
system.c div.c ldiv.c getpt.c ptsname.c grantpt.c unlockpt.c gcvt.c
CSRC+= drand48.c drand48-iter.c drand48_r.c erand48.c erand48_r.c \
diff --git a/libc/stdlib/stdlib.c b/libc/stdlib/stdlib.c
index 40286f0e5..101debb40 100644
--- a/libc/stdlib/stdlib.c
+++ b/libc/stdlib/stdlib.c
@@ -27,30 +27,44 @@
#define _ISOC99_SOURCE /* for ULLONG primarily... */
#define _GNU_SOURCE
-#include <stdlib.h>
#include <limits.h>
#include <stdint.h>
#include <inttypes.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
+#include <unistd.h>
+
+/* Work around gcc's refusal to create aliases. */
+#define atoi __ignore_atoi
+#define abs __ignore_abs
+#include <stdlib.h>
+#undef atoi
+#undef abs
extern unsigned long
_stdlib_strto_l(register const char * __restrict str,
char ** __restrict endptr, int base, int sflag);
+
+#if defined(ULLONG_MAX)
extern unsigned long long
_stdlib_strto_ll(register const char * __restrict str,
char ** __restrict endptr, int base, int sflag);
+#endif
-/* TODO: gcc reports an error due to prototype conflicts. Don't include
- * the header for the problem cases? */
-#define HEADER_ALIAS_PROBLEM
+/**********************************************************************/
+#ifdef L_atof
+double atof(const char *nptr)
+{
+ return strtod(nptr, (char **) NULL);
+}
+
+#endif
/**********************************************************************/
#ifdef L_abs
-#ifdef HEADER_ALIAS_PROBLEM
-/* #if UINT_MAX < ULONG_MAX */
+#if UINT_MAX < ULONG_MAX
int abs(int j)
{
@@ -63,8 +77,7 @@ int abs(int j)
/**********************************************************************/
#ifdef L_labs
-#ifndef HEADER_ALIAS_PROBLEM
-/* #if UINT_MAX == ULONG_MAX */
+#if UINT_MAX == ULONG_MAX
strong_alias(labs,abs)
#endif
@@ -102,8 +115,7 @@ long long int llabs(long long int j)
/**********************************************************************/
#ifdef L_atoi
-#ifdef HEADER_ALIAS_PROBLEM
-/* #if UINT_MAX < ULONG_MAX */
+#if UINT_MAX < ULONG_MAX
int atoi(const char *nptr)
{
@@ -116,8 +128,7 @@ int atoi(const char *nptr)
/**********************************************************************/
#ifdef L_atol
-#ifndef HEADER_ALIAS_PROBLEM
-/* #if UINT_MAX == ULONG_MAX */
+#if UINT_MAX == ULONG_MAX
strong_alias(atol,atoi)
#endif
@@ -446,3 +457,149 @@ unsigned long long _stdlib_strto_ll(register const char * __restrict str,
#endif
/**********************************************************************/
+/* Made _Exit() an alias for _exit(), as per C99. */
+/* #ifdef L__Exit */
+
+/* void _Exit(int status) */
+/* { */
+/* _exit(status); */
+/* } */
+
+/* #endif */
+/**********************************************************************/
+#ifdef L_bsearch
+
+void *bsearch(const void *key, const void *base, size_t /* nmemb */ high,
+ size_t size, int (*compar)(const void *, const void *))
+{
+ register char *p;
+ size_t low;
+ size_t mid;
+ int r;
+
+ if (size > 0) { /* TODO: change this to an assert?? */
+ low = 0;
+ while (low < high) {
+ mid = low + ((high - low) >> 1); /* Avoid possible overflow here. */
+ p = ((char *)base) + mid * size; /* Could overflow here... */
+ r = (*compar)(key, p); /* but that's an application problem! */
+ if (r > 0) {
+ low = mid + 1;
+ } else if (r < 0) {
+ high = mid;
+ } else {
+ return p;
+ }
+ }
+ }
+ return NULL;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_qsort
+
+/* This code is derived from a public domain shell sort routine by
+ * Ray Gardner and found in Bob Stout's snippets collection. The
+ * original code is included below in an #if 0/#endif block.
+ *
+ * I modified it to avoid the possibility of overflow in the wgap
+ * calculation, as well as to reduce the generated code size with
+ * bcc and gcc. */
+
+void qsort (void *base,
+ size_t nel,
+ size_t width,
+ int (*comp)(const void *, const void *))
+{
+ size_t wgap, i, j, k;
+ char tmp;
+
+ if ((nel > 1) && (width > 0)) {
+ assert( nel <= ((size_t)(-1)) / width ); /* check for overflow */
+ wgap = 0;
+ do {
+ wgap = 3 * wgap + 1;
+ } while (wgap < (nel-1)/3);
+ /* From the above, we know that either wgap == 1 < nel or */
+ /* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */
+ wgap *= width; /* So this can not overflow if wnel doesn't. */
+ nel *= width; /* Convert nel to 'wnel' */
+ do {
+ i = wgap;
+ do {
+ j = i;
+ do {
+ register char *a;
+ register char *b;
+
+ j -= wgap;
+ a = j + ((char *)base);
+ b = a + wgap;
+ if ( (*comp)(a, b) <= 0 ) {
+ break;
+ }
+ k = width;
+ do {
+ tmp = *a;
+ *a++ = *b;
+ *b++ = tmp;
+ } while ( --k );
+ } while (j >= wgap);
+ i += width;
+ } while (i < nel);
+ wgap = (wgap - width)/3;
+ } while (wgap);
+ }
+}
+
+/* ---------- original snippets version below ---------- */
+
+#if 0
+/*
+** ssort() -- Fast, small, qsort()-compatible Shell sort
+**
+** by Ray Gardner, public domain 5/90
+*/
+
+#include <stddef.h>
+
+void ssort (void *base,
+ size_t nel,
+ size_t width,
+ int (*comp)(const void *, const void *))
+{
+ size_t wnel, gap, wgap, i, j, k;
+ char *a, *b, tmp;
+
+ wnel = width * nel;
+ for (gap = 0; ++gap < nel;)
+ gap *= 3;
+ while ( gap /= 3 )
+ {
+ wgap = width * gap;
+ for (i = wgap; i < wnel; i += width)
+ {
+ for (j = i - wgap; ;j -= wgap)
+ {
+ a = j + (char *)base;
+ b = a + wgap;
+ if ( (*comp)(a, b) <= 0 )
+ break;
+ k = width;
+ do
+ {
+ tmp = *a;
+ *a++ = *b;
+ *b++ = tmp;
+ } while ( --k );
+ if (j < wgap)
+ break;
+ }
+ }
+ }
+}
+#endif
+
+#endif
+/**********************************************************************/
diff --git a/libc/string/Makefile b/libc/string/Makefile
index c7a4c128a..0d034d1d6 100644
--- a/libc/string/Makefile
+++ b/libc/string/Makefile
@@ -24,27 +24,48 @@
TOPDIR=../../
include $(TOPDIR)Rules.mak
+MSRCW= wstring.c
+MOBJW= basename.o bcopy.o bzero.o dirname.o ffs.o memccpy.o memchr.o memcmp.o \
+ memcpy.o memmove.o mempcpy.o memrchr.o memset.o rawmemchr.o stpcpy.o \
+ stpncpy.o strcasecmp.o strcasestr.o strcat.o strchrnul.o strchr.o \
+ strcmp.o strcpy.o strcspn.o strdup.o strlen.o strncasecmp.o strncat.o \
+ strncmp.o strncpy.o strndup.o strnlen.o strpbrk.o strrchr.o strsep.o \
+ strspn.o strstr.o strtok.o strtok_r.o \
+ __xpg_basename.o # strcoll.o strerror.o strxfrm.o
+
+MOBJW2= wcscasecmp.o wcscat.o wcschrnul.o wcschr.o wcscmp.o wcscpy.o wcscspn.o \
+ wcsdup.o wcslen.o wcsncasecmp.o wcsncat.o wcsncmp.o wcsncpy.o \
+ wcsnlen.o wcspbrk.o wcsrchr.o wcsspn.o wcsstr.o wcstok.o wmemchr.o \
+ wmemcmp.o wmemcpy.o wmemmove.o wmempcpy.o wmemset.o
+
MSRC=string.c
-MOBJ=strlen.o strcat.o strcpy.o strchr.o strcmp.o strncat.o strncpy.o \
- strncmp.o strrchr.o strdup.o strndup.o memcpy.o memccpy.o memset.o \
- memmove.o memcmp.o memchr.o ffs.o strnlen.o strxfrm.o stpcpy.o \
- stpncpy.o memrchr.o mempcpy.o
+# MOBJ=strlen.o strcat.o strcpy.o strchr.o strcmp.o strncat.o strncpy.o \
+# strncmp.o strrchr.o strdup.o strndup.o memcpy.o memccpy.o memset.o \
+# memmove.o memcmp.o memchr.o ffs.o strnlen.o strxfrm.o stpcpy.o \
+# stpncpy.o memrchr.o mempcpy.o
+MOBJ=strxfrm.o
-ifeq ($(HAS_LOCALE),true)
- MOBJ += strcoll.o
-endif
+# ifeq ($(HAS_LOCALE),true)
+# MOBJ += strcoll.o
+# endif
MSRC1=strsignal.c
MOBJ1=strsignal.o psignal.o
-MSRC2=strstr.c
-MOBJ2=strstr.o strcasestr.o
+MOBJ2=
+#MSRC2=strstr.c
+#MOBJ2=strstr.o strcasestr.o
-CSRC=strpbrk.c strsep.c strtok.c strtok_r.c strcspn.c \
- strspn.c strcasecmp.c strncasecmp.c strerror.c bcopy.c bzero.c \
- bcmp.c sys_errlist.c dirname.c basename.c
+# CSRC=strpbrk.c strsep.c strtok.c strtok_r.c strcspn.c \
+# strspn.c strcasecmp.c strncasecmp.c strerror.c bcopy.c bzero.c \
+# bcmp.c sys_errlist.c dirname.c basename.c
+CSRC=strerror.c sys_errlist.c
COBJS=$(patsubst %.c,%.o, $(CSRC))
-OBJS=$(MOBJ) $(MOBJ1) $(MOBJ2) $(COBJS)
+OBJS=$(MOBJ) $(MOBJ1) $(MOBJ2) $(COBJS) $(MOBJW)
+
+ifeq ($(HAS_WCHAR),true)
+ OBJS += $(MOBJW2)
+endif
all: $(OBJS) $(LIBC)
@@ -53,6 +74,14 @@ $(LIBC): ar-target
ar-target: $(OBJS)
$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+$(MOBJW): $(MSRCW)
+ $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+ $(STRIPTOOL) -x -R .note -R .comment $*.o
+
+$(MOBJW2): $(MSRCW)
+ $(CC) $(CFLAGS) -DWANT_WIDE -DL_$* $< -c -o $*.o
+ $(STRIPTOOL) -x -R .note -R .comment $*.o
+
$(MOBJ): $(MSRC)
$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
$(STRIPTOOL) -x -R .note -R .comment $*.o
diff --git a/libc/string/wstring.c b/libc/string/wstring.c
new file mode 100644
index 000000000..53c5af99c
--- /dev/null
+++ b/libc/string/wstring.c
@@ -0,0 +1,1273 @@
+/* Copyright (C) 2002 Manuel Novoa III
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
+ *
+ * Besides uClibc, I'm using this code in my libc for elks, which is
+ * a 16-bit environment with a fairly limited compiler. It would make
+ * things much easier for me if this file isn't modified unnecessarily.
+ * In particular, please put any new or replacement functions somewhere
+ * else, and modify the makefile to use your version instead.
+ * Thanks. Manuel
+ *
+ * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <strings.h>
+#include <limits.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#ifdef WANT_WIDE
+#include <wchar.h>
+#include <wctype.h>
+#include <locale.h>
+
+#define Wvoid wchar_t
+#define Wchar wchar_t
+#define Wuchar __uwchar_t
+#define Wint wchar_t
+
+#else
+
+#define Wvoid void
+#define Wchar char
+typedef unsigned char __string_uchar_t;
+#define Wuchar __string_uchar_t
+#define Wint int
+
+#endif
+
+/**********************************************************************/
+#ifdef L_wmemcpy
+#define L_memcpy
+#define Wmemcpy wmemcpy
+#else
+#define Wmemcpy memcpy
+#endif
+
+#ifdef L_memcpy
+
+Wvoid *Wmemcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
+{
+ register Wchar *r1 = s1;
+ register const Wchar *r2 = s2;
+
+#ifdef __BCC__
+ while (n--) {
+ *r1++ = *r2++;
+ }
+#else
+ while (n) {
+ *r1++ = *r2++;
+ --n;
+ }
+#endif
+
+ return s1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wmemmove
+#define L_memmove
+#define Wmemmove wmemmove
+#else
+#define Wmemmove memmove
+#endif
+
+#ifdef L_memmove
+
+Wvoid *Wmemmove(Wvoid *s1, const Wvoid *s2, size_t n)
+{
+#ifdef __BCC__
+ register Wchar *s = (Wchar *) s1;
+ register const Wchar *p = (const Wchar *) s2;
+
+ if (p >= s) {
+ while (n--) {
+ *s++ = *p++;
+ }
+ } else {
+ s += n;
+ p += n;
+ while (n--) {
+ *--s = *--p;
+ }
+ }
+
+ return s1;
+#else
+ register Wchar *s = (Wchar *) s1;
+ register const Wchar *p = (const Wchar *) s2;
+
+ if (p >= s) {
+ while (n) {
+ *s++ = *p++;
+ --n;
+ }
+ } else {
+ while (n) {
+ --n;
+ s[n] = p[n];
+ }
+ }
+
+ return s1;
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcscpy
+#define L_strcpy
+#define Wstrcpy wcscpy
+#else
+#define Wstrcpy strcpy
+#endif
+
+#ifdef L_strcpy
+
+Wchar *Wstrcpy(Wchar * __restrict s1, const Wchar * __restrict s2)
+{
+ register Wchar *s = s1;
+
+#ifdef __BCC__
+ do {
+ *s = *s2++;
+ } while (*s++ != 0);
+#else
+ while ( (*s++ = *s2++) != 0 );
+#endif
+
+ return s1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcsncpy
+#define L_strncpy
+#define Wstrncpy wcsncpy
+#else
+#define Wstrncpy strncpy
+#endif
+
+#ifdef L_strncpy
+
+Wchar *Wstrncpy(Wchar * __restrict s1, register const Wchar * __restrict s2,
+ size_t n)
+{
+ register Wchar *s = s1;
+
+#ifdef __BCC__
+ while (n--) {
+ if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
+ ++s;
+ }
+#else
+ while (n) {
+ if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
+ ++s;
+ --n;
+ }
+#endif
+
+ return s1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcscat
+#define L_strcat
+#define Wstrcat wcscat
+#else
+#define Wstrcat strcat
+#endif
+
+#ifdef L_strcat
+
+Wchar *Wstrcat(Wchar * __restrict s1, register const Wchar * __restrict s2)
+{
+ register Wchar *s = s1;
+
+ while (*s++);
+ --s;
+ while ((*s++ = *s2++) != 0);
+
+ return s1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcsncat
+#define L_strncat
+#define Wstrncat wcsncat
+#else
+#define Wstrncat strncat
+#endif
+
+#ifdef L_strncat
+
+Wchar *Wstrncat(Wchar * __restrict s1, register const Wchar * __restrict s2,
+ size_t n)
+{
+ register Wchar *s = s1;
+
+ while (*s++);
+ --s;
+#if __BCC__
+ while (n-- && ((*s = *s2++) != 0)) ++s;
+#else
+ while (n && ((*s = *s2++) != 0)) {
+ --n;
+ ++s;
+ }
+#endif
+ *s = 0;
+
+ return s1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wmemcmp
+#define L_memcmp
+#define Wmemcmp wmemcmp
+#else
+#define Wmemcmp memcmp
+#endif
+
+#ifdef L_memcmp
+
+#ifndef L_wmemcmp
+weak_alias(memcmp,bcmp)
+#endif
+
+int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n)
+{
+ register const Wuchar *r1 = (const Wuchar *) s1;
+ register const Wuchar *r2 = (const Wuchar *) s2;
+
+#ifdef WANT_WIDE
+ while (n && (*r1 == *r2)) {
+ ++r1;
+ ++r2;
+ --n;
+ }
+
+ return (n == 0) ? 0 : ((*r1 < *r2) ? -1 : 1);
+#else
+ int r = 0;
+
+ while (n-- && ((r = ((int)(*r1++)) - *r2++) == 0));
+
+ return r;
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcscmp
+#define L_strcmp
+#define Wstrcmp wcscmp
+#else
+#define Wstrcmp strcmp
+#endif
+
+#ifdef L_strcmp
+
+#ifndef L_wcscmp
+#warning implement strcoll and remove weak alias (or enable for C locale only)
+weak_alias(strcmp, strcoll);
+#endif
+
+int Wstrcmp(register const Wchar *s1, register const Wchar *s2)
+{
+#ifdef WANT_WIDE
+ while (*((Wuchar *)s1) == *((Wuchar *)s2)) {
+ if (!*s1++) {
+ return 0;
+ }
+ ++s2;
+ }
+
+ return (*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1;
+#else
+ int r;
+
+ while (((r = ((int)(*((Wuchar *)s1))) - *((Wuchar *)s2++))
+ == 0) && *s1++);
+
+ return r;
+#endif
+}
+#endif
+/**********************************************************************/
+#ifdef L_strcoll
+#error implement strcoll and remove weak_alias!!
+/* extern unsigned char *_ctype_collate; */
+
+/* int strcoll(register const char *s1, const char *s2) */
+/* { */
+/* int r; */
+
+/* while (!(r = (_ctype_collate[(int)(*s1++)]-_ctype_collate[(int)(*s2++)]))); */
+
+/* return r; */
+/* } */
+#endif
+/**********************************************************************/
+#ifdef L_wcsncmp
+#define L_strncmp
+#define Wstrncmp wcsncmp
+#else
+#define Wstrncmp strncmp
+#endif
+
+#ifdef L_strncmp
+
+int Wstrncmp(register const Wchar *s1, register const Wchar *s2, size_t n)
+{
+#ifdef WANT_WIDE
+ while (n && (*((Wuchar *)s1) == *((Wuchar *)s2))) {
+ if (!*s1++) {
+ return 0;
+ }
+ ++s2;
+ --n;
+ }
+
+ return (n == 0) ? 0 : ((*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1);
+#else
+ int r = 0;
+
+ while (n--
+ && ((r = ((int)(*((unsigned char *)s1))) - *((unsigned char *)s2++))
+ == 0)
+ && *s1++);
+
+ return r;
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_strxfrm
+#error implement strxfrm
+/* size_t strxfrm(char * __restrict s1, const char * __restrict s2, size_t n) */
+#endif
+/**********************************************************************/
+#ifdef L_wmemchr
+#define L_memchr
+#define Wmemchr wmemchr
+#else
+#define Wmemchr memchr
+#endif
+
+#ifdef L_memchr
+
+Wvoid *Wmemchr(const Wvoid *s, Wint c, size_t n)
+{
+ register const Wuchar *r = (const Wuchar *) s;
+#ifdef __BCC__
+ /* bcc can optimize the counter if it thinks it is a pointer... */
+ register const char *np = (const char *) n;
+#else
+#define np n
+#endif
+
+ while (np) {
+ if (*r == ((Wuchar)c)) {
+ return (Wvoid *) r; /* silence the warning */
+ }
+ ++r;
+ --np;
+ }
+
+ return NULL;
+}
+#undef np
+
+#endif
+/**********************************************************************/
+#ifdef L_wcschr
+#define L_strchr
+#define Wstrchr wcschr
+#else
+#define Wstrchr strchr
+#endif
+
+#ifdef L_strchr
+
+#ifndef L_wcschr
+weak_alias(strchr,index)
+#endif
+
+Wchar *Wstrchr(register const Wchar *s, Wint c)
+{
+ do {
+ if (*s == ((Wchar)c)) {
+ return (Wchar *) s; /* silence the warning */
+ }
+ } while (*s++);
+
+ return NULL;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcscspn
+#define L_strcspn
+#define Wstrcspn wcscspn
+#else
+#define Wstrcspn strcspn
+#endif
+
+#ifdef L_strcspn
+
+size_t Wstrcspn(const Wchar *s1, const Wchar *s2)
+{
+ register const Wchar *s;
+ register const Wchar *p;
+
+ for ( s=s1 ; *s ; s++ ) {
+ for ( p=s2 ; *p ; p++ ) {
+ if (*p == *s) goto done;
+ }
+ }
+ done:
+ return s - s1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcspbrk
+#define L_strpbrk
+#define Wstrpbrk wcspbrk
+#else
+#define Wstrpbrk strpbrk
+#endif
+
+#ifdef L_strpbrk
+
+Wchar *Wstrpbrk(const Wchar *s1, const Wchar *s2)
+{
+ register const Wchar *s;
+ register const Wchar *p;
+
+ for ( s=s1 ; *s ; s++ ) {
+ for ( p=s2 ; *p ; p++ ) {
+ if (*p == *s) return (Wchar *) s; /* silence the warning */
+ }
+ }
+ return NULL;
+}
+#endif
+/**********************************************************************/
+#ifdef L_wcsrchr
+#define L_strrchr
+#define Wstrrchr wcsrchr
+#else
+#define Wstrrchr strrchr
+#endif
+
+#ifdef L_strrchr
+
+#ifndef L_wcsrchr
+weak_alias(strrchr,rindex)
+#endif
+
+Wchar *Wstrrchr(register const Wchar *s, Wint c)
+{
+ register const Wchar *p;
+
+ p = NULL;
+ do {
+ if (*s == (Wchar) c) {
+ p = s;
+ }
+ } while (*s++);
+
+ return (Wchar *) p; /* silence the warning */
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcsspn
+#define L_strspn
+#define Wstrspn wcsspn
+#else
+#define Wstrspn strspn
+#endif
+
+#ifdef L_strspn
+
+size_t Wstrspn(const Wchar *s1, const Wchar *s2)
+{
+ register const Wchar *s = s1;
+ register const Wchar *p = s2;
+
+ while (*p) {
+ if (*p++ == *s) {
+ ++s;
+ p = s2;
+ }
+ }
+ return s - s1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcsstr
+#define L_strstr
+#define Wstrstr wcsstr
+#else
+#define Wstrstr strstr
+#endif
+
+#ifdef L_strstr
+
+/* NOTE: This is the simple-minded O(len(s1) * len(s2)) worst-case approach. */
+
+#ifdef L_wcsstr
+weak_alias(wcsstr,wcswcs)
+#endif
+
+Wchar *Wstrstr(const Wchar *s1, const Wchar *s2)
+{
+ register const Wchar *s = s1;
+ register const Wchar *p = s2;
+
+ do {
+ if (!*p) {
+ return (Wchar *) s1;;
+ }
+ if (*p == *s) {
+ ++p;
+ ++s;
+ } else {
+ p = s2;
+ if (!*s) {
+ return NULL;
+ }
+ s = ++s1;
+ }
+ } while (1);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcstok
+#define L_strtok_r
+#define Wstrtok_r wcstok
+#define Wstrspn wcsspn
+#define Wstrpbrk wcspbrk
+#else
+#define Wstrtok_r strtok_r
+#define Wstrspn strspn
+#define Wstrpbrk strpbrk
+#endif
+
+#ifdef L_strtok_r
+
+Wchar *Wstrtok_r(Wchar * __restrict s1, const Wchar * __restrict s2,
+ Wchar ** __restrict next_start)
+{
+ register Wchar *s;
+ register Wchar *p;
+
+#if 1
+ if (((s = s1) != NULL) || ((s = *next_start) != NULL)) {
+ if (*(s += Wstrspn(s, s2))) {
+ if ((p = Wstrpbrk(s, s2)) != NULL) {
+ *p++ = 0;
+ }
+ } else {
+ p = s = NULL;
+ }
+ *next_start = p;
+ }
+ return s;
+#else
+ if (!(s = s1)) {
+ s = *next_start;
+ }
+ if (s && *(s += Wstrspn(s, s2))) {
+ if (*(p = s + Wstrcspn(s, s2))) {
+ *p++ = 0;
+ }
+ *next_start = p;
+ return s;
+ }
+ return NULL; /* TODO: set *next_start = NULL for safety? */
+#endif
+}
+
+#endif
+/**********************************************************************/
+/* #ifdef L_wcstok */
+/* #define L_strtok */
+/* #define Wstrtok wcstok */
+/* #define Wstrtok_r wcstok_r */
+/* #else */
+/* #define Wstrtok strtok */
+/* #define Wstrtok_r strtok_r */
+/* #endif */
+
+#ifdef L_strtok
+#define Wstrtok strtok
+#define Wstrtok_r strtok_r
+
+Wchar *Wstrtok(Wchar * __restrict s1, const Wchar * __restrict s2)
+{
+ static Wchar *next_start; /* Initialized to 0 since in bss. */
+ return Wstrtok_r(s1, s2, &next_start);
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wmemset
+#define L_memset
+#define Wmemset wmemset
+#else
+#define Wmemset memset
+#endif
+
+#ifdef L_memset
+
+Wvoid *Wmemset(Wvoid *s, Wint c, size_t n)
+{
+ register Wuchar *p = (Wuchar *) s;
+#ifdef __BCC__
+ /* bcc can optimize the counter if it thinks it is a pointer... */
+ register const char *np = (const char *) n;
+#else
+#define np n
+#endif
+
+ while (np) {
+ *p++ = (Wuchar) c;
+ --np;
+ }
+
+ return s;
+}
+#undef np
+
+#endif
+/**********************************************************************/
+#ifdef L_strerror
+#error implement strerror
+/* char *strerror(int errnum); */
+#endif
+/**********************************************************************/
+#ifdef L_wcslen
+#define L_strlen
+#define Wstrlen wcslen
+#else
+#define Wstrlen strlen
+#endif
+
+#ifdef L_strlen
+
+size_t Wstrlen(const Wchar *s)
+{
+ register const Wchar *p;
+
+ for (p=s ; *p ; p++);
+
+ return p - s;
+}
+
+#endif
+/**********************************************************************/
+/* ANSI/ISO end here */
+/**********************************************************************/
+#ifdef L_ffs
+
+int ffs(int i)
+{
+#if 1
+ /* inlined binary search method */
+ char n = 1;
+#if UINT_MAX == 0xffffU
+ /* nothing to do here -- just trying to avoiding possible problems */
+#elif UINT_MAX == 0xffffffffU
+ if (!(i & 0xffff)) {
+ n += 16;
+ i >>= 16;
+ }
+#else
+#error ffs needs rewriting!
+#endif
+
+ if (!(i & 0xff)) {
+ n += 8;
+ i >>= 8;
+ }
+ if (!(i & 0x0f)) {
+ n += 4;
+ i >>= 4;
+ }
+ if (!(i & 0x03)) {
+ n += 2;
+ i >>= 2;
+ }
+ return (i) ? (n + ((i+1) & 0x01)) : 0;
+
+#else
+ /* linear search -- slow, but small */
+ int n;
+
+ for (n = 0 ; i ; ++n) {
+ i >>= 1;
+ }
+
+ return n;
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcscasecmp
+#define L_strcasecmp
+#define Wstrcasecmp wcscasecmp
+#else
+#define Wstrcasecmp strcasecmp
+#endif
+
+#ifdef L_strcasecmp
+
+int Wstrcasecmp(register const Wchar *s1, register const Wchar *s2)
+{
+#ifdef WANT_WIDE
+ while ((*s1 == *s2) || (towlower(*s1) == towlower(*s2))) {
+ if (!*s1++) {
+ return 0;
+ }
+ ++s2;
+ }
+
+ return (((Wuchar)towlower(*s1)) < ((Wuchar)towlower(*s2))) ? -1 : 1;
+ /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */
+#else
+ int r = 0;
+
+ while ( ((s1 == s2) ||
+ !(r = ((int)( tolower(*((Wuchar *)s1))))
+ - tolower(*((Wuchar *)s2))))
+ && (++s2, *s1++));
+
+ return r;
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcsncasecmp
+#define L_strncasecmp
+#define Wstrncasecmp wcsncasecmp
+#else
+#define Wstrncasecmp strncasecmp
+#endif
+
+#ifdef L_strncasecmp
+
+int Wstrncasecmp(register const Wchar *s1, register const Wchar *s2, size_t n)
+{
+#ifdef WANT_WIDE
+ while (n && ((*s1 == *s2) || (towlower(*s1) == towlower(*s2)))) {
+ if (!*s1++) {
+ return 0;
+ }
+ ++s2;
+ --n;
+ }
+
+ return (n == 0)
+ ? 0
+ : ((((Wuchar)towlower(*s1)) < ((Wuchar)towlower(*s2))) ? -1 : 1);
+ /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */
+#else
+ int r = 0;
+
+ while ( n
+ && ((s1 == s2) ||
+ !(r = ((int)( tolower(*((unsigned char *)s1))))
+ - tolower(*((unsigned char *)s2))))
+ && (--n, ++s2, *s1++));
+ return r;
+#endif
+}
+#endif
+/**********************************************************************/
+#ifdef L_wcsnlen
+#define L_strnlen
+#define Wstrnlen wcsnlen
+#else
+#define Wstrnlen strnlen
+#endif
+
+#ifdef L_strnlen
+
+size_t Wstrnlen(const Wchar *s, size_t max)
+{
+ register const Wchar *p = s;
+#ifdef __BCC__
+ /* bcc can optimize the counter if it thinks it is a pointer... */
+ register const char *maxp = (const char *) max;
+#else
+#define maxp max
+#endif
+
+ while (maxp && *p) {
+ ++p;
+ --maxp;
+ }
+
+ return p - s;
+}
+#undef maxp
+#endif
+/**********************************************************************/
+/* No wide analog. */
+
+#ifdef L_memccpy
+
+void *memccpy(void * __restrict s1, const void * __restrict s2, int c, size_t n)
+{
+ register char *r1 = s1;
+ register const char *r2 = s2;
+
+ while (n-- && (((unsigned char)(*r1++ = *r2++)) != ((unsigned char) c)));
+
+ return (n == (size_t) -1) ? NULL : r1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcsdup
+#define L_strdup
+#define Wstrdup wcsdup
+#define Wstrlen wcslen
+#define Wstrcpy wcscpy
+#else
+#define Wstrdup strdup
+#define Wstrlen strlen
+#define Wstrcpy strcpy
+#endif
+
+#ifdef L_strdup
+
+Wchar *Wstrdup(register const Wchar *s1)
+{
+ register Wchar *s;
+
+ if ((s = malloc((Wstrlen(s1) + 1) * sizeof(Wchar))) != NULL) {
+ Wstrcpy(s, s1);
+ }
+
+ return s;
+}
+
+#endif
+/**********************************************************************/
+/* GNU extension functions. */
+/**********************************************************************/
+#ifdef L_wmempcpy
+#define L_mempcpy
+#define Wmempcpy wmempcpy
+#else
+#define Wmempcpy mempcpy
+#endif
+
+#ifdef L_mempcpy
+
+#ifndef L_wmempcpy
+/* uClibc's old string implementation did this to cater to some app. */
+weak_alias(mempcpy,__mempcpy)
+#endif
+
+Wvoid *Wmempcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n)
+{
+ register Wchar *r1 = s1;
+ register const Wchar *r2 = s2;
+
+#ifdef __BCC__
+ while (n--) {
+ *r1++ = *r2++;
+ }
+#else
+ while (n) {
+ *r1++ = *r2++;
+ --n;
+ }
+#endif
+
+ return r1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_memrchr
+
+void *memrchr(const void *s, int c, size_t n)
+{
+ register const unsigned char *r;
+#ifdef __BCC__
+ /* bcc can optimize the counter if it thinks it is a pointer... */
+ register const char *np = (const char *) n;
+#else
+#define np n
+#endif
+
+ r = ((unsigned char *)s) + ((size_t) np);
+
+ while (np) {
+ if (*--r == ((unsigned char)c)) {
+ return (void *) r; /* silence the warning */
+ }
+ --np;
+ }
+
+ return NULL;
+}
+#undef np
+
+#endif
+/**********************************************************************/
+#ifdef L_stpcpy
+
+char *stpcpy(register char * __restrict s1, const char * __restrict s2)
+{
+#ifdef __BCC__
+ do {
+ *s1 = *s2++;
+ } while (*s1++ != 0);
+#else
+ while ( (*s1++ = *s2++) != 0 );
+#endif
+
+ return s1 - 1;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_stpncpy
+
+char *stpncpy(register char * __restrict s1,
+ register const char * __restrict s2,
+ size_t n)
+{
+ char *s = s1;
+ const char *p = s2;
+
+#ifdef __BCC__
+ while (n--) {
+ if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
+ ++s;
+ }
+ return s1 + (s2 - p);
+#else
+ while (n) {
+ if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */
+ ++s;
+ --n;
+ }
+ return s1 + (s2 - p);
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_bzero
+
+void bzero(void *s, size_t n)
+{
+ register unsigned char *p = s;
+#ifdef __BCC__
+ /* bcc can optimize the counter if it thinks it is a pointer... */
+ register const char *np = (const char *) n;
+#else
+#define np n
+#endif
+
+ while (np) {
+ *p++ = 0;
+ --np;
+ }
+}
+#undef np
+
+#endif
+/**********************************************************************/
+#ifdef L_bcopy
+
+void bcopy(const void *s2, void *s1, size_t n)
+{
+#if 1
+ memmove(s1, s2, n);
+#else
+#ifdef __BCC__
+ register char *s;
+ register const char *p;
+
+ s = s1;
+ p = s2;
+ if (p >= s) {
+ while (n--) {
+ *s++ = *p++;
+ }
+ } else {
+ s += n;
+ p += n;
+ while (n--) {
+ *--s = *--p;
+ }
+ }
+#else
+ register char *s;
+ register const char *p;
+
+ s = s1;
+ p = s2;
+ if (p >= s) {
+ while (n) {
+ *s++ = *p++;
+ --n;
+ }
+ } else {
+ while (n) {
+ --n;
+ s[n] = p[n];
+ }
+ }
+#endif
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_strcasestr
+
+char *strcasestr(const char *s1, const char *s2)
+{
+ register const char *s = s1;
+ register const char *p = s2;
+
+#if 1
+ do {
+ if (!*p) {
+ return (char *) s1;;
+ }
+ if ((*p == *s)
+ || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s)))
+ ) {
+ ++p;
+ ++s;
+ } else {
+ p = s2;
+ if (!*s) {
+ return NULL;
+ }
+ s = ++s1;
+ }
+ } while (1);
+#else
+ while (*p && *s) {
+ if ((*p == *s)
+ || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s)))
+ ) {
+ ++p;
+ ++s;
+ } else {
+ p = s2;
+ s = ++s1;
+ }
+ }
+
+ return (*p) ? NULL : (char *) s1;
+#endif
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_strndup
+
+char *strndup(register const char *s1, size_t n)
+{
+ register char *s;
+
+ n = strnlen(s1,n); /* Avoid problems if s1 not nul-terminated. */
+
+ if ((s = malloc(n + 1)) != NULL) {
+ memcpy(s, s1, n);
+ s[n] = 0;
+ }
+
+ return s;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_strsep
+
+char *strsep(char ** __restrict s1, const char * __restrict s2)
+{
+ register char *s = *s1;
+ register char *p;
+
+#if 1
+ p = NULL;
+ if (s && *s && (p = strpbrk(s, s2))) {
+ *p++ = 0;
+ }
+#else
+ if (s && *s && *(p = s + strcspn(s, s2))) {
+ *p++ = 0;
+ } else {
+ p = NULL;
+ }
+#endif
+ *s1 = p;
+ return s;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_wcschrnul
+#define L_strchrnul
+#define Wstrchrnul wcschrnul
+#else
+#define Wstrchrnul strchrnul
+#endif
+
+#ifdef L_strchrnul
+
+Wchar *Wstrchrnul(register const Wchar *s, Wint c)
+{
+ --s;
+ while (*++s && (*s != ((Wchar)c)));
+ return (Wchar *) s;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_rawmemchr
+
+void *rawmemchr(const void *s, int c)
+{
+ register const unsigned char *r = s;
+
+ while (*r != ((unsigned char)c)) ++r;
+
+ return (void *) r; /* silence the warning */
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_basename
+
+char *basename(const char *path)
+{
+ register const char *s;
+ register const char *p;
+
+ p = s = path;
+
+ while (*s) {
+ if (*s++ == '/') {
+ p = s;
+ }
+ }
+
+ return (char *) p;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L___xpg_basename
+
+char *__xpg_basename(register char *path)
+{
+ static const char null_or_empty[] = ".";
+ char *first;
+ register char *last;
+
+ first = (char *) null_or_empty;
+
+ if (path && *path) {
+ first = path;
+ last = path - 1;
+
+ do {
+ if ((*path != '/') && (path > ++last)) {
+ last = first = path;
+ }
+ } while (*++path);
+
+ if (*first == '/') {
+ last = first;
+ }
+ last[1] = 0;
+ }
+
+ return first;
+}
+
+#endif
+/**********************************************************************/
+#ifdef L_dirname
+
+char *dirname(char *path)
+{
+ static const char null_or_empty_or_noslash[] = ".";
+ register char *s;
+ register char *last;
+ char *first;
+
+ last = s = path;
+
+ if (s != NULL) {
+
+ LOOP:
+ while (*s && (*s != '/')) ++s;
+ first = s;
+ while (*s == '/') ++s;
+ if (*s) {
+ last = first;
+ goto LOOP;
+ }
+
+ if (last == path) {
+ if (*last != '/') {
+ goto DOT;
+ }
+ if ((*++last == '/') && (last[1] == 0)) {
+ ++last;
+ }
+ }
+ *last = 0;
+ return path;
+ }
+ DOT:
+ return (char *) null_or_empty_or_noslash;
+}
+
+#endif
+/**********************************************************************/
diff --git a/libc/sysdeps/linux/common/bits/.cvsignore b/libc/sysdeps/linux/common/bits/.cvsignore
new file mode 100644
index 000000000..02b6bca59
--- /dev/null
+++ b/libc/sysdeps/linux/common/bits/.cvsignore
@@ -0,0 +1 @@
+uClibc_locale_data.h
diff --git a/libc/sysdeps/linux/common/bits/uClibc_ctype.h b/libc/sysdeps/linux/common/bits/uClibc_ctype.h
new file mode 100644
index 000000000..875070452
--- /dev/null
+++ b/libc/sysdeps/linux/common/bits/uClibc_ctype.h
@@ -0,0 +1,250 @@
+/* Copyright (C) 2002 Manuel Novoa III
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
+ *
+ * Besides uClibc, I'm using this code in my libc for elks, which is
+ * a 16-bit environment with a fairly limited compiler. It would make
+ * things much easier for me if this file isn't modified unnecessarily.
+ * In particular, please put any new or replacement functions somewhere
+ * else, and modify the makefile to use your version instead.
+ * Thanks. Manuel
+ *
+ * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
+
+#if !defined(_CTYPE_H) && !defined(_WCTYPE_H)
+#error Always include <{w}ctype.h> rather than <bits/uClibc_ctype.h>
+#endif
+
+#ifndef _BITS_CTYPE_H
+#define _BITS_CTYPE_H
+
+/* Taking advantage of the C99 mutual-exclusion guarantees for the various
+ * (w)ctype classes, including the descriptions of printing and control
+ * (w)chars, we can place each in one of the following mutually-exlusive
+ * subsets. Since there are less than 16, we can store the data for
+ * each (w)chars in a nibble. In contrast, glibc uses an unsigned int
+ * per (w)char, with one bit flag for each is* type. While this allows
+ * a simple '&' operation to determine the type vs. a range test and a
+ * little special handling for the "blank" and "xdigit" types in my
+ * approach, it also uses 8 times the space for the tables on the typical
+ * 32-bit archs we supported.*/
+enum {
+ __CTYPE_unclassified = 0,
+ __CTYPE_alpha_nonupper_nonlower,
+ __CTYPE_alpha_lower,
+ __CTYPE_alpha_upper_lower,
+ __CTYPE_alpha_upper,
+ __CTYPE_digit,
+ __CTYPE_punct,
+ __CTYPE_graph,
+ __CTYPE_print_space_nonblank,
+ __CTYPE_print_space_blank,
+ __CTYPE_space_nonblank_noncntrl,
+ __CTYPE_space_blank_noncntrl,
+ __CTYPE_cntrl_space_nonblank,
+ __CTYPE_cntrl_space_blank,
+ __CTYPE_cntrl_nonspace,
+};
+
+/* Some macros that test for various (w)ctype classes when passed one of the
+ * designator values enumerated above. */
+#define __CTYPE_isalnum(D) ((unsigned int)(D-1) <= (__CTYPE_digit-1))
+#define __CTYPE_isalpha(D) ((unsigned int)(D-1) <= (__CTYPE_alpha_upper-1))
+#define __CTYPE_isblank(D) \
+ ((((unsigned int)(D - __CTYPE_print_space_nonblank)) <= 5) && (D & 1))
+#define __CTYPE_iscntrl(D) (((unsigned int)(D - __CTYPE_cntrl_space_nonblank)) <= 2)
+#define __CTYPE_isdigit(D) (D == __CTYPE_digit)
+#define __CTYPE_isgraph(D) ((unsigned int)(D-1) <= (__CTYPE_graph-1))
+#define __CTYPE_islower(D) (((unsigned int)(D - __CTYPE_alpha_lower)) <= 1)
+#define __CTYPE_isprint(D) ((unsigned int)(D-1) <= (__CTYPE_print_space_blank-1))
+#define __CTYPE_ispunct(D) (D == __CTYPE_punct)
+#define __CTYPE_isspace(D) (((unsigned int)(D - __CTYPE_print_space_nonblank)) <= 5)
+#define __CTYPE_isupper(D) (((unsigned int)(D - __CTYPE_alpha_upper_lower)) <= 1)
+/* #define __CTYPE_isxdigit(D) -- isxdigit is untestable this way.
+ * But that's ok as isxdigit() (and isdigit() too) are locale-invariant. */
+
+/* The values for wctype_t. */
+enum {
+ _CTYPE_unclassified = 0,
+ _CTYPE_isalnum,
+ _CTYPE_isalpha,
+ _CTYPE_isblank,
+ _CTYPE_iscntrl,
+ _CTYPE_isdigit,
+ _CTYPE_isgraph,
+ _CTYPE_islower,
+ _CTYPE_isprint,
+ _CTYPE_ispunct,
+ _CTYPE_isspace,
+ _CTYPE_isupper,
+ _CTYPE_isxdigit /* _MUST_ be last of the standard classes! */
+};
+
+
+/* The following is used to implement wctype(), but it is defined
+ * here because the ordering must agree with that of the enumeration
+ * above (ignoring unclassified). */
+#define __CTYPE_TYPESTRING \
+ "\6alnum\0\6alpha\0\6blank\0\6cntrl\0\6digit\0\6graph\0\6lower\0" \
+ "\6print\0\6punct\0\6space\0\6upper\0\7xdigit\0\0"
+
+/* Used in implementing iswctype(), but defined here as it must agree
+ * in ordering with the string above. */
+#define __CTYPE_RANGES \
+ 0, -1, /* unclassified */ \
+ 1, __CTYPE_digit - 1, /* alnum */ \
+ 1, __CTYPE_alpha_upper - 1, /* alpha */ \
+ __CTYPE_print_space_blank, 5, /* blank -- also must be odd! */ \
+ __CTYPE_cntrl_space_nonblank, 2, /* cntrl */ \
+ __CTYPE_digit, 0, /* digit */ \
+ 1, __CTYPE_graph - 1, /* graph */ \
+ __CTYPE_alpha_lower, 1, /* lower */ \
+ 1, __CTYPE_print_space_blank - 1, /* print */ \
+ __CTYPE_punct, 0, /* punct */ \
+ __CTYPE_print_space_nonblank, 5, /* space */ \
+ __CTYPE_alpha_upper_lower, 1, /* upper */ \
+ /* No entry for xdigit as it is handled specially. */
+
+#define _CTYPE_iswalnum _CTYPE_isalnum
+#define _CTYPE_iswalpha _CTYPE_isalpha
+#define _CTYPE_iswblank _CTYPE_isblank
+#define _CTYPE_iswcntrl _CTYPE_iscntrl
+#define _CTYPE_iswdigit _CTYPE_isdigit
+#define _CTYPE_iswgraph _CTYPE_isgraph
+#define _CTYPE_iswlower _CTYPE_islower
+#define _CTYPE_iswprint _CTYPE_isprint
+#define _CTYPE_iswpunct _CTYPE_ispunct
+#define _CTYPE_iswspace _CTYPE_isspace
+#define _CTYPE_iswupper _CTYPE_isupper
+#define _CTYPE_iswxdigit _CTYPE_isxdigit
+
+/* The following is used to implement wctrans(). */
+
+enum {
+ _CTYPE_tolower = 1,
+ _CTYPE_toupper,
+ _CTYPE_totitle
+};
+
+#define __CTYPE_TRANSTRING "\10tolower\0\10toupper\0\10totitle\0\0"
+
+/* Now define some ctype macros valid for the C/POSIX locale. */
+
+/* ASCII ords of \t, \f, \n, \r, and \v are 9, 12, 10, 13, 11 respectively. */
+#define __C_isspace(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? ((((c) == ' ') || (((unsigned char)((c) - 9)) <= (13 - 9)))) \
+ : ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9)))))
+#define __C_isblank(c) (((c) == ' ') || ((c) == '\t'))
+#define __C_isdigit(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)((c) - '0')) < 10) \
+ : (((unsigned int)((c) - '0')) < 10))
+#define __C_isxdigit(c) \
+ (__C_isdigit(c) \
+ || ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)((((c)) | 0x20) - 'a')) < 6) \
+ : (((unsigned int)((((c)) | 0x20) - 'a')) < 6)))
+#define __C_iscntrl(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? ((((unsigned char)(c)) < 0x20) || ((c) == 0x7f)) \
+ : ((((unsigned int)(c)) < 0x20) || ((c) == 0x7f)))
+#define __C_isalpha(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)(((c) | 0x20) - 'a')) < 26) \
+ : (((unsigned int)(((c) | 0x20) - 'a')) < 26))
+#define __C_isalnum(c) (__C_isalpha(c) || __C_isdigit(c))
+#define __C_isprint(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)((c) - 0x20)) <= (0x7e - 0x20)) \
+ : (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20)))
+#define __C_islower(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)((c) - 'a')) < 26) \
+ : (((unsigned int)((c) - 'a')) < 26))
+#define __C_isupper(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)((c) - 'A')) < 26) \
+ : (((unsigned int)((c) - 'A')) < 26))
+#define __C_ispunct(c) \
+ ((!__C_isalnum(c)) \
+ && ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)((c) - 0x21)) <= (0x7e - 0x21)) \
+ : (((unsigned int)((c) - 0x21)) <= (0x7e - 0x21))))
+#define __C_isgraph(c) \
+ ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned int)((c) - 0x21)) <= (0x7e - 0x21)) \
+ : (((unsigned int)((c) - 0x21)) <= (0x7e - 0x21)))
+
+#define __C_tolower(c) (__C_isupper(c) ? ((c) | 0x20) : (c))
+#define __C_toupper(c) (__C_islower(c) ? ((c) ^ 0x20) : (c))
+
+#define __C_isxlower(c) \
+ (__C_isdigit(c) \
+ || ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)(((c)) - 'a')) < 6) \
+ : (((unsigned int)(((c)) - 'a')) < 6)))
+#define __C_isxupper(c) \
+ (__C_isdigit(c) \
+ || ((sizeof(c) == sizeof(char)) \
+ ? (((unsigned char)(((c)) - 'A')) < 6) \
+ : (((unsigned int)(((c)) - 'A')) < 6)))
+
+/* TODO: Replace the above with expressions like the following? */
+/* #define __C_isdigit(c) ((sizeof(c) == sizeof(char)) \ */
+/* ? (((unsigned char)((c) - '0')) < 10) \ */
+/* : (((unsigned int)((c) - '0')) < 10)) */
+
+/* Similarly, define some wctype macros valid for the C/POSIX locale. */
+
+/* First, we need some way to make sure the arg is in range. */
+#define __C_classed(c) \
+ ((sizeof(c) <= sizeof(int)) || (c == ((unsigned char)c)))
+
+#define __C_iswspace(c) (__C_classed(c) && __C_isspace(c))
+#define __C_iswblank(c) (__C_classed(c) && __C_isblank(c))
+#define __C_iswdigit(c) (__C_classed(c) && __C_isdigit(c))
+#define __C_iswxdigit(c) (__C_classed(c) && __C_isxdigit(c))
+#define __C_iswcntrl(c) (__C_classed(c) && __C_iscntrl(c))
+#define __C_iswalpha(c) (__C_classed(c) && __C_isalpha(c))
+#define __C_iswalnum(c) (__C_classed(c) && __C_isalnum(c))
+#define __C_iswprint(c) (__C_classed(c) && __C_isprint(c))
+#define __C_iswlower(c) (__C_classed(c) && __C_islower(c))
+#define __C_iswupper(c) (__C_classed(c) && __C_isupper(c))
+#define __C_iswpunct(c) (__C_classed(c) && __C_ispunct(c))
+#define __C_iswgraph(c) (__C_classed(c) && __C_isgraph(c))
+#define __C_towlower(c) \
+ ((__C_classed(c) && __C_isupper(c)) ? ((c) | 0x20) : (c))
+#define __C_towupper(c) \
+ ((__C_classed(c) && __C_islower(c)) ? ((c) ^ 0x20) : (c))
+
+/* Now define some macros to aviod the extra wrapper-function call. */
+#define __iswalnum(c) iswctype(c, _CTYPE_iswalnum)
+#define __iswalpha(c) iswctype(c, _CTYPE_iswalpha)
+#define __iswblank(c) iswctype(c, _CTYPE_iswblank)
+#define __iswcntrl(c) iswctype(c, _CTYPE_iswcntrl)
+#define __iswgraph(c) iswctype(c, _CTYPE_iswgraph)
+#define __iswlower(c) iswctype(c, _CTYPE_iswlower)
+#define __iswprint(c) iswctype(c, _CTYPE_iswprint)
+#define __iswpunct(c) iswctype(c, _CTYPE_iswpunct)
+#define __iswspace(c) iswctype(c, _CTYPE_iswspace)
+#define __iswupper(c) iswctype(c, _CTYPE_iswupper)
+#define __iswdigit(c) __C_iswdigit(c)
+#define __iswxdigit(c) __C_iswxdigit(c)
+
+#endif /* _BITS_CTYPE_H */
diff --git a/libc/sysdeps/linux/common/bits/uClibc_locale.h b/libc/sysdeps/linux/common/bits/uClibc_locale.h
new file mode 100644
index 000000000..2a35d38ec
--- /dev/null
+++ b/libc/sysdeps/linux/common/bits/uClibc_locale.h
@@ -0,0 +1,261 @@
+/* Copyright (C) 2002 Manuel Novoa III
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
+ *
+ * Besides uClibc, I'm using this code in my libc for elks, which is
+ * a 16-bit environment with a fairly limited compiler. It would make
+ * things much easier for me if this file isn't modified unnecessarily.
+ * In particular, please put any new or replacement functions somewhere
+ * else, and modify the makefile to use your version instead.
+ * Thanks. Manuel
+ *
+ * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */
+
+#ifndef _UCLIBC_LOCALE_H
+#define _UCLIBC_LOCALE_H
+
+/**********************************************************************/
+/* uClibc compatibilty stuff */
+
+#ifdef __UCLIBC_HAS_WCHAR__
+#define __WCHAR_ENABLED
+#endif
+
+
+#ifdef __UCLIBC_HAS_LOCALE__
+
+#undef __LOCALE_C_ONLY
+
+#else /* __UCLIBC_HAS_LOCALE__ */
+
+#define __LOCALE_C_ONLY
+
+#endif /* __UCLIBC_HAS_LOCALE__ */
+
+/**********************************************************************/
+
+#define __NL_ITEM_CATEGORY_SHIFT (8)
+#define __NL_ITEM_INDEX_MASK (0xff)
+
+/* TODO: Make sure these agree with the locale mmap file gererator! */
+
+#define __LC_CTYPE 0
+#define __LC_NUMERIC 1
+#define __LC_MONETARY 2
+#define __LC_TIME 3
+#define __LC_COLLATE 4
+#define __LC_MESSAGES 5
+#define __LC_ALL 6
+
+/**********************************************************************/
+#if defined(_LIBC) && !defined(__LOCALE_C_ONLY)
+
+#include <stddef.h>
+#include <stdint.h>
+#include <bits/uClibc_locale_data.h>
+
+/* TODO: This really needs to be somewhere else... */
+#include <limits.h>
+#include <stdint.h>
+
+#if WCHAR_MIN == 0
+typedef wchar_t __uwchar_t;
+#elif WCHAR_MAX <= USHRT_MAX
+typedef unsigned short __uwchar_t;
+#elif WCHAR_MAX <= UINT_MAX
+typedef unsigned int __uwchar_t;
+#elif WCHAR_MAX <= ULONG_MAX
+typedef unsigned long __uwchar_t;
+#elif defined(ULLONG_MAX) && (WCHAR_MAX <= ULLONG_MAX)
+typedef unsigned long long __uwchar_t;
+#elif WCHAR_MAX <= UINT_MAX
+typedef uintmax_t __uwchar_t;
+#else
+#error Can not determine an appropriate type for __uwchar_t!
+#endif
+
+
+
+extern void _locale_set(const unsigned char *p);
+extern void _locale_init(void);
+
+/* TODO: assumes 8-bit chars!!! */
+
+enum {
+ __ctype_encoding_7_bit, /* C/POSIX */
+ __ctype_encoding_utf8, /* UTF-8 */
+ __ctype_encoding_8_bit /* for 8-bit codeset locales */
+};
+
+#define LOCALE_STRING_SIZE (2 * __LC_ALL + 2)
+
+ /*
+ * '#' + 2_per_category + '\0'
+ * {locale row # : 0 = C|POSIX} + 0x8001
+ * encoded in two chars as (((N+1) >> 8) | 0x80) and ((N+1) & 0xff)
+ * so decode is ((((uint16_t)(*s & 0x7f)) << 8) + s[1]) - 1
+ *
+ * Note: 0s are not used as they are nul-terminators for strings.
+ * Note: 0xff, 0xff is the encoding for a non-selected locale.
+ * (see setlocale() below).
+ * In particular, C/POSIX locale is '#' + "\x80\x01"}*LC_ALL + nul.
+ */
+
+
+/* static unsigned char cur_locale[LOCALE_STRING_SIZE]; */
+
+typedef struct {
+/* int tables_loaded; */
+/* unsigned char lctypes[LOCALE_STRING_SIZE]; */
+ unsigned char cur_locale[LOCALE_STRING_SIZE];
+
+ /* NL_LANGINFO stuff. BEWARE ORDERING!!! must agree with NL_* constants! */
+ /* Also, numeric must be followed by monetary and the items must be in
+ * the "struct lconv" order. */
+
+ uint16_t category_offsets[__LC_ALL]; /* TODO -- fix? */
+ unsigned char category_item_count[__LC_ALL]; /* TODO - fix */
+
+ /* ctype */
+ unsigned char encoding; /* C/POSIX, 8-bit, UTF-8 */
+ unsigned char mb_cur_max; /* determined by encoding _AND_ translit!!! */
+
+ const char *codeset;
+
+#ifdef __CTYPE_HAS_8_BIT_LOCALES
+ const unsigned char *idx8ctype;
+ const unsigned char *tbl8ctype;
+ const unsigned char *idx8uplow;
+ const unsigned char *tbl8uplow;
+#ifdef __WCHAR_ENABLED
+ const unsigned char *idx8c2wc;
+ const uint16_t *tbl8c2wc; /* char > 0x7f to wide char */
+ const unsigned char *idx8wc2c;
+ const unsigned char *tbl8wc2c;
+ /* translit */
+#endif /* __WCHAR_ENABLED */
+#endif /* __CTYPE_HAS_8_BIT_LOCALES */
+#ifdef __WCHAR_ENABLED
+ const unsigned char *tblwctype;
+ const unsigned char *tblwuplow;
+ const unsigned char *tblwcomb;
+ const int16_t *tblwuplow_diff; /* yes... signed */
+ /* width?? */
+#endif /* __WCHAR_ENABLED */
+
+ /* numeric */
+ const char *decimal_point;
+ const char *thousands_sep;
+ const char *grouping;
+
+ /* monetary */
+ const char *int_curr_symbol;
+ const char *currency_symbol;
+ const char *mon_decimal_point;
+ const char *mon_thousands_sep;
+ const char *mon_grouping;
+ const char *positive_sign;
+ const char *negative_sign;
+ const char *int_frac_digits;
+ const char *frac_digits;
+ const char *p_cs_precedes;
+ const char *p_sep_by_space;
+ const char *n_cs_precedes;
+ const char *n_sep_by_space;
+ const char *p_sign_posn;
+ const char *n_sign_posn;
+ const char *int_p_cs_precedes;
+ const char *int_p_sep_by_space;
+ const char *int_n_cs_precedes;
+ const char *int_n_sep_by_space;
+ const char *int_p_sign_posn;
+ const char *int_n_sign_posn;
+
+ const char *crncystr; /* not returned by localeconv */
+
+ /* time */
+ const char *abday_1;
+ const char *abday_2;
+ const char *abday_3;
+ const char *abday_4;
+ const char *abday_5;
+ const char *abday_6;
+ const char *abday_7;
+
+ const char *day_1;
+ const char *day_2;
+ const char *day_3;
+ const char *day_4;
+ const char *day_5;
+ const char *day_6;
+ const char *day_7;
+
+ const char *abmon_1;
+ const char *abmon_2;
+ const char *abmon_3;
+ const char *abmon_4;
+ const char *abmon_5;
+ const char *abmon_6;
+ const char *abmon_7;
+ const char *abmon_8;
+ const char *abmon_9;
+ const char *abmon_10;
+ const char *abmon_11;
+ const char *abmon_12;
+
+ const char *mon_1;
+ const char *mon_2;
+ const char *mon_3;
+ const char *mon_4;
+ const char *mon_5;
+ const char *mon_6;
+ const char *mon_7;
+ const char *mon_8;
+ const char *mon_9;
+ const char *mon_10;
+ const char *mon_11;
+ const char *mon_12;
+
+ const char *am_str;
+ const char *pm_str;
+
+ const char *d_t_fmt;
+ const char *d_fmt;
+ const char *t_fmt;
+ const char *t_fmt_ampm;
+ const char *era;
+
+ const char *era_year; /* non SUSv3 */
+ const char *era_d_fmt;
+ const char *alt_digits;
+ const char *era_d_t_fmt;
+ const char *era_t_fmt;
+
+ /* collate */
+
+ /* messages */
+ const char *yesexpr;
+ const char *noexpr;
+
+} __locale_t;
+
+extern __locale_t __global_locale;
+
+#endif /* defined(_LIBC) && !defined(__LOCALE_C_ONLY) */
+
+#endif /* _UCLIBC_LOCALE_H */