summaryrefslogtreecommitdiffstats
path: root/intl/locale/unix
diff options
context:
space:
mode:
Diffstat (limited to 'intl/locale/unix')
-rw-r--r--intl/locale/unix/moz.build38
-rw-r--r--intl/locale/unix/nsAndroidCharset.cpp49
-rw-r--r--intl/locale/unix/nsCollationUnix.cpp189
-rw-r--r--intl/locale/unix/nsCollationUnix.h43
-rw-r--r--intl/locale/unix/nsDateTimeFormatUnix.cpp284
-rw-r--r--intl/locale/unix/nsDateTimeFormatUnix.h70
-rw-r--r--intl/locale/unix/nsPosixLocale.cpp243
-rw-r--r--intl/locale/unix/nsUNIXCharset.cpp185
-rw-r--r--intl/locale/unix/unixcharset.properties536
9 files changed, 1637 insertions, 0 deletions
diff --git a/intl/locale/unix/moz.build b/intl/locale/unix/moz.build
new file mode 100644
index 000000000..7685d0a01
--- /dev/null
+++ b/intl/locale/unix/moz.build
@@ -0,0 +1,38 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SOURCES += [
+ 'nsCollationUnix.cpp',
+ 'nsDateTimeFormatUnix.cpp',
+ 'nsPosixLocale.cpp',
+]
+
+if CONFIG['OS_TARGET'] == 'Android':
+ SOURCES += [
+ 'nsAndroidCharset.cpp',
+ ]
+else:
+ SOURCES += [
+ 'nsUNIXCharset.cpp',
+ ]
+ GENERATED_FILES = [
+ 'unixcharset.properties.h',
+ ]
+ unixcharset = GENERATED_FILES['unixcharset.properties.h']
+ unixcharset.script = '../props2arrays.py'
+ unixcharset.inputs = ['unixcharset.properties']
+
+FINAL_LIBRARY = 'xul'
+
+LOCAL_INCLUDES += [
+ '..',
+]
+
+# CODESET is not automatically defined on some older versions of Redhat.
+# Define _XOPEN_SOURCE so CODESET will get defined and thus allow
+# nl_langinfo(CODESET) to compile on these systems.
+if CONFIG['OS_ARCH'] == 'Linux':
+ DEFINES['_XOPEN_SOURCE'] = 500
diff --git a/intl/locale/unix/nsAndroidCharset.cpp b/intl/locale/unix/nsAndroidCharset.cpp
new file mode 100644
index 000000000..ed646039c
--- /dev/null
+++ b/intl/locale/unix/nsAndroidCharset.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIPlatformCharset.h"
+#include "nsPlatformCharset.h"
+
+NS_IMPL_ISUPPORTS(nsPlatformCharset, nsIPlatformCharset)
+
+nsPlatformCharset::nsPlatformCharset()
+{
+}
+
+nsPlatformCharset::~nsPlatformCharset()
+{
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::Init()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::GetCharset(nsPlatformCharsetSel selector, nsACString& oResult)
+{
+ oResult.AssignLiteral("UTF-8");
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACString &oResult)
+{
+ oResult.AssignLiteral("UTF-8");
+ return NS_OK;
+}
+
+nsresult
+nsPlatformCharset::InitGetCharset(nsACString &oString)
+{
+ return NS_OK;
+}
+
+nsresult
+nsPlatformCharset::VerifyCharset(nsCString &aCharset)
+{
+ return NS_OK;
+}
diff --git a/intl/locale/unix/nsCollationUnix.cpp b/intl/locale/unix/nsCollationUnix.cpp
new file mode 100644
index 000000000..3bc5a731c
--- /dev/null
+++ b/intl/locale/unix/nsCollationUnix.cpp
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <locale.h>
+#include "prmem.h"
+#include "nsCollationUnix.h"
+#include "nsIServiceManager.h"
+#include "nsIComponentManager.h"
+#include "nsILocaleService.h"
+#include "nsIPlatformCharset.h"
+#include "nsPosixLocale.h"
+#include "nsCOMPtr.h"
+#include "nsUnicharUtils.h"
+#include "nsCRT.h"
+//#define DEBUG_UNIX_COLLATION
+
+inline void nsCollationUnix::DoSetLocale()
+{
+ char *locale = setlocale(LC_COLLATE, nullptr);
+ mSavedLocale.Assign(locale ? locale : "");
+ if (!mSavedLocale.EqualsIgnoreCase(mLocale.get())) {
+ (void) setlocale(LC_COLLATE, PromiseFlatCString(Substring(mLocale,0,MAX_LOCALE_LEN)).get());
+ }
+}
+
+inline void nsCollationUnix::DoRestoreLocale()
+{
+ if (!mSavedLocale.EqualsIgnoreCase(mLocale.get())) {
+ (void) setlocale(LC_COLLATE, PromiseFlatCString(Substring(mSavedLocale,0,MAX_LOCALE_LEN)).get());
+ }
+}
+
+nsCollationUnix::nsCollationUnix() : mCollation(nullptr)
+{
+}
+
+nsCollationUnix::~nsCollationUnix()
+{
+ if (mCollation)
+ delete mCollation;
+}
+
+NS_IMPL_ISUPPORTS(nsCollationUnix, nsICollation)
+
+nsresult nsCollationUnix::Initialize(nsILocale* locale)
+{
+#define kPlatformLocaleLength 64
+ NS_ASSERTION(!mCollation, "Should only be initialized once");
+
+ nsresult res;
+
+ mCollation = new nsCollation;
+
+ // default platform locale
+ mLocale.Assign('C');
+
+ nsAutoString localeStr;
+ NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_COLLATE##PLATFORM");
+
+ // get locale string, use app default if no locale specified
+ if (locale == nullptr) {
+ nsCOMPtr<nsILocaleService> localeService =
+ do_GetService(NS_LOCALESERVICE_CONTRACTID, &res);
+ if (NS_SUCCEEDED(res)) {
+ nsCOMPtr<nsILocale> appLocale;
+ res = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
+ if (NS_SUCCEEDED(res)) {
+ res = appLocale->GetCategory(aCategory, localeStr);
+ NS_ASSERTION(NS_SUCCEEDED(res), "failed to get app locale info");
+ }
+ }
+ }
+ else {
+ res = locale->GetCategory(aCategory, localeStr);
+ NS_ASSERTION(NS_SUCCEEDED(res), "failed to get locale info");
+ }
+
+ // Get platform locale and charset name from locale, if available
+ if (NS_SUCCEEDED(res)) {
+ // keep the same behavior as 4.x as well as avoiding Linux collation key problem
+ if (localeStr.LowerCaseEqualsLiteral("en_us")) { // note: locale is in platform format
+ localeStr.Assign('C');
+ }
+
+ nsPosixLocale::GetPlatformLocale(localeStr, mLocale);
+
+ nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &res);
+ if (NS_SUCCEEDED(res)) {
+ nsAutoCString mappedCharset;
+ res = platformCharset->GetDefaultCharsetForLocale(localeStr, mappedCharset);
+ if (NS_SUCCEEDED(res)) {
+ mCollation->SetCharset(mappedCharset.get());
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
+
+nsresult nsCollationUnix::CompareString(int32_t strength,
+ const nsAString& string1,
+ const nsAString& string2,
+ int32_t* result)
+{
+ nsresult res = NS_OK;
+
+ nsAutoString stringNormalized1, stringNormalized2;
+ if (strength != kCollationCaseSensitive) {
+ res = mCollation->NormalizeString(string1, stringNormalized1);
+ if (NS_FAILED(res)) {
+ return res;
+ }
+ res = mCollation->NormalizeString(string2, stringNormalized2);
+ if (NS_FAILED(res)) {
+ return res;
+ }
+ } else {
+ stringNormalized1 = string1;
+ stringNormalized2 = string2;
+ }
+
+ // convert unicode to charset
+ char *str1, *str2;
+
+ res = mCollation->UnicodeToChar(stringNormalized1, &str1);
+ if (NS_SUCCEEDED(res) && str1) {
+ res = mCollation->UnicodeToChar(stringNormalized2, &str2);
+ if (NS_SUCCEEDED(res) && str2) {
+ DoSetLocale();
+ *result = strcoll(str1, str2);
+ DoRestoreLocale();
+ PR_Free(str2);
+ }
+ PR_Free(str1);
+ }
+
+ return res;
+}
+
+
+nsresult nsCollationUnix::AllocateRawSortKey(int32_t strength,
+ const nsAString& stringIn,
+ uint8_t** key, uint32_t* outLen)
+{
+ nsresult res = NS_OK;
+
+ nsAutoString stringNormalized;
+ if (strength != kCollationCaseSensitive) {
+ res = mCollation->NormalizeString(stringIn, stringNormalized);
+ if (NS_FAILED(res))
+ return res;
+ } else {
+ stringNormalized = stringIn;
+ }
+ // convert unicode to charset
+ char *str;
+
+ res = mCollation->UnicodeToChar(stringNormalized, &str);
+ if (NS_SUCCEEDED(res) && str) {
+ DoSetLocale();
+ // call strxfrm to generate a key
+ size_t len = strxfrm(nullptr, str, 0) + 1;
+ void *buffer = PR_Malloc(len);
+ if (!buffer) {
+ res = NS_ERROR_OUT_OF_MEMORY;
+ } else if (strxfrm((char *)buffer, str, len) >= len) {
+ PR_Free(buffer);
+ res = NS_ERROR_FAILURE;
+ } else {
+ *key = (uint8_t *)buffer;
+ *outLen = len;
+ }
+ DoRestoreLocale();
+ PR_Free(str);
+ }
+
+ return res;
+}
+
+nsresult nsCollationUnix::CompareRawSortKey(const uint8_t* key1, uint32_t len1,
+ const uint8_t* key2, uint32_t len2,
+ int32_t* result)
+{
+ *result = PL_strcmp((const char *)key1, (const char *)key2);
+ return NS_OK;
+}
diff --git a/intl/locale/unix/nsCollationUnix.h b/intl/locale/unix/nsCollationUnix.h
new file mode 100644
index 000000000..dd2126b44
--- /dev/null
+++ b/intl/locale/unix/nsCollationUnix.h
@@ -0,0 +1,43 @@
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsCollationUnix_h__
+#define nsCollationUnix_h__
+
+
+#include "nsICollation.h"
+#include "nsCollation.h" // static library
+#include "plstr.h"
+#include "mozilla/Attributes.h"
+#include "nsString.h"
+
+
+
+class nsCollationUnix final : public nsICollation {
+
+protected:
+ nsCollation *mCollation;
+ nsCString mLocale;
+ nsCString mSavedLocale;
+ bool mUseCodePointOrder;
+
+ void DoSetLocale();
+ void DoRestoreLocale();
+
+ ~nsCollationUnix();
+
+public:
+ nsCollationUnix();
+
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsICollation interface
+ NS_DECL_NSICOLLATION
+
+};
+
+#endif /* nsCollationUnix_h__ */
diff --git a/intl/locale/unix/nsDateTimeFormatUnix.cpp b/intl/locale/unix/nsDateTimeFormatUnix.cpp
new file mode 100644
index 000000000..a70b54102
--- /dev/null
+++ b/intl/locale/unix/nsDateTimeFormatUnix.cpp
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <locale.h>
+#include "plstr.h"
+#include "nsIServiceManager.h"
+#include "nsDateTimeFormatUnix.h"
+#include "nsIComponentManager.h"
+#include "nsILocaleService.h"
+#include "nsIPlatformCharset.h"
+#include "nsPosixLocale.h"
+#include "nsCRT.h"
+#include "nsReadableUtils.h"
+#include "nsUnicharUtils.h"
+#include "mozilla/dom/EncodingUtils.h"
+
+using mozilla::dom::EncodingUtils;
+
+NS_IMPL_ISUPPORTS(nsDateTimeFormatUnix, nsIDateTimeFormat)
+
+// init this interface to a specified locale
+nsresult nsDateTimeFormatUnix::Initialize(nsILocale* locale)
+{
+ nsAutoString localeStr;
+ NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_TIME##PLATFORM");
+ nsresult res = NS_OK;
+
+ // use cached info if match with stored locale
+ if (!locale) {
+ if (!mLocale.IsEmpty() &&
+ mLocale.Equals(mAppLocale, nsCaseInsensitiveStringComparator())) {
+ return NS_OK;
+ }
+ }
+ else {
+ res = locale->GetCategory(aCategory, localeStr);
+ if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
+ if (!mLocale.IsEmpty() &&
+ mLocale.Equals(localeStr,
+ nsCaseInsensitiveStringComparator())) {
+ return NS_OK;
+ }
+ }
+ }
+
+ mCharset.AssignLiteral("windows-1252");
+ mPlatformLocale.AssignLiteral("en_US");
+
+ // get locale name string, use app default if no locale specified
+ if (!locale) {
+ nsCOMPtr<nsILocaleService> localeService =
+ do_GetService(NS_LOCALESERVICE_CONTRACTID, &res);
+ if (NS_SUCCEEDED(res)) {
+ nsCOMPtr<nsILocale> appLocale;
+ res = localeService->GetApplicationLocale(getter_AddRefs(appLocale));
+ if (NS_SUCCEEDED(res)) {
+ res = appLocale->GetCategory(aCategory, localeStr);
+ if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
+ NS_ASSERTION(NS_SUCCEEDED(res), "failed to get app locale info");
+ mAppLocale = localeStr; // cache app locale name
+ }
+ }
+ }
+ }
+ else {
+ res = locale->GetCategory(aCategory, localeStr);
+ NS_ASSERTION(NS_SUCCEEDED(res), "failed to get locale info");
+ }
+
+ if (NS_SUCCEEDED(res) && !localeStr.IsEmpty()) {
+ mLocale = localeStr; // cache locale name
+
+ nsPosixLocale::GetPlatformLocale(mLocale, mPlatformLocale);
+
+ nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &res);
+ if (NS_SUCCEEDED(res)) {
+ nsAutoCString mappedCharset;
+ res = platformCharset->GetDefaultCharsetForLocale(mLocale, mappedCharset);
+ if (NS_SUCCEEDED(res)) {
+ mCharset = mappedCharset;
+ }
+ }
+ }
+
+ mDecoder = EncodingUtils::DecoderForEncoding(mCharset);
+
+ LocalePreferred24hour();
+
+ return res;
+}
+
+void nsDateTimeFormatUnix::LocalePreferred24hour()
+{
+ char str[100];
+ time_t tt;
+ struct tm *tmc;
+ int i;
+
+ tt = time(nullptr);
+ tmc = localtime(&tt);
+
+ tmc->tm_hour=22; // put the test sample hour to 22:00 which is 10PM
+ tmc->tm_min=0; // set the min & sec other number than '2'
+ tmc->tm_sec=0;
+
+ char *temp = setlocale(LC_TIME, mPlatformLocale.get());
+ strftime(str, (size_t)99, "%X", (struct tm *)tmc);
+
+ (void) setlocale(LC_TIME, temp);
+
+ mLocalePreferred24hour = false;
+ for (i=0; str[i]; i++) {
+ if (str[i] == '2') { // if there is any '2', that locale use 0-23 time format
+ mLocalePreferred24hour = true;
+ break;
+ }
+ }
+
+ mLocaleAMPMfirst = true;
+ if (mLocalePreferred24hour == false) {
+ if (str[0] && str[0] == '1') { // if the first character is '1' of 10:00,
+ // AMPM string is located after 10:00
+ mLocaleAMPMfirst = false;
+ }
+ }
+}
+
+nsresult nsDateTimeFormatUnix::FormatTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const time_t timetTime,
+ nsAString& stringOut)
+{
+ struct tm tmTime;
+ memcpy(&tmTime, localtime(&timetTime), sizeof(struct tm));
+ return FormatTMTime(locale, dateFormatSelector, timeFormatSelector, &tmTime, stringOut);
+}
+
+// performs a locale sensitive date formatting operation on the struct tm parameter
+nsresult nsDateTimeFormatUnix::FormatTMTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const struct tm* tmTime,
+ nsAString& stringOut)
+{
+#define NSDATETIME_FORMAT_BUFFER_LEN 80
+ char strOut[NSDATETIME_FORMAT_BUFFER_LEN*2]; // buffer for date and time
+ char fmtD[NSDATETIME_FORMAT_BUFFER_LEN], fmtT[NSDATETIME_FORMAT_BUFFER_LEN];
+ nsresult rv;
+
+
+ // set up locale data
+ (void) Initialize(locale);
+ NS_ENSURE_TRUE(mDecoder, NS_ERROR_NOT_INITIALIZED);
+
+ // set date format
+ if (dateFormatSelector == kDateFormatLong && timeFormatSelector == kTimeFormatSeconds) {
+ PL_strncpy(fmtD, "%c", NSDATETIME_FORMAT_BUFFER_LEN);
+ PL_strncpy(fmtT, "", NSDATETIME_FORMAT_BUFFER_LEN);
+ } else {
+
+ switch (dateFormatSelector) {
+ case kDateFormatNone:
+ PL_strncpy(fmtD, "", NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ case kDateFormatLong:
+ case kDateFormatShort:
+ PL_strncpy(fmtD, "%x", NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ case kDateFormatYearMonth:
+ PL_strncpy(fmtD, "%Y/%m", NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ case kDateFormatWeekday:
+ PL_strncpy(fmtD, "%a", NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ default:
+ PL_strncpy(fmtD, "", NSDATETIME_FORMAT_BUFFER_LEN);
+ }
+
+ // set time format
+ switch (timeFormatSelector) {
+ case kTimeFormatNone:
+ PL_strncpy(fmtT, "", NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ case kTimeFormatSeconds:
+ PL_strncpy(fmtT, "%X", NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ case kTimeFormatNoSeconds:
+ PL_strncpy(fmtT,
+ mLocalePreferred24hour ? "%H:%M" : mLocaleAMPMfirst ? "%p %I:%M" : "%I:%M %p",
+ NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ case kTimeFormatSecondsForce24Hour:
+ PL_strncpy(fmtT, "%H:%M:%S", NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ case kTimeFormatNoSecondsForce24Hour:
+ PL_strncpy(fmtT, "%H:%M", NSDATETIME_FORMAT_BUFFER_LEN);
+ break;
+ default:
+ PL_strncpy(fmtT, "", NSDATETIME_FORMAT_BUFFER_LEN);
+ }
+ }
+
+ // generate data/time string
+ char *old_locale = setlocale(LC_TIME, nullptr);
+ (void) setlocale(LC_TIME, mPlatformLocale.get());
+ if (strlen(fmtD) && strlen(fmtT)) {
+ PL_strncat(fmtD, " ", NSDATETIME_FORMAT_BUFFER_LEN);
+ PL_strncat(fmtD, fmtT, NSDATETIME_FORMAT_BUFFER_LEN);
+ strftime(strOut, NSDATETIME_FORMAT_BUFFER_LEN, fmtD, tmTime);
+ }
+ else if (strlen(fmtD) && !strlen(fmtT)) {
+ strftime(strOut, NSDATETIME_FORMAT_BUFFER_LEN, fmtD, tmTime);
+ }
+ else if (!strlen(fmtD) && strlen(fmtT)) {
+ strftime(strOut, NSDATETIME_FORMAT_BUFFER_LEN, fmtT, tmTime);
+ }
+ else {
+ PL_strncpy(strOut, "", NSDATETIME_FORMAT_BUFFER_LEN);
+ }
+ (void) setlocale(LC_TIME, old_locale);
+
+ // convert result to unicode
+ int32_t srcLength = (int32_t) strlen(strOut);
+ int32_t unicharLength = NSDATETIME_FORMAT_BUFFER_LEN*2;
+ char16_t unichars[NSDATETIME_FORMAT_BUFFER_LEN*2]; // buffer for date and time
+
+ rv = mDecoder->Convert(strOut, &srcLength, unichars, &unicharLength);
+ if (NS_FAILED(rv))
+ return rv;
+ stringOut.Assign(unichars, unicharLength);
+
+ return rv;
+}
+
+// performs a locale sensitive date formatting operation on the PRTime parameter
+nsresult nsDateTimeFormatUnix::FormatPRTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const PRTime prTime,
+ nsAString& stringOut)
+{
+ PRExplodedTime explodedTime;
+ PR_ExplodeTime(prTime, PR_LocalTimeParameters, &explodedTime);
+
+ return FormatPRExplodedTime(locale, dateFormatSelector, timeFormatSelector, &explodedTime, stringOut);
+}
+
+// performs a locale sensitive date formatting operation on the PRExplodedTime parameter
+nsresult nsDateTimeFormatUnix::FormatPRExplodedTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const PRExplodedTime* explodedTime,
+ nsAString& stringOut)
+{
+ struct tm tmTime;
+ /* be safe and set all members of struct tm to zero
+ *
+ * there are other fields in the tm struct that we aren't setting
+ * (tm_isdst, tm_gmtoff, tm_zone, should we set these?) and since
+ * tmTime is on the stack, it may be filled with garbage, but
+ * the garbage may vary. (this may explain why some saw bug #10412, and
+ * others did not.
+ *
+ * when tmTime is passed to strftime() with garbage bad things may happen.
+ * see bug #10412
+ */
+ memset( &tmTime, 0, sizeof(tmTime) );
+
+ tmTime.tm_yday = explodedTime->tm_yday;
+ tmTime.tm_wday = explodedTime->tm_wday;
+ tmTime.tm_year = explodedTime->tm_year;
+ tmTime.tm_year -= 1900;
+ tmTime.tm_mon = explodedTime->tm_month;
+ tmTime.tm_mday = explodedTime->tm_mday;
+ tmTime.tm_hour = explodedTime->tm_hour;
+ tmTime.tm_min = explodedTime->tm_min;
+ tmTime.tm_sec = explodedTime->tm_sec;
+
+ return FormatTMTime(locale, dateFormatSelector, timeFormatSelector, &tmTime, stringOut);
+}
+
diff --git a/intl/locale/unix/nsDateTimeFormatUnix.h b/intl/locale/unix/nsDateTimeFormatUnix.h
new file mode 100644
index 000000000..6c305556f
--- /dev/null
+++ b/intl/locale/unix/nsDateTimeFormatUnix.h
@@ -0,0 +1,70 @@
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsDateTimeFormatUnix_h__
+#define nsDateTimeFormatUnix_h__
+
+
+#include "nsCOMPtr.h"
+#include "nsIDateTimeFormat.h"
+#include "nsIUnicodeDecoder.h"
+
+#define kPlatformLocaleLength 64
+
+class nsDateTimeFormatUnix : public nsIDateTimeFormat {
+
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ // performs a locale sensitive date formatting operation on the time_t parameter
+ NS_IMETHOD FormatTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const time_t timetTime,
+ nsAString& stringOut) override;
+
+ // performs a locale sensitive date formatting operation on the struct tm parameter
+ NS_IMETHOD FormatTMTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const struct tm* tmTime,
+ nsAString& stringOut) override;
+
+ // performs a locale sensitive date formatting operation on the PRTime parameter
+ NS_IMETHOD FormatPRTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const PRTime prTime,
+ nsAString& stringOut) override;
+
+ // performs a locale sensitive date formatting operation on the PRExplodedTime parameter
+ NS_IMETHOD FormatPRExplodedTime(nsILocale* locale,
+ const nsDateFormatSelector dateFormatSelector,
+ const nsTimeFormatSelector timeFormatSelector,
+ const PRExplodedTime* explodedTime,
+ nsAString& stringOut) override;
+
+
+ nsDateTimeFormatUnix() {mLocale.Truncate();mAppLocale.Truncate();}
+
+private:
+ virtual ~nsDateTimeFormatUnix() {}
+
+ // init this interface to a specified locale
+ NS_IMETHOD Initialize(nsILocale* locale);
+
+ void LocalePreferred24hour();
+
+ nsString mLocale;
+ nsString mAppLocale;
+ nsCString mCharset; // in order to convert API result to unicode
+ nsCString mPlatformLocale; // for setlocale
+ bool mLocalePreferred24hour; // true if 24 hour format is preferred by current locale
+ bool mLocaleAMPMfirst; // true if AM/PM string is preferred before the time
+ nsCOMPtr <nsIUnicodeDecoder> mDecoder;
+};
+
+#endif /* nsDateTimeFormatUnix_h__ */
diff --git a/intl/locale/unix/nsPosixLocale.cpp b/intl/locale/unix/nsPosixLocale.cpp
new file mode 100644
index 000000000..16299afed
--- /dev/null
+++ b/intl/locale/unix/nsPosixLocale.cpp
@@ -0,0 +1,243 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nscore.h"
+#include "nsString.h"
+#include "nsPosixLocale.h"
+#include "mozilla/Sprintf.h"
+#include "plstr.h"
+#include "nsReadableUtils.h"
+
+static bool
+ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator);
+
+nsresult
+nsPosixLocale::GetPlatformLocale(const nsAString& locale, nsACString& posixLocale)
+{
+ char country_code[MAX_COUNTRY_CODE_LEN+1];
+ char lang_code[MAX_LANGUAGE_CODE_LEN+1];
+ char extra[MAX_EXTRA_LEN+1];
+ char posix_locale[MAX_LOCALE_LEN+1];
+ NS_LossyConvertUTF16toASCII xp_locale(locale);
+
+ if (!xp_locale.IsEmpty()) {
+ if (!ParseLocaleString(xp_locale.get(),lang_code,country_code,extra,'-')) {
+// strncpy(posixLocale,"C",length);
+ posixLocale = xp_locale; // use xp locale if parse failed
+ return NS_OK;
+ }
+
+ if (*country_code) {
+ if (*extra) {
+ SprintfLiteral(posix_locale,"%s_%s.%s",lang_code,country_code,extra);
+ }
+ else {
+ SprintfLiteral(posix_locale,"%s_%s",lang_code,country_code);
+ }
+ }
+ else {
+ if (*extra) {
+ SprintfLiteral(posix_locale,"%s.%s",lang_code,extra);
+ }
+ else {
+ SprintfLiteral(posix_locale,"%s",lang_code);
+ }
+ }
+
+ posixLocale = posix_locale;
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
+nsresult
+nsPosixLocale::GetXPLocale(const char* posixLocale, nsAString& locale)
+{
+ char country_code[MAX_COUNTRY_CODE_LEN+1];
+ char lang_code[MAX_LANGUAGE_CODE_LEN+1];
+ char extra[MAX_EXTRA_LEN+1];
+ char posix_locale[MAX_LOCALE_LEN+1];
+
+ if (posixLocale!=nullptr) {
+ if (strcmp(posixLocale,"C")==0 || strcmp(posixLocale,"POSIX")==0) {
+ locale.AssignLiteral("en-US");
+ return NS_OK;
+ }
+ if (strcmp(posixLocale,"C.UTF-8")==0) {
+ locale.AssignLiteral("en-US.UTF-8");
+ return NS_OK;
+ }
+ if (!ParseLocaleString(posixLocale,lang_code,country_code,extra,'_')) {
+// * locale = "x-user-defined";
+ // use posix if parse failed
+ CopyASCIItoUTF16(nsDependentCString(posixLocale), locale);
+ return NS_OK;
+ }
+
+ // Special case: substitute "nb" (Norwegian Bokmal) for macrolanguage
+ // code "no" (Norwegian)
+ if (nsDependentCString(lang_code).LowerCaseEqualsLiteral("no")) {
+ lang_code[1] = 'b';
+ }
+
+ if (*country_code) {
+ SprintfLiteral(posix_locale,"%s-%s",lang_code,country_code);
+ }
+ else {
+ SprintfLiteral(posix_locale,"%s",lang_code);
+ }
+
+ CopyASCIItoUTF16(nsDependentCString(posix_locale), locale);
+ return NS_OK;
+
+ }
+
+ return NS_ERROR_FAILURE;
+
+}
+
+//
+// returns false/true depending on if it was of the form LL-CC.Extra
+static bool
+ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator)
+{
+ const char *src = locale_string;
+ char modifier[MAX_EXTRA_LEN+1];
+ char *dest;
+ int dest_space, len;
+
+ *language = '\0';
+ *country = '\0';
+ *extra = '\0';
+ if (strlen(locale_string) < 2) {
+ return(false);
+ }
+
+ //
+ // parse the language part
+ //
+ dest = language;
+ dest_space = MAX_LANGUAGE_CODE_LEN;
+ while ((*src) && (isalpha(*src)) && (dest_space--)) {
+ *dest++ = tolower(*src++);
+ }
+ *dest = '\0';
+ len = dest - language;
+ if ((len != 2) && (len != 3)) {
+ NS_ASSERTION((len == 2) || (len == 3), "language code too short");
+ NS_ASSERTION(len < 3, "reminder: verify we can handle 3+ character language code in all parts of the system; eg: language packs");
+ *language = '\0';
+ return(false);
+ }
+
+ // check if all done
+ if (*src == '\0') {
+ return(true);
+ }
+
+ if ((*src != '_') && (*src != '-') && (*src != '.') && (*src != '@')) {
+ NS_ASSERTION(isalpha(*src), "language code too long");
+ NS_ASSERTION(!isalpha(*src), "unexpected language/country separator");
+ *language = '\0';
+ return(false);
+ }
+
+ //
+ // parse the country part
+ //
+ if ((*src == '_') || (*src == '-')) {
+ src++;
+ dest = country;
+ dest_space = MAX_COUNTRY_CODE_LEN;
+ while ((*src) && (isalpha(*src)) && (dest_space--)) {
+ *dest++ = toupper(*src++);
+ }
+ *dest = '\0';
+ len = dest - country;
+ if (len != 2) {
+ NS_ASSERTION(len == 2, "unexpected country code length");
+ *language = '\0';
+ *country = '\0';
+ return(false);
+ }
+ }
+
+ // check if all done
+ if (*src == '\0') {
+ return(true);
+ }
+
+ if ((*src != '.') && (*src != '@')) {
+ NS_ASSERTION(isalpha(*src), "country code too long");
+ NS_ASSERTION(!isalpha(*src), "unexpected country/extra separator");
+ *language = '\0';
+ *country = '\0';
+ return(false);
+ }
+
+ //
+ // handle the extra part
+ //
+ if (*src == '.') {
+ src++; // move past the extra part separator
+ dest = extra;
+ dest_space = MAX_EXTRA_LEN;
+ while ((*src) && (*src != '@') && (dest_space--)) {
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+ len = dest - extra;
+ if (len < 1) {
+ NS_ASSERTION(len > 0, "found country/extra separator but no extra code");
+ *language = '\0';
+ *country = '\0';
+ *extra = '\0';
+ return(false);
+ }
+ }
+
+ // check if all done
+ if (*src == '\0') {
+ return(true);
+ }
+
+ //
+ // handle the modifier part
+ //
+
+ if (*src == '@') {
+ src++; // move past the modifier separator
+ NS_ASSERTION(strcmp("euro",src) == 0, "found non euro modifier");
+ dest = modifier;
+ dest_space = MAX_EXTRA_LEN;
+ while ((*src) && (dest_space--)) {
+ *dest++ = *src++;
+ }
+ *dest = '\0';
+ len = dest - modifier;
+ if (len < 1) {
+ NS_ASSERTION(len > 0, "found modifier separator but no modifier code");
+ *language = '\0';
+ *country = '\0';
+ *extra = '\0';
+ *modifier = '\0';
+ return(false);
+ }
+ }
+
+ // check if all done
+ if (*src == '\0') {
+ return(true);
+ }
+
+ NS_ASSERTION(*src == '\0', "extra/modifier code too long");
+ *language = '\0';
+ *country = '\0';
+ *extra = '\0';
+
+ return(false);
+}
+
diff --git a/intl/locale/unix/nsUNIXCharset.cpp b/intl/locale/unix/nsUNIXCharset.cpp
new file mode 100644
index 000000000..d72305e55
--- /dev/null
+++ b/intl/locale/unix/nsUNIXCharset.cpp
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <locale.h>
+
+#include "mozilla/ArrayUtils.h"
+
+#include "nsIPlatformCharset.h"
+#include "nsUConvPropertySearch.h"
+#include "nsCOMPtr.h"
+#include "nsReadableUtils.h"
+#include "nsEncoderDecoderUtils.h"
+#if HAVE_GNU_LIBC_VERSION_H
+#include <gnu/libc-version.h>
+#endif
+#ifdef HAVE_NL_TYPES_H
+#include <nl_types.h>
+#endif
+#if HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
+#include "nsPlatformCharset.h"
+#include "prinit.h"
+#include "nsUnicharUtils.h"
+#include "mozilla/dom/EncodingUtils.h"
+
+using mozilla::dom::EncodingUtils;
+using namespace mozilla;
+
+static const nsUConvProp kUnixCharsets[] = {
+#include "unixcharset.properties.h"
+};
+
+NS_IMPL_ISUPPORTS(nsPlatformCharset, nsIPlatformCharset)
+
+nsPlatformCharset::nsPlatformCharset()
+{
+}
+
+static nsresult
+ConvertLocaleToCharsetUsingDeprecatedConfig(const nsACString& locale,
+ nsACString& oResult)
+{
+ if (!(locale.IsEmpty())) {
+ if (NS_SUCCEEDED(nsUConvPropertySearch::SearchPropertyValue(kUnixCharsets,
+ ArrayLength(kUnixCharsets), locale, oResult))) {
+ return NS_OK;
+ }
+ }
+ NS_ERROR("unable to convert locale to charset using deprecated config");
+ oResult.AssignLiteral("ISO-8859-1");
+ return NS_SUCCESS_USING_FALLBACK_LOCALE;
+}
+
+nsPlatformCharset::~nsPlatformCharset()
+{
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::GetCharset(nsPlatformCharsetSel selector, nsACString& oResult)
+{
+ oResult = mCharset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACString &oResult)
+{
+ //
+ // if this locale is the user's locale then use the charset
+ // we already determined at initialization
+ //
+ if (mLocale.Equals(localeName) ||
+ // support the 4.x behavior
+ (mLocale.LowerCaseEqualsLiteral("en_us") &&
+ localeName.LowerCaseEqualsLiteral("c"))) {
+ oResult = mCharset;
+ return NS_OK;
+ }
+
+#if HAVE_LANGINFO_CODESET
+ //
+ // This locale appears to be a different locale from the user's locale.
+ // To do this we would need to lock the global resource we are currently
+ // using or use a library that provides multi locale support.
+ // ICU is a possible example of a multi locale library.
+ // http://oss.software.ibm.com/icu/
+ //
+ // A more common cause of hitting this warning than the above is that
+ // Mozilla is launched under an ll_CC.UTF-8 locale. In xpLocale,
+ // we only store the language and the region (ll-CC) losing 'UTF-8', which
+ // leads |mLocale| to be different from |localeName|. Although we lose
+ // 'UTF-8', we init'd |mCharset| with the value obtained via
+ // |nl_langinfo(CODESET)| so that we're all right here.
+ //
+ NS_WARNING("GetDefaultCharsetForLocale: need to add multi locale support");
+#ifdef DEBUG_jungshik
+ printf("localeName=%s mCharset=%s\n", NS_ConvertUTF16toUTF8(localeName).get(),
+ mCharset.get());
+#endif
+ // until we add multi locale support: use the the charset of the user's locale
+ oResult = mCharset;
+ return NS_SUCCESS_USING_FALLBACK_LOCALE;
+#else
+ //
+ // convert from locale to charset
+ // using the deprecated locale to charset mapping
+ //
+ NS_LossyConvertUTF16toASCII localeStr(localeName);
+ return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oResult);
+#endif
+}
+
+nsresult
+nsPlatformCharset::InitGetCharset(nsACString &oString)
+{
+#if HAVE_LANGINFO_CODESET
+ char* nl_langinfo_codeset = nullptr;
+ nsCString aCharset;
+ nsresult res;
+
+ nl_langinfo_codeset = nl_langinfo(CODESET);
+ NS_ASSERTION(nl_langinfo_codeset, "cannot get nl_langinfo(CODESET)");
+
+ //
+ // see if we can use nl_langinfo(CODESET) directly
+ //
+ if (nl_langinfo_codeset) {
+ aCharset.Assign(nl_langinfo_codeset);
+ res = VerifyCharset(aCharset);
+ if (NS_SUCCEEDED(res)) {
+ oString = aCharset;
+ return res;
+ }
+ }
+
+ NS_ERROR("unable to use nl_langinfo(CODESET)");
+#endif
+
+ //
+ // try falling back on a deprecated (locale based) name
+ //
+ char* locale = setlocale(LC_CTYPE, nullptr);
+ nsAutoCString localeStr;
+ localeStr.Assign(locale);
+ return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
+}
+
+NS_IMETHODIMP
+nsPlatformCharset::Init()
+{
+ //
+ // remember default locale so we can use the
+ // same charset when asked for the same locale
+ //
+ char* locale = setlocale(LC_CTYPE, nullptr);
+ NS_ASSERTION(locale, "cannot setlocale");
+ if (locale) {
+ CopyASCIItoUTF16(locale, mLocale);
+ } else {
+ mLocale.AssignLiteral("en_US");
+ }
+
+ // InitGetCharset only returns NS_OK or NS_SUCESS_USING_FALLBACK_LOCALE
+ return InitGetCharset(mCharset);
+}
+
+nsresult
+nsPlatformCharset::VerifyCharset(nsCString &aCharset)
+{
+ // fast path for UTF-8. Most platform uses UTF-8 as charset now.
+ if (aCharset.EqualsLiteral("UTF-8")) {
+ return NS_OK;
+ }
+
+ nsAutoCString encoding;
+ if (!EncodingUtils::FindEncodingForLabelNoReplacement(aCharset, encoding)) {
+ return NS_ERROR_UCONV_NOCONV;
+ }
+
+ aCharset.Assign(encoding);
+ return NS_OK;
+}
diff --git a/intl/locale/unix/unixcharset.properties b/intl/locale/unix/unixcharset.properties
new file mode 100644
index 000000000..1376b49d6
--- /dev/null
+++ b/intl/locale/unix/unixcharset.properties
@@ -0,0 +1,536 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+##
+## NOTE: THIS FILE IS DEPRECATED
+## except for those *nix systems that do not support
+## nl_langinfo(CODESET) this file should not be used
+##
+## All platform section
+## Put the general locale to charset mapping here.
+## If somehow two platform use the same locale name with different
+## charset, put the least common one in the platform specific section
+## This section have lower priority than the platform specific section
+##
+## The key is the locale name
+# AIX
+ar_AA=ISO-8859-6
+# Solaris
+Ar_ARM=ISO-8859-6
+american.iso88591=ISO-8859-1
+bulgarian=ISO-8859-2
+bg_BG.ISO8859-5=ISO-8859-5
+# AIX
+bg_BG=ISO-8859-5
+C=ISO-8859-1
+# HP
+C.iso885915=ISO-8859-15
+c-french.iso88591=ISO-8859-1
+chinese=gb18030
+chinese-s=gb18030
+chinese-t.big5=Big5
+cs=ISO-8859-2
+cs_CZ=ISO-8859-2
+cs_CZ.ISO8859-2=ISO-8859-2
+cs_CZ.88592=ISO-8859-2
+czech=ISO-8859-2
+da=ISO-8859-1
+# Solaris
+da.ISO8859-15=ISO-8859-15
+da_DK.ISO8859-15=ISO-8859-15
+da_DK.ISO8859-15@euro=ISO-8859-15
+# Solaris
+da.ISO8859-15@euro=ISO-8859-15
+da_DK.88591=ISO-8859-1
+# HP
+da_DK.iso885915@euro=ISO-8859-15
+da_DK.ISO8859-1=ISO-8859-1
+da_DK=ISO-8859-1
+# AIX
+#Da_DK=IBM-850
+danish.iso88591=ISO-8859-1
+dutch.iso88591=ISO-8859-1
+de=ISO-8859-1
+# Solaris
+de.ISO8859-15=ISO-8859-15
+# Solaris
+de.ISO8859-15@euro=ISO-8859-15
+# Solaris
+de.UTF-8=UTF-8
+# Solaris
+de.UTF-8@euro=UTF-8
+de_AT=ISO-8859-1
+# Solaris
+de_AT.ISO8859-15=ISO-8859-15
+# Solaris
+de_AT.ISO8859-15@euro=ISO-8859-15
+de_CH=ISO-8859-1
+de_CH.88591=ISO-8859-1
+de_CH.ISO8859-1=ISO-8859-1
+de_DE.ISO8859-15=ISO-8859-15
+de_DE.ISO8859-15@euro=ISO-8859-15
+# AIX
+#De_CH=IBM-850
+de_DE=ISO-8859-1
+de_DE.88591=ISO-8859-1
+# HP
+de_DE.iso885915=ISO-8859-15
+# HP
+de_DE.iso885915@euro=ISO-8859-15
+de_DE.ISO8859-1=ISO-8859-1
+# AIX
+#De_DE=IBM-850
+# Solaris
+el_GR.ISO8859-7=ISO-8859-7
+el_GR.ISO8859-7@euro=ISO-8859-7
+en_AU.ISO8859-1=ISO-8859-1
+en_CA.ISO8859-1=ISO-8859-1
+# AIX
+el_GR=ISO-8859-7
+en=ISO-8859-1
+en_AU=ISO-8859-1
+en_CA=ISO-8859-1
+en_GB=ISO-8859-1
+# Solaris
+en_GB.ISO8859-15=ISO-8859-15
+# Solaris
+en_GB.ISO8859-15@euro=ISO-8859-15
+en_GB.88591=ISO-8859-1
+en_GB.ISO8859-1=ISO-8859-1
+# HP
+en_GB.iso885915@euro=ISO-8859-15
+# AIX
+#En_GB=IBM-850
+# Solaris
+en_IE.ISO8859-1=ISO-8859-1
+en_IE.ISO8859-15=ISO-8859-15
+# Solaris
+en_IE.ISO8859-15@euro=ISO-8859-15
+en_JP=EUC-JP
+en_JP.IBM-eucJP=EUC-JP
+En_JP.IBM-932=Shift_JIS
+En_JP=Shift_JIS
+en_KR=EUC-KR
+en_KR.IBM-eucKR=EUC-KR
+en_TH=ISO-8859-1
+en_US=ISO-8859-1
+en_US.88591=ISO-8859-1
+en_US.ISO8859-1=ISO-8859-1
+#FreeBSD
+en_US.ISO_8859-1=ISO-8859-1
+da_DK.ISO_8859-1=ISO-8859-1
+de_AT.ISO_8859-1=ISO-8859-1
+de_CH.ISO_8859-1=ISO-8859-1
+de_DE.ISO_8859-1=ISO-8859-1
+en_AU.ISO_8859-1=ISO-8859-1
+en_CA.ISO_8859-1=ISO-8859-1
+en_GB.ISO_8859-1=ISO-8859-1
+es_ES.ISO_8859-1=ISO-8859-1
+fi_FI.ISO_8859-1=ISO-8859-1
+fr_BE.ISO_8859-1=ISO-8859-1
+fr_CA.ISO_8859-1=ISO-8859-1
+fr_CH.ISO_8859-1=ISO-8859-1
+fr_FR.ISO_8859-1=ISO-8859-1
+is_IS.ISO_8859-1=ISO-8859-1
+it_CH.ISO_8859-1=ISO-8859-1
+it_IT.ISO_8859-1=ISO-8859-1
+la_LN.ISO_8859-1=ISO-8859-1
+nl_BE.ISO_8859-1=ISO-8859-1
+nl_NL.ISO_8859-1=ISO-8859-1
+no_NO.ISO_8859-1=ISO-8859-1
+pt_PT.ISO_8859-1=ISO-8859-1
+sv_SE.ISO_8859-1=ISO-8859-1
+# FreeBSD 8859-15
+da_DK.DIS_8859-15=ISO-8859-15
+de_AT.DIS_8859-15=ISO-8859-15
+de_CH.DIS_8859-15=ISO-8859-15
+de_DE.DIS_8859-15=ISO-8859-15
+en_AU.DIS_8859-15=ISO-8859-15
+en_CA.DIS_8859-15=ISO-8859-15
+en_GB.DIS_8859-15=ISO-8859-15
+en_US.DIS_8859-15=ISO-8859-15
+es_ES.DIS_8859-15=ISO-8859-15
+fi_FI.DIS_8859-15=ISO-8859-15
+fr_BE.DIS_8859-15=ISO-8859-15
+fr_CA.DIS_8859-15=ISO-8859-15
+fr_CH.DIS_8859-15=ISO-8859-15
+fr_FR.DIS_8859-15=ISO-8859-15
+is_IS.DIS_8859-15=ISO-8859-15
+it_CH.DIS_8859-15=ISO-8859-15
+it_IT.DIS_8859-15=ISO-8859-15
+la_LN.DIS_8859-15=ISO-8859-15
+nl_BE.DIS_8859-15=ISO-8859-15
+nl_NL.DIS_8859-15=ISO-8859-15
+no_NO.DIS_8859-15=ISO-8859-15
+pt_PT.DIS_8859-15=ISO-8859-15
+sv_SE.DIS_8859-15=ISO-8859-15
+# FreeBSD 8859-2
+cs_CZ.ISO_8859-2=ISO-8859-2
+hr_HR.ISO_8859-2=ISO-8859-2
+hu_HU.ISO_8859-2=ISO-8859-2
+la_LN.ISO_8859-2=ISO-8859-2
+pl_PL.ISO_8859-2=ISO-8859-2
+sl_SI.ISO_8859-2=ISO-8859-2
+# FreeBSD 8859-4
+la_LN.ISO_8859-4=ISO-8859-4
+lt_LT.ISO_8859-4=ISO-8859-4
+# FreeBSD 8859-5
+ru_RU.ISO_8859-5=ISO-8859-5
+ru_SU.ISO_8859-5=ISO-8859-5
+# FreeBSD Russian
+ru_SU.KOI8-R=KOI8-R
+# FreeBSD Ukrainian
+uk_UA.KOI8-U=KOI8-U
+# Solaris
+en_US.UTF-8=UTF-8
+# Solaris
+en_US.UTF-8@euro=UTF-8
+# AIX
+#En_US=IBM-850
+english.iso88591=ISO-8859-1
+es=ISO-8859-1
+# Solaris
+es.ISO8859-15=ISO-8859-15
+# Solaris
+es.ISO8859-15@euro=ISO-8859-15
+# Solaris
+es.UTF-8=UTF-8
+# Solaris
+es.UTF-8@euro=UTF-8
+es_ES=ISO-8859-1
+es_ES.ISO8859-15=ISO-8859-15
+es_ES.ISO8859-15@euro=ISO-8859-15
+es_AR.ISO8859-1=ISO-8859-1
+es_BO.ISO8859-1=ISO-8859-1
+es_CL.ISO8859-1=ISO-8859-1
+es_CO.ISO8859-1=ISO-8859-1
+es_CR.ISO8859-1=ISO-8859-1
+es_EC.ISO8859-1=ISO-8859-1
+es_GT.ISO8859-1=ISO-8859-1
+es_MX.ISO8859-1=ISO-8859-1
+es_NI.ISO8859-1=ISO-8859-1
+es_PA.ISO8859-1=ISO-8859-1
+es_PE.ISO8859-1=ISO-8859-1
+es_PY.ISO8859-1=ISO-8859-1
+es_SV.ISO8859-1=ISO-8859-1
+es_UY.ISO8859-1=ISO-8859-1
+es_VE.ISO8859-1=ISO-8859-1
+# HP
+es_ES.iso885915=ISO-8859-15
+# HP
+es_ES.iso885915@euro=ISO-8859-15
+es_ES.88591=ISO-8859-1
+es_ES.ISO8859-1=ISO-8859-1
+# AIX
+#En_ES=IBM-850
+# Solaris
+et_EE.ISO8859-15=ISO-8859-15
+# AIX
+#Et_ET=IBM-922
+# AIX
+ET_ET=UTF-8
+fi=ISO-8859-1
+# Solaris
+fi.ISO8859-15=ISO-8859-15
+# Solaris
+fi.ISO8859-15@euro=ISO-8859-15
+fi_FI=ISO-8859-1
+fi_FI.88591=ISO-8859-1
+fi_FI.ISO8859-1=ISO-8859-1
+fi_FI.ISO8859-15=ISO-8859-15
+fi_FI.ISO8859-15@euro=ISO-8859-15
+# HP
+fi_FI.iso885915@euro=ISO-8859-15
+# AIX
+#Fi_ES=IBM-850
+finnish.iso88591=ISO-8859-1
+fr=ISO-8859-1
+# Solaris
+fr.ISO8859-15=ISO-8859-15
+# Solaris
+fr.ISO8859-15@euro=ISO-8859-15
+# Solaris
+fr.UTF-8=UTF-8
+# Solaris
+fr.UTF-8@euro=UTF-8
+fr_BE=ISO-8859-1
+# Solaris
+fr_BE.ISO8859-15=ISO-8859-15
+# Solaris
+fr_BE.ISO8859-15@euro=ISO-8859-15
+fr_BE.88591=ISO-8859-1
+fr_BE.ISO8859-1=ISO-8859-1
+fr_BE.iso8859=ISO-8859-1
+# AIX
+#Fr_BE=IBM-850
+fr_CA=ISO-8859-1
+fr_CA.88591=ISO-8859-1
+fr_CA.iso8859=ISO-8859-1
+# HP
+fr_CA.iso885915@euro=ISO-8859-15
+fr_CA.ISO8859-1=ISO-8859-1
+# AIX
+#Fr_CA=IBM-850
+fr_CH=ISO-8859-1
+fr_CH.88591=ISO-8859-1
+fr_CH.iso8859=ISO-8859-1
+fr_CH.ISO8859-1=ISO-8859-1
+# Solaris
+fr_FR.ISO8859-15=ISO-8859-15
+fr_FR.ISO8859-15@euro=ISO-8859-15
+# AIX
+#Fr_CH=IBM-850
+fr_FR=ISO-8859-1
+fr_FR.88591=ISO-8859-1
+fr_FR.iso8859=ISO-8859-1
+# HP
+fr_FR.iso885915=ISO-8859-15
+# HP
+fr_FR.iso885915@euro=ISO-8859-15
+fr_FR.ISO8859-1=ISO-8859-1
+# AIX
+#Fr_FR=IBM-850
+french.iso88591=ISO-8859-1
+german.iso88591=ISO-8859-1
+# Solaris
+he_HE=ISO-8859-8
+he_IL=ISO-8859-8
+hr_HR.ISO8859-2=ISO-8859-2
+# AIX
+hr_HR=ISO-8859-2
+hu_HU=ISO-8859-2
+hu_HU.88592=ISO-8859-2
+hu_HU.ISO8859-2=ISO-8859-2
+hungarian=ISO-8859-2
+icelandic.iso88591=ISO-8859-1
+iso_8859_1=ISO-8859-1
+is=ISO-8859-1
+is_IS=ISO-8859-1
+is_IS.88591=ISO-8859-1
+is_IS.ISO8859-1=ISO-8859-1
+# HP
+is_IS.iso885915@euro=ISO-8859-15
+# AIX
+#Is_IS=IBM-850
+it=ISO-8859-1
+# Solaris
+it.ISO8859-15=ISO-8859-15
+# Solaris
+it.ISO8859-15@euro=ISO-8859-15
+# Solaris
+it.UTF-8=UTF-8
+# Solaris
+it.UTF-8@euro=UTF-8
+it_IT.ISO8859-15=ISO-8859-15
+it_IT.ISO8859-15@euro=ISO-8859-15
+# AIX
+#It_IT=IBM-850
+italian.iso8859-1=ISO-8859-1
+it_CH=ISO-8859-1
+it_IT=ISO-8859-1
+it_IT.88591=ISO-8859-1
+it_IT.ISO8859-1=ISO-8859-1
+# HP
+it_IT.iso885915=ISO-8859-15
+# HP
+it_IT.iso885915@euro=ISO-8859-15
+# AIX
+iw_IL=ISO-8859-8
+# AIX
+#Iw_IL=IBM-856
+ja=EUC-JP
+Ja_JP.IBM-932=Shift_JIS
+Ja_JP=Shift_JIS
+japanese=EUC-JP
+japanese.euc=EUC-JP
+ja_JP=EUC-JP
+# Solaris
+ja_JP.UTF-8=UTF-8
+# Solaris
+ja_JP.UTF-8@euro=UTF-8
+ja_JP.EUC=EUC-JP
+ja_JP.eucJP=EUC-JP
+ja_JP.SJIS=Shift_JIS
+ja_JP.PCK=Shift_JIS
+ja_JP.IBM-eucJP=EUC-JP
+ja_JP.mscode=Shift_JIS
+ja_JP.ujis=EUC-JP
+katakana=Shift_JIS
+ko=EUC-KR
+ko_KR=EUC-KR
+# Solaris
+ko_KR.UTF-8=UTF-8
+# Solaris
+ko_KR.UTF-8@euro=UTF-8
+ko_KR.euc=EUC-KR
+ko_KR.euckr=EUC-KR
+ko_KR.eucKR=EUC-KR
+ko_KR.IBM-eucKR=EUC-KR
+ko_KR.EUC=EUC-KR
+ko.UTF-8=UTF-8
+korean=EUC-KR
+# Solaris
+lt_LT.ISO8859-13=ISO-8859-13
+# AIX
+#Lt_LT=IBM-921
+# AIX
+LT_LT=UTF-8
+# Solaris
+lv_LV.ISO8859-13=ISO-8859-13
+# AIX
+#Lt_LV=IBM-921
+# AIX
+LT_LV=UTF-8
+# Solaris
+mk_MK.ISO8859-5=ISO-8859-5
+# AIX
+mk_MK=ISO-8859-5
+nl=ISO-8859-1
+# Solaris
+nl.ISO8859-15=ISO-8859-15
+# Solaris
+nl.ISO8859-15@euro=ISO-8859-15
+nl_BE=ISO-8859-1
+# Solaris
+nl_BE.ISO8859-15=ISO-8859-15
+# Solaris
+nl_BE.ISO8859-15@euro=ISO-8859-15
+nl_BE.88591=ISO-8859-1
+nl_BE.ISO8859-1=ISO-8859-1
+# Solaris
+nl_NL.ISO8859-15=ISO-8859-15
+nl_NL.ISO8859-15@euro=ISO-8859-15
+# AIX
+#NL_BE=IBM-850
+nl_NL=ISO-8859-1
+nl_NL.88591=ISO-8859-1
+nl_NL.ISO8859-1=ISO-8859-1
+# HP
+nl_NL.iso885915@euro=ISO-8859-15
+# AIX
+#NL_NL=IBM-850
+no=ISO-8859-1
+no_NO=ISO-8859-1
+no_NO.88591=ISO-8859-1
+no_NO.ISO8859-1=ISO-8859-1
+# Solaris
+no_NO.ISO8859-1@bokmal=ISO-8859-1
+no_NO.ISO8859-1@nynorsk=ISO-8859-1
+# HP
+no_NO.iso885915@euro=ISO-8859-15
+# AIX
+#No_NO=IBM-850
+norwegian.iso88591=ISO-8859-1
+pl=ISO-8859-2
+pl_PL=ISO-8859-2
+pl_PL.88592=ISO-8859-2
+pl_PL.ISO8859-2=ISO-8859-2
+polish=ISO-8859-2
+portuguese.iso88591=ISO-8859-1
+pt=ISO-8859-1
+# Solaris
+pt.ISO8859-15=ISO-8859-15
+# Solaris
+pt.ISO8859-15@euro=ISO-8859-15
+# Solaris
+pt_BR.ISO8859-1=ISO-8859-1
+pt_PT.ISO8859-15=ISO-8859-15
+pt_PT.ISO8859-15@euro=ISO-8859-15
+# AIX
+#Pt.PT=IBM-850
+pt_PT=ISO-8859-1
+pt_PT.88591=ISO-8859-1
+# HP
+pt_PT.iso885915@euro=ISO-8859-15
+pt_PT.ISO8859-1=ISO-8859-1
+# Solaris
+ro_RO.ISO8859-2=ISO-8859-2
+# AIX
+ro_RO=ISO-8859-5
+# Solaris
+#ru_RU.ANSI1251= ??? ANSI-1251 ???
+ru_RU.ISO8859-5=ISO-8859-5
+# AIX
+ru_RU=ISO-8859-5
+ru_RU.KOI8-R=KOI8-R
+# RedHat 7 reported by Garaschenko Slava <slava@maze.ambernet.kiev.ua bug 70601
+ru_RU.koi8r=KOI8-R
+# RedHat 7 reported by Garaschenko Slava <slava@maze.ambernet.kiev.ua bug 70601
+ru_UA=KOI8-U
+rumanian=ISO-8859-2
+serbocroatian=ISO-8859-2
+sh=ISO-8859-2
+# Solaris
+sh_BA.ISO8859-2@bosnia=ISO-8859-2
+sl_SI.ISO8859-2=ISO-8859-2
+sq_AL.ISO8859-2=ISO-8859-2
+# AIX
+sh_SP=ISO-8859-2
+sk=ISO-8859-2
+sk_SK=ISO-8859-2
+sk_SK.88592=ISO-8859-2
+sk_SK.ISO8859-2=ISO-8859-2
+slovene=ISO-8859-2
+spanish.iso88591=ISO-8859-1
+# AIX
+sq_AL=ISO-8859-1
+# Solaris
+sr_YU.ISO8859-5=ISO-8859-5
+# AIX
+sr_SP=ISO-8859-5
+sv=ISO-8859-1
+# Solaris
+sv.ISO8859-15=ISO-8859-15
+# Solaris
+sv.ISO8859-15@euro=ISO-8859-15
+# Solaris
+sv.UTF-8=UTF-8
+# Solaris
+sv.UTF-8@euro=UTF-8
+sv_SE=ISO-8859-1
+sv_SE.88591=ISO-8859-1
+sv_SE.ISO8859-15=ISO-8859-15
+sv_SE.ISO8859-15@euro=ISO-8859-15
+# HP
+sv_SE.iso885915=ISO-8859-15
+# HP
+sv_SE.iso885915@euro=ISO-8859-15
+sv_SE.ISO8859-1=ISO-8859-1
+# AIX
+swedish.iso88591=ISO-8859-1
+# Solaris
+tr_TR.ISO8859-9=windows-1254
+# AIX
+tr_TR=windows-1254
+# Solaris
+th_TH=windows-874
+th_TH.TIS620=windows-874
+th=windows-874
+th_TH.UTF-8=UTF-8
+# RedHat 7 reported by Garaschenko Slava <slava@maze.ambernet.kiev.ua bug 70601
+uk_UA=KOI8-U
+zh=gb18030
+zh_CN=gb18030
+zh_CN.EUC=gb18030
+zh.GBK=gbk
+zh_CN.UTF-8=UTF-8
+zh.UTF-8=UTF-8
+zh_TW.BIG5=Big5
+# saw the following name from news://xcin.linux.org.tw/tlug.cle-devel
+zh_CN.gb18030=gb18030
+# AIX
+ZH_CN=UTF-8
+zh_CN.ugb=gb18030
+zh_CN.GBK=gbk
+zh_HK.big5=Big5
+zh_TW.big5=Big5
+zh_TW.big5@chuyin=Big5
+zh_TW.big5@radical=Big5
+zh_TW.big5@stroke=Big5
+# AIX
+Zh_TW.big5=Big5
+# CLE 0.8
+zh_TW.Big5=Big5
+# SunOS 5.7 according to pofeng@linux.org.tw (already above)
+# zh_TW.BIG5=Big5