* reintegrated posix-locale

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37725 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe
2010-07-23 23:13:00 +00:00
parent b891b0acae
commit a3f665982e
297 changed files with 5900 additions and 46769 deletions
+1 -1
View File
@@ -87,7 +87,7 @@ SYSTEM_LIBS =
libmail.so libmedia.so libmidi.so libmidi2.so
libnetwork.so
libpng.so
<revisioned>libroot.so
<revisioned>libroot.so libroot-addon-icu.so
libscreensaver.so
libtextencoding.so libtiff.so libtracker.so libtranslation.so
libz.so
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright 2010, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _LANGINFO_H_
#define _LANGINFO_H_
#include <locale.h>
#include <nl_types.h>
#include <sys/cdefs.h>
enum {
CODESET, /* codeset name */
D_T_FMT, /* string for formatting date and time */
D_FMT, /* date format string */
T_FMT, /* time format string */
T_FMT_AMPM, /* a.m. or p.m. time formatting string */
AM_STR, /* Ante Meridian affix */
PM_STR, /* Post Meridian affix */
/* week day names */
DAY_1,
DAY_2,
DAY_3,
DAY_4,
DAY_5,
DAY_6,
DAY_7,
/* abbreviated week day names */
ABDAY_1,
ABDAY_2,
ABDAY_3,
ABDAY_4,
ABDAY_5,
ABDAY_6,
ABDAY_7,
/* month names */
MON_1,
MON_2,
MON_3,
MON_4,
MON_5,
MON_6,
MON_7,
MON_8,
MON_9,
MON_10,
MON_11,
MON_12,
/* abbreviated month names */
ABMON_1,
ABMON_2,
ABMON_3,
ABMON_4,
ABMON_5,
ABMON_6,
ABMON_7,
ABMON_8,
ABMON_9,
ABMON_10,
ABMON_11,
ABMON_12,
ERA, /* era description segments */
ERA_D_FMT, /* era date format string */
ERA_D_T_FMT, /* era date and time format string */
ERA_T_FMT, /* era time format string */
ALT_DIGITS, /* alternative symbols for digits */
RADIXCHAR, /* radix char */
THOUSEP, /* separator for thousands */
YESEXPR, /* affirmative response expression */
NOEXPR, /* negative response expression */
CRNCYSTR, /* currency symbol */
_NL_LANGINFO_LAST
};
__BEGIN_DECLS
extern char* nl_langinfo(nl_item item);
__END_DECLS
#endif /* _LANGINFO_H_ */
+11
View File
@@ -25,6 +25,12 @@ struct lconv {
char n_sep_by_space;
char p_sign_posn;
char n_sign_posn;
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;
};
#define LC_ALL 0
@@ -34,6 +40,11 @@ struct lconv {
#define LC_NUMERIC 4
#define LC_TIME 5
#define LC_MESSAGES 6
/*
* the values above must be kept in loopable order (i.e. strictly increasing
* with no holes) and in sync with the value below
*/
#define LC_LAST LC_MESSAGES
#ifdef __cplusplus
extern "C" {
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2010, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _MONETARY_H_
#define _MONETARY_H_
#include <locale.h>
#include <stddef.h>
#include <sys/cdefs.h>
#include <sys/types.h>
__BEGIN_DECLS
extern ssize_t strfmon(char* s, size_t maxsize, const char* format, ...);
__END_DECLS
#endif /* _MONETARY_H_ */
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright 2010, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _NL_TYPES_H_
#define _NL_TYPES_H_
#include <sys/cdefs.h>
#define NL_SETD 0
#define NL_CAT_LOCALE 1
typedef int nl_item;
typedef void* nl_catd;
__BEGIN_DECLS
extern nl_catd catopen(const char *name, int oflag);
extern char* catgets(nl_catd cat, int setID, int msgID,
const char *defaultMessage);
extern int catclose(nl_catd cat);
__END_DECLS
#endif /* _NL_TYPES_H_ */
+6
View File
@@ -36,6 +36,12 @@ typedef struct {
#define WCHAR_MIN 0x00000000UL
#define WCHAR_MAX 0x7FFFFFFFUL
/*
* Haiku is always using UTF32 in wchars, other encodings can be handled
* by converting to/from wchar by means of mbsrtowcs() or wcsrtombs().
* TODO: define __STDC_ISO_10646__ accordingly in our compilers.
*/
#ifdef __cplusplus
extern "C" {
+2 -2
View File
@@ -8,7 +8,7 @@
#include <wchar.h>
typedef const int *wctrans_t;
typedef int wctrans_t;
#ifdef __cplusplus
extern "C" {
@@ -28,7 +28,7 @@ extern int iswupper(wint_t wc);
extern int iswxdigit(wint_t wc);
extern int iswctype(wint_t wc, wctype_t charClass);
extern wint_t towctrans(wint_t wc, wctrans_t charClass);
extern wint_t towctrans(wint_t wc, wctrans_t transition);
extern wint_t towlower(wint_t wc);
extern wint_t towupper(wint_t wc);
@@ -0,0 +1,53 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_CATEGORY_DATA_H
#define _ICU_CATEGORY_DATA_H
#include <unicode/locid.h>
#include <unicode/ucnv.h>
#include <unicode/unistr.h>
#include <SupportDefs.h>
namespace BPrivate {
class ICUCategoryData {
public:
ICUCategoryData();
virtual ~ICUCategoryData();
virtual status_t SetTo(const Locale& locale,
const char* posixLocaleName);
virtual status_t SetToPosix();
const char * PosixLocaleName()
{ return fPosixLocaleName; }
protected:
status_t _ConvertUnicodeStringToLocaleconvEntry(
const UnicodeString& string,
char* destination, int destinationSize,
const char* defaultValue = "");
static const uint16 skMaxPosixLocaleNameLen = 128;
static const size_t skLCBufSize = 16;
Locale fLocale;
UConverter* fConverter;
char fPosixLocaleName[skMaxPosixLocaleNameLen];
char fGivenCharset[UCNV_MAX_CONVERTER_NAME_LENGTH];
private:
status_t _SetupConverter();
};
} // namespace BPrivate
#endif // _ICU_CATEGORY_DATA_H
@@ -0,0 +1,43 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_COLLATE_DATA_H
#define _ICU_COLLATE_DATA_H
#include "ICUCategoryData.h"
#include <unicode/coll.h>
namespace BPrivate {
class ICUCollateData : public ICUCategoryData {
typedef ICUCategoryData inherited;
public:
ICUCollateData();
virtual ~ICUCollateData();
virtual status_t SetTo(const Locale& locale,
const char* posixLocaleName);
virtual status_t SetToPosix();
status_t Strcoll(const char* a, const char* b, int& out);
status_t Strxfrm(char* out, const char* in, size_t size,
size_t& outSize);
private:
status_t _ToUnicodeString(const char* in,
UnicodeString& out);
Collator* fCollator;
};
} // namespace BPrivate
#endif // _ICU_COLLATE_DATA_H
@@ -0,0 +1,46 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_CTYPE_DATA_H
#define _ICU_CTYPE_DATA_H
#include "ICUCategoryData.h"
#include "LocaleBackend.h"
namespace BPrivate {
class ICUCtypeData : public ICUCategoryData {
typedef ICUCategoryData inherited;
public:
ICUCtypeData();
virtual ~ICUCtypeData();
void Initialize(LocaleCtypeDataBridge* dataBridge);
virtual status_t SetTo(const Locale& locale,
const char* posixLocaleName);
virtual status_t SetToPosix();
int IsWCType(wint_t wc, wctype_t charClass);
status_t ToWCTrans(wint_t wc, wctrans_t transition,
wint_t& result);
const char* GetLanginfo(int index);
private:
unsigned short fClassInfo[256];
int fToLowerMap[256];
int fToUpperMap[256];
LocaleCtypeDataBridge* fDataBridge;
};
} // namespace BPrivate
#endif // _ICU_CTYPE_DATA_H
@@ -0,0 +1,74 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_LOCALE_BACKEND_H
#define _ICU_LOCALE_BACKEND_H
#include "LocaleBackend.h"
#include <locale.h>
#include <timelocal.h>
#include "ICUCollateData.h"
#include "ICUCtypeData.h"
#include "ICUMessagesData.h"
#include "ICUMonetaryData.h"
#include "ICUNumericData.h"
#include "ICUTimeData.h"
namespace BPrivate {
class ICULocaleBackend : public LocaleBackend {
public:
ICULocaleBackend();
virtual ~ICULocaleBackend();
virtual void Initialize(LocaleDataBridge* dataBridge);
virtual const char* SetLocale(int category,
const char* posixLocaleName);
virtual const struct lconv* LocaleConv();
virtual const struct lc_time_t* LCTimeInfo();
virtual int IsWCType(wint_t wc, wctype_t charClass);
virtual status_t ToWCTrans(wint_t wc, wctrans_t transition,
wint_t& result);
virtual const char* GetLanginfo(int index);
virtual status_t Strcoll(const char* a, const char* b, int& out);
virtual status_t Strxfrm(char* out, const char* in, size_t size,
size_t& outSize);
private:
const char* _QueryLocale(int category);
const char* _SetPosixLocale(int category);
// buffer for locale names (up to one per category)
char fLocaleDescription[512];
// data containers
struct lconv fLocaleConv;
struct lc_time_t fLCTimeInfo;
// these work on the data containers above
ICUCollateData fCollateData;
ICUCtypeData fCtypeData;
ICUMessagesData fMessagesData;
ICUMonetaryData fMonetaryData;
ICUNumericData fNumericData;
ICUTimeData fTimeData;
// static posix langinfo data
const char** fPosixLanginfo;
};
} // namespace BPrivate
#endif // _ICU_LOCALE_BACKEND_H
@@ -0,0 +1,33 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_LOCALECONV_DATA_H
#define _ICU_LOCALECONV_DATA_H
#include "ICUCategoryData.h"
#include <unicode/decimfmt.h>
namespace BPrivate {
typedef DecimalFormatSymbols::ENumberFormatSymbol FormatSymbol;
class ICULocaleconvData : public ICUCategoryData {
typedef ICUCategoryData inherited;
protected:
status_t _SetLocaleconvEntry(
const DecimalFormatSymbols* formatSymbols,
char* destination, FormatSymbol symbol,
const char* defaultValue = "");
};
} // namespace BPrivate
#endif // _ICU_LOCALECONV_DATA_H
@@ -0,0 +1,39 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_MESSAGES_DATA_H
#define _ICU_MESSAGES_DATA_H
#include "ICUCategoryData.h"
#include "LocaleBackend.h"
namespace BPrivate {
class ICUMessagesData : public ICUCategoryData {
typedef ICUCategoryData inherited;
public:
virtual status_t SetTo(const Locale& locale,
const char* posixLocaleName);
virtual status_t SetToPosix();
void Initialize(
LocaleMessagesDataBridge* dataBridge);
const char* GetLanginfo(int index);
private:
char fYesExpression[80];
char fNoExpression[80];
const char** fPosixLanginfo;
};
} // namespace BPrivate
#endif // _ICU_MESSAGES_DATA_H
@@ -0,0 +1,69 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_MONETARY_DATA_H
#define _ICU_MONETARY_DATA_H
#include "ICULocaleconvData.h"
#include "LocaleBackend.h"
#include <locale.h>
namespace BPrivate {
class ICUMonetaryData : public ICULocaleconvData {
typedef ICULocaleconvData inherited;
public:
static const int32 kParenthesesAroundCurrencyAndValue = 0;
static const int32 kSignPrecedesCurrencyAndValue = 1;
static const int32 kSignSucceedsCurrencyAndValue = 2;
static const int32 kSignImmediatelyPrecedesCurrency = 3;
static const int32 kSignImmediatelySucceedsCurrency = 4;
ICUMonetaryData(struct lconv& localeConv);
void Initialize(
LocaleMonetaryDataBridge* dataBridge);
virtual status_t SetTo(const Locale& locale,
const char* posixLocaleName);
virtual status_t SetToPosix();
const char* GetLanginfo(int index);
private:
static const int32 kCsPrecedesFlag = 1 << 0;
static const int32 kSepBySpaceFlag = 1 << 1;
int32 _DetermineCurrencyPosAndSeparator(
const UnicodeString& prefix,
const UnicodeString& suffix,
const UnicodeString& signSymbol,
const UnicodeString& currencySymbol,
UChar& currencySeparatorChar);
int32 _DetermineSignPos(const UnicodeString& prefix,
const UnicodeString& suffix,
const UnicodeString& signSymbol,
const UnicodeString& currencySymbol);
char fDecimalPoint[skLCBufSize];
char fThousandsSep[skLCBufSize];
char fGrouping[skLCBufSize];
char fIntCurrSymbol[skLCBufSize];
char fCurrencySymbol[skLCBufSize];
char fPositiveSign[skLCBufSize];
char fNegativeSign[skLCBufSize];
struct lconv& fLocaleConv;
const struct lconv* fPosixLocaleConv;
};
} // namespace BPrivate
#endif // _ICU_MONETARY_DATA_H
@@ -0,0 +1,43 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_NUMERIC_DATA_H
#define _ICU_NUMERIC_DATA_H
#include "ICULocaleconvData.h"
#include "LocaleBackend.h"
namespace BPrivate {
class ICUNumericData : public ICULocaleconvData {
typedef ICULocaleconvData inherited;
public:
ICUNumericData(struct lconv& localeConv);
void Initialize(LocaleNumericDataBridge* dataBridge);
virtual status_t SetTo(const Locale& locale,
const char* posixLocaleName);
virtual status_t SetToPosix();
virtual const char* GetLanginfo(int index);
private:
char fDecimalPoint[skLCBufSize];
char fThousandsSep[skLCBufSize];
char fGrouping[skLCBufSize];
struct lconv& fLocaleConv;
LocaleNumericDataBridge* fDataBridge;
};
} // namespace BPrivate
#endif // _ICU_NUMERIC_DATA_H
@@ -0,0 +1,62 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _ICU_TIME_DATA_H
#define _ICU_TIME_DATA_H
#include "ICUCategoryData.h"
#include "LocaleBackend.h"
#include <unicode/datefmt.h>
#include <timelocal.h>
namespace BPrivate {
class ICUTimeData : public ICUCategoryData {
typedef ICUCategoryData inherited;
public:
ICUTimeData(struct lc_time_t& lcTimeInfo);
void Initialize(LocaleTimeDataBridge* dataBridge);
virtual status_t SetTo(const Locale& locale,
const char* posixLocaleName);
virtual status_t SetToPosix();
const char* GetLanginfo(int index);
private:
status_t _SetLCTimeEntries(const UnicodeString* strings,
char* destination, int entrySize,
int count, int maxCount);
status_t _SetLCTimePattern(DateFormat* format,
char* destination, int destinationSize);
char fMon[12][24];
char fMonth[12][64];
char fWday[7][24];
char fWeekday[7][64];
char fTimeFormat[24];
char fDateFormat[24];
char fDateTimeFormat[32];
char fAm[24];
char fPm[24];
char fDateTimeZoneFormat[32];
char fAltMonth[12][64];
char fMonthDayOrder[4];
char fAmPmFormat[32];
struct lc_time_t& fLCTimeInfo;
const struct lc_time_t* fPosixLCTimeInfo;
};
} // namespace BPrivate
#endif // _ICU_TIME_DATA_H
@@ -0,0 +1,111 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _LOCALE_BACKEND_H
#define _LOCALE_BACKEND_H
#include <SupportDefs.h>
#include <wctype.h>
struct lconv;
struct lc_time_t;
namespace BPrivate {
struct LocaleCtypeDataBridge {
const unsigned short** addrOfClassInfoTable;
const int** addrOfToLowerTable;
const int** addrOfToUpperTable;
const unsigned short* posixClassInfo;
const int* posixToLowerMap;
const int* posixToUpperMap;
LocaleCtypeDataBridge();
};
struct LocaleMessagesDataBridge {
const char** posixLanginfo;
LocaleMessagesDataBridge();
};
struct LocaleMonetaryDataBridge {
const struct lconv* posixLocaleConv;
LocaleMonetaryDataBridge();
};
struct LocaleNumericDataBridge {
const char** addrOfGlibcDecimalPoint;
const char** addrOfGlibcThousandsSep;
const char** addrOfGlibcGrouping;
uint32_t* addrOfGlibcWCDecimalPoint;
uint32_t* addrOfGlibcWCThousandsSep;
const struct lconv* posixLocaleConv;
LocaleNumericDataBridge();
};
struct LocaleTimeDataBridge {
const struct lc_time_t* posixLCTimeInfo;
LocaleTimeDataBridge();
};
struct LocaleDataBridge {
LocaleCtypeDataBridge ctypeDataBridge;
LocaleMessagesDataBridge messagesDataBridge;
LocaleMonetaryDataBridge monetaryDataBridge;
LocaleNumericDataBridge numericDataBridge;
LocaleTimeDataBridge timeDataBridge;
const char** posixLanginfo;
LocaleDataBridge();
};
class LocaleBackend {
public:
LocaleBackend();
virtual ~LocaleBackend();
virtual const char* SetLocale(int category, const char* locale) = 0;
virtual const struct lconv* LocaleConv() = 0;
virtual const struct lc_time_t* LCTimeInfo() = 0;
virtual int IsWCType(wint_t wc, wctype_t charClass) = 0;
virtual status_t ToWCTrans(wint_t wc, wctrans_t transition,
wint_t& result) = 0;
virtual const char* GetLanginfo(int index) = 0;
virtual status_t Strcoll(const char* a, const char* b,
int& out) = 0;
virtual status_t Strxfrm(char* out, const char* in, size_t size,
size_t& outSize) = 0;
virtual void Initialize(LocaleDataBridge* dataBridge) = 0;
static status_t LoadBackend();
};
extern LocaleBackend* gLocaleBackend;
} // namespace BPrivate
#endif // _LOCALE_BACKEND_H
@@ -0,0 +1,20 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _POSIX_CTYPE_H
#define _POSIX_CTYPE_H
namespace BPrivate {
extern const unsigned short gPosixClassInfo[256];
extern const int gPosixToLowerMap[256];
extern const int gPosixToUpperMap[256];
} // namespace BPrivate
#endif // _POSIX_CTYPE_H
@@ -0,0 +1,18 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _POSIX_LANGINFO_H
#define _POSIX_LANGINFO_H
namespace BPrivate {
extern const char* gPosixLanginfo[];
} // namespace BPrivate
#endif // _POSIX_LANGINFO_H
@@ -0,0 +1,21 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _POSIX_LOCALE_CONV_H
#define _POSIX_LOCALE_CONV_H
#include <locale.h>
namespace BPrivate {
extern struct lconv gPosixLocaleConv;
} // namespace BPrivate
#endif // _POSIX_LOCALE_CONV_H
@@ -0,0 +1,21 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _POSIX_LC_TIME_INFO_H
#define _POSIX_LC_TIME_INFO_H
#include <timelocal.h>
namespace BPrivate {
extern const struct lc_time_t gPosixLCTimeInfo;
} // namespace BPrivate
#endif // _POSIX_LC_TIME_INFO_H
@@ -25,31 +25,36 @@
*
* $FreeBSD: /repoman/r/ncvs/src/lib/libc/stdtime/timelocal.h,v 1.11 2002/01/24 15:07:44 phantom Exp $
*/
#ifndef _TIMELOCAL_H_
#define _TIMELOCAL_H_
#include <sys/cdefs.h>
/*
* Private header file for the strftime and strptime localization
* stuff.
*/
struct lc_time_T {
const char *mon[12];
const char *month[12];
const char *wday[7];
const char *weekday[7];
const char *X_fmt;
const char *x_fmt;
const char *c_fmt;
const char *am;
const char *pm;
const char *date_fmt;
const char *alt_month[12];
const char *md_order;
const char *ampm_fmt;
struct lc_time_t {
const char* mon[12];
const char* month[12];
const char* wday[7];
const char* weekday[7];
const char* X_fmt;
const char* x_fmt;
const char* c_fmt;
const char* am;
const char* pm;
const char* date_fmt;
const char* alt_month[12];
const char* md_order;
const char* ampm_fmt;
};
struct lc_time_T *__get_current_time_locale(void);
int __time_load_locale(const char *);
__BEGIN_DECLS
const struct lc_time_t* __get_current_time_locale(void);
__END_DECLS
#endif /* !_TIMELOCAL_H_ */
-84
View File
@@ -1,84 +0,0 @@
#ifndef _LANGINFO_H_
#define _LANGINFO_H_
#include <LocaleStrings.h>
#include <nl_types.h>
#define CODESET B_CODESET /* codeset name */
#define D_T_FMT B_DATE_TIME_FORMAT /* string for formatting date and time */
#define D_FMT B_DATE_FORMAT /* date format string */
#define T_FMT B_TIME_FORMAT /* time format string */
#define T_FMT_AMPM B_AM_PM_TIME_FORMAT /* a.m. or p.m. time formatting string */
#define AM_STR B_AM_STRING /* Ante Meridian affix */
#define PM_STR B_PM_STRING /* Post Meridian affix */
/* week day names */
#define DAY_1 B_DAY_1
#define DAY_2 B_DAY_2
#define DAY_3 B_DAY_3
#define DAY_4 B_DAY_4
#define DAY_5 B_DAY_5
#define DAY_6 B_DAY_6
#define DAY_7 B_DAY_7
/* abbreviated week day names */
#define ABDAY_1 B_AB_DAY_1
#define ABDAY_2 B_AB_DAY_2
#define ABDAY_3 B_AB_DAY_3
#define ABDAY_4 B_AB_DAY_4
#define ABDAY_5 B_AB_DAY_5
#define ABDAY_6 B_AB_DAY_6
#define ABDAY_7 B_AB_DAY_7
/* month names */
#define MON_1 B_MON_1
#define MON_2 B_MON_2
#define MON_3 B_MON_3
#define MON_4 B_MON_4
#define MON_5 B_MON_5
#define MON_6 B_MON_6
#define MON_7 B_MON_7
#define MON_8 B_MON_8
#define MON_9 B_MON_9
#define MON_10 B_MON_10
#define MON_11 B_MON_11
#define MON_12 B_MON_12
/* abbreviated month names */
#define ABMON_1 B_AB_MON_1
#define ABMON_2 B_AB_MON_2
#define ABMON_3 B_AB_MON_3
#define ABMON_4 B_AB_MON_4
#define ABMON_5 B_AB_MON_5
#define ABMON_6 B_AB_MON_6
#define ABMON_7 B_AB_MON_7
#define ABMON_8 B_AB_MON_8
#define ABMON_9 B_AB_MON_9
#define ABMON_10 B_AB_MON_10
#define ABMON_11 B_AB_MON_11
#define ABMON_12 B_AB_MON_12
#define ERA B_ERA /* era description segments */
#define ERA_D_FMT B_ERA_DATE_FORMAT /* era date format string */
#define ERA_D_T_FMT B_ERA_DATE_TIME_FORMAT /* era date and time format string */
#define ERA_T_FMT B_TIME_FORMAT /* era time format string */
#define ALT_DIGITS B_ALT_DIGITS /* alternative symbols for digits */
#define RADIXCHAR B_DECIMAL_POINT /* radix char */
#define THOUSEP B_THOUSANDS_SEPARATOR /* separator for thousands */
#define YESEXPR B_YES_EXPRESSION /* affirmative response expression */
#define NOEXPR B_NO_EXPRESSION /* negative response expression */
#define YESSTR B_YES_STRING /* affirmative response for yes/no queries */
#define NOSTR B_NO_STRING /* negative response for yes/no queries */
#define CRNCYSTR B_CURRENCY_SYMBOL /* currency symbol */
//#define D_MD_ORDER 57 /* month/day order (local extension) */
#ifdef __cplusplus
extern "C"
#endif
char *nl_langinfo(nl_item);
#endif /* _LANGINFO_H_ */
-17
View File
@@ -1,17 +0,0 @@
#ifndef _MONETARY_H_
#define _MONETARY_H_
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
ssize_t strfmon(char *string, size_t maxSize, const char *format, ...);
ssize_t vstrfmon(char *string, size_t maxSize, const char *format, va_list args);
#ifdef __cplusplus
}
#endif
#endif /* _MONETARY_H_ */
-26
View File
@@ -1,26 +0,0 @@
/*
* Distributed under the terms of the MIT License.
*/
#ifndef _NL_TYPES_H_
#define _NL_TYPES_H_
#define NL_SETD 0
#define NL_CAT_LOCALE 1
typedef int nl_item;
typedef void *nl_catd;
#ifdef __cplusplus
extern "C" {
#endif
extern nl_catd catopen(const char *name, int oflag);
extern char *catgets(nl_catd cat, int setID, int msgID, const char *defaultMessage);
extern int catclose(nl_catd cat);
#ifdef __cplusplus
}
#endif
#endif /* _NL_TYPES_H_ */
+1
View File
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src system boot ;
local librootFunctions =
abs.o
ctype.o
LocaleData.o
qsort.o
kernel_vsprintf.o
memcmp.o
+4 -2
View File
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src system kernel lib ;
UsePrivateHeaders shared ;
UsePrivateHeaders [ FDirName libroot locale ] ;
# kernel libroot os files
@@ -41,8 +42,9 @@ KernelMergeObject kernel_lib_posix.o :
poll.c
utime.c
# locale
ctype.c
localeconv.c
ctype.cpp
localeconv.cpp
LocaleData.cpp
# stdio (this subdir)
kernel_vsprintf.cpp
# stdlib
+1 -1
View File
@@ -30,7 +30,6 @@ local librootObjects =
posix_gnu_stdlib.o
posix_gnu_string.o
posix_gnu_wcsmbs.o
posix_gnu_wctype.o
posix_stdlib.o
posix_string.o
posix_string_arch_$(TARGET_ARCH).o
@@ -92,5 +91,6 @@ if $(TARGET_PLATFORM) = haiku {
}
SubInclude HAIKU_TOP src system libroot add-ons ;
SubInclude HAIKU_TOP src system libroot os ;
SubInclude HAIKU_TOP src system libroot posix ;
+3
View File
@@ -0,0 +1,3 @@
SubDir HAIKU_TOP src system libroot add-ons ;
SubInclude HAIKU_TOP src system libroot add-ons icu ;
+14
View File
@@ -0,0 +1,14 @@
SubDir HAIKU_TOP src system libroot add-ons icu ;
local addonIcuObjects =
addon_icu_locale.o
;
SharedLibrary libroot-addon-icu.so
:
:
$(addonIcuObjects:G=nogrist)
$(TARGET_LIBSTDC++) $(HAIKU_ICU_LIBS)
;
SubInclude HAIKU_TOP src system libroot add-ons icu locale ;
@@ -0,0 +1,133 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICUCategoryData.h"
#include <string.h>
#include <unicode/uchar.h>
namespace BPrivate {
ICUCategoryData::ICUCategoryData()
:
fConverter(NULL)
{
*fPosixLocaleName = '\0';
*fGivenCharset = '\0';
}
ICUCategoryData::~ICUCategoryData()
{
if (fConverter)
ucnv_close(fConverter);
}
status_t
ICUCategoryData::_SetupConverter()
{
if (fConverter != NULL) {
ucnv_close(fConverter);
fConverter = NULL;
}
UErrorCode icuStatus = U_ZERO_ERROR;
fConverter = ucnv_open(fGivenCharset, &icuStatus);
if (fConverter == NULL)
return B_NAME_NOT_FOUND;
icuStatus = U_ZERO_ERROR;
ucnv_setToUCallBack(fConverter, UCNV_TO_U_CALLBACK_STOP, NULL, NULL,
NULL, &icuStatus);
icuStatus = U_ZERO_ERROR;
ucnv_setFromUCallBack(fConverter, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL,
NULL, &icuStatus);
if (!U_SUCCESS(icuStatus))
return B_ERROR;
return B_OK;
}
status_t
ICUCategoryData::SetTo(const Locale& locale, const char* posixLocaleName)
{
if (!posixLocaleName)
return B_BAD_VALUE;
fLocale = locale;
strlcpy(fPosixLocaleName, posixLocaleName, skMaxPosixLocaleNameLen);
*fGivenCharset = '\0';
// POSIX locales often contain an embedded charset, but ICU does not
// handle these within locales (that part of the name is simply
// ignored).
// We need to fetch the charset specification and lookup an appropriate
// ICU charset converter. This converter will later be used to get info
// about ctype properties.
const char* charsetStart = strchr(fPosixLocaleName, '.');
if (charsetStart) {
++charsetStart;
int l = 0;
while (charsetStart[l] != '\0' && charsetStart[l] != '@')
++l;
snprintf(fGivenCharset, UCNV_MAX_CONVERTER_NAME_LENGTH, "%.*s", l,
charsetStart);
}
if (!strlen(fGivenCharset))
strcpy(fGivenCharset, "utf-8");
return _SetupConverter();
}
status_t
ICUCategoryData::SetToPosix()
{
fLocale = Locale::createFromName("en_US_POSIX");
strcpy(fPosixLocaleName, "POSIX");
strcpy(fGivenCharset, "US-ASCII");
return _SetupConverter();
}
status_t
ICUCategoryData::_ConvertUnicodeStringToLocaleconvEntry(
const UnicodeString& string, char* destination, int destinationSize,
const char* defaultValue)
{
status_t result = B_OK;
UErrorCode icuStatus = U_ZERO_ERROR;
ucnv_fromUChars(fConverter, destination, destinationSize,
string.getBuffer(), string.length(), &icuStatus);
if (!U_SUCCESS(icuStatus)) {
switch (icuStatus) {
case U_BUFFER_OVERFLOW_ERROR:
result = B_NAME_TOO_LONG;
break;
case U_INVALID_CHAR_FOUND:
case U_TRUNCATED_CHAR_FOUND:
case U_ILLEGAL_CHAR_FOUND:
result = B_BAD_DATA;
break;
default:
result = B_ERROR;
break;
}
strcpy(destination, defaultValue);
}
return result;
}
} // namespace BPrivate
@@ -0,0 +1,176 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICUCollateData.h"
#include <string.h>
#include <unicode/unistr.h>
namespace BPrivate {
ICUCollateData::ICUCollateData()
:
fCollator(NULL)
{
}
ICUCollateData::~ICUCollateData()
{
delete fCollator;
}
status_t
ICUCollateData::SetTo(const Locale& locale, const char* posixLocaleName)
{
status_t result = inherited::SetTo(locale, posixLocaleName);
if (result == B_OK) {
UErrorCode icuStatus = U_ZERO_ERROR;
delete fCollator;
fCollator = Collator::createInstance(fLocale, icuStatus);
if (!U_SUCCESS(icuStatus))
return B_NO_MEMORY;
}
return result;
}
status_t
ICUCollateData::SetToPosix()
{
status_t result = inherited::SetToPosix();
if (result == B_OK) {
delete fCollator;
fCollator = NULL;
}
return result;
}
status_t
ICUCollateData::Strcoll(const char* a, const char* b, int& result)
{
if (strcmp(fPosixLocaleName, "POSIX") == 0) {
// handle POSIX here as the collator ICU uses for that (english) is
// incompatible in too many ways
result = strcmp(a, b);
for (const char* aIter = a; *aIter != 0; ++aIter) {
if (*aIter < 0)
return B_BAD_VALUE;
}
for (const char* bIter = b; *bIter != 0; ++bIter) {
if (*bIter < 0)
return B_BAD_VALUE;
}
return B_OK;
}
status_t status = B_OK;
UErrorCode icuStatus = U_ZERO_ERROR;
if (strcasecmp(fGivenCharset, "utf-8") == 0) {
UCharIterator aIter, bIter;
uiter_setUTF8(&aIter, a, -1);
uiter_setUTF8(&bIter, b, -1);
result = fCollator->compare(aIter, bIter, icuStatus);
} else {
UnicodeString unicodeA;
UnicodeString unicodeB;
if (_ToUnicodeString(a, unicodeA) != B_OK
|| _ToUnicodeString(b, unicodeB) != B_OK) {
status = B_BAD_VALUE;
}
result = fCollator->compare(unicodeA, unicodeB, icuStatus);
}
if (!U_SUCCESS(icuStatus))
status = B_BAD_VALUE;
return status;
}
status_t
ICUCollateData::Strxfrm(char* out, const char* in, size_t size, size_t& outSize)
{
if (strcmp(fPosixLocaleName, "POSIX") == 0) {
// handle POSIX here as the collator ICU uses for that (english) is
// incompatible in too many ways
outSize = strlcpy(out, in, size);
for (const char* inIter = in; *inIter != 0; ++inIter) {
if (*inIter < 0)
return B_BAD_VALUE;
}
return B_OK;
}
if (in == NULL) {
outSize = 0;
return B_OK;
}
UErrorCode icuStatus = U_ZERO_ERROR;
UnicodeString unicodeIn;
if (_ToUnicodeString(in, unicodeIn) != B_OK)
return B_BAD_VALUE;
outSize = fCollator->getSortKey(unicodeIn, (uint8_t*)out, size);
if (!U_SUCCESS(icuStatus))
return B_BAD_VALUE;
return B_OK;
}
status_t
ICUCollateData::_ToUnicodeString(const char* in, UnicodeString& out)
{
out.remove();
if (in == NULL)
return B_OK;
size_t inLen = strlen(in);
if (inLen == 0)
return B_OK;
UErrorCode icuStatus = U_ZERO_ERROR;
int32_t outLen = ucnv_toUChars(fConverter, NULL, 0, in, inLen, &icuStatus);
if (icuStatus != U_BUFFER_OVERFLOW_ERROR)
return B_BAD_VALUE;
if (outLen < 0)
return B_ERROR;
if (outLen == 0)
return B_OK;
UChar* outBuf = out.getBuffer(outLen + 1);
icuStatus = U_ZERO_ERROR;
outLen
= ucnv_toUChars(fConverter, outBuf, outLen + 1, in, inLen, &icuStatus);
if (!U_SUCCESS(icuStatus)) {
out.releaseBuffer(0);
return B_BAD_VALUE;
}
out.releaseBuffer(outLen);
return B_OK;
}
} // namespace BPrivate
@@ -0,0 +1,186 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICUCtypeData.h"
#include <langinfo.h>
#include <string.h>
#include <unicode/uchar.h>
namespace BPrivate {
ICUCtypeData::ICUCtypeData()
:
fDataBridge(NULL)
{
}
ICUCtypeData::~ICUCtypeData()
{
}
void
ICUCtypeData::Initialize(LocaleCtypeDataBridge* dataBridge)
{
*dataBridge->addrOfClassInfoTable = fClassInfo;
*dataBridge->addrOfToLowerTable = fToLowerMap;
*dataBridge->addrOfToUpperTable = fToUpperMap;
fDataBridge = dataBridge;
}
status_t
ICUCtypeData::SetTo(const Locale& locale, const char* posixLocaleName)
{
status_t result = inherited::SetTo(locale, posixLocaleName);
if (result != B_OK)
return result;
UErrorCode icuStatus = U_ZERO_ERROR;
ucnv_reset(fConverter);
char buffer[] = { 0, 0 };
for (int i = 0; i < 256; ++i) {
const char* source = buffer;
buffer[0] = (char)i;
buffer[1] = '\0';
icuStatus = U_ZERO_ERROR;
UChar32 unicodeChar
= ucnv_getNextUChar(fConverter, &source, source + 1, &icuStatus);
unsigned short classInfo = 0;
unsigned int toLower = i;
unsigned int toUpper = i;
if (U_SUCCESS(icuStatus)) {
if (u_isblank(unicodeChar))
classInfo |= _ISblank;
if (u_charType(unicodeChar) == U_CONTROL_CHAR)
classInfo |= _IScntrl;
if (u_ispunct(unicodeChar))
classInfo |= _ISpunct;
if (u_hasBinaryProperty(unicodeChar, UCHAR_POSIX_ALNUM))
classInfo |= _ISalnum;
if (u_isUUppercase(unicodeChar))
classInfo |= _ISupper;
if (u_isULowercase(unicodeChar))
classInfo |= _ISlower;
if (u_isUAlphabetic(unicodeChar))
classInfo |= _ISalpha;
if (u_isdigit(unicodeChar))
classInfo |= _ISdigit;
if (u_isxdigit(unicodeChar))
classInfo |= _ISxdigit;
if (u_isUWhiteSpace(unicodeChar))
classInfo |= _ISspace;
if (u_hasBinaryProperty(unicodeChar, UCHAR_POSIX_PRINT))
classInfo |= _ISprint;
if (u_hasBinaryProperty(unicodeChar, UCHAR_POSIX_GRAPH))
classInfo |= _ISgraph;
UChar lowerChar = u_tolower(unicodeChar);
icuStatus = U_ZERO_ERROR;
ucnv_fromUChars(fConverter, buffer, 1, &lowerChar, 1, &icuStatus);
if (U_SUCCESS(icuStatus))
toLower = (unsigned char)buffer[0];
UChar upperChar = u_toupper(unicodeChar);
icuStatus = U_ZERO_ERROR;
ucnv_fromUChars(fConverter, buffer, 1, &upperChar, 1, &icuStatus);
if (U_SUCCESS(icuStatus))
toUpper = (unsigned char)buffer[0];
}
fClassInfo[i] = classInfo;
fToLowerMap[i] = toLower;
fToUpperMap[i] = toUpper;
}
return B_OK;
}
status_t
ICUCtypeData::SetToPosix()
{
status_t result = inherited::SetToPosix();
if (result == B_OK) {
memcpy(fClassInfo, fDataBridge->posixClassInfo, sizeof(fClassInfo));
memcpy(fToLowerMap, fDataBridge->posixToLowerMap, sizeof(fToLowerMap));
memcpy(fToUpperMap, fDataBridge->posixToUpperMap, sizeof(fToUpperMap));
}
return result;
}
int
ICUCtypeData::IsWCType(wint_t wc, wctype_t charClass)
{
switch (charClass) {
case _ISalnum:
return u_hasBinaryProperty(wc, UCHAR_POSIX_ALNUM);
case _ISalpha:
return u_isUAlphabetic(wc);
case _ISblank:
return u_isblank(wc);
case _IScntrl:
return u_charType(wc) == U_CONTROL_CHAR;
case _ISdigit:
return u_isdigit(wc);
case _ISgraph:
return u_hasBinaryProperty(wc, UCHAR_POSIX_GRAPH);
case _ISlower:
return u_isULowercase(wc);
case _ISprint:
return u_hasBinaryProperty(wc, UCHAR_POSIX_PRINT);
case _ISpunct:
return u_ispunct(wc);
case _ISspace:
return u_isUWhiteSpace(wc);
case _ISupper:
return u_isUUppercase(wc);
case _ISxdigit:
return u_isxdigit(wc);
default:
return 0;
}
}
status_t
ICUCtypeData::ToWCTrans(wint_t wc, wctrans_t transition, wint_t& result)
{
switch (transition) {
case _ISlower:
result = u_tolower(wc);
return B_OK;
case _ISupper:
result = u_toupper(wc);
return B_OK;
default:
return B_BAD_VALUE;
}
}
const char*
ICUCtypeData::GetLanginfo(int index)
{
switch(index) {
case CODESET:
return fGivenCharset;
default:
return "";
}
}
} // namespace BPrivate
@@ -0,0 +1,319 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICULocaleBackend.h"
#include <new>
#include <langinfo.h>
#include <locale.h>
#include <string.h>
namespace BPrivate {
extern "C" LocaleBackend*
CreateInstance()
{
return new(std::nothrow) ICULocaleBackend();
}
ICULocaleBackend::ICULocaleBackend()
:
fMonetaryData(fLocaleConv),
fNumericData(fLocaleConv),
fTimeData(fLCTimeInfo)
{
}
ICULocaleBackend::~ICULocaleBackend()
{
}
void
ICULocaleBackend::Initialize(LocaleDataBridge* dataBridge)
{
fCtypeData.Initialize(&dataBridge->ctypeDataBridge);
fMessagesData.Initialize(&dataBridge->messagesDataBridge);
fMonetaryData.Initialize(&dataBridge->monetaryDataBridge);
fNumericData.Initialize(&dataBridge->numericDataBridge);
fTimeData.Initialize(&dataBridge->timeDataBridge);
fPosixLanginfo = dataBridge->posixLanginfo;
_SetPosixLocale(LC_ALL);
}
const char*
ICULocaleBackend::SetLocale(int category, const char* posixLocaleName)
{
if (posixLocaleName == NULL)
return _QueryLocale(category);
if (strcasecmp(posixLocaleName, "POSIX") == 0
|| strcasecmp(posixLocaleName, "C") == 0)
return _SetPosixLocale(category);
Locale locale = Locale::createCanonical(posixLocaleName);
switch (category) {
case LC_ALL:
if (fCollateData.SetTo(locale, posixLocaleName) != B_OK
|| fCtypeData.SetTo(locale, posixLocaleName) != B_OK
|| fMessagesData.SetTo(locale, posixLocaleName) != B_OK
|| fMonetaryData.SetTo(locale, posixLocaleName) != B_OK
|| fNumericData.SetTo(locale, posixLocaleName) != B_OK
|| fTimeData.SetTo(locale, posixLocaleName) != B_OK)
return NULL;
break;
case LC_COLLATE:
if (fCollateData.SetTo(locale, posixLocaleName) != B_OK)
return NULL;
break;
case LC_CTYPE:
if (fCtypeData.SetTo(locale, posixLocaleName) != B_OK)
return NULL;
break;
case LC_MESSAGES:
if (fMessagesData.SetTo(locale, posixLocaleName) != B_OK)
return NULL;
break;
case LC_MONETARY:
if (fMonetaryData.SetTo(locale, posixLocaleName) != B_OK)
return NULL;
break;
case LC_NUMERIC:
if (fNumericData.SetTo(locale, posixLocaleName) != B_OK)
return NULL;
break;
case LC_TIME:
if (fTimeData.SetTo(locale, posixLocaleName) != B_OK)
return NULL;
break;
default:
// unsupported category
return NULL;
}
return posixLocaleName;
}
const struct lconv*
ICULocaleBackend::LocaleConv()
{
return &fLocaleConv;
}
const struct lc_time_t*
ICULocaleBackend::LCTimeInfo()
{
return &fLCTimeInfo;
}
int
ICULocaleBackend::IsWCType(wint_t wc, wctype_t charClass)
{
return fCtypeData.IsWCType(wc, charClass);
}
status_t
ICULocaleBackend::ToWCTrans(wint_t wc, wctrans_t transition, wint_t& result)
{
return fCtypeData.ToWCTrans(wc, transition, result);
}
const char*
ICULocaleBackend::GetLanginfo(int index)
{
switch(index) {
case CODESET:
return fCtypeData.GetLanginfo(index);
case D_T_FMT:
case D_FMT:
case T_FMT:
case T_FMT_AMPM:
case AM_STR:
case PM_STR:
case DAY_1:
case DAY_2:
case DAY_3:
case DAY_4:
case DAY_5:
case DAY_6:
case DAY_7:
case ABDAY_1:
case ABDAY_2:
case ABDAY_3:
case ABDAY_4:
case ABDAY_5:
case ABDAY_6:
case ABDAY_7:
case MON_1:
case MON_2:
case MON_3:
case MON_4:
case MON_5:
case MON_6:
case MON_7:
case MON_8:
case MON_9:
case MON_10:
case MON_11:
case MON_12:
case ABMON_1:
case ABMON_2:
case ABMON_3:
case ABMON_4:
case ABMON_5:
case ABMON_6:
case ABMON_7:
case ABMON_8:
case ABMON_9:
case ABMON_10:
case ABMON_11:
case ABMON_12:
return fTimeData.GetLanginfo(index);
case ERA:
case ERA_D_FMT:
case ERA_D_T_FMT:
case ERA_T_FMT:
case ALT_DIGITS:
return fPosixLanginfo[index];
case RADIXCHAR:
case THOUSEP:
return fNumericData.GetLanginfo(index);
case YESEXPR:
case NOEXPR:
return fMessagesData.GetLanginfo(index);
case CRNCYSTR:
return fMonetaryData.GetLanginfo(index);
default:
return "";
}
}
status_t
ICULocaleBackend::Strcoll(const char* a, const char* b, int& result)
{
return fCollateData.Strcoll(a, b, result);
}
status_t
ICULocaleBackend::Strxfrm(char* out, const char* in, size_t size,
size_t& outSize)
{
return fCollateData.Strxfrm(out, in, size, outSize);
}
const char*
ICULocaleBackend::_QueryLocale(int category)
{
switch (category) {
case LC_ALL:
{
// if all categories have the same locale, return that
const char* locale = fCollateData.PosixLocaleName();
if (strcmp(locale, fCtypeData.PosixLocaleName()) == 0
&& strcmp(locale, fMessagesData.PosixLocaleName()) == 0
&& strcmp(locale, fMonetaryData.PosixLocaleName()) == 0
&& strcmp(locale, fNumericData.PosixLocaleName()) == 0
&& strcmp(locale, fTimeData.PosixLocaleName()) == 0)
return locale;
// build a string with all info (at least glibc does it, too)
snprintf(fLocaleDescription, sizeof(fLocaleDescription),
"LC_COLLATE=%s;LC_CTYPE=%s;LC_MESSAGES=%s;LC_MONETARY=%s;"
"LC_NUMERIC=%s;LC_TIME=%s",
fCollateData.PosixLocaleName(), fCtypeData.PosixLocaleName(),
fMessagesData.PosixLocaleName(),
fMonetaryData.PosixLocaleName(), fNumericData.PosixLocaleName(),
fTimeData.PosixLocaleName());
return fLocaleDescription;
}
case LC_COLLATE:
return fCollateData.PosixLocaleName();
case LC_CTYPE:
return fCtypeData.PosixLocaleName();
case LC_MESSAGES:
return fMessagesData.PosixLocaleName();
case LC_MONETARY:
return fMonetaryData.PosixLocaleName();
case LC_NUMERIC:
return fNumericData.PosixLocaleName();
case LC_TIME:
return fTimeData.PosixLocaleName();
default:
// unsupported category
return NULL;
}
}
const char*
ICULocaleBackend::_SetPosixLocale(int category)
{
switch (category) {
case LC_ALL:
if (fCollateData.SetToPosix() != B_OK
|| fCtypeData.SetToPosix() != B_OK
|| fMessagesData.SetToPosix() != B_OK
|| fMonetaryData.SetToPosix() != B_OK
|| fNumericData.SetToPosix() != B_OK
|| fTimeData.SetToPosix() != B_OK)
return NULL;
break;
case LC_COLLATE:
if (fCollateData.SetToPosix() != B_OK)
return NULL;
break;
case LC_CTYPE:
if (fCtypeData.SetToPosix() != B_OK)
return NULL;
break;
case LC_MESSAGES:
if (fMessagesData.SetToPosix() != B_OK)
return NULL;
break;
case LC_MONETARY:
if (fMonetaryData.SetToPosix() != B_OK)
return NULL;
break;
case LC_NUMERIC:
if (fNumericData.SetToPosix() != B_OK)
return NULL;
break;
case LC_TIME:
if (fTimeData.SetToPosix() != B_OK)
return NULL;
break;
default:
// unsupported category
return NULL;
}
return "POSIX";
}
} // namespace BPrivate
@@ -0,0 +1,32 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICULocaleconvData.h"
#include <string.h>
namespace BPrivate {
status_t
ICULocaleconvData::_SetLocaleconvEntry(const DecimalFormatSymbols* formatSymbols,
char* destination, FormatSymbol symbol, const char* defaultValue)
{
status_t result = B_OK;
UnicodeString symbolString = formatSymbols->getSymbol(symbol);
if (!symbolString.isEmpty()) {
result = _ConvertUnicodeStringToLocaleconvEntry(symbolString,
destination, skLCBufSize, defaultValue);
} else
destination[0] = '\0';
return result;
}
} // namespace BPrivate
@@ -0,0 +1,60 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICUMessagesData.h"
#include <langinfo.h>
#include <string.h>
namespace BPrivate {
void
ICUMessagesData::Initialize(LocaleMessagesDataBridge* dataBridge)
{
fPosixLanginfo = dataBridge->posixLanginfo;
}
status_t
ICUMessagesData::SetTo(const Locale& locale, const char* posixLocaleName)
{
status_t result = inherited::SetTo(locale, posixLocaleName);
// TODO: open the "POSIX" catalog and fetch the translations from there!
return result;
}
status_t
ICUMessagesData::SetToPosix()
{
status_t result = inherited::SetToPosix();
strcpy(fYesExpression, fPosixLanginfo[YESEXPR]);
strcpy(fNoExpression, fPosixLanginfo[NOEXPR]);
return result;
}
const char*
ICUMessagesData::GetLanginfo(int index)
{
switch(index) {
case YESEXPR:
return fYesExpression;
case NOEXPR:
return fNoExpression;
default:
return "";
}
}
} // namespace BPrivate
@@ -0,0 +1,322 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICUMonetaryData.h"
#include <langinfo.h>
#include <limits.h>
#include <strings.h>
namespace BPrivate {
ICUMonetaryData::ICUMonetaryData(struct lconv& localeConv)
:
fLocaleConv(localeConv),
fPosixLocaleConv(NULL)
{
fLocaleConv.int_curr_symbol = fIntCurrSymbol;
fLocaleConv.currency_symbol = fCurrencySymbol;
fLocaleConv.mon_decimal_point = fDecimalPoint;
fLocaleConv.mon_thousands_sep = fThousandsSep;
fLocaleConv.mon_grouping = fGrouping;
fLocaleConv.positive_sign = fPositiveSign;
fLocaleConv.negative_sign = fNegativeSign;
}
void
ICUMonetaryData::Initialize(LocaleMonetaryDataBridge* dataBridge)
{
fPosixLocaleConv = dataBridge->posixLocaleConv;
}
status_t
ICUMonetaryData::SetTo(const Locale& locale, const char* posixLocaleName)
{
status_t result = inherited::SetTo(locale, posixLocaleName);
if (result == B_OK) {
UErrorCode icuStatus = U_ZERO_ERROR;
UChar intlCurrencySeparatorChar = CHAR_MAX;
DecimalFormat* currencyFormat = dynamic_cast<DecimalFormat*>(
NumberFormat::createCurrencyInstance(locale, icuStatus));
if (!U_SUCCESS(icuStatus))
return B_UNSUPPORTED;
if (!currencyFormat)
return B_BAD_TYPE;
const DecimalFormatSymbols* formatSymbols
= currencyFormat->getDecimalFormatSymbols();
if (!formatSymbols)
result = B_BAD_DATA;
if (result == B_OK) {
result = _SetLocaleconvEntry(formatSymbols, fDecimalPoint,
DecimalFormatSymbols::kMonetarySeparatorSymbol);
}
if (result == B_OK) {
result = _SetLocaleconvEntry(formatSymbols, fThousandsSep,
DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
}
if (result == B_OK) {
int32 groupingSize = currencyFormat->getGroupingSize();
if (groupingSize < 1)
fGrouping[0] = '\0';
else {
fGrouping[0] = groupingSize;
int32 secondaryGroupingSize
= currencyFormat->getSecondaryGroupingSize();
if (secondaryGroupingSize < 1)
fGrouping[1] = '\0';
else {
fGrouping[1] = secondaryGroupingSize;
fGrouping[2] = '\0';
}
}
}
if (result == B_OK) {
fLocaleConv.int_frac_digits
= currencyFormat->getMinimumFractionDigits();
fLocaleConv.frac_digits
= currencyFormat->getMinimumFractionDigits();
}
if (result == B_OK) {
UnicodeString positivePrefix, positiveSuffix, negativePrefix,
negativeSuffix;
currencyFormat->getPositivePrefix(positivePrefix);
currencyFormat->getPositiveSuffix(positiveSuffix);
currencyFormat->getNegativePrefix(negativePrefix);
currencyFormat->getNegativeSuffix(negativeSuffix);
UnicodeString currencySymbol = formatSymbols->getSymbol(
DecimalFormatSymbols::kCurrencySymbol);
UnicodeString plusSymbol = formatSymbols->getSymbol(
DecimalFormatSymbols::kPlusSignSymbol);
UnicodeString minusSymbol = formatSymbols->getSymbol(
DecimalFormatSymbols::kMinusSignSymbol);
// fill national values
int32 positiveCurrencyFlags = _DetermineCurrencyPosAndSeparator(
positivePrefix, positiveSuffix, plusSymbol, currencySymbol,
intlCurrencySeparatorChar);
fLocaleConv.p_cs_precedes
= (positiveCurrencyFlags & kCsPrecedesFlag) ? 1 : 0;
fLocaleConv.p_sep_by_space
= (positiveCurrencyFlags & kSepBySpaceFlag) ? 1 : 0;
int32 negativeCurrencyFlags = _DetermineCurrencyPosAndSeparator(
negativePrefix, negativeSuffix, minusSymbol, currencySymbol,
intlCurrencySeparatorChar);
fLocaleConv.n_cs_precedes
= (negativeCurrencyFlags & kCsPrecedesFlag) ? 1 : 0;
fLocaleConv.n_sep_by_space
= (negativeCurrencyFlags & kSepBySpaceFlag) ? 1 : 0;
fLocaleConv.p_sign_posn = _DetermineSignPos(positivePrefix,
positiveSuffix, plusSymbol, currencySymbol);
fLocaleConv.n_sign_posn = _DetermineSignPos(negativePrefix,
negativeSuffix, minusSymbol, currencySymbol);
if (fLocaleConv.p_sign_posn == CHAR_MAX) {
// usually there is no positive sign indicator, so we
// adopt the sign pos of the negative sign symbol
fLocaleConv.p_sign_posn = fLocaleConv.n_sign_posn;
}
// copy national to international values, as ICU does not seem
// to have separate info for those
fLocaleConv.int_p_cs_precedes = fLocaleConv.p_cs_precedes;
fLocaleConv.int_p_sep_by_space = fLocaleConv.p_sep_by_space;
fLocaleConv.int_n_cs_precedes = fLocaleConv.n_cs_precedes;
fLocaleConv.int_n_sep_by_space = fLocaleConv.n_sep_by_space;
fLocaleConv.int_p_sign_posn = fLocaleConv.p_sign_posn;
fLocaleConv.int_n_sign_posn = fLocaleConv.n_sign_posn;
// only set sign symbols if they are actually used in any pattern
if (positivePrefix.indexOf(plusSymbol) > -1
|| positiveSuffix.indexOf(plusSymbol) > -1) {
result = _SetLocaleconvEntry(formatSymbols, fPositiveSign,
DecimalFormatSymbols::kPlusSignSymbol);
} else
fPositiveSign[0] = '\0';
if (negativePrefix.indexOf(minusSymbol) > -1
|| negativeSuffix.indexOf(minusSymbol) > -1) {
result = _SetLocaleconvEntry(formatSymbols, fNegativeSign,
DecimalFormatSymbols::kMinusSignSymbol);
} else
fNegativeSign[0] = '\0';
}
if (result == B_OK) {
UnicodeString intlCurrencySymbol = formatSymbols->getSymbol(
DecimalFormatSymbols::kIntlCurrencySymbol);
if (intlCurrencySeparatorChar != CHAR_MAX)
intlCurrencySymbol += intlCurrencySeparatorChar;
else
intlCurrencySymbol += ' ';
result = _ConvertUnicodeStringToLocaleconvEntry(intlCurrencySymbol,
fIntCurrSymbol, skLCBufSize);
}
if (result == B_OK) {
result = _SetLocaleconvEntry(formatSymbols, fCurrencySymbol,
DecimalFormatSymbols::kCurrencySymbol);
if (fCurrencySymbol[0] == '\0') {
// fall back to the international currency symbol
result = _SetLocaleconvEntry(formatSymbols, fCurrencySymbol,
DecimalFormatSymbols::kIntlCurrencySymbol);
fCurrencySymbol[3] = '\0';
// drop separator char that's contained in int-curr-symbol
}
}
delete currencyFormat;
}
return result;
}
status_t
ICUMonetaryData::SetToPosix()
{
status_t result = inherited::SetToPosix();
if (result == B_OK) {
strcpy(fDecimalPoint, fPosixLocaleConv->mon_decimal_point);
strcpy(fThousandsSep, fPosixLocaleConv->mon_thousands_sep);
strcpy(fGrouping, fPosixLocaleConv->mon_grouping);
strcpy(fCurrencySymbol, fPosixLocaleConv->currency_symbol);
strcpy(fIntCurrSymbol, fPosixLocaleConv->int_curr_symbol);
strcpy(fPositiveSign, fPosixLocaleConv->positive_sign);
strcpy(fNegativeSign, fPosixLocaleConv->negative_sign);
fLocaleConv.int_frac_digits = fPosixLocaleConv->int_frac_digits;
fLocaleConv.frac_digits = fPosixLocaleConv->frac_digits;
fLocaleConv.p_cs_precedes = fPosixLocaleConv->p_cs_precedes;
fLocaleConv.p_sep_by_space = fPosixLocaleConv->p_sep_by_space;
fLocaleConv.n_cs_precedes = fPosixLocaleConv->n_cs_precedes;
fLocaleConv.n_sep_by_space = fPosixLocaleConv->n_sep_by_space;
fLocaleConv.p_sign_posn = fPosixLocaleConv->p_sign_posn;
fLocaleConv.n_sign_posn = fPosixLocaleConv->n_sign_posn;
fLocaleConv.int_p_cs_precedes = fPosixLocaleConv->int_p_cs_precedes;
fLocaleConv.int_p_sep_by_space = fPosixLocaleConv->int_p_sep_by_space;
fLocaleConv.int_n_cs_precedes = fPosixLocaleConv->int_n_cs_precedes;
fLocaleConv.int_n_sep_by_space = fPosixLocaleConv->int_n_sep_by_space;
fLocaleConv.int_p_sign_posn = fPosixLocaleConv->int_p_sign_posn;
fLocaleConv.int_n_sign_posn = fPosixLocaleConv->int_n_sign_posn;
}
return result;
}
const char*
ICUMonetaryData::GetLanginfo(int index)
{
switch(index) {
case CRNCYSTR:
return fCurrencySymbol;
default:
return "";
}
}
int32
ICUMonetaryData::_DetermineCurrencyPosAndSeparator(const UnicodeString& prefix,
const UnicodeString& suffix, const UnicodeString& signSymbol,
const UnicodeString& currencySymbol, UChar& currencySeparatorChar)
{
int32 result = 0;
int32 currencySymbolPos = prefix.indexOf(currencySymbol);
if (currencySymbolPos > -1) {
result |= kCsPrecedesFlag;
int32 signSymbolPos = prefix.indexOf(signSymbol);
// if a char is following the currency symbol, we assume it's
// the separator (usually space), but we need to take care to
// skip over the sign symbol, if found
int32 potentialSeparatorPos
= currencySymbolPos + currencySymbol.length();
if (potentialSeparatorPos == signSymbolPos)
potentialSeparatorPos++;
if (prefix.charAt(potentialSeparatorPos) != 0xFFFF) {
// We can't use the actual separator char since this is usually
// 'c2a0' (non-breakable space), which is not available in the
// ASCII charset used/assumed by POSIX lconv. So we use space
// instead.
currencySeparatorChar = ' ';
result |= kSepBySpaceFlag;
}
} else {
currencySymbolPos = suffix.indexOf(currencySymbol);
if (currencySymbolPos > -1) {
int32 signSymbolPos = suffix.indexOf(signSymbol);
// if a char is preceding the currency symbol, we assume
// it's the separator (usually space), but we need to take
// care to skip the sign symbol, if found
int32 potentialSeparatorPos = currencySymbolPos - 1;
if (potentialSeparatorPos == signSymbolPos)
potentialSeparatorPos--;
if (suffix.charAt(potentialSeparatorPos) != 0xFFFF) {
// We can't use the actual separator char since this is usually
// 'c2a0' (non-breakable space), which is not available in the
// ASCII charset used/assumed by POSIX lconv. So we use space
// instead.
currencySeparatorChar = ' ';
result |= kSepBySpaceFlag;
}
}
}
return result;
}
/*
* This method determines the positive/negative sign position value according to
* the following map (where '$' indicated the currency symbol, '#' the number
* value, and '-' or parantheses the sign symbol):
* ($#) -> 0
* (#$) -> 0
* -$# -> 1
* -#$ -> 1
* $-# -> 4
* $#- -> 2
* #$- -> 2
* #-$ -> 3
*/
int32
ICUMonetaryData::_DetermineSignPos(const UnicodeString& prefix,
const UnicodeString& suffix, const UnicodeString& signSymbol,
const UnicodeString& currencySymbol)
{
if (prefix.indexOf(UnicodeString("(", "")) >= 0
&& suffix.indexOf(UnicodeString(")", "")) >= 0)
return kParenthesesAroundCurrencyAndValue;
UnicodeString value("#", "");
UnicodeString prefixNumberSuffixString = prefix + value + suffix;
int32 signSymbolPos = prefixNumberSuffixString.indexOf(signSymbol);
if (signSymbolPos >= 0) {
int32 valuePos = prefixNumberSuffixString.indexOf(value);
int32 currencySymbolPos
= prefixNumberSuffixString.indexOf(currencySymbol);
if (signSymbolPos < valuePos && signSymbolPos < currencySymbolPos)
return kSignPrecedesCurrencyAndValue;
if (signSymbolPos > valuePos && signSymbolPos > currencySymbolPos)
return kSignSucceedsCurrencyAndValue;
if (signSymbolPos == currencySymbolPos - 1)
return kSignImmediatelyPrecedesCurrency;
if (signSymbolPos == currencySymbolPos + currencySymbol.length())
return kSignImmediatelySucceedsCurrency;
}
return CHAR_MAX;
}
} // namespace BPrivate
@@ -0,0 +1,126 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICUNumericData.h"
#include <langinfo.h>
#include <locale.h>
#include <strings.h>
namespace BPrivate {
ICUNumericData::ICUNumericData(struct lconv& localeConv)
:
fLocaleConv(localeConv),
fDataBridge(NULL)
{
fLocaleConv.decimal_point = fDecimalPoint;
fLocaleConv.thousands_sep = fThousandsSep;
fLocaleConv.grouping = fGrouping;
}
void
ICUNumericData::Initialize(LocaleNumericDataBridge* dataBridge)
{
*dataBridge->addrOfGlibcDecimalPoint = fDecimalPoint;
*dataBridge->addrOfGlibcThousandsSep = fThousandsSep;
*dataBridge->addrOfGlibcGrouping = fGrouping;
fDataBridge = dataBridge;
}
status_t
ICUNumericData::SetTo(const Locale& locale, const char* posixLocaleName)
{
status_t result = inherited::SetTo(locale, posixLocaleName);
if (result == B_OK) {
UErrorCode icuStatus = U_ZERO_ERROR;
DecimalFormat* numberFormat = dynamic_cast<DecimalFormat*>(
NumberFormat::createInstance(locale, DecimalFormat::kNumberStyle,
icuStatus));
if (!U_SUCCESS(icuStatus))
return B_UNSUPPORTED;
if (!numberFormat)
return B_BAD_TYPE;
const DecimalFormatSymbols* formatSymbols
= numberFormat->getDecimalFormatSymbols();
if (!formatSymbols)
result = B_BAD_DATA;
if (result == B_OK) {
result = _SetLocaleconvEntry(formatSymbols, fDecimalPoint,
DecimalFormatSymbols::kDecimalSeparatorSymbol);
*fDataBridge->addrOfGlibcWCDecimalPoint
= (unsigned int)fDecimalPoint[0];
}
if (result == B_OK) {
result = _SetLocaleconvEntry(formatSymbols, fThousandsSep,
DecimalFormatSymbols::kGroupingSeparatorSymbol);
*fDataBridge->addrOfGlibcWCThousandsSep
= (unsigned int)fThousandsSep[0];
}
if (result == B_OK) {
int32 groupingSize = numberFormat->getGroupingSize();
if (groupingSize < 1)
fGrouping[0] = '\0';
else {
fGrouping[0] = groupingSize;
int32 secondaryGroupingSize
= numberFormat->getSecondaryGroupingSize();
if (secondaryGroupingSize < 1)
fGrouping[1] = '\0';
else {
fGrouping[1] = secondaryGroupingSize;
fGrouping[2] = '\0';
}
}
}
delete numberFormat;
}
return result;
}
status_t
ICUNumericData::SetToPosix()
{
status_t result = inherited::SetToPosix();
if (result == B_OK) {
strcpy(fDecimalPoint, fDataBridge->posixLocaleConv->decimal_point);
strcpy(fThousandsSep, fDataBridge->posixLocaleConv->thousands_sep);
strcpy(fGrouping, fDataBridge->posixLocaleConv->grouping);
*fDataBridge->addrOfGlibcWCDecimalPoint
= (unsigned int)fDecimalPoint[0];
*fDataBridge->addrOfGlibcWCThousandsSep
= (unsigned int)fThousandsSep[0];
}
return result;
}
const char*
ICUNumericData::GetLanginfo(int index)
{
switch(index) {
case RADIXCHAR:
return fDecimalPoint;
case THOUSEP:
return fThousandsSep;
default:
return "";
}
}
} // namespace BPrivate
@@ -0,0 +1,400 @@
/*
* Copyright 2010, Oliver Tappe, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "ICUTimeData.h"
#include <langinfo.h>
#include <strings.h>
#include <unicode/dtfmtsym.h>
#include <unicode/smpdtfmt.h>
namespace BPrivate {
ICUTimeData::ICUTimeData(struct lc_time_t& lcTimeInfo)
:
fLCTimeInfo(lcTimeInfo),
fPosixLCTimeInfo(NULL)
{
for (int i = 0; i < 12; ++i) {
fLCTimeInfo.mon[i] = fMon[i];
fLCTimeInfo.month[i] = fMonth[i];
fLCTimeInfo.alt_month[i] = fAltMonth[i];
}
for (int i = 0; i < 7; ++i) {
fLCTimeInfo.wday[i] = fWday[i];
fLCTimeInfo.weekday[i] = fWeekday[i];
}
fLCTimeInfo.X_fmt = fTimeFormat;
fLCTimeInfo.x_fmt = fDateFormat;
fLCTimeInfo.c_fmt = fDateTimeFormat;
fLCTimeInfo.am = fAm;
fLCTimeInfo.pm = fPm;
fLCTimeInfo.date_fmt = fDateTimeZoneFormat;
fLCTimeInfo.md_order = fMonthDayOrder;
fLCTimeInfo.ampm_fmt = fAmPmFormat;
}
void
ICUTimeData::Initialize(LocaleTimeDataBridge* dataBridge)
{
fPosixLCTimeInfo = dataBridge->posixLCTimeInfo;
}
status_t
ICUTimeData::SetTo(const Locale& locale, const char* posixLocaleName)
{
status_t result = inherited::SetTo(locale, posixLocaleName);
if (result != B_OK)
return result;
UErrorCode icuStatus = U_ZERO_ERROR;
DateFormatSymbols formatSymbols(fLocale, icuStatus);
if (!U_SUCCESS(icuStatus))
return B_UNSUPPORTED;
int count = 0;
const UnicodeString* strings = formatSymbols.getShortMonths(count);
result = _SetLCTimeEntries(strings, fMon[0], sizeof(fMon[0]), count, 12);
if (result == B_OK) {
strings = formatSymbols.getMonths(count);
result = _SetLCTimeEntries(strings, fMonth[0], sizeof(fMonth[0]), count,
12);
}
if (result == B_OK) {
strings = formatSymbols.getShortWeekdays(count);
if (count == 8 && strings[0].length() == 0) {
// ICUs weekday arrays are 1-based
strings++;
count = 7;
}
result
= _SetLCTimeEntries(strings, fWday[0], sizeof(fWday[0]), count, 7);
}
if (result == B_OK) {
strings = formatSymbols.getWeekdays(count);
if (count == 8 && strings[0].length() == 0) {
// ICUs weekday arrays are 1-based
strings++;
count = 7;
}
result = _SetLCTimeEntries(strings, fWeekday[0], sizeof(fWeekday[0]),
count, 7);
}
if (result == B_OK) {
try {
DateFormat* format = DateFormat::createTimeInstance(
DateFormat::kDefault, fLocale);
result = _SetLCTimePattern(format, fTimeFormat, sizeof(fTimeFormat));
delete format;
} catch(...) {
result = B_NO_MEMORY;
}
}
if (result == B_OK) {
try {
DateFormat* format = DateFormat::createDateInstance(
DateFormat::kDefault, fLocale);
result = _SetLCTimePattern(format, fDateFormat, sizeof(fDateFormat));
delete format;
} catch(...) {
result = B_NO_MEMORY;
}
}
if (result == B_OK) {
try {
DateFormat* format = DateFormat::createDateTimeInstance(
DateFormat::kFull, DateFormat::kFull, fLocale);
result = _SetLCTimePattern(format, fDateTimeFormat,
sizeof(fDateTimeFormat));
delete format;
} catch(...) {
result = B_NO_MEMORY;
}
}
if (result == B_OK) {
strings = formatSymbols.getAmPmStrings(count);
result = _SetLCTimeEntries(strings, fAm, sizeof(fAm), 1, 1);
if (result == B_OK)
result = _SetLCTimeEntries(&strings[1], fPm, sizeof(fPm), 1, 1);
}
if (result == B_OK) {
strings = formatSymbols.getMonths(count, DateFormatSymbols::STANDALONE,
DateFormatSymbols::WIDE);
result = _SetLCTimeEntries(strings, fAltMonth[0], sizeof(fAltMonth[0]),
count, 12);
}
strcpy(fAmPmFormat, fPosixLCTimeInfo->ampm_fmt);
// ICU does not provide anything for this (and that makes sense, too)
return result;
}
status_t
ICUTimeData::SetToPosix()
{
status_t result = inherited::SetToPosix();
if (result == B_OK) {
for (int i = 0; i < 12; ++i) {
strcpy(fMon[i], fPosixLCTimeInfo->mon[i]);
strcpy(fMonth[i], fPosixLCTimeInfo->month[i]);
strcpy(fAltMonth[i], fPosixLCTimeInfo->alt_month[i]);
}
for (int i = 0; i < 7; ++i) {
strcpy(fWday[i], fPosixLCTimeInfo->wday[i]);
strcpy(fWeekday[i], fPosixLCTimeInfo->weekday[i]);
}
strcpy(fTimeFormat, fPosixLCTimeInfo->X_fmt);
strcpy(fDateFormat, fPosixLCTimeInfo->x_fmt);
strcpy(fDateTimeFormat, fPosixLCTimeInfo->c_fmt);
strcpy(fAm, fPosixLCTimeInfo->am);
strcpy(fPm, fPosixLCTimeInfo->pm);
strcpy(fDateTimeZoneFormat, fPosixLCTimeInfo->date_fmt);
strcpy(fMonthDayOrder, fPosixLCTimeInfo->md_order);
strcpy(fAmPmFormat, fPosixLCTimeInfo->ampm_fmt);
}
return result;
}
const char*
ICUTimeData::GetLanginfo(int index)
{
switch(index) {
case D_T_FMT:
return fDateTimeFormat;
case D_FMT:
return fDateFormat;
case T_FMT:
return fTimeFormat;
case T_FMT_AMPM:
return fAmPmFormat;
case AM_STR:
return fAm;
case PM_STR:
return fPm;
case DAY_1:
case DAY_2:
case DAY_3:
case DAY_4:
case DAY_5:
case DAY_6:
case DAY_7:
return fWeekday[index - DAY_1];
case ABDAY_1:
case ABDAY_2:
case ABDAY_3:
case ABDAY_4:
case ABDAY_5:
case ABDAY_6:
case ABDAY_7:
return fWday[index - ABDAY_1];
case MON_1:
case MON_2:
case MON_3:
case MON_4:
case MON_5:
case MON_6:
case MON_7:
case MON_8:
case MON_9:
case MON_10:
case MON_11:
case MON_12:
return fMonth[index - MON_1];
case ABMON_1:
case ABMON_2:
case ABMON_3:
case ABMON_4:
case ABMON_5:
case ABMON_6:
case ABMON_7:
case ABMON_8:
case ABMON_9:
case ABMON_10:
case ABMON_11:
case ABMON_12:
return fMon[index - ABMON_1];
default:
return "";
}
}
status_t
ICUTimeData::_SetLCTimeEntries(const UnicodeString* strings, char* destination,
int entrySize, int count, int maxCount)
{
if (strings == NULL)
return B_ERROR;
status_t result = B_OK;
if (count > maxCount)
count = maxCount;
for (int32 i = 0; result == B_OK && i < count; ++i) {
result = _ConvertUnicodeStringToLocaleconvEntry(strings[i], destination,
entrySize);
destination += entrySize;
}
return result;
}
status_t
ICUTimeData::_SetLCTimePattern(DateFormat* format, char* destination,
int destinationSize)
{
SimpleDateFormat* simpleFormat = dynamic_cast<SimpleDateFormat*>(format);
if (!simpleFormat)
return B_BAD_TYPE;
// convert ICU-type pattern to posix (i.e. strftime()) format string
UnicodeString icuPattern;
simpleFormat->toPattern(icuPattern);
UnicodeString posixPattern;
if (icuPattern.length() > 0) {
UChar lastCharSeen = 0;
int lastCharCount = 1;
bool inSingleQuotes = false;
bool inDoubleQuotes = false;
// we loop one character past the end on purpose, which will result in a
// final -1 char to be processed, which in turn will let us handle the
// last character (via lastCharSeen)
for (int i = 0; i <= icuPattern.length(); ++i) {
UChar currChar = icuPattern.charAt(i);
if (lastCharSeen != 0 && currChar == lastCharSeen) {
lastCharCount++;
continue;
}
if (!inSingleQuotes && !inDoubleQuotes) {
switch (lastCharSeen) {
case L'a':
posixPattern.append(UnicodeString("%p", ""));
break;
case L'd':
if (lastCharCount == 2)
posixPattern.append(UnicodeString("%d", ""));
else
posixPattern.append(UnicodeString("%e", ""));
break;
case L'D':
posixPattern.append(UnicodeString("%j", ""));
break;
case L'c':
// fall through, to handle 'c' the same as 'e'
case L'e':
if (lastCharCount == 4)
posixPattern.append(UnicodeString("%A", ""));
else if (lastCharCount <= 2)
posixPattern.append(UnicodeString("%u", ""));
else
posixPattern.append(UnicodeString("%a", ""));
break;
case L'E':
if (lastCharCount == 4)
posixPattern.append(UnicodeString("%A", ""));
else
posixPattern.append(UnicodeString("%a", ""));
break;
case L'k':
// fall through, to handle 'k' the same as 'h'
case L'h':
if (lastCharCount == 2)
posixPattern.append(UnicodeString("%I", ""));
else
posixPattern.append(UnicodeString("%l", ""));
break;
case L'H':
if (lastCharCount == 2)
posixPattern.append(UnicodeString("%H", ""));
else
posixPattern.append(UnicodeString("%k", ""));
break;
case L'm':
posixPattern.append(UnicodeString("%M", ""));
break;
case L'L':
// fall through, to handle 'L' the same as 'M'
case L'M':
if (lastCharCount == 4)
posixPattern.append(UnicodeString("%B", ""));
else if (lastCharCount == 3)
posixPattern.append(UnicodeString("%b", ""));
else
posixPattern.append(UnicodeString("%m", ""));
break;
case L's':
posixPattern.append(UnicodeString("%S", ""));
break;
case L'w':
posixPattern.append(UnicodeString("%V", ""));
break;
case L'y':
if (lastCharCount == 2)
posixPattern.append(UnicodeString("%y", ""));
else
posixPattern.append(UnicodeString("%Y", ""));
break;
case L'Y':
posixPattern.append(UnicodeString("%G", ""));
break;
case L'z':
posixPattern.append(UnicodeString("%Z", ""));
break;
case L'Z':
posixPattern.append(UnicodeString("%z", ""));
break;
default:
if (lastCharSeen != 0)
posixPattern.append(lastCharSeen);
}
} else {
if (lastCharSeen != 0)
posixPattern.append(lastCharSeen);
}
if (currChar == L'"') {
inDoubleQuotes = !inDoubleQuotes;
lastCharSeen = 0;
} else if (currChar == L'\'') {
inSingleQuotes = !inSingleQuotes;
lastCharSeen = 0;
} else
lastCharSeen = currChar;
lastCharCount = 1;
}
}
return _ConvertUnicodeStringToLocaleconvEntry(posixPattern, destination,
destinationSize);
}
} // namespace BPrivate
@@ -0,0 +1,23 @@
SubDir HAIKU_TOP src system libroot add-ons icu locale ;
UsePrivateHeaders [ FDirName libroot locale ] ;
UsePrivateHeaders [ FDirName libroot time ] ;
local sources =
ICUCategoryData.cpp
ICUCollateData.cpp
ICUCtypeData.cpp
ICULocaleBackend.cpp
ICULocaleconvData.cpp
ICUMessagesData.cpp
ICUMonetaryData.cpp
ICUNumericData.cpp
ICUTimeData.cpp
;
SubDirSysHdrs $(HAIKU_ICU_HEADERS) ;
Includes [ FGristFiles $(sources) ] : $(HAIKU_ICU_HEADERS_DEPENDENCY) ;
# Dependency needed to trigger downloading/unzipping the package before
# compiling the files.
MergeObject addon_icu_locale.o : $(sources) ;
-1
View File
@@ -12,4 +12,3 @@ SubInclude HAIKU_TOP src system libroot posix glibc stdio-common ;
SubInclude HAIKU_TOP src system libroot posix glibc stdlib ;
SubInclude HAIKU_TOP src system libroot posix glibc string ;
SubInclude HAIKU_TOP src system libroot posix glibc wcsmbs ;
SubInclude HAIKU_TOP src system libroot posix glibc wctype ;
@@ -21,32 +21,11 @@
#include <features.h>
/* The default message set used by the gencat program. */
#define NL_SETD 1
/* Value for FLAG parameter of `catgets' to say we want XPG4 compliance. */
#define NL_CAT_LOCALE 1
__BEGIN_DECLS
/* Message catalog descriptor type. */
typedef void *nl_catd;
/* Type used by `nl_langinfo'. */
typedef int nl_item;
/* Open message catalog for later use, returning descriptor. */
extern nl_catd catopen (__const char *__cat_name, int __flag) __THROW;
/* Return translation with NUMBER in SET of CATALOG; if not found
return STRING. */
extern char *catgets (nl_catd __catalog, int __set, int __number,
__const char *__string) __THROW;
/* Close message CATALOG. */
extern int catclose (nl_catd __catalog) __THROW;
__END_DECLS
#endif /* nl_types.h */
@@ -9,8 +9,5 @@ SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc locale ;
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ;
MergeObject posix_gnu_ctype.o :
ctype_l.c
ctype.c
ctype-extn.c
ctype-info.c
;
@@ -1,30 +0,0 @@
# Copyright (C) 1991, 1992, 1993, 1997, 2002 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.
#
# Sub-makefile for ctype portion of the library.
#
subdir := ctype
headers := ctype.h
routines := ctype ctype-extn ctype_l isctype
aux := ctype-info
tests := test_ctype
include ../Rules
@@ -1,24 +0,0 @@
libc {
GLIBC_2.0 {
# global variables
__ctype_b; __ctype32_b; __ctype_tolower; __ctype_toupper;
_tolower; _toupper;
# i*
isalnum; isalpha; isascii; isblank; iscntrl; isdigit; isgraph; islower;
isprint; ispunct; isspace; isupper; isxdigit;
# t*
toascii; tolower; toupper;
}
GLIBC_2.2 {
# global variables
__ctype32_tolower; __ctype32_toupper;
}
GLIBC_2.3 {
isctype; __isctype;
# functions used by optimized macros in ctype.h
__ctype_b_loc; __ctype_tolower_loc; __ctype_toupper_loc;
}
}
@@ -1,68 +0,0 @@
/* Copyright (C) 1991, 1997, 1999, 2000, 2002 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. */
#define __NO_CTYPE
#include <ctype.h>
/*
#define __ctype_tolower \
((uint32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER) + 128)
#define __ctype_toupper \
((uint32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER) + 128)
*/
/* Real function versions of the non-ANSI ctype functions. isblank is
now in ISO C99 but we leave it here. */
int
isblank (int c)
{
return __isctype (c, _ISblank);
}
int
_tolower (int c)
{
return __ctype_tolower[c];
}
int
_toupper (int c)
{
return __ctype_toupper[c];
}
int
toascii (int c)
{
return __toascii (c);
}
weak_alias (toascii, __toascii_l)
int
isascii (int c)
{
return __isascii (c);
}
weak_alias (isascii, __isascii_l)
/*
int
__isblank_l (int c, __locale_t l)
{
return __isctype_l (c, _ISblank, l);
}
weak_alias (__isblank_l, isblank_l)
*/
@@ -42,12 +42,6 @@ extern const char _nl_C_LC_CTYPE_width[];
#define b(t,x,o) (((const t *) _nl_C_LC_CTYPE_##x) + o)
const unsigned short int *__ctype_b = b (unsigned short int, class, 128);
const __uint32_t *__ctype32_b = b (__uint32_t, class32, 0);
const __int32_t *__ctype_tolower = b (__int32_t, tolower, 128);
const __int32_t *__ctype_toupper = b (__int32_t, toupper, 128);
const __uint32_t *__ctype32_tolower = b (__uint32_t, tolower, 128);
const __uint32_t *__ctype32_toupper = b (__uint32_t, toupper, 128);
const char *__ctype32_wctype[12] =
{
b(char, class_upper, 32),
@@ -68,4 +62,3 @@ const char *__ctype32_wctrans[2] =
b(char, map_toupper, 0),
b(char, map_tolower, 0)
};
const char *__ctype32_width = b (char, width, 0);
@@ -1,49 +0,0 @@
/* Copyright (C) 1991, 1992, 1997, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU 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. */
#define __NO_CTYPE
#include <ctype.h>
/* Provide real-function versions of all the ctype macros. */
#define func(name, type) \
int name (int c) { return __isctype (c, type); }
func (isalnum, _ISalnum)
func (isalpha, _ISalpha)
func (iscntrl, _IScntrl)
func (isdigit, _ISdigit)
func (islower, _ISlower)
func (isgraph, _ISgraph)
func (isprint, _ISprint)
func (ispunct, _ISpunct)
func (isspace, _ISspace)
func (isupper, _ISupper)
func (isxdigit, _ISxdigit)
int
tolower (int c)
{
return c >= -128 && c < 256 ? __ctype_tolower[c] : c;
}
int
toupper (int c)
{
return c >= -128 && c < 256 ? __ctype_toupper[c] : c;
}
@@ -1,63 +0,0 @@
/* Copyright (C) 1991,92,97,2001,02 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. */
#define __NO_CTYPE
#include <ctype.h>
#include <xlocale.h>
/* Provide real-function versions of all the ctype macros. */
int __isctype_l(int c, unsigned short int t, __locale_t l);
#define func(name, type) \
int __##name (int c, __locale_t l) { return __isctype_l (c, type, l); } \
weak_alias (__##name, name)
func (isalnum_l, _ISalnum)
func (isalpha_l, _ISalpha)
func (iscntrl_l, _IScntrl)
func (isdigit_l, _ISdigit)
func (islower_l, _ISlower)
func (isgraph_l, _ISgraph)
func (isprint_l, _ISprint)
func (ispunct_l, _ISpunct)
func (isspace_l, _ISspace)
func (isupper_l, _ISupper)
func (isxdigit_l, _ISxdigit)
int
(__tolower_l) (int c, __locale_t l)
{
return l->__ctype_tolower[c];
}
weak_alias (__tolower_l, tolower_l)
int
(__toupper_l) (int c, __locale_t l)
{
return l->__ctype_toupper[c];
}
weak_alias (__toupper_l, toupper_l)
int
(__isctype_l) (int c, unsigned short int t, __locale_t l)
{
return (l->__ctype_b[c] & t);
}
weak_alias (__isctype_l, isctype_l)
@@ -1,31 +0,0 @@
/* Copyright (C) 2002 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. */
#include <ctype.h>
#undef __isctype
int
__isctype (ch, mask)
int ch;
int mask;
{
return (((uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128)
[(int) (ch)] & mask);
}
weak_alias (__isctype, isctype)
@@ -1,101 +0,0 @@
/* Copyright (C) 1991, 1994, 1996, 1997, 2000 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. */
#include <limits.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#define XOR(e,f) (((e) && !(f)) || (!(e) && (f)))
#ifdef __GNUC__
__inline
#endif
static void
print_char (unsigned char c)
{
printf("%d/", (int) c);
if (isgraph(c))
printf("'%c'", c);
else
printf("'\\%.3o'", c);
}
int
main (int argc, char **argv)
{
unsigned short int c;
int lose = 0;
#define TRYEM do { \
TRY (isascii); \
TRY (isalnum); \
TRY (isalpha); \
TRY (iscntrl); \
TRY (isdigit); \
TRY (isgraph); \
TRY (islower); \
TRY (isprint); \
TRY (ispunct); \
TRY (isspace); \
TRY (isupper); \
TRY (isxdigit); \
TRY (isblank); \
} while (0)
for (c = 0; c <= UCHAR_MAX; ++c)
{
print_char (c);
if (XOR (islower (c), ISLOWER (c)) || toupper (c) != TOUPPER (c))
{
fputs (" BOGUS", stdout);
++lose;
}
#define TRY(isfoo) if (isfoo (c)) fputs (" " #isfoo, stdout)
TRYEM;
#undef TRY
fputs("; lower = ", stdout);
print_char(tolower(c));
fputs("; upper = ", stdout);
print_char(toupper(c));
putchar('\n');
}
fputs ("EOF", stdout);
if (tolower (EOF) != EOF)
{
++lose;
printf (" tolower BOGUS %d;", tolower (EOF));
}
if (toupper (EOF) != EOF)
{
++lose;
printf (" toupper BOGUS %d;", toupper (EOF));
}
#define TRY(isfoo) if (isfoo (EOF)) fputs (" " #isfoo, stdout), ++lose
TRYEM;
#undef TRY
return lose ? EXIT_FAILURE : EXIT_SUCCESS;
}
@@ -8,7 +8,6 @@ SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc libio ;
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ctype ;
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc iconv ;
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc locale ;
#SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc string ;
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ;
SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ;
@@ -18,7 +17,6 @@ MergeObject posix_gnu_iconv.o :
gconv_cache.c
gconv_conf.c
gconv_db.c
# gconv_dl.c
gconv_simple.c
gconv_trans.c
;
@@ -1,80 +0,0 @@
# Copyright (C) 1997, 1998, 2000, 2001, 2002 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.
#
# Makefile for iconv.
#
subdir := iconv
include ../Makeconfig
headers = iconv.h gconv.h
routines = iconv_open iconv iconv_close \
gconv_open gconv gconv_close gconv_db gconv_conf \
gconv_builtin gconv_simple gconv_trans gconv_cache
ifeq ($(elf),yes)
routines += gconv_dl
else
CFLAGS-gconv_db.c = -DSTATIC_GCONV
CFLAGS-gconv_cache.c = -DSTATIC_GCONV
CFLAGS-gconv_simple.c = -DSTATIC_GCONV
endif
vpath %.c ../locale/programs
iconv_prog-modules = iconv_charmap charmap charmap-dir linereader \
dummy-repertoire simple-hash xstrdup xmalloc
iconvconfig-modules = strtab xmalloc
extra-objs = $(iconv_prog-modules:=.o) $(iconvconfig-modules:=.o)
CFLAGS-iconv_prog.c = -I../locale/programs
CFLAGS-iconv_charmap.c = -I../locale/programs
CFLAGS-dummy-repertoire.c = -I../locale/programs
CFLAGS-charmap.c = -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \
-DDEFAULT_CHARMAP=null_pointer -DNEED_NULL_POINTER
CFLAGS-linereader.c = -DNO_TRANSLITERATION
CFLAGS-simple-hash.c = -I../locale
tests = tst-iconv1 tst-iconv2 tst-iconv3
distribute = gconv_builtin.h gconv_int.h loop.c skeleton.c iconv_prog.h \
iconv_charmap.c dummy-repertoire.c gconv_charset.h strtab.c \
iconvconfig.h
others = iconv_prog iconvconfig
install-others = $(inst_bindir)/iconv
install-sbin = iconvconfig
CFLAGS-gconv_cache.c += -DGCONV_DIR='"$(gconvdir)"'
CFLAGS-gconv_conf.c = -DGCONV_PATH='"$(gconvdir)"'
CFLAGS-iconvconfig.c = -DGCONV_PATH='"$(gconvdir)"' -DGCONV_DIR='"$(gconvdir)"'
CPPFLAGS-iconv_prog = -DNOT_IN_libc
CPPFLAGS-iconv_charmap = -DNOT_IN_libc
CPPFLAGS-iconvconfig = -DNOT_IN_libc
CPPFLAGS-linereader = -DNOT_IN_libc
CPPFLAGS-strtab = -DNOT_IN_libc
CPPFLAGS-charmap = -DNOT_IN_libc
CPPFLAGS-charmap-dir = -DNOT_IN_libc
include ../Rules
$(inst_bindir)/iconv: $(objpfx)iconv_prog $(+force)
$(do-install-program)
$(objpfx)iconv_prog: $(iconv_prog-modules:%=$(objpfx)%.o)
$(objpfx)iconvconfig: $(iconvconfig-modules:%=$(objpfx)%.o)
@@ -1,10 +0,0 @@
libc {
GLIBC_2.1 {
# i*
iconv_open; iconv; iconv_close;
}
GLIBC_PRIVATE {
# functions shared with iconv program
__gconv_get_alias_db; __gconv_get_modules_db; __gconv_get_cache;
}
}
@@ -1,37 +0,0 @@
/* Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 2001.
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. */
/* For iconv we don't have to handle repertoire maps. Provide dummy
definitions to allow the use of linereader.c unchanged. */
#include <repertoire.h>
uint32_t
repertoire_find_value (const struct repertoire_t *repertoire, const char *name,
size_t len)
{
return ILLEGAL_CHAR_VALUE;
}
const char *
repertoire_find_symbol (const struct repertoire_t *repertoire, uint32_t ucs)
{
return NULL;
}
@@ -1,75 +0,0 @@
/* Convert characters in input buffer using conversion descriptor to
output buffer.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
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. */
#include <assert.h>
#include <gconv_int.h>
#include <sys/param.h>
#include <dlfcn.h>
#include <stddef.h>
int
internal_function
__gconv (__gconv_t cd, const unsigned char **inbuf,
const unsigned char *inbufend, unsigned char **outbuf,
unsigned char *outbufend, size_t *irreversible)
{
size_t last_step;
int result;
if (cd == (__gconv_t) -1L)
return __GCONV_ILLEGAL_DESCRIPTOR;
last_step = cd->__nsteps - 1;
assert (irreversible != NULL);
*irreversible = 0;
cd->__data[last_step].__outbuf = outbuf != NULL ? *outbuf : NULL;
cd->__data[last_step].__outbufend = outbufend;
if (inbuf == NULL || *inbuf == NULL)
/* We just flush. */
result = DL_CALL_FCT (cd->__steps->__fct,
(cd->__steps, cd->__data, NULL, NULL, NULL,
irreversible,
cd->__data[last_step].__outbuf == NULL ? 2 : 1, 0));
else
{
const unsigned char *last_start;
assert (outbuf != NULL && *outbuf != NULL);
do
{
last_start = *inbuf;
result = DL_CALL_FCT (cd->__steps->__fct,
(cd->__steps, cd->__data, inbuf, inbufend,
NULL, irreversible, 0, 0));
}
while (result == __GCONV_EMPTY_INPUT && last_start != *inbuf
&& *inbuf + cd->__steps->__min_needed_from <= inbufend);
}
if (outbuf != NULL && *outbuf != NULL)
*outbuf = cd->__data[last_step].__outbuf;
return result;
}
@@ -1,65 +0,0 @@
/* Release any resource associated with given conversion descriptor.
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
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. */
#include <stdlib.h>
#include <gconv_int.h>
int
internal_function
__gconv_close (__gconv_t cd)
{
struct __gconv_step *srunp;
struct __gconv_step_data *drunp;
size_t nsteps;
/* Free all resources by calling destructor functions and release
the implementations. */
srunp = cd->__steps;
nsteps = cd->__nsteps;
drunp = cd->__data;
do
{
struct __gconv_trans_data *transp;
transp = drunp->__trans;
while (transp != NULL)
{
struct __gconv_trans_data *curp = transp;
transp = transp->__next;
if (__builtin_expect (curp->__trans_end_fct != NULL, 0))
curp->__trans_end_fct (curp->__data);
free (curp);
}
if (!(drunp->__flags & __GCONV_IS_LAST) && drunp->__outbuf != NULL)
free (drunp->__outbuf);
}
while (!((drunp++)->__flags & __GCONV_IS_LAST));
/* Free the data allocated for the descriptor. */
free (cd);
/* Close the participating modules. */
return __gconv_close_transform (srunp, nsteps);
}
@@ -1,337 +0,0 @@
/* Find matching transformation algorithms and initialize steps.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
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. */
#include <errno.h>
#include <locale.h>
#include "../locale/localeinfo.h"
#include <stdlib.h>
#include <string.h>
#include <gconv_int.h>
int
internal_function
__gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
int flags)
{
struct __gconv_step *steps;
size_t nsteps;
__gconv_t result = NULL;
size_t cnt = 0;
int res;
int conv_flags = 0;
const char *errhand;
const char *ignore;
struct trans_struct *trans = NULL;
/* Find out whether any error handling method is specified. */
errhand = strchr (toset, '/');
if (errhand != NULL)
errhand = strchr (errhand + 1, '/');
if (__builtin_expect (errhand != NULL, 1))
{
if (*++errhand == '\0')
errhand = NULL;
else
{
/* Make copy without the error handling description. */
char *newtoset = (char *) alloca (errhand - toset + 1);
char *tok;
char *ptr;
newtoset[errhand - toset] = '\0';
toset = memcpy (newtoset, toset, errhand - toset);
/* Find the appropriate transliteration handlers. */
tok = strdupa (errhand);
tok = __strtok_r (tok, ",", &ptr);
while (tok != NULL)
{
if (__strcasecmp_l (tok, "TRANSLIT", &_nl_C_locobj) == 0)
{
/* It's the builtin transliteration handling. We only
support it for working on the internal encoding. */
static const char *internal_trans_names[1] = { "INTERNAL" };
struct trans_struct *lastp = NULL;
struct trans_struct *runp;
for (runp = trans; runp != NULL; runp = runp->next)
if (runp->trans_fct == __gconv_transliterate)
break;
else
lastp = runp;
if (runp == NULL)
{
struct trans_struct *newp;
newp = (struct trans_struct *) alloca (sizeof (*newp));
memset (newp, '\0', sizeof (*newp));
/* We leave the `name' field zero to signal that
this is an internal transliteration step. */
newp->csnames = internal_trans_names;
newp->ncsnames = 1;
newp->trans_fct = __gconv_transliterate;
if (lastp == NULL)
trans = newp;
else
lastp->next = newp;
}
}
else if (__strcasecmp_l (tok, "IGNORE", &_nl_C_locobj) == 0)
/* Set the flag to ignore all errors. */
conv_flags |= __GCONV_IGNORE_ERRORS;
else
{
/* `tok' is possibly a module name. We'll see later
whether we can find it. But first see that we do
not already a module of this name. */
struct trans_struct *lastp = NULL;
struct trans_struct *runp;
for (runp = trans; runp != NULL; runp = runp->next)
if (runp->name != NULL
&& __strcasecmp_l (tok, runp->name,
&_nl_C_locobj) == 0)
break;
else
lastp = runp;
if (runp == NULL)
{
struct trans_struct *newp;
newp = (struct trans_struct *) alloca (sizeof (*newp));
memset (newp, '\0', sizeof (*newp));
newp->name = tok;
if (lastp == NULL)
trans = newp;
else
lastp->next = newp;
}
}
tok = __strtok_r (NULL, ",", &ptr);
}
}
}
/* For the source character set we ignore the error handler specification.
XXX Is this really always the best? */
ignore = strchr (fromset, '/');
if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL
&& *++ignore != '\0')
{
char *newfromset = (char *) alloca (ignore - fromset + 1);
newfromset[ignore - fromset] = '\0';
fromset = memcpy (newfromset, fromset, ignore - fromset);
}
/* If the string is empty define this to mean the charset of the
currently selected locale. */
if (strcmp (toset, "//") == 0)
{
const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET);
size_t len = strlen (codeset);
char *dest;
toset = dest = (char *) alloca (len + 3);
memcpy (__mempcpy (dest, codeset, len), "//", 3);
}
if (strcmp (fromset, "//") == 0)
{
const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET);
size_t len = strlen (codeset);
char *dest;
fromset = dest = (char *) alloca (len + 3);
memcpy (__mempcpy (dest, codeset, len), "//", 3);
}
res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags);
if (res == __GCONV_OK)
{
/* Find the modules. */
struct trans_struct *lastp = NULL;
struct trans_struct *runp;
for (runp = trans; runp != NULL; runp = runp->next)
{
if (runp->name == NULL
|| __builtin_expect (__gconv_translit_find (runp), 0) == 0)
lastp = runp;
else
/* This means we haven't found the module. Remove it. */
(lastp == NULL ? trans : lastp->next) = runp->next;
}
/* Allocate room for handle. */
result = (__gconv_t) malloc (sizeof (struct __gconv_info)
+ (nsteps
* sizeof (struct __gconv_step_data)));
if (result == NULL)
res = __GCONV_NOMEM;
else
{
size_t n;
/* Remember the list of steps. */
result->__steps = steps;
result->__nsteps = nsteps;
/* Clear the array for the step data. */
memset (result->__data, '\0',
nsteps * sizeof (struct __gconv_step_data));
/* Call all initialization functions for the transformation
step implementations. */
for (cnt = 0; cnt < nsteps; ++cnt)
{
size_t size;
/* Would have to be done if we would not clear the whole
array above. */
#if 0
/* Reset the counter. */
result->__data[cnt].__invocation_counter = 0;
/* It's a regular use. */
result->__data[cnt].__internal_use = 0;
#endif
/* We use the `mbstate_t' member in DATA. */
result->__data[cnt].__statep = &result->__data[cnt].__state;
/* Now see whether we can use any of the transliteration
modules for this step. */
for (runp = trans; runp != NULL; runp = runp->next)
for (n = 0; n < runp->ncsnames; ++n)
if (__strcasecmp_l (steps[cnt].__from_name,
runp->csnames[n], &_nl_C_locobj) == 0)
{
void *data = NULL;
/* Match! Now try the initializer. */
if (runp->trans_init_fct == NULL
|| (runp->trans_init_fct (&data,
steps[cnt].__to_name)
== __GCONV_OK))
{
/* Append at the end of the list. */
struct __gconv_trans_data *newp;
struct __gconv_trans_data **lastp;
newp = (struct __gconv_trans_data *)
malloc (sizeof (struct __gconv_trans_data));
if (newp == NULL)
{
res = __GCONV_NOMEM;
goto bail;
}
newp->__trans_fct = runp->trans_fct;
newp->__trans_context_fct = runp->trans_context_fct;
newp->__trans_end_fct = runp->trans_end_fct;
newp->__data = data;
newp->__next = NULL;
lastp = &result->__data[cnt].__trans;
while (*lastp != NULL)
lastp = &(*lastp)->__next;
*lastp = newp;
}
break;
}
/* If this is the last step we must not allocate an
output buffer. */
if (cnt < nsteps - 1)
{
result->__data[cnt].__flags = conv_flags;
/* Allocate the buffer. */
size = (GCONV_NCHAR_GOAL * steps[cnt].__max_needed_to);
result->__data[cnt].__outbuf = (char *) malloc (size);
if (result->__data[cnt].__outbuf == NULL)
{
res = __GCONV_NOMEM;
goto bail;
}
result->__data[cnt].__outbufend =
result->__data[cnt].__outbuf + size;
}
else
{
/* Handle the last entry. */
result->__data[cnt].__flags = conv_flags | __GCONV_IS_LAST;
break;
}
}
}
if (res != __GCONV_OK)
{
/* Something went wrong. Free all the resources. */
int serrno;
bail:
serrno = errno;
if (result != NULL)
{
while (cnt-- > 0)
{
struct __gconv_trans_data *transp;
transp = result->__data[cnt].__trans;
while (transp != NULL)
{
struct __gconv_trans_data *curp = transp;
transp = transp->__next;
if (__builtin_expect (curp->__trans_end_fct != NULL, 0))
curp->__trans_end_fct (curp->__data);
free (curp);
}
free (result->__data[cnt].__outbuf);
}
free (result);
result = NULL;
}
__gconv_close_transform (steps, nsteps);
__set_errno (serrno);
}
}
*handle = result;
return res;
}
@@ -1,96 +0,0 @@
/* Convert characters in input buffer using conversion descriptor to
output buffer.
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
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. */
#include <stddef.h> /* for NULL */
#include <errno.h>
#include <iconv.h>
#include <gconv_int.h>
#include <assert.h>
size_t
iconv (iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf,
size_t *outbytesleft)
{
__gconv_t gcd = (__gconv_t) cd;
char *outstart = outbuf ? *outbuf : NULL;
size_t irreversible;
int result;
if (__builtin_expect (inbuf == NULL || *inbuf == NULL, 0))
{
if (outbuf == NULL || *outbuf == NULL)
result = __gconv (gcd, NULL, NULL, NULL, NULL, &irreversible);
else
result = __gconv (gcd, NULL, NULL, (unsigned char **) outbuf,
(unsigned char *) (outstart + *outbytesleft),
&irreversible);
}
else
{
const char *instart = *inbuf;
result = __gconv (gcd, (const unsigned char **) inbuf,
(const unsigned char *) (*inbuf + *inbytesleft),
(unsigned char **) outbuf,
(unsigned char *) (*outbuf + *outbytesleft),
&irreversible);
*inbytesleft -= *inbuf - instart;
}
if (outstart != NULL)
*outbytesleft -= *outbuf - outstart;
switch (__builtin_expect (result, __GCONV_OK))
{
case __GCONV_ILLEGAL_DESCRIPTOR:
__set_errno (EBADF);
irreversible = (size_t) -1L;
break;
case __GCONV_ILLEGAL_INPUT:
__set_errno (EILSEQ);
irreversible = (size_t) -1L;
break;
case __GCONV_FULL_OUTPUT:
__set_errno (E2BIG);
irreversible = (size_t) -1L;
break;
case __GCONV_INCOMPLETE_INPUT:
__set_errno (EINVAL);
irreversible = (size_t) -1L;
break;
case __GCONV_EMPTY_INPUT:
case __GCONV_OK:
/* Nothing. */
break;
default:
assert (!"Nothing like this should happen");
}
return irreversible;
}
@@ -1,51 +0,0 @@
/* Copyright (C) 1997, 1998, 1999, 2000 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. */
#ifndef _ICONV_H
#define _ICONV_H 1
#include <features.h>
#define __need_size_t
#include <stddef.h>
__BEGIN_DECLS
/* Identifier for conversion method from one codeset to another. */
typedef void *iconv_t;
/* Allocate descriptor for code conversion from codeset FROMCODE to
codeset TOCODE. */
extern iconv_t iconv_open (__const char *__tocode, __const char *__fromcode)
__THROW;
/* Convert at most *INBYTESLEFT bytes from *INBUF according to the
code conversion algorithm specified by CD and place up to
*OUTBYTESLEFT bytes in buffer at *OUTBUF. */
extern size_t iconv (iconv_t __cd, char **__restrict __inbuf,
size_t *__restrict __inbytesleft,
char **__restrict __outbuf,
size_t *__restrict __outbytesleft);
/* Free resources allocated for descriptor CD for code conversion. */
extern int iconv_close (iconv_t __cd) __THROW;
__END_DECLS
#endif /* iconv.h */
@@ -1,568 +0,0 @@
/* Convert using charmaps and possibly iconv().
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 2001.
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. */
#include <assert.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <iconv.h>
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "iconv_prog.h"
/* Prototypes for a few program-wide used functions. */
extern void *xmalloc (size_t __n);
extern void *xcalloc (size_t __n, size_t __s);
struct convtable
{
int term[256 / 8];
union
{
struct convtable *sub;
struct charseq *out;
} val[256];
};
static inline struct convtable *
allocate_table (void)
{
return (struct convtable *) xcalloc (1, sizeof (struct convtable));
}
static inline int
is_term (struct convtable *tbl, unsigned int idx)
{
return tbl->term[idx / 8] & (1 << (idx % 8));
}
static inline void
clear_term (struct convtable *tbl, unsigned int idx)
{
tbl->term[idx / 8] &= ~(1 << (idx % 8));
}
static inline void
set_term (struct convtable *tbl, unsigned int idx)
{
tbl->term[idx / 8] |= 1 << (idx % 8);
}
/* Generate the conversion table. */
static struct convtable *use_from_charmap (struct charmap_t *from_charmap,
const char *to_code);
static struct convtable *use_to_charmap (const char *from_code,
struct charmap_t *to_charmap);
static struct convtable *use_both_charmaps (struct charmap_t *from_charmap,
struct charmap_t *to_charmap);
/* Prototypes for the functions doing the actual work. */
static int process_block (struct convtable *tbl, char *addr, size_t len,
FILE *output);
static int process_fd (struct convtable *tbl, int fd, FILE *output);
static int process_file (struct convtable *tbl, FILE *input, FILE *output);
int
charmap_conversion (const char *from_code, struct charmap_t *from_charmap,
const char *to_code, struct charmap_t *to_charmap,
int argc, int remaining, char *argv[], FILE *output)
{
struct convtable *cvtbl;
int status = EXIT_SUCCESS;
/* We have three different cases to handle:
- both, from_charmap and to_charmap, are available. This means we
can assume that the symbolic names match and use them to create
the mapping.
- only from_charmap is available. In this case we can only hope that
the symbolic names used are of the <Uxxxx> form in which case we
can use a UCS4->"to_code" iconv() conversion for the second step.
- only to_charmap is available. This is similar, only that we would
use iconv() for the "to_code"->UCS4 conversion.
We first create a table which maps input bytes into output bytes.
Once this is done we can handle all three of the cases above
equally. */
if (from_charmap != NULL)
{
if (to_charmap == NULL)
cvtbl = use_from_charmap (from_charmap, to_code);
else
cvtbl = use_both_charmaps (from_charmap, to_charmap);
}
else
{
assert (to_charmap != NULL);
cvtbl = use_to_charmap (from_code, to_charmap);
}
/* If we couldn't generate a table stop now. */
if (cvtbl == NULL)
return EXIT_FAILURE;
/* We can now start the conversion. */
if (remaining == argc)
{
if (process_file (cvtbl, stdin, output) != 0)
status = EXIT_FAILURE;
}
else
do
{
struct stat st;
char *addr;
int fd;
if (verbose)
printf ("%s:\n", argv[remaining]);
if (strcmp (argv[remaining], "-") == 0)
fd = 0;
else
{
fd = open (argv[remaining], O_RDONLY);
if (fd == -1)
{
error (0, errno, _("cannot open input file `%s'"),
argv[remaining]);
status = EXIT_FAILURE;
continue;
}
}
#ifdef _POSIX_MAPPED_FILES
/* We have possibilities for reading the input file. First try
to mmap() it since this will provide the fastest solution. */
if (fstat (fd, &st) == 0
&& ((addr = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE,
fd, 0)) != MAP_FAILED))
{
/* Yes, we can use mmap(). The descriptor is not needed
anymore. */
if (close (fd) != 0)
error (EXIT_FAILURE, errno,
_("error while closing input `%s'"), argv[remaining]);
if (process_block (cvtbl, addr, st.st_size, output) < 0)
{
/* Something went wrong. */
status = EXIT_FAILURE;
/* We don't need the input data anymore. */
munmap ((void *) addr, st.st_size);
/* We cannot go on with producing output since it might
lead to problem because the last output might leave
the output stream in an undefined state. */
break;
}
/* We don't need the input data anymore. */
munmap ((void *) addr, st.st_size);
}
else
#endif /* _POSIX_MAPPED_FILES */
{
/* Read the file in pieces. */
if (process_fd (cvtbl, fd, output) != 0)
{
/* Something went wrong. */
status = EXIT_FAILURE;
/* We don't need the input file anymore. */
close (fd);
/* We cannot go on with producing output since it might
lead to problem because the last output might leave
the output stream in an undefined state. */
break;
}
/* Now close the file. */
close (fd);
}
}
while (++remaining < argc);
/* All done. */
return status;
}
static void
add_bytes (struct convtable *tbl, struct charseq *in, struct charseq *out)
{
int n = 0;
unsigned int byte;
assert (in->nbytes > 0);
byte = ((unsigned char *) in->bytes)[n];
while (n + 1 < in->nbytes)
{
if (is_term (tbl, byte) || tbl->val[byte].sub == NULL)
{
/* Note that we simply ignore a definition for a byte sequence
which is also the prefix for a longer one. */
clear_term (tbl, byte);
tbl->val[byte].sub =
(struct convtable *) xcalloc (1, sizeof (struct convtable));
}
tbl = tbl->val[byte].sub;
byte = ((unsigned char *) in->bytes)[++n];
}
/* Only add the new sequence if there is none yet and the byte sequence
is not part of an even longer one. */
if (! is_term (tbl, byte) && tbl->val[byte].sub == NULL)
{
set_term (tbl, byte);
tbl->val[byte].out = out;
}
}
static struct convtable *
use_from_charmap (struct charmap_t *from_charmap, const char *to_code)
{
/* We iterate over all entries in the from_charmap and for those which
have a known UCS4 representation we use an iconv() call to determine
the mapping to the to_code charset. */
struct convtable *rettbl;
iconv_t cd;
void *ptr = NULL;
const void *key;
size_t keylen;
void *data;
cd = iconv_open (to_code, "WCHAR_T");
if (cd == (iconv_t) -1)
/* We cannot do anything. */
return NULL;
rettbl = allocate_table ();
while (iterate_table (&from_charmap->char_table, &ptr, &key, &keylen, &data)
>= 0)
{
struct charseq *in = (struct charseq *) data;
if (in->ucs4 != UNINITIALIZED_CHAR_VALUE)
{
/* There is a chance. Try the iconv module. */
wchar_t inbuf[1] = { in->ucs4 };
unsigned char outbuf[64];
char *inptr = (char *) inbuf;
size_t inlen = sizeof (inbuf);
char *outptr = (char *) outbuf;
size_t outlen = sizeof (outbuf);
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
if (outptr != (char *) outbuf)
{
/* We got some output. Good, use it. */
struct charseq *newp;
outlen = sizeof (outbuf) - outlen;
assert ((char *) outbuf + outlen == outptr);
newp = (struct charseq *) xmalloc (sizeof (struct charseq)
+ outlen);
newp->name = in->name;
newp->ucs4 = in->ucs4;
newp->nbytes = outlen;
memcpy (newp->bytes, outbuf, outlen);
add_bytes (rettbl, in, newp);
}
/* Clear any possible state left behind. */
(void) iconv (cd, NULL, NULL, NULL, NULL);
}
}
iconv_close (cd);
return rettbl;
}
static struct convtable *
use_to_charmap (const char *from_code, struct charmap_t *to_charmap)
{
/* We iterate over all entries in the to_charmap and for those which
have a known UCS4 representation we use an iconv() call to determine
the mapping to the from_code charset. */
struct convtable *rettbl;
iconv_t cd;
void *ptr = NULL;
const void *key;
size_t keylen;
void *data;
/* Note that the conversion we use here is the reverse direction. Without
exhaustive search we cannot figure out which input yields the UCS4
character we are looking for. Therefore we determine it the other
way round. */
cd = iconv_open (from_code, "WCHAR_T");
if (cd == (iconv_t) -1)
/* We cannot do anything. */
return NULL;
rettbl = allocate_table ();
while (iterate_table (&to_charmap->char_table, &ptr, &key, &keylen, &data)
>= 0)
{
struct charseq *out = (struct charseq *) data;
if (out->ucs4 != UNINITIALIZED_CHAR_VALUE)
{
/* There is a chance. Try the iconv module. */
wchar_t inbuf[1] = { out->ucs4 };
unsigned char outbuf[64];
char *inptr = (char *) inbuf;
size_t inlen = sizeof (inbuf);
char *outptr = (char *) outbuf;
size_t outlen = sizeof (outbuf);
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
if (outptr != (char *) outbuf)
{
/* We got some output. Good, use it. */
struct charseq *newp;
outlen = sizeof (outbuf) - outlen;
assert ((char *) outbuf + outlen == outptr);
newp = (struct charseq *) xmalloc (sizeof (struct charseq)
+ outlen);
newp->name = out->name;
newp->ucs4 = out->ucs4;
newp->nbytes = outlen;
memcpy (newp->bytes, outbuf, outlen);
add_bytes (rettbl, newp, out);
}
/* Clear any possible state left behind. */
(void) iconv (cd, NULL, NULL, NULL, NULL);
}
}
iconv_close (cd);
return rettbl;
}
static struct convtable *
use_both_charmaps (struct charmap_t *from_charmap,
struct charmap_t *to_charmap)
{
/* In this case we iterate over all the entries in the from_charmap,
determine the internal name, and find an appropriate entry in the
to_charmap (if it exists). */
struct convtable *rettbl = allocate_table ();
void *ptr = NULL;
const void *key;
size_t keylen;
void *data;
while (iterate_table (&from_charmap->char_table, &ptr, &key, &keylen, &data)
>= 0)
{
struct charseq *in = (struct charseq *) data;
struct charseq *out = charmap_find_value (to_charmap, key, keylen);
if (out != NULL)
add_bytes (rettbl, in, out);
}
return rettbl;
}
static int
process_block (struct convtable *tbl, char *addr, size_t len, FILE *output)
{
size_t n = 0;
while (n < len)
{
struct convtable *cur = tbl;
unsigned char *curp = (unsigned char *) addr;
unsigned int byte = *curp;
int cnt;
struct charseq *out;
while (! is_term (cur, byte))
if (cur->val[byte].sub == NULL)
{
/* This is a invalid sequence. Skip the first byte if we are
ignoring errors. Otherwise punt. */
if (! omit_invalid)
{
error (0, 0, _("illegal input sequence at position %Zd"), n);
return -1;
}
n -= curp - (unsigned char *) addr;
byte = *(curp = (unsigned char *) ++addr);
if (++n >= len)
/* All converted. */
return 0;
cur = tbl;
}
else
{
cur = cur->val[byte].sub;
if (++n >= len)
{
error (0, 0, _("\
incomplete character or shift sequence at end of buffer"));
return -1;
}
byte = *++curp;
}
/* We found a final byte. Write the output bytes. */
out = cur->val[byte].out;
for (cnt = 0; cnt < out->nbytes; ++cnt)
fputc_unlocked (out->bytes[cnt], output);
addr = (char *) curp + 1;
++n;
}
return 0;
}
static int
process_fd (struct convtable *tbl, int fd, FILE *output)
{
/* We have a problem with reading from a descriptor since we must not
provide the iconv() function an incomplete character or shift
sequence at the end of the buffer. Since we have to deal with
arbitrary encodings we must read the whole text in a buffer and
process it in one step. */
static char *inbuf = NULL;
static size_t maxlen = 0;
char *inptr = NULL;
size_t actlen = 0;
while (actlen < maxlen)
{
ssize_t n = read (fd, inptr, maxlen - actlen);
if (n == 0)
/* No more text to read. */
break;
if (n == -1)
{
/* Error while reading. */
error (0, errno, _("error while reading the input"));
return -1;
}
inptr += n;
actlen += n;
}
if (actlen == maxlen)
while (1)
{
ssize_t n;
char *new_inbuf;
/* Increase the buffer. */
new_inbuf = (char *) realloc (inbuf, maxlen + 32768);
if (new_inbuf == NULL)
{
error (0, errno, _("unable to allocate buffer for input"));
return -1;
}
inbuf = new_inbuf;
maxlen += 32768;
inptr = inbuf + actlen;
do
{
n = read (fd, inptr, maxlen - actlen);
if (n == 0)
/* No more text to read. */
break;
if (n == -1)
{
/* Error while reading. */
error (0, errno, _("error while reading the input"));
return -1;
}
inptr += n;
actlen += n;
}
while (actlen < maxlen);
if (n == 0)
/* Break again so we leave both loops. */
break;
}
/* Now we have all the input in the buffer. Process it in one run. */
return process_block (tbl, inbuf, actlen, output);
}
static int
process_file (struct convtable *tbl, FILE *input, FILE *output)
{
/* This should be safe since we use this function only for `stdin' and
we haven't read anything so far. */
return process_fd (tbl, fileno (input), output);
}
@@ -1,37 +0,0 @@
/* Release any resource associated with given conversion descriptor.
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
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. */
#include <errno.h>
#include <iconv.h>
#include <gconv_int.h>
int
iconv_close (iconv_t cd)
{
if (__builtin_expect (cd == (iconv_t *) -1L, 0))
{
__set_errno (EBADF);
return -1;
}
return __gconv_close ((__gconv_t) cd) ? -1 : 0;
}
@@ -1,66 +0,0 @@
/* Get descriptor for character set conversion.
Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
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. */
#include <errno.h>
#include <iconv.h>
#include <stdlib.h>
#include <string.h>
#include <gconv_int.h>
#include "gconv_charset.h"
iconv_t
iconv_open (const char *tocode, const char *fromcode)
{
char *tocode_conv;
char *fromcode_conv;
size_t tocode_len;
size_t fromcode_len;
__gconv_t cd;
int res;
/* Normalize the name. We remove all characters beside alpha-numeric,
'_', '-', '/', and '.'. */
tocode_len = strlen (tocode);
tocode_conv = (char *) alloca (tocode_len + 3);
strip (tocode_conv, tocode);
tocode = (tocode_conv[2] == '\0' && tocode[0] != '\0'
? upstr (tocode_conv, tocode) : tocode_conv);
fromcode_len = strlen (fromcode);
fromcode_conv = (char *) alloca (fromcode_len + 3);
strip (fromcode_conv, fromcode);
fromcode = (fromcode_conv[2] == '\0' && fromcode[0] != '\0'
? upstr (fromcode_conv, fromcode) : fromcode_conv);
res = __gconv_open (tocode, fromcode, &cd, 0);
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
{
/* We must set the error number according to the specs. */
if (res == __GCONV_NOCONV || res == __GCONV_NODB)
__set_errno (EINVAL);
return (iconv_t) -1;
}
return (iconv_t) cd;
}
@@ -1,770 +0,0 @@
/* Convert text in given files from the specified from-set to the to-set.
Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1998.
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. */
#include <argp.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <iconv.h>
#include <langinfo.h>
#include <locale.h>
#include <search.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libintl.h>
#ifdef _POSIX_MAPPED_FILES
# include <sys/mman.h>
#endif
#include <charmap.h>
#include <gconv_int.h>
#include "iconv_prog.h"
#include "iconvconfig.h"
/* Get libc version number. */
#include "../version.h"
#define PACKAGE _libc_intl_domainname
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
#define OPT_VERBOSE 1000
#define OPT_LIST 'l'
/* Definitions of arguments for argp functions. */
static const struct argp_option options[] =
{
{ NULL, 0, NULL, 0, N_("Input/Output format specification:") },
{ "from-code", 'f', "NAME", 0, N_("encoding of original text") },
{ "to-code", 't', "NAME", 0, N_("encoding for output") },
{ NULL, 0, NULL, 0, N_("Information:") },
{ "list", 'l', NULL, 0, N_("list all known coded character sets") },
{ NULL, 0, NULL, 0, N_("Output control:") },
{ NULL, 'c', NULL, 0, N_("omit invalid characters from output") },
{ "output", 'o', "FILE", 0, N_("output file") },
{ "silent", 's', NULL, 0, N_("suppress warnings") },
{ "verbose", OPT_VERBOSE, NULL, 0, N_("print progress information") },
{ NULL, 0, NULL, 0, NULL }
};
/* Short description of program. */
static const char doc[] = N_("\
Convert encoding of given files from one encoding to another.");
/* Strings for arguments in help texts. */
static const char args_doc[] = N_("[FILE...]");
/* Prototype for option handler. */
static error_t parse_opt (int key, char *arg, struct argp_state *state);
/* Function to print some extra text in the help message. */
static char *more_help (int key, const char *text, void *input);
/* Data structure to communicate with argp functions. */
static struct argp argp =
{
options, parse_opt, args_doc, doc, NULL, more_help
};
/* Code sets to convert from and to respectively. An empty string as the
default causes the 'iconv_open' function to look up the charset of the
currently selected locale and use it. */
static const char *from_code = "";
static const char *to_code = "";
/* File to write output to. If NULL write to stdout. */
static const char *output_file;
/* Nonzero if verbose ouput is wanted. */
int verbose;
/* Nonzero if list of all coded character sets is wanted. */
static int list;
/* If nonzero omit invalid character from output. */
int omit_invalid;
/* Prototypes for the functions doing the actual work. */
static int process_block (iconv_t cd, char *addr, size_t len, FILE *output);
static int process_fd (iconv_t cd, int fd, FILE *output);
static int process_file (iconv_t cd, FILE *input, FILE *output);
static void print_known_names (void) internal_function;
int
main (int argc, char *argv[])
{
int status = EXIT_SUCCESS;
int remaining;
FILE *output;
iconv_t cd;
const char *orig_to_code;
struct charmap_t *from_charmap = NULL;
struct charmap_t *to_charmap = NULL;
/* Set locale via LC_ALL. */
setlocale (LC_ALL, "");
/* Set the text message domain. */
textdomain (_libc_intl_domainname);
/* Parse and process arguments. */
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
/* List all coded character sets if wanted. */
if (list)
{
print_known_names ();
exit (EXIT_SUCCESS);
}
/* If we have to ignore errors make sure we use the appropriate name for
the to-character-set. */
orig_to_code = to_code;
if (omit_invalid)
{
const char *errhand = strchrnul (to_code, '/');
int nslash = 2;
char *newp;
char *cp;
if (*errhand == '/')
{
--nslash;
errhand = strchrnul (errhand, '/');
if (*errhand == '/')
{
--nslash;
++errhand;
}
}
newp = (char *) alloca (errhand - to_code + nslash + 6 + 1);
cp = mempcpy (newp, to_code, errhand - to_code);
while (nslash-- > 0)
*cp++ = '/';
memcpy (cp, "IGNORE", sizeof ("IGNORE"));
to_code = newp;
}
/* POSIX 1003.2b introduces a silly thing: the arguments to -t anf -f
can be file names of charmaps. In this case iconv will have to read
those charmaps and use them to do the conversion. But there are
holes in the specification. There is nothing said that if -f is a
charmap filename that -t must be, too. And vice versa. There is
also no word about the symbolic names used. What if they don't
match? */
if (strchr (from_code, '/') != NULL)
/* The from-name might be a charmap file name. Try reading the
file. */
from_charmap = charmap_read (from_code, /*0, 1*/1, 0, 0);
if (strchr (orig_to_code, '/') != NULL)
/* The to-name might be a charmap file name. Try reading the
file. */
to_charmap = charmap_read (orig_to_code, /*0, 1,*/1,0, 0);
/* Determine output file. */
if (output_file != NULL && strcmp (output_file, "-") != 0)
{
output = fopen (output_file, "w");
if (output == NULL)
error (EXIT_FAILURE, errno, _("cannot open output file"));
}
else
output = stdout;
/* At this point we have to handle two cases. The first one is
where a charmap is used for the from- or to-charset, or both. We
handle this special since it is very different from the sane way of
doing things. The other case allows converting using the iconv()
function. */
if (from_charmap != NULL || to_charmap != NULL)
/* Construct the conversion table and do the conversion. */
status = charmap_conversion (from_code, from_charmap, to_code, to_charmap,
argc, remaining, argv, output);
else
{
/* Let's see whether we have these coded character sets. */
cd = iconv_open (to_code, from_code);
if (cd == (iconv_t) -1)
{
if (errno == EINVAL)
{
/* Try to be nice with the user and tell her which of the
two encoding names is wrong. This is possible because
all supported encodings can be converted from/to Unicode,
in other words, because the graph of encodings is
connected. */
bool from_wrong =
(iconv_open ("UTF-8", from_code) == (iconv_t) -1
&& errno == EINVAL);
bool to_wrong =
(iconv_open (to_code, "UTF-8") == (iconv_t) -1
&& errno == EINVAL);
const char *from_pretty =
(from_code[0] ? from_code : nl_langinfo (CODESET));
const char *to_pretty =
(orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET));
if (from_wrong)
{
if (to_wrong)
error (EXIT_FAILURE, 0,
_("\
conversion from `%s' and to `%s' are not supported"),
from_pretty, to_pretty);
else
error (EXIT_FAILURE, 0,
_("conversion from `%s' is not supported"),
from_pretty);
}
else
{
if (to_wrong)
error (EXIT_FAILURE, 0,
_("conversion to `%s' is not supported"),
to_pretty);
else
error (EXIT_FAILURE, 0,
_("conversion from `%s' to `%s' is not supported"),
from_pretty, to_pretty);
}
}
else
error (EXIT_FAILURE, errno,
_("failed to start conversion processing"));
}
/* Now process the remaining files. Write them to stdout or the file
specified with the `-o' parameter. If we have no file given as
the parameter process all from stdin. */
if (remaining == argc)
{
if (process_file (cd, stdin, output) != 0)
status = EXIT_FAILURE;
}
else
do
{
#ifdef _POSIX_MAPPED_FILES
struct stat st;
char *addr;
#endif
int fd;
if (verbose)
printf ("%s:\n", argv[remaining]);
if (strcmp (argv[remaining], "-") == 0)
fd = 0;
else
{
fd = open (argv[remaining], O_RDONLY);
if (fd == -1)
{
error (0, errno, _("cannot open input file `%s'"),
argv[remaining]);
status = EXIT_FAILURE;
continue;
}
}
#ifdef _POSIX_MAPPED_FILES
/* We have possibilities for reading the input file. First try
to mmap() it since this will provide the fastest solution. */
if (fstat (fd, &st) == 0
&& ((addr = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE,
fd, 0)) != MAP_FAILED))
{
/* Yes, we can use mmap(). The descriptor is not needed
anymore. */
if (close (fd) != 0)
error (EXIT_FAILURE, errno,
_("error while closing input `%s'"),
argv[remaining]);
if (process_block (cd, addr, st.st_size, output) < 0)
{
/* Something went wrong. */
status = EXIT_FAILURE;
/* We don't need the input data anymore. */
munmap ((void *) addr, st.st_size);
/* We cannot go on with producing output since it might
lead to problem because the last output might leave
the output stream in an undefined state. */
break;
}
/* We don't need the input data anymore. */
munmap ((void *) addr, st.st_size);
}
else
#endif /* _POSIX_MAPPED_FILES */
{
/* Read the file in pieces. */
if (process_fd (cd, fd, output) != 0)
{
/* Something went wrong. */
status = EXIT_FAILURE;
/* We don't need the input file anymore. */
close (fd);
/* We cannot go on with producing output since it might
lead to problem because the last output might leave
the output stream in an undefined state. */
break;
}
/* Now close the file. */
close (fd);
}
}
while (++remaining < argc);
}
/* Close the output file now. */
if (fclose (output))
error (EXIT_FAILURE, errno, _("error while closing output file"));
return status;
}
/* Handle program arguments. */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
switch (key)
{
case 'f':
from_code = arg;
break;
case 't':
to_code = arg;
break;
case 'o':
output_file = arg;
break;
case 's':
/* Nothing, for now at least. We are not giving out any information
about missing character or so. */
break;
case 'c':
/* Omit invalid characters from output. */
omit_invalid = 1;
break;
case OPT_VERBOSE:
verbose = 1;
break;
case OPT_LIST:
list = 1;
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static char *
more_help (int key, const char *text, void *input)
{
switch (key)
{
case ARGP_KEY_HELP_EXTRA:
/* We print some extra information. */
return strdup (gettext ("\
Report bugs using the `glibcbug' script to <[email protected]>.\n"));
default:
break;
}
return (char *) text;
}
/* Print the version information. */
static void
print_version (FILE *stream, struct argp_state *state)
{
fprintf (stream, "iconv (GNU %s) %s\n", PACKAGE, VERSION);
fprintf (stream, gettext ("\
Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"), "2003");
fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
}
static int
process_block (iconv_t cd, char *addr, size_t len, FILE *output)
{
#define OUTBUF_SIZE 32768
const char *start = addr;
char outbuf[OUTBUF_SIZE];
char *outptr;
size_t outlen;
size_t n;
while (len > 0)
{
outptr = outbuf;
outlen = OUTBUF_SIZE;
n = iconv (cd, &addr, &len, &outptr, &outlen);
if (outptr != outbuf)
{
/* We have something to write out. */
int errno_save = errno;
if (fwrite (outbuf, 1, outptr - outbuf, output)
< (size_t) (outptr - outbuf)
|| ferror (output))
{
/* Error occurred while printing the result. */
error (0, 0, _("\
conversion stopped due to problem in writing the output"));
return -1;
}
errno = errno_save;
}
if (n != (size_t) -1)
{
/* All the input test is processed. For state-dependent
character sets we have to flush the state now. */
outptr = outbuf;
outlen = OUTBUF_SIZE;
(void) iconv (cd, NULL, NULL, &outptr, &outlen);
if (outptr != outbuf)
{
/* We have something to write out. */
int errno_save = errno;
if (fwrite (outbuf, 1, outptr - outbuf, output)
< (size_t) (outptr - outbuf)
|| ferror (output))
{
/* Error occurred while printing the result. */
error (0, 0, _("\
conversion stopped due to problem in writing the output"));
return -1;
}
errno = errno_save;
}
break;
}
if (errno != E2BIG)
{
/* iconv() ran into a problem. */
switch (errno)
{
case EILSEQ:
error (0, 0, _("illegal input sequence at position %ld"),
(long) (addr - start));
break;
case EINVAL:
error (0, 0, _("\
incomplete character or shift sequence at end of buffer"));
break;
case EBADF:
error (0, 0, _("internal error (illegal descriptor)"));
break;
default:
error (0, 0, _("unknown iconv() error %d"), errno);
break;
}
return -1;
}
}
return 0;
}
static int
process_fd (iconv_t cd, int fd, FILE *output)
{
/* we have a problem with reading from a desriptor since we must not
provide the iconv() function an incomplete character or shift
sequence at the end of the buffer. Since we have to deal with
arbitrary encodings we must read the whole text in a buffer and
process it in one step. */
static char *inbuf = NULL;
static size_t maxlen = 0;
char *inptr = NULL;
size_t actlen = 0;
while (actlen < maxlen)
{
ssize_t n = read (fd, inptr, maxlen - actlen);
if (n == 0)
/* No more text to read. */
break;
if (n == -1)
{
/* Error while reading. */
error (0, errno, _("error while reading the input"));
return -1;
}
inptr += n;
actlen += n;
}
if (actlen == maxlen)
while (1)
{
ssize_t n;
char *new_inbuf;
/* Increase the buffer. */
new_inbuf = (char *) realloc (inbuf, maxlen + 32768);
if (new_inbuf == NULL)
{
error (0, errno, _("unable to allocate buffer for input"));
return -1;
}
inbuf = new_inbuf;
maxlen += 32768;
inptr = inbuf + actlen;
do
{
n = read (fd, inptr, maxlen - actlen);
if (n == 0)
/* No more text to read. */
break;
if (n == -1)
{
/* Error while reading. */
error (0, errno, _("error while reading the input"));
return -1;
}
inptr += n;
actlen += n;
}
while (actlen < maxlen);
if (n == 0)
/* Break again so we leave both loops. */
break;
}
/* Now we have all the input in the buffer. Process it in one run. */
return process_block (cd, inbuf, actlen, output);
}
static int
process_file (iconv_t cd, FILE *input, FILE *output)
{
/* This should be safe since we use this function only for `stdin' and
we haven't read anything so far. */
return process_fd (cd, fileno (input), output);
}
/* Print all known character sets/encodings. */
static void *printlist;
static size_t column;
static int not_first;
static void
insert_print_list (const void *nodep, VISIT value, int level)
{
if (value == leaf || value == postorder)
{
const struct gconv_alias *s = *(const struct gconv_alias **) nodep;
tsearch (s->fromname, &printlist, (__compar_fn_t) strverscmp);
}
}
static void
do_print_human (const void *nodep, VISIT value, int level)
{
if (value == leaf || value == postorder)
{
const char *s = *(const char **) nodep;
size_t len = strlen (s);
size_t cnt;
while (len > 0 && s[len - 1] == '/')
--len;
for (cnt = 0; cnt < len; ++cnt)
if (isalnum (s[cnt]))
break;
if (cnt == len)
return;
if (not_first)
{
putchar (',');
++column;
if (column > 2 && column + len > 77)
{
fputs ("\n ", stdout);
column = 2;
}
else
{
putchar (' ');
++column;
}
}
else
not_first = 1;
fwrite (s, len, 1, stdout);
column += len;
}
}
static void
do_print (const void *nodep, VISIT value, int level)
{
if (value == leaf || value == postorder)
{
const char *s = *(const char **) nodep;
puts (s);
}
}
static void
internal_function
add_known_names (struct gconv_module *node)
{
if (node->left != NULL)
add_known_names (node->left);
if (node->right != NULL)
add_known_names (node->right);
do
{
if (strcmp (node->from_string, "INTERNAL"))
tsearch (node->from_string, &printlist,
(__compar_fn_t) strverscmp);
if (strcmp (node->to_string, "INTERNAL") != 0)
tsearch (node->to_string, &printlist, (__compar_fn_t) strverscmp);
node = node->same;
}
while (node != NULL);
}
static void
insert_cache (void)
{
const struct gconvcache_header *header;
const char *strtab;
const struct hash_entry *hashtab;
size_t cnt;
header = (const struct gconvcache_header *) __gconv_get_cache ();
strtab = (char *) header + header->string_offset;
hashtab = (struct hash_entry *) ((char *) header + header->hash_offset);
for (cnt = 0; cnt < header->hash_size; ++cnt)
if (hashtab[cnt].string_offset != 0)
{
const char *str = strtab + hashtab[cnt].string_offset;
if (strcmp (str, "INTERNAL") != 0)
tsearch (str, &printlist, (__compar_fn_t) strverscmp);
}
}
static void
internal_function
print_known_names (void)
{
iconv_t h;
void *cache;
/* We must initialize the internal databases first. */
h = iconv_open ("L1", "L1");
iconv_close (h);
/* See whether we have a cache. */
cache = __gconv_get_cache ();
if (cache != NULL)
/* Yep, use only this information. */
insert_cache ();
else
{
struct gconv_module *modules;
/* No, then use the information read from the gconv-modules file.
First add the aliases. */
twalk (__gconv_get_alias_db (), insert_print_list);
/* Add the from- and to-names from the known modules. */
modules = __gconv_get_modules_db ();
if (modules != NULL)
add_known_names (modules);
}
fputs (_("\
The following list contain all the coded character sets known. This does\n\
not necessarily mean that all combinations of these names can be used for\n\
the FROM and TO command line parameters. One coded character set can be\n\
listed with several different names (aliases).\n\n "), stdout);
/* Now print the collected names. */
column = 2;
if (isatty (fileno (stdout)))
{
twalk (printlist, do_print_human);
if (column != 0)
puts ("");
}
else
twalk (printlist, do_print);
}
@@ -1,42 +0,0 @@
/* Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 2001.
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. */
#ifndef _ICONV_PROG_H
#define _ICONV_PROG_H 1
#include <stdio.h>
#include <charmap.h>
/* Nonzero if verbose ouput is wanted. */
extern int verbose;
/* If nonzero omit invalid character from output. */
extern int omit_invalid;
/* Perform the conversion using a charmap or two. */
extern int charmap_conversion (const char *from_code,
struct charmap_t *from_charmap,
const char *to_code,
struct charmap_t *to_charmap,
int argc, int remaining, char *argv[],
FILE *output);
#endif /* iconv_prog.h */
File diff suppressed because it is too large Load Diff
@@ -1,340 +0,0 @@
/* C string table handling.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Written by Ulrich Drepper <[email protected]>, 2000.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/cdefs.h>
#include <sys/param.h>
struct Strent
{
const char *string;
size_t len;
struct Strent *next;
struct Strent *left;
struct Strent *right;
size_t offset;
char reverse[0];
};
struct memoryblock
{
struct memoryblock *next;
char memory[0];
};
struct Strtab
{
struct Strent *root;
struct memoryblock *memory;
char *backp;
size_t left;
size_t total;
struct Strent null;
};
/* Cache for the pagesize. We correct this value a bit so that `malloc'
is not allocating more than a page. */
static size_t ps;
extern void *xmalloc (size_t n) __attribute_malloc__;
/* Prototypes for our functions that are used from iconvconfig.c. If
you change these, change also iconvconfig.c. */
/* Create new C string table object in memory. */
extern struct Strtab *strtabinit (void);
/* Free resources allocated for C string table ST. */
extern void strtabfree (struct Strtab *st);
/* Add string STR (length LEN is != 0) to C string table ST. */
extern struct Strent *strtabadd (struct Strtab *st, const char *str,
size_t len);
/* Finalize string table ST and store size in *SIZE and return a pointer. */
extern void *strtabfinalize (struct Strtab *st, size_t *size);
/* Get offset in string table for string associated with SE. */
extern size_t strtaboffset (struct Strent *se);
struct Strtab *
strtabinit (void)
{
struct Strtab *ret;
if (ps == 0)
{
ps = sysconf (_SC_PAGESIZE) - 2 * sizeof (void *);
assert (sizeof (struct memoryblock) < ps);
}
ret = (struct Strtab *) calloc (1, sizeof (struct Strtab));
if (ret != NULL)
{
ret->null.len = 1;
ret->null.string = "";
}
return ret;
}
static void
morememory (struct Strtab *st, size_t len)
{
struct memoryblock *newmem;
if (len < ps)
len = ps;
newmem = (struct memoryblock *) malloc (len);
if (newmem == NULL)
abort ();
newmem->next = st->memory;
st->memory = newmem;
st->backp = newmem->memory;
st->left = len - offsetof (struct memoryblock, memory);
}
void
strtabfree (struct Strtab *st)
{
struct memoryblock *mb = st->memory;
while (mb != NULL)
{
void *old = mb;
mb = mb->next;
free (old);
}
free (st);
}
static struct Strent *
newstring (struct Strtab *st, const char *str, size_t len)
{
struct Strent *newstr;
size_t align;
int i;
/* Compute the amount of padding needed to make the structure aligned. */
align = ((__alignof__ (struct Strent)
- (((uintptr_t) st->backp)
& (__alignof__ (struct Strent) - 1)))
& (__alignof__ (struct Strent) - 1));
/* Make sure there is enough room in the memory block. */
if (st->left < align + sizeof (struct Strent) + len)
{
morememory (st, sizeof (struct Strent) + len);
align = 0;
}
/* Create the reserved string. */
newstr = (struct Strent *) (st->backp + align);
newstr->string = str;
newstr->len = len;
newstr->next = NULL;
newstr->left = NULL;
newstr->right = NULL;
newstr->offset = 0;
for (i = len - 2; i >= 0; --i)
newstr->reverse[i] = str[len - 2 - i];
newstr->reverse[len - 1] = '\0';
st->backp += align + sizeof (struct Strent) + len;
st->left -= align + sizeof (struct Strent) + len;
return newstr;
}
/* XXX This function should definitely be rewritten to use a balancing
tree algorith (AVL, red-black trees). For now a simple, correct
implementation is enough. */
static struct Strent **
searchstring (struct Strent **sep, struct Strent *newstr)
{
int cmpres;
/* More strings? */
if (*sep == NULL)
{
*sep = newstr;
return sep;
}
/* Compare the strings. */
cmpres = memcmp ((*sep)->reverse, newstr->reverse,
MIN ((*sep)->len, newstr->len) - 1);
if (cmpres == 0)
/* We found a matching string. */
return sep;
else if (cmpres > 0)
return searchstring (&(*sep)->left, newstr);
else
return searchstring (&(*sep)->right, newstr);
}
/* Add new string. The actual string is assumed to be permanent. */
struct Strent *
strtabadd (struct Strtab *st, const char *str, size_t len)
{
struct Strent *newstr;
struct Strent **sep;
/* Compute the string length if the caller doesn't know it. */
if (len == 0)
len = strlen (str) + 1;
/* Make sure all "" strings get offset 0. */
if (len == 1)
return &st->null;
/* Allocate memory for the new string and its associated information. */
newstr = newstring (st, str, len);
/* Search in the array for the place to insert the string. If there
is no string with matching prefix and no string with matching
leading substring, create a new entry. */
sep = searchstring (&st->root, newstr);
if (*sep != newstr)
{
/* This is not the same entry. This means we have a prefix match. */
if ((*sep)->len > newstr->len)
{
struct Strent *subs;
for (subs = (*sep)->next; subs; subs = subs->next)
if (subs->len == newstr->len)
{
/* We have an exact match with a substring. Free the memory
we allocated. */
st->left += st->backp - (char *) newstr;
st->backp = (char *) newstr;
return subs;
}
/* We have a new substring. This means we don't need the reverse
string of this entry anymore. */
st->backp -= newstr->len;
st->left += newstr->len;
newstr->next = (*sep)->next;
(*sep)->next = newstr;
}
else if ((*sep)->len != newstr->len)
{
/* When we get here it means that the string we are about to
add has a common prefix with a string we already have but
it is longer. In this case we have to put it first. */
st->total += newstr->len - (*sep)->len;
newstr->next = *sep;
newstr->left = (*sep)->left;
newstr->right = (*sep)->right;
*sep = newstr;
}
else
{
/* We have an exact match. Free the memory we allocated. */
st->left += st->backp - (char *) newstr;
st->backp = (char *) newstr;
newstr = *sep;
}
}
else
st->total += newstr->len;
return newstr;
}
static void
copystrings (struct Strent *nodep, char **freep, size_t *offsetp)
{
struct Strent *subs;
if (nodep->left != NULL)
copystrings (nodep->left, freep, offsetp);
/* Process the current node. */
nodep->offset = *offsetp;
*freep = (char *) mempcpy (*freep, nodep->string, nodep->len);
*offsetp += nodep->len;
for (subs = nodep->next; subs != NULL; subs = subs->next)
{
assert (subs->len < nodep->len);
subs->offset = nodep->offset + nodep->len - subs->len;
}
if (nodep->right != NULL)
copystrings (nodep->right, freep, offsetp);
}
void *
strtabfinalize (struct Strtab *st, size_t *size)
{
size_t copylen;
char *endp;
char *retval;
/* Fill in the information. */
endp = retval = (char *) xmalloc (st->total + 1);
/* Always put an empty string at the beginning so that a zero offset
can mean error. */
*endp++ = '\0';
/* Now run through the tree and add all the string while also updating
the offset members of the elfstrent records. */
copylen = 1;
copystrings (st->root, &endp, &copylen);
assert (copylen == st->total + 1);
assert (endp = retval + st->total + 1);
*size = copylen;
return retval;
}
size_t
strtaboffset (struct Strent *se)
{
return se->offset;
}
@@ -1,44 +0,0 @@
/* Test case by [email protected]. */
#include <iconv.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
int
main (void)
{
char utf8[5];
wchar_t ucs4[5];
iconv_t cd;
char *inbuf;
char *outbuf;
size_t inbytes;
size_t outbytes;
size_t n;
strcpy (utf8, "abcd");
/* From UTF8 to UCS4. */
cd = iconv_open ("UCS4", "UTF8");
if (cd == (iconv_t) -1)
{
perror ("iconv_open");
return 1;
}
inbuf = utf8;
inbytes = 4;
outbuf = (char *) ucs4;
outbytes = 4 * sizeof (wchar_t); /* "Argument list too long" error. */
n = iconv (cd, &inbuf, &inbytes, &outbuf, &outbytes);
if (n == (size_t) -1)
{
printf ("iconv: %m\n");
iconv_close (cd);
return 1;
}
iconv_close (cd);
return 0;
}
@@ -1,100 +0,0 @@
/* Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 2001.
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. */
#include <errno.h>
#include <iconv.h>
#include <mcheck.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main (void)
{
char buf[3];
const wchar_t wc[1] = L"a";
iconv_t cd;
char *inptr;
size_t inlen;
char *outptr;
size_t outlen;
size_t n;
int e;
int result = 0;
mtrace ();
cd = iconv_open ("UCS4", "WCHAR_T");
if (cd == (iconv_t) -1)
{
printf ("cannot convert from wchar_t to UCS4: %m\n");
exit (1);
}
inptr = (char *) wc;
inlen = sizeof (wchar_t);
outptr = buf;
outlen = 3;
n = iconv (cd, &inptr, &inlen, &outptr, &outlen);
e = errno;
if (n != (size_t) -1)
{
printf ("incorrect iconv() return value: %zd, expected -1\n", n);
result = 1;
}
if (e != E2BIG)
{
printf ("incorrect error value: %s, expected %s\n",
strerror (e), strerror (E2BIG));
result = 1;
}
if (inptr != (char *) wc)
{
puts ("inptr changed");
result = 1;
}
if (inlen != sizeof (wchar_t))
{
puts ("inlen changed");
result = 1;
}
if (outptr != buf)
{
puts ("outptr changed");
result = 1;
}
if (outlen != 3)
{
puts ("outlen changed");
result = 1;
}
iconv_close (cd);
return result;
}
@@ -1,53 +0,0 @@
/* Contributed by Owen Taylor <[email protected]>. */
#include <iconv.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#define BUFSIZE 10000
int
main (int argc, char *argv[])
{
char inbuf[BUFSIZE];
wchar_t outbuf[BUFSIZE];
iconv_t cd;
int i;
char *inptr;
char *outptr;
size_t inbytes_left, outbytes_left;
int count;
int result = 0;
for (i=0; i < BUFSIZE; i++)
inbuf[i] = 'a';
cd = iconv_open ("UCS-4LE", "UTF-8");
inbytes_left = BUFSIZE;
outbytes_left = BUFSIZE * 4;
inptr = inbuf;
outptr = (char *) outbuf;
count = iconv (cd, &inptr, &inbytes_left, &outptr, &outbytes_left);
if (count < 0)
{
if (errno == E2BIG)
printf ("Received E2BIG\n");
else
printf ("Received something else\n");
printf ("inptr change: %td\n", inptr - inbuf);
printf ("inlen change: %zd\n", BUFSIZE - inbytes_left);
printf ("outptr change: %zd\n", outptr - (char *) outbuf);
printf ("outlen change: %zd\n", BUFSIZE * 4 - outbytes_left);
result = 1;
}
else
printf ("Succeeded\n");
return result;
}
@@ -1,2 +0,0 @@
iconvdata
localedata
@@ -1,96 +0,0 @@
# Copyright (C) 1995-1999, 2000, 2001, 2002 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.
# Makefile for intl subdirectory: message handling code from GNU gettext.
subdir = intl
headers = libintl.h
routines = bindtextdom dcgettext dgettext gettext \
dcigettext dcngettext dngettext ngettext \
finddomain loadmsgcat localealias textdomain \
l10nflist explodename plural plural-exp
distribute = gmo.h gettextP.h hash-string.h loadinfo.h locale.alias \
plural.y plural-exp.h po2test.sed tst-gettext.sh tst-translit.sh \
translit.po tst-gettext2.sh tstlang1.po tstlang2.po tstcodeset.po\
tst-codeset.sh plural-eval.c
test-srcs := tst-gettext tst-translit tst-gettext2 tst-codeset
tests = tst-ngettext
before-compile = $(objpfx)msgs.h
install-others = $(inst_msgcatdir)/locale.alias
generated = msgs.h mtrace-tst-gettext tst-gettext.mtrace
generated-dirs := domaindir localedir
include ../Makeconfig
ifneq (no,$(BISON))
plural.c: plural.y
$(BISON) $(BISONFLAGS) $@ $^
ifeq ($(with-cvs),yes)
test ! -d CVS || cvs $(CVSOPTS) commit -m'$(BISON) $(BISONFLAGS) $@ $^' $@
endif
endif
$(objpfx)plural.o: plural.c
include ../Rules
ifeq (no,$(cross-compiling))
ifeq (yes,$(build-shared))
ifneq ($(strip $(MSGFMT)),:)
tests: $(objpfx)tst-translit.out $(objpfx)tst-gettext2.out \
$(objpfx)tst-codeset.out
ifneq (no,$(PERL))
tests: $(objpfx)mtrace-tst-gettext
endif
endif
$(objpfx)mtrace-tst-gettext: $(objpfx)tst-gettext.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-gettext.mtrace > $@
$(objpfx)tst-gettext.out: tst-gettext.sh $(objpfx)tst-gettext
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/ \
$(objpfx)tst-gettext.mtrace
$(objpfx)tst-translit.out: tst-translit.sh $(objpfx)tst-translit
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
$(objpfx)tst-gettext2.out: tst-gettext2.sh $(objpfx)tst-gettext2
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
$(objpfx)tst-codeset.out: tst-codeset.sh $(objpfx)tst-codeset
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
endif
endif
$(objpfx)msgs.h: po2test.sed ../po/de.po
$(make-target-directory)
sed -f $^ > $@
CFLAGS-tst-gettext.c = -DTESTSTRS_H=\"$(objpfx)msgs.h\"
CFLAGS-tst-gettext2.c = -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-translit.c = -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-codeset.c = -DOBJPFX=\"$(objpfx)\"
$(objpfx)tst-translit.out: $(objpfx)tst-gettext.out
$(objpfx)tst-gettext2.out: $(objpfx)tst-gettext.out
$(objpfx)tst-codeset.out: $(objpfx)tst-gettext.out
CPPFLAGS += -D'LOCALEDIR="$(msgcatdir)"' \
-D'LOCALE_ALIAS_PATH="$(msgcatdir)"'
BISONFLAGS = --yacc --name-prefix=__gettext --output
$(inst_msgcatdir)/locale.alias: locale.alias $(+force)
$(do-install)
@@ -1,31 +0,0 @@
libc {
GLIBC_2.0 {
# global variables
_nl_msg_cat_cntr; _nl_default_dirname; _nl_domain_bindings;
# functions used in inline functions or macros
__dcgettext;
# functions used in other libraries
__dgettext;
# b*
bindtextdomain;
# d*
dcgettext; dgettext; gettext;
# t*
textdomain;
}
GLIBC_2.2 {
# b*
bind_textdomain_codeset;
# d*
dcngettext; dngettext;
# n*
ngettext;
}
}
@@ -1,375 +0,0 @@
/* Implementation of the bindtextdomain(3) function
Copyright (C) 1995-1998, 2000, 2001, 2002 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
#include "gettextP.h"
#ifdef _LIBC
/* We have to handle multi-threaded applications. */
# include <bits/libc-lock.h>
#else
/* Provide dummy implementation if this is outside glibc. */
# define __libc_rwlock_define(CLASS, NAME)
# define __libc_rwlock_wrlock(NAME)
# define __libc_rwlock_unlock(NAME)
#endif
/* The internal variables in the standalone libintl.a must have different
names than the internal variables in GNU libc, otherwise programs
using libintl.a cannot be linked statically. */
#if !defined _LIBC
# define _nl_default_dirname libintl_nl_default_dirname
# define _nl_domain_bindings libintl_nl_domain_bindings
#endif
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
#ifndef offsetof
# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
#endif
/* @@ end of prolog @@ */
/* Contains the default location of the message catalogs. */
extern const char _nl_default_dirname[];
#ifdef _LIBC
extern const char _nl_default_dirname_internal[] attribute_hidden;
#else
# define INTUSE(name) name
#endif
/* List with bindings of specific domains. */
extern struct binding *_nl_domain_bindings;
/* Lock variable to protect the global data in the gettext implementation. */
__libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define BINDTEXTDOMAIN __bindtextdomain
# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
# ifndef strdup
# define strdup(str) __strdup (str)
# endif
#else
# define BINDTEXTDOMAIN libintl_bindtextdomain
# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
#endif
/* Prototypes for local functions. */
static void set_binding_values PARAMS ((const char *domainname,
const char **dirnamep,
const char **codesetp));
/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
to be used for the DOMAINNAME message catalog.
If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
modified, only the current value is returned.
If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
modified nor returned. */
static void
set_binding_values (domainname, dirnamep, codesetp)
const char *domainname;
const char **dirnamep;
const char **codesetp;
{
struct binding *binding;
int modified;
/* Some sanity checks. */
if (domainname == NULL || domainname[0] == '\0')
{
if (dirnamep)
*dirnamep = NULL;
if (codesetp)
*codesetp = NULL;
return;
}
__libc_rwlock_wrlock (_nl_state_lock);
modified = 0;
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
{
int compare = strcmp (domainname, binding->domainname);
if (compare == 0)
/* We found it! */
break;
if (compare < 0)
{
/* It is not in the list. */
binding = NULL;
break;
}
}
if (binding != NULL)
{
if (dirnamep)
{
const char *dirname = *dirnamep;
if (dirname == NULL)
/* The current binding has be to returned. */
*dirnamep = binding->dirname;
else
{
/* The domain is already bound. If the new value and the old
one are equal we simply do nothing. Otherwise replace the
old binding. */
char *result = binding->dirname;
if (strcmp (dirname, result) != 0)
{
if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
result = (char *) INTUSE(_nl_default_dirname);
else
{
#if defined _LIBC || defined HAVE_STRDUP
result = strdup (dirname);
#else
size_t len = strlen (dirname) + 1;
result = (char *) malloc (len);
if (__builtin_expect (result != NULL, 1))
memcpy (result, dirname, len);
#endif
}
if (__builtin_expect (result != NULL, 1))
{
if (binding->dirname != INTUSE(_nl_default_dirname))
free (binding->dirname);
binding->dirname = result;
modified = 1;
}
}
*dirnamep = result;
}
}
if (codesetp)
{
const char *codeset = *codesetp;
if (codeset == NULL)
/* The current binding has be to returned. */
*codesetp = binding->codeset;
else
{
/* The domain is already bound. If the new value and the old
one are equal we simply do nothing. Otherwise replace the
old binding. */
char *result = binding->codeset;
if (result == NULL || strcmp (codeset, result) != 0)
{
#if defined _LIBC || defined HAVE_STRDUP
result = strdup (codeset);
#else
size_t len = strlen (codeset) + 1;
result = (char *) malloc (len);
if (__builtin_expect (result != NULL, 1))
memcpy (result, codeset, len);
#endif
if (__builtin_expect (result != NULL, 1))
{
if (binding->codeset != NULL)
free (binding->codeset);
binding->codeset = result;
++binding->codeset_cntr;
modified = 1;
}
}
*codesetp = result;
}
}
}
else if ((dirnamep == NULL || *dirnamep == NULL)
&& (codesetp == NULL || *codesetp == NULL))
{
/* Simply return the default values. */
if (dirnamep)
*dirnamep = INTUSE(_nl_default_dirname);
if (codesetp)
*codesetp = NULL;
}
else
{
/* We have to create a new binding. */
size_t len = strlen (domainname) + 1;
struct binding *new_binding =
(struct binding *) malloc (offsetof (struct binding, domainname) + len);
if (__builtin_expect (new_binding == NULL, 0))
goto failed;
memcpy (new_binding->domainname, domainname, len);
if (dirnamep)
{
const char *dirname = *dirnamep;
if (dirname == NULL)
/* The default value. */
dirname = INTUSE(_nl_default_dirname);
else
{
if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
dirname = INTUSE(_nl_default_dirname);
else
{
char *result;
#if defined _LIBC || defined HAVE_STRDUP
result = strdup (dirname);
if (__builtin_expect (result == NULL, 0))
goto failed_dirname;
#else
size_t len = strlen (dirname) + 1;
result = (char *) malloc (len);
if (__builtin_expect (result == NULL, 0))
goto failed_dirname;
memcpy (result, dirname, len);
#endif
dirname = result;
}
}
*dirnamep = dirname;
new_binding->dirname = (char *) dirname;
}
else
/* The default value. */
new_binding->dirname = (char *) INTUSE(_nl_default_dirname);
new_binding->codeset_cntr = 0;
if (codesetp)
{
const char *codeset = *codesetp;
if (codeset != NULL)
{
char *result;
#if defined _LIBC || defined HAVE_STRDUP
result = strdup (codeset);
if (__builtin_expect (result == NULL, 0))
goto failed_codeset;
#else
size_t len = strlen (codeset) + 1;
result = (char *) malloc (len);
if (__builtin_expect (result == NULL, 0))
goto failed_codeset;
memcpy (result, codeset, len);
#endif
codeset = result;
++new_binding->codeset_cntr;
}
*codesetp = codeset;
new_binding->codeset = (char *) codeset;
}
else
new_binding->codeset = NULL;
/* Now enqueue it. */
if (_nl_domain_bindings == NULL
|| strcmp (domainname, _nl_domain_bindings->domainname) < 0)
{
new_binding->next = _nl_domain_bindings;
_nl_domain_bindings = new_binding;
}
else
{
binding = _nl_domain_bindings;
while (binding->next != NULL
&& strcmp (domainname, binding->next->domainname) > 0)
binding = binding->next;
new_binding->next = binding->next;
binding->next = new_binding;
}
modified = 1;
/* Here we deal with memory allocation failures. */
if (0)
{
failed_codeset:
if (new_binding->dirname != INTUSE(_nl_default_dirname))
free (new_binding->dirname);
failed_dirname:
free (new_binding);
failed:
if (dirnamep)
*dirnamep = NULL;
if (codesetp)
*codesetp = NULL;
}
}
/* If we modified any binding, we flush the caches. */
if (modified)
++_nl_msg_cat_cntr;
__libc_rwlock_unlock (_nl_state_lock);
}
/* Specify that the DOMAINNAME message catalog will be found
in DIRNAME rather than in the system locale data base. */
char *
BINDTEXTDOMAIN (domainname, dirname)
const char *domainname;
const char *dirname;
{
set_binding_values (domainname, &dirname, NULL);
return (char *) dirname;
}
/* Specify the character encoding in which the messages from the
DOMAINNAME message catalog will be returned. */
char *
BIND_TEXTDOMAIN_CODESET (domainname, codeset)
const char *domainname;
const char *codeset;
{
set_binding_values (domainname, NULL, &codeset);
return (char *) codeset;
}
#ifdef _LIBC
/* Aliases for function names in GNU C Library. */
weak_alias (__bindtextdomain, bindtextdomain);
weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
#endif
@@ -1,60 +0,0 @@
/* Implementation of the dcgettext(3) function.
Copyright (C) 1995-1999, 2000, 2001, 2002 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "gettextP.h"
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
/* @@ end of prolog @@ */
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define DCGETTEXT __dcgettext
# define DCIGETTEXT __dcigettext
#else
# define DCGETTEXT libintl_dcgettext
# define DCIGETTEXT libintl_dcigettext
#endif
/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
locale. */
char *
DCGETTEXT (domainname, msgid, category)
const char *domainname;
const char *msgid;
int category;
{
return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category);
}
#ifdef _LIBC
/* Alias for function name in GNU C Library. */
INTDEF(__dcgettext)
weak_alias (__dcgettext, dcgettext);
#endif
File diff suppressed because it is too large Load Diff
@@ -1,61 +0,0 @@
/* Implementation of the dcngettext(3) function.
Copyright (C) 1995-1999, 2000, 2001, 2002 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "gettextP.h"
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
/* @@ end of prolog @@ */
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define DCNGETTEXT __dcngettext
# define DCIGETTEXT __dcigettext
#else
# define DCNGETTEXT libintl_dcngettext
# define DCIGETTEXT libintl_dcigettext
#endif
/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
locale. */
char *
DCNGETTEXT (domainname, msgid1, msgid2, n, category)
const char *domainname;
const char *msgid1;
const char *msgid2;
unsigned long int n;
int category;
{
return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category);
}
#ifdef _LIBC
/* Alias for function name in GNU C Library. */
weak_alias (__dcngettext, dcngettext);
#endif
@@ -1,60 +0,0 @@
/* Implementation of the dgettext(3) function.
Copyright (C) 1995-1997, 2000, 2001, 2002 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <locale.h>
#include "gettextP.h"
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
/* @@ end of prolog @@ */
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define DGETTEXT __dgettext
# define DCGETTEXT INTUSE(__dcgettext)
#else
# define DGETTEXT libintl_dgettext
# define DCGETTEXT libintl_dcgettext
#endif
/* Look up MSGID in the DOMAINNAME message catalog of the current
LC_MESSAGES locale. */
char *
DGETTEXT (domainname, msgid)
const char *domainname;
const char *msgid;
{
return DCGETTEXT (domainname, msgid, LC_MESSAGES);
}
#ifdef _LIBC
/* Alias for function name in GNU C Library. */
weak_alias (__dgettext, dgettext);
#endif
@@ -1,62 +0,0 @@
/* Implementation of the dngettext(3) function.
Copyright (C) 1995-1997, 2000, 2001, 2002 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <locale.h>
#include "gettextP.h"
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
/* @@ end of prolog @@ */
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define DNGETTEXT __dngettext
# define DCNGETTEXT __dcngettext
#else
# define DNGETTEXT libintl_dngettext
# define DCNGETTEXT libintl_dcngettext
#endif
/* Look up MSGID in the DOMAINNAME message catalog of the current
LC_MESSAGES locale and skip message according to the plural form. */
char *
DNGETTEXT (domainname, msgid1, msgid2, n)
const char *domainname;
const char *msgid1;
const char *msgid2;
unsigned long int n;
{
return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES);
}
#ifdef _LIBC
/* Alias for function name in GNU C Library. */
weak_alias (__dngettext, dngettext);
#endif
@@ -1,136 +0,0 @@
/* Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1995.
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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "loadinfo.h"
/* On some strange systems still no definition of NULL is found. Sigh! */
#ifndef NULL
# if defined __STDC__ && __STDC__
# define NULL ((void *) 0)
# else
# define NULL 0
# endif
#endif
/* @@ end of prolog @@ */
static char *_nl_find_language PARAMS ((const char *name));
static char *
_nl_find_language (name)
const char *name;
{
while (name[0] != '\0' && name[0] != '_' && name[0] != '@' && name[0] != '.')
++name;
return (char *) name;
}
int
_nl_explode_name (name, language, modifier, territory, codeset,
normalized_codeset)
char *name;
const char **language;
const char **modifier;
const char **territory;
const char **codeset;
const char **normalized_codeset;
{
char *cp;
int mask;
*modifier = NULL;
*territory = NULL;
*codeset = NULL;
*normalized_codeset = NULL;
/* Now we determine the single parts of the locale name. First
look for the language. Termination symbols are `_', '.', and `@'. */
mask = 0;
*language = cp = name;
cp = _nl_find_language (*language);
if (*language == cp)
/* This does not make sense: language has to be specified. Use
this entry as it is without exploding. Perhaps it is an alias. */
cp = strchr (*language, '\0');
else if (cp[0] != '@')
{
if (cp[0] == '_')
{
/* Next is the territory. */
cp[0] = '\0';
*territory = ++cp;
while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@')
++cp;
mask |= XPG_TERRITORY;
}
if (cp[0] == '.')
{
/* Next is the codeset. */
cp[0] = '\0';
*codeset = ++cp;
while (cp[0] != '\0' && cp[0] != '@')
++cp;
mask |= XPG_CODESET;
if (*codeset != cp && (*codeset)[0] != '\0')
{
*normalized_codeset = _nl_normalize_codeset (*codeset,
cp - *codeset);
if (strcmp (*codeset, *normalized_codeset) == 0)
free ((char *) *normalized_codeset);
else
mask |= XPG_NORM_CODESET;
}
}
}
if (cp[0] == '@')
{
/* Next is the modifier. */
cp[0] = '\0';
*modifier = ++cp;
if (cp[0] != '\0')
mask |= XPG_MODIFIER;
}
if (*territory != NULL && (*territory)[0] == '\0')
mask &= ~XPG_TERRITORY;
if (*codeset != NULL && (*codeset)[0] == '\0')
mask &= ~XPG_CODESET;
return mask;
}
@@ -1,185 +0,0 @@
/* Handle list of needed message catalogs
Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <drepper@gnu.org>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#if defined HAVE_UNISTD_H || defined _LIBC
# include <unistd.h>
#endif
#include "gettextP.h"
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
/* @@ end of prolog @@ */
/* List of already loaded domains. */
static struct loaded_l10nfile *_nl_loaded_domains;
/* Return a data structure describing the message catalog described by
the DOMAINNAME and CATEGORY parameters with respect to the currently
established bindings. */
struct loaded_l10nfile *
internal_function
_nl_find_domain (dirname, locale, domainname, domainbinding)
const char *dirname;
char *locale;
const char *domainname;
struct binding *domainbinding;
{
struct loaded_l10nfile *retval;
const char *language;
const char *modifier;
const char *territory;
const char *codeset;
const char *normalized_codeset;
const char *alias_value;
int mask;
/* LOCALE can consist of up to four recognized parts for the XPG syntax:
language[_territory[.codeset]][@modifier]
Beside the first part all of them are allowed to be missing. If
the full specified locale is not found, the less specific one are
looked for. The various parts will be stripped off according to
the following order:
(1) codeset
(2) normalized codeset
(3) territory
(4) modifier
*/
/* If we have already tested for this locale entry there has to
be one data set in the list of loaded domains. */
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
strlen (dirname) + 1, 0, locale, NULL, NULL,
NULL, NULL, domainname, 0);
if (retval != NULL)
{
/* We know something about this locale. */
int cnt;
if (retval->decided == 0)
_nl_load_domain (retval, domainbinding);
if (retval->data != NULL)
return retval;
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
{
if (retval->successor[cnt]->decided == 0)
_nl_load_domain (retval->successor[cnt], domainbinding);
if (retval->successor[cnt]->data != NULL)
break;
}
return cnt >= 0 ? retval : NULL;
/* NOTREACHED */
}
/* See whether the locale value is an alias. If yes its value
*overwrites* the alias name. No test for the original value is
done. */
alias_value = _nl_expand_alias (locale);
if (alias_value != NULL)
{
#if defined _LIBC || defined HAVE_STRDUP
locale = strdup (alias_value);
if (locale == NULL)
return NULL;
#else
size_t len = strlen (alias_value) + 1;
locale = (char *) malloc (len);
if (locale == NULL)
return NULL;
memcpy (locale, alias_value, len);
#endif
}
/* Now we determine the single parts of the locale name. First
look for the language. Termination symbols are `_' and `@' if
we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */
mask = _nl_explode_name (locale, &language, &modifier, &territory,
&codeset, &normalized_codeset);
/* Create all possible locale entries which might be interested in
generalization. */
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
strlen (dirname) + 1, mask, language, territory,
codeset, normalized_codeset, modifier,
domainname, 1);
if (retval == NULL)
/* This means we are out of core. */
return NULL;
if (retval->decided == 0)
_nl_load_domain (retval, domainbinding);
if (retval->data == NULL)
{
int cnt;
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
{
if (retval->successor[cnt]->decided == 0)
_nl_load_domain (retval->successor[cnt], domainbinding);
if (retval->successor[cnt]->data != NULL)
break;
}
}
/* The room for an alias was dynamically allocated. Free it now. */
if (alias_value != NULL)
free (locale);
/* The space for normalized_codeset is dynamically allocated. Free it. */
if (mask & XPG_NORM_CODESET)
free ((void *) normalized_codeset);
return retval;
}
#ifdef _LIBC
libc_freeres_fn (free_mem)
{
struct loaded_l10nfile *runp = _nl_loaded_domains;
while (runp != NULL)
{
struct loaded_l10nfile *here = runp;
if (runp->data != NULL)
_nl_unload_domain ((struct loaded_domain *) runp->data);
runp = runp->next;
free ((char *) here->filename);
free (here);
}
}
#endif
@@ -1,65 +0,0 @@
/* Implementation of gettext(3) function.
Copyright (C) 1995, 1997, 2000, 2001, 2002 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef _LIBC
# define __need_NULL
# include <stddef.h>
#else
# include <stdlib.h> /* Just for NULL. */
#endif
#include "gettextP.h"
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
/* @@ end of prolog @@ */
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define GETTEXT __gettext
# define DCGETTEXT INTUSE(__dcgettext)
#else
# define GETTEXT libintl_gettext
# define DCGETTEXT libintl_dcgettext
#endif
/* Look up MSGID in the current default message catalog for the current
LC_MESSAGES locale. If not found, returns MSGID itself (the default
text). */
char *
GETTEXT (msgid)
const char *msgid;
{
return DCGETTEXT (NULL, msgid, LC_MESSAGES);
}
#ifdef _LIBC
/* Alias for function name in GNU C Library. */
weak_alias (__gettext, gettext);
#endif
@@ -1,245 +0,0 @@
/* Header describing internals of libintl library.
Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU 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. */
#ifndef _GETTEXTP_H
#define _GETTEXTP_H
#include <stddef.h> /* Get size_t. */
#ifdef _LIBC
# include "../iconv/gconv_int.h"
#else
# if HAVE_ICONV
# include <iconv.h>
# endif
#endif
#include "loadinfo.h"
#include "gmo.h" /* Get nls_uint32. */
/* @@ end of prolog @@ */
#ifndef PARAMS
# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
# define PARAMS(args) args
# else
# define PARAMS(args) ()
# endif
#endif
#ifndef internal_function
# define internal_function
#endif
#ifndef attribute_hidden
# define attribute_hidden
#endif
/* Tell the compiler when a conditional or integer expression is
almost always true or almost always false. */
#ifndef HAVE_BUILTIN_EXPECT
# define __builtin_expect(expr, val) (expr)
#endif
#ifndef W
# define W(flag, data) ((flag) ? SWAP (data) : (data))
#endif
#ifdef _LIBC
# include <byteswap.h>
# define SWAP(i) bswap_32 (i)
#else
static nls_uint32 SWAP PARAMS ((nls_uint32 i));
static inline nls_uint32
SWAP (i)
nls_uint32 i;
{
return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
}
#endif
/* In-memory representation of system dependent string. */
struct sysdep_string_desc
{
/* Length of addressed string, including the trailing NUL. */
size_t length;
/* Pointer to addressed string. */
const char *pointer;
};
/* The representation of an opened message catalog. */
struct loaded_domain
{
/* Pointer to memory containing the .mo file. */
const char *data;
/* 1 if the memory is mmap()ed, 0 if the memory is malloc()ed. */
int use_mmap;
/* Size of mmap()ed memory. */
size_t mmap_size;
/* 1 if the .mo file uses a different endianness than this machine. */
int must_swap;
/* Pointer to additional malloc()ed memory. */
void *malloced;
/* Number of static strings pairs. */
nls_uint32 nstrings;
/* Pointer to descriptors of original strings in the file. */
const struct string_desc *orig_tab;
/* Pointer to descriptors of translated strings in the file. */
const struct string_desc *trans_tab;
/* Number of system dependent strings pairs. */
nls_uint32 n_sysdep_strings;
/* Pointer to descriptors of original sysdep strings. */
const struct sysdep_string_desc *orig_sysdep_tab;
/* Pointer to descriptors of translated sysdep strings. */
const struct sysdep_string_desc *trans_sysdep_tab;
/* Size of hash table. */
nls_uint32 hash_size;
/* Pointer to hash table. */
const nls_uint32 *hash_tab;
/* 1 if the hash table uses a different endianness than this machine. */
int must_swap_hash_tab;
int codeset_cntr;
#ifdef _LIBC
__gconv_t conv;
#else
# if HAVE_ICONV
iconv_t conv;
# endif
#endif
char **conv_tab;
struct expression *plural;
unsigned long int nplurals;
};
/* We want to allocate a string at the end of the struct. But ISO C
doesn't allow zero sized arrays. */
#ifdef __GNUC__
# define ZERO 0
#else
# define ZERO 1
#endif
/* A set of settings bound to a message domain. Used to store settings
from bindtextdomain() and bind_textdomain_codeset(). */
struct binding
{
struct binding *next;
char *dirname;
int codeset_cntr; /* Incremented each time codeset changes. */
char *codeset;
char domainname[ZERO];
};
/* A counter which is incremented each time some previous translations
become invalid.
This variable is part of the external ABI of the GNU libintl. */
extern int _nl_msg_cat_cntr;
#ifndef _LIBC
const char *_nl_locale_name PARAMS ((int category, const char *categoryname));
#endif
struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
char *__locale,
const char *__domainname,
struct binding *__domainbinding))
internal_function;
void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain,
struct binding *__domainbinding))
internal_function;
void _nl_unload_domain PARAMS ((struct loaded_domain *__domain))
internal_function;
const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file,
struct loaded_domain *__domain,
struct binding *__domainbinding))
internal_function;
void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain))
internal_function;
char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
struct binding *domainbinding,
const char *msgid, size_t *lengthp))
internal_function;
#ifdef _LIBC
extern char *__gettext PARAMS ((const char *__msgid));
extern char *__dgettext PARAMS ((const char *__domainname,
const char *__msgid));
extern char *__dcgettext PARAMS ((const char *__domainname,
const char *__msgid, int __category));
extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2,
unsigned long int __n));
extern char *__dngettext PARAMS ((const char *__domainname,
const char *__msgid1, const char *__msgid2,
unsigned long int n));
extern char *__dcngettext PARAMS ((const char *__domainname,
const char *__msgid1, const char *__msgid2,
unsigned long int __n, int __category));
extern char *__dcigettext PARAMS ((const char *__domainname,
const char *__msgid1, const char *__msgid2,
int __plural, unsigned long int __n,
int __category));
extern char *__textdomain PARAMS ((const char *__domainname));
extern char *__bindtextdomain PARAMS ((const char *__domainname,
const char *__dirname));
extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname,
const char *__codeset));
#else
extern char *libintl_gettext PARAMS ((const char *__msgid));
extern char *libintl_dgettext PARAMS ((const char *__domainname,
const char *__msgid));
extern char *libintl_dcgettext PARAMS ((const char *__domainname,
const char *__msgid, int __category));
extern char *libintl_ngettext PARAMS ((const char *__msgid1,
const char *__msgid2,
unsigned long int __n));
extern char *libintl_dngettext PARAMS ((const char *__domainname,
const char *__msgid1,
const char *__msgid2,
unsigned long int __n));
extern char *libintl_dcngettext PARAMS ((const char *__domainname,
const char *__msgid1,
const char *__msgid2,
unsigned long int __n,
int __category));
extern char *libintl_dcigettext PARAMS ((const char *__domainname,
const char *__msgid1,
const char *__msgid2,
int __plural, unsigned long int __n,
int __category));
extern char *libintl_textdomain PARAMS ((const char *__domainname));
extern char *libintl_bindtextdomain PARAMS ((const char *__domainname,
const char *__dirname));
extern char *libintl_bind_textdomain_codeset PARAMS ((const char *__domainname,
const char *__codeset));
#endif
/* @@ begin of epilog @@ */
#endif /* gettextP.h */
-149
View File
@@ -1,149 +0,0 @@
/* Internal header for GNU gettext internationalization functions.
Copyright (C) 1995, 1997, 2000-2002 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. */
#ifndef _GETTEXT_H
#define _GETTEXT_H 1
#include <limits.h>
/* @@ end of prolog @@ */
/* The magic number of the GNU message catalog format. */
#define _MAGIC 0x950412de
#define _MAGIC_SWAPPED 0xde120495
/* Revision number of the currently used .mo (binary) file format. */
#define MO_REVISION_NUMBER 0
/* The following contortions are an attempt to use the C preprocessor
to determine an unsigned integral type that is 32 bits wide. An
alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work
when cross-compiling. */
#if __STDC__
# define UINT_MAX_32_BITS 4294967295U
#else
# define UINT_MAX_32_BITS 0xFFFFFFFF
#endif
/* If UINT_MAX isn't defined, assume it's a 32-bit type.
This should be valid for all systems GNU cares about because
that doesn't include 16-bit systems, and only modern systems
(that certainly have <limits.h>) have 64+-bit integral types. */
#ifndef UINT_MAX
# define UINT_MAX UINT_MAX_32_BITS
#endif
#if UINT_MAX == UINT_MAX_32_BITS
typedef unsigned nls_uint32;
#else
# if USHRT_MAX == UINT_MAX_32_BITS
typedef unsigned short nls_uint32;
# else
# if ULONG_MAX == UINT_MAX_32_BITS
typedef unsigned long nls_uint32;
# else
/* The following line is intended to throw an error. Using #error is
not portable enough. */
"Cannot determine unsigned 32-bit data type."
# endif
# endif
#endif
/* Header for binary .mo file format. */
struct mo_file_header
{
/* The magic number. */
nls_uint32 magic;
/* The revision number of the file format. */
nls_uint32 revision;
/* The following are only used in .mo files with major revision 0. */
/* The number of strings pairs. */
nls_uint32 nstrings;
/* Offset of table with start offsets of original strings. */
nls_uint32 orig_tab_offset;
/* Offset of table with start offsets of translated strings. */
nls_uint32 trans_tab_offset;
/* Size of hash table. */
nls_uint32 hash_tab_size;
/* Offset of first hash table entry. */
nls_uint32 hash_tab_offset;
/* The following are only used in .mo files with minor revision >= 1. */
/* The number of system dependent segments. */
nls_uint32 n_sysdep_segments;
/* Offset of table describing system dependent segments. */
nls_uint32 sysdep_segments_offset;
/* The number of system dependent strings pairs. */
nls_uint32 n_sysdep_strings;
/* Offset of table with start offsets of original sysdep strings. */
nls_uint32 orig_sysdep_tab_offset;
/* Offset of table with start offsets of translated sysdep strings. */
nls_uint32 trans_sysdep_tab_offset;
};
/* Descriptor for static string contained in the binary .mo file. */
struct string_desc
{
/* Length of addressed string, not including the trailing NUL. */
nls_uint32 length;
/* Offset of string in file. */
nls_uint32 offset;
};
/* The following are only used in .mo files with minor revision >= 1. */
/* Descriptor for system dependent string segment. */
struct sysdep_segment
{
/* Length of addressed string, including the trailing NUL. */
nls_uint32 length;
/* Offset of string in file. */
nls_uint32 offset;
};
/* Descriptor for system dependent string. */
struct sysdep_string
{
/* Offset of static string segments in file. */
nls_uint32 offset;
/* Alternating sequence of static and system dependent segments.
The last segment is a static segment, including the trailing NUL. */
struct segment_pair
{
/* Size of static segment. */
nls_uint32 segsize;
/* Reference to system dependent string segment, or ~0 at the end. */
nls_uint32 sysdepref;
} segments[1];
};
/* Marker for the end of the segments[] array. This has the value 0xFFFFFFFF,
regardless whether 'int' is 16 bit, 32 bit, or 64 bit. */
#define SEGMENTS_END ((nls_uint32) ~0)
/* @@ begin of epilog @@ */
#endif /* gettext.h */
@@ -1,377 +0,0 @@
/* Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
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. */
/* Tell glibc's <string.h> to provide a prototype for stpcpy().
This must come before <config.h> because <config.h> may include
<features.h>, and once <features.h> has been included, it's too late. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#if defined _LIBC || defined HAVE_ARGZ_H
# include <argz.h>
#endif
#include <ctype.h>
#include <sys/types.h>
#include <stdlib.h>
#include "loadinfo.h"
/* On some strange systems still no definition of NULL is found. Sigh! */
#ifndef NULL
# if defined __STDC__ && __STDC__
# define NULL ((void *) 0)
# else
# define NULL 0
# endif
#endif
/* @@ end of prolog @@ */
#ifdef _LIBC
/* Rename the non ANSI C functions. This is required by the standard
because some ANSI C functions will require linking with this object
file and the name space must not be polluted. */
# ifndef stpcpy
# define stpcpy(dest, src) __stpcpy(dest, src)
# endif
#else
# ifndef HAVE_STPCPY
static char *stpcpy PARAMS ((char *dest, const char *src));
# endif
#endif
/* Define function which are usually not available. */
#if !defined _LIBC && !defined HAVE___ARGZ_COUNT
/* Returns the number of strings in ARGZ. */
static size_t argz_count__ PARAMS ((const char *argz, size_t len));
static size_t
argz_count__ (argz, len)
const char *argz;
size_t len;
{
size_t count = 0;
while (len > 0)
{
size_t part_len = strlen (argz);
argz += part_len + 1;
len -= part_len + 1;
count++;
}
return count;
}
# undef __argz_count
# define __argz_count(argz, len) argz_count__ (argz, len)
#else
# ifdef _LIBC
# define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
# endif
#endif /* !_LIBC && !HAVE___ARGZ_COUNT */
#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
except the last into the character SEP. */
static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
static void
argz_stringify__ (argz, len, sep)
char *argz;
size_t len;
int sep;
{
while (len > 0)
{
size_t part_len = strlen (argz);
argz += part_len;
len -= part_len + 1;
if (len > 0)
*argz++ = sep;
}
}
# undef __argz_stringify
# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
#else
# ifdef _LIBC
# define __argz_stringify(argz, len, sep) \
INTUSE(__argz_stringify) (argz, len, sep)
# endif
#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
#if !defined _LIBC && !defined HAVE___ARGZ_NEXT
static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
const char *entry));
static char *
argz_next__ (argz, argz_len, entry)
char *argz;
size_t argz_len;
const char *entry;
{
if (entry)
{
if (entry < argz + argz_len)
entry = strchr (entry, '\0') + 1;
return entry >= argz + argz_len ? NULL : (char *) entry;
}
else
if (argz_len > 0)
return argz;
else
return 0;
}
# undef __argz_next
# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
#endif /* !_LIBC && !HAVE___ARGZ_NEXT */
/* Return number of bits set in X. */
static int pop PARAMS ((int x));
static inline int
pop (x)
int x;
{
/* We assume that no more than 16 bits are used. */
x = ((x & ~0x5555) >> 1) + (x & 0x5555);
x = ((x & ~0x3333) >> 2) + (x & 0x3333);
x = ((x >> 4) + x) & 0x0f0f;
x = ((x >> 8) + x) & 0xff;
return x;
}
struct loaded_l10nfile *
_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
territory, codeset, normalized_codeset, modifier,
filename, do_allocate)
struct loaded_l10nfile **l10nfile_list;
const char *dirlist;
size_t dirlist_len;
int mask;
const char *language;
const char *territory;
const char *codeset;
const char *normalized_codeset;
const char *modifier;
const char *filename;
int do_allocate;
{
char *abs_filename;
struct loaded_l10nfile *last = NULL;
struct loaded_l10nfile *retval;
char *cp;
size_t entries;
int cnt;
/* Allocate room for the full file name. */
abs_filename = (char *) malloc (dirlist_len
+ strlen (language)
+ ((mask & XPG_TERRITORY) != 0
? strlen (territory) + 1 : 0)
+ ((mask & XPG_CODESET) != 0
? strlen (codeset) + 1 : 0)
+ ((mask & XPG_NORM_CODESET) != 0
? strlen (normalized_codeset) + 1 : 0)
+ ((mask & XPG_MODIFIER) != 0
? strlen (modifier) + 1 : 0)
+ 1 + strlen (filename) + 1);
if (abs_filename == NULL)
return NULL;
retval = NULL;
last = NULL;
/* Construct file name. */
memcpy (abs_filename, dirlist, dirlist_len);
__argz_stringify (abs_filename, dirlist_len, ':');
cp = abs_filename + (dirlist_len - 1);
*cp++ = '/';
cp = stpcpy (cp, language);
if ((mask & XPG_TERRITORY) != 0)
{
*cp++ = '_';
cp = stpcpy (cp, territory);
}
if ((mask & XPG_CODESET) != 0)
{
*cp++ = '.';
cp = stpcpy (cp, codeset);
}
if ((mask & XPG_NORM_CODESET) != 0)
{
*cp++ = '.';
cp = stpcpy (cp, normalized_codeset);
}
if ((mask & XPG_MODIFIER) != 0)
{
*cp++ = '@';
cp = stpcpy (cp, modifier);
}
*cp++ = '/';
stpcpy (cp, filename);
/* Look in list of already loaded domains whether it is already
available. */
last = NULL;
for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
if (retval->filename != NULL)
{
int compare = strcmp (retval->filename, abs_filename);
if (compare == 0)
/* We found it! */
break;
if (compare < 0)
{
/* It's not in the list. */
retval = NULL;
break;
}
last = retval;
}
if (retval != NULL || do_allocate == 0)
{
free (abs_filename);
return retval;
}
retval = (struct loaded_l10nfile *)
malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
* (1 << pop (mask))
* sizeof (struct loaded_l10nfile *)));
if (retval == NULL)
return NULL;
retval->filename = abs_filename;
retval->decided = (__argz_count (dirlist, dirlist_len) != 1
|| ((mask & XPG_CODESET) != 0
&& (mask & XPG_NORM_CODESET) != 0));
retval->data = NULL;
if (last == NULL)
{
retval->next = *l10nfile_list;
*l10nfile_list = retval;
}
else
{
retval->next = last->next;
last->next = retval;
}
entries = 0;
/* If the DIRLIST is a real list the RETVAL entry corresponds not to
a real file. So we have to use the DIRLIST separation mechanism
of the inner loop. */
cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
for (; cnt >= 0; --cnt)
if ((cnt & ~mask) == 0)
{
/* Iterate over all elements of the DIRLIST. */
char *dir = NULL;
while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
!= NULL)
retval->successor[entries++]
= _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
language, territory, codeset,
normalized_codeset, modifier, filename, 1);
}
retval->successor[entries] = NULL;
return retval;
}
/* Normalize codeset name. There is no standard for the codeset
names. Normalization allows the user to use any of the common
names. The return value is dynamically allocated and has to be
freed by the caller. */
const char *
_nl_normalize_codeset (codeset, name_len)
const char *codeset;
size_t name_len;
{
int len = 0;
int only_digit = 1;
char *retval;
char *wp;
size_t cnt;
for (cnt = 0; cnt < name_len; ++cnt)
if (isalnum ((unsigned char) codeset[cnt]))
{
++len;
if (isalpha ((unsigned char) codeset[cnt]))
only_digit = 0;
}
retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
if (retval != NULL)
{
if (only_digit)
wp = stpcpy (retval, "iso");
else
wp = retval;
for (cnt = 0; cnt < name_len; ++cnt)
if (isalpha ((unsigned char) codeset[cnt]))
*wp++ = tolower ((unsigned char) codeset[cnt]);
else if (isdigit ((unsigned char) codeset[cnt]))
*wp++ = codeset[cnt];
*wp = '\0';
}
return (const char *) retval;
}
/* @@ begin of epilog @@ */
/* We don't want libintl.a to depend on any other library. So we
avoid the non-standard function stpcpy. In GNU C Library this
function is available, though. Also allow the symbol HAVE_STPCPY
to be defined. */
#if !_LIBC && !HAVE_STPCPY
static char *
stpcpy (dest, src)
char *dest;
const char *src;
{
while ((*dest++ = *src++) != '\0')
/* Do nothing. */ ;
return dest - 1;
}
#endif
@@ -1,122 +0,0 @@
/* Message catalogs for internationalization.
Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This file is derived from the file libgettext.h in the GNU gettext package.
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. */
#ifndef _LIBINTL_H
#define _LIBINTL_H 1
#include <features.h>
/* We define an additional symbol to signal that we use the GNU
implementation of gettext. */
#define __USE_GNU_GETTEXT 1
/* Provide information about the supported file formats. Returns the
maximum minor revision number supported for a given major revision. */
#define __GNU_GETTEXT_SUPPORTED_REVISION(major) \
((major) == 0 ? 1 : -1)
__BEGIN_DECLS
/* Look up MSGID in the current default message catalog for the current
LC_MESSAGES locale. If not found, returns MSGID itself (the default
text). */
extern char *gettext (__const char *__msgid) __THROW;
/* Look up MSGID in the DOMAINNAME message catalog for the current
LC_MESSAGES locale. */
extern char *dgettext (__const char *__domainname, __const char *__msgid)
__THROW;
extern char *__dgettext (__const char *__domainname, __const char *__msgid)
__THROW __attribute_format_arg__ (2);
/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
locale. */
extern char *dcgettext (__const char *__domainname,
__const char *__msgid, int __category) __THROW;
extern char *__dcgettext (__const char *__domainname,
__const char *__msgid, int __category)
__THROW __attribute_format_arg__ (2);
/* Similar to `gettext' but select the plural form corresponding to the
number N. */
extern char *ngettext (__const char *__msgid1, __const char *__msgid2,
unsigned long int __n)
__THROW __attribute_format_arg__ (1) __attribute_format_arg__ (2);
/* Similar to `dgettext' but select the plural form corresponding to the
number N. */
extern char *dngettext (__const char *__domainname, __const char *__msgid1,
__const char *__msgid2, unsigned long int __n)
__THROW __attribute_format_arg__ (2) __attribute_format_arg__ (3);
/* Similar to `dcgettext' but select the plural form corresponding to the
number N. */
extern char *dcngettext (__const char *__domainname, __const char *__msgid1,
__const char *__msgid2, unsigned long int __n,
int __category)
__THROW __attribute_format_arg__ (2) __attribute_format_arg__ (3);
/* Set the current default message catalog to DOMAINNAME.
If DOMAINNAME is null, return the current default.
If DOMAINNAME is "", reset to the default of "messages". */
extern char *textdomain (__const char *__domainname) __THROW;
/* Specify that the DOMAINNAME message catalog will be found
in DIRNAME rather than in the system locale data base. */
extern char *bindtextdomain (__const char *__domainname,
__const char *__dirname) __THROW;
/* Specify the character encoding in which the messages from the
DOMAINNAME message catalog will be returned. */
extern char *bind_textdomain_codeset (__const char *__domainname,
__const char *__codeset) __THROW;
/* Optimized version of the function above. */
#if defined __OPTIMIZE__
/* We need NULL for `gettext'. */
# define __need_NULL
# include <stddef.h>
/* We need LC_MESSAGES for `dgettext'. */
# include <locale.h>
/* These must be macros. Inlined functions are useless because the
`__builtin_constant_p' predicate in dcgettext would always return
false. */
# define gettext(msgid) dgettext (NULL, msgid)
# define dgettext(domainname, msgid) \
dcgettext (domainname, msgid, LC_MESSAGES)
# define ngettext(msgid1, msgid2, n) dngettext (NULL, msgid1, msgid2, n)
# define dngettext(domainname, msgid1, msgid2, n) \
dcngettext (domainname, msgid1, msgid2, n, LC_MESSAGES)
#endif /* Optimizing. */
__END_DECLS
#endif /* libintl.h */
File diff suppressed because it is too large Load Diff
@@ -1,75 +0,0 @@
# Locale name alias data base.
# Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# The format of this file is the same as for the corresponding file of
# the X Window System, which normally can be found in
# /usr/lib/X11/locale/locale.alias
# A single line contains two fields: an alias and a substitution value.
# All entries are case independent.
# Note: This file is far from being complete. If you have a value for
# your own site which you think might be useful for others too, share
# it with the rest of us. Send it using the `glibcbug' script to
# [email protected].
bokmal no_NO.ISO-8859-1
bokmål no_NO.ISO-8859-1
catalan ca_ES.ISO-8859-1
croatian hr_HR.ISO-8859-2
czech cs_CZ.ISO-8859-2
danish da_DK.ISO-8859-1
dansk da_DK.ISO-8859-1
deutsch de_DE.ISO-8859-1
dutch nl_NL.ISO-8859-1
eesti et_EE.ISO-8859-1
estonian et_EE.ISO-8859-1
finnish fi_FI.ISO-8859-1
français fr_FR.ISO-8859-1
french fr_FR.ISO-8859-1
galego gl_ES.ISO-8859-1
galician gl_ES.ISO-8859-1
german de_DE.ISO-8859-1
greek el_GR.ISO-8859-7
hebrew he_IL.ISO-8859-8
hrvatski hr_HR.ISO-8859-2
hungarian hu_HU.ISO-8859-2
icelandic is_IS.ISO-8859-1
italian it_IT.ISO-8859-1
japanese ja_JP.eucJP
japanese.euc ja_JP.eucJP
ja_JP ja_JP.eucJP
ja_JP.ujis ja_JP.eucJP
japanese.sjis ja_JP.SJIS
korean ko_KR.eucKR
korean.euc ko_KR.eucKR
ko_KR ko_KR.eucKR
lithuanian lt_LT.ISO-8859-13
nb_NO no_NO.ISO-8859-1
nb_NO.ISO-8859-1 no_NO.ISO-8859-1
norwegian no_NO.ISO-8859-1
nynorsk nn_NO.ISO-8859-1
polish pl_PL.ISO-8859-2
portuguese pt_PT.ISO-8859-1
romanian ro_RO.ISO-8859-2
russian ru_RU.ISO-8859-5
slovak sk_SK.ISO-8859-2
slovene sl_SI.ISO-8859-2
slovenian sl_SI.ISO-8859-2
spanish es_ES.ISO-8859-1
swedish sv_SE.ISO-8859-1
thai th_TH.TIS-620
turkish tr_TR.ISO-8859-9
@@ -1,405 +0,0 @@
/* Handle aliases for locale names.
Copyright (C) 1995-1999, 2000,01,02 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. */
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
This must come before <config.h> because <config.h> may include
<features.h>, and once <features.h> has been included, it's too late. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <ctype.h>
#include <stdio.h>
#if defined _LIBC || defined HAVE___FSETLOCKING
# include <stdio_ext.h>
#endif
#include <sys/types.h>
#ifdef __GNUC__
# undef alloca
# define alloca __builtin_alloca
# define HAVE_ALLOCA 1
#else
# if defined HAVE_ALLOCA_H || defined _LIBC
# include <alloca.h>
# else
# ifdef _AIX
#pragma alloca
# else
# ifndef alloca
char *alloca ();
# endif
# endif
# endif
#endif
#include <stdlib.h>
#include <string.h>
#include "gettextP.h"
/* @@ end of prolog @@ */
#ifdef _LIBC
/* Rename the non ANSI C functions. This is required by the standard
because some ANSI C functions will require linking with this object
file and the name space must not be polluted. */
# define strcasecmp __strcasecmp
# ifndef mempcpy
# define mempcpy __mempcpy
# endif
# define HAVE_MEMPCPY 1
# define HAVE___FSETLOCKING 1
/* We need locking here since we can be called from different places. */
# include <bits/libc-lock.h>
__libc_lock_define_initialized (static, lock);
#endif
#ifndef internal_function
# define internal_function
#endif
/* Some optimizations for glibc. */
#ifdef _LIBC
# define FEOF(fp) feof_unlocked (fp)
# define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp)
#else
# define FEOF(fp) feof (fp)
# define FGETS(buf, n, fp) fgets (buf, n, fp)
#endif
/* For those losing systems which don't have `alloca' we have to add
some additional code emulating it. */
#ifdef HAVE_ALLOCA
# define freea(p) /* nothing */
#else
# define alloca(n) malloc (n)
# define freea(p) free (p)
#endif
#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED
# undef fgets
# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
#endif
#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED
# undef feof
# define feof(s) feof_unlocked (s)
#endif
struct alias_map
{
const char *alias;
const char *value;
};
#ifndef _LIBC
# define libc_freeres_ptr(decl) decl
#endif
libc_freeres_ptr (static char *string_space);
static size_t string_space_act;
static size_t string_space_max;
libc_freeres_ptr (static struct alias_map *map);
static size_t nmap;
static size_t maxmap;
/* Prototypes for local functions. */
static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
internal_function;
static int extend_alias_table PARAMS ((void));
static int alias_compare PARAMS ((const struct alias_map *map1,
const struct alias_map *map2));
const char *
_nl_expand_alias (name)
const char *name;
{
static const char *locale_alias_path = LOCALE_ALIAS_PATH;
struct alias_map *retval;
const char *result = NULL;
size_t added;
#ifdef _LIBC
__libc_lock_lock (lock);
#endif
do
{
struct alias_map item;
item.alias = name;
if (nmap > 0)
retval = (struct alias_map *) bsearch (&item, map, nmap,
sizeof (struct alias_map),
(int (*) PARAMS ((const void *,
const void *))
) alias_compare);
else
retval = NULL;
/* We really found an alias. Return the value. */
if (retval != NULL)
{
result = retval->value;
break;
}
/* Perhaps we can find another alias file. */
added = 0;
while (added == 0 && locale_alias_path[0] != '\0')
{
const char *start;
while (locale_alias_path[0] == ':')
++locale_alias_path;
start = locale_alias_path;
while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ':')
++locale_alias_path;
if (start < locale_alias_path)
added = read_alias_file (start, locale_alias_path - start);
}
}
while (added != 0);
#ifdef _LIBC
__libc_lock_unlock (lock);
#endif
return result;
}
static size_t
internal_function
read_alias_file (fname, fname_len)
const char *fname;
int fname_len;
{
FILE *fp;
char *full_fname;
size_t added;
static const char aliasfile[] = "/locale.alias";
full_fname = (char *) alloca (fname_len + sizeof aliasfile);
#ifdef HAVE_MEMPCPY
mempcpy (mempcpy (full_fname, fname, fname_len),
aliasfile, sizeof aliasfile);
#else
memcpy (full_fname, fname, fname_len);
memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
#endif
fp = fopen (full_fname, "r");
freea (full_fname);
if (fp == NULL)
return 0;
#ifdef HAVE___FSETLOCKING
/* No threads present. */
__fsetlocking (fp, FSETLOCKING_BYCALLER);
#endif
added = 0;
while (!FEOF (fp))
{
/* It is a reasonable approach to use a fix buffer here because
a) we are only interested in the first two fields
b) these fields must be usable as file names and so must not
be that long
We avoid a multi-kilobyte buffer here since this would use up
stack space which we might not have if the program ran out of
memory. */
char buf[400];
char *alias;
char *value;
char *cp;
if (FGETS (buf, sizeof buf, fp) == NULL)
/* EOF reached. */
break;
cp = buf;
/* Ignore leading white space. */
while (isspace ((unsigned char) cp[0]))
++cp;
/* A leading '#' signals a comment line. */
if (cp[0] != '\0' && cp[0] != '#')
{
alias = cp++;
while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
++cp;
/* Terminate alias name. */
if (cp[0] != '\0')
*cp++ = '\0';
/* Now look for the beginning of the value. */
while (isspace ((unsigned char) cp[0]))
++cp;
if (cp[0] != '\0')
{
size_t alias_len;
size_t value_len;
value = cp++;
while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
++cp;
/* Terminate value. */
if (cp[0] == '\n')
{
/* This has to be done to make the following test
for the end of line possible. We are looking for
the terminating '\n' which do not overwrite here. */
*cp++ = '\0';
*cp = '\n';
}
else if (cp[0] != '\0')
*cp++ = '\0';
if (nmap >= maxmap)
if (__builtin_expect (extend_alias_table (), 0))
return added;
alias_len = strlen (alias) + 1;
value_len = strlen (value) + 1;
if (string_space_act + alias_len + value_len > string_space_max)
{
/* Increase size of memory pool. */
size_t new_size = (string_space_max
+ (alias_len + value_len > 1024
? alias_len + value_len : 1024));
char *new_pool = (char *) realloc (string_space, new_size);
if (new_pool == NULL)
return added;
if (__builtin_expect (string_space != new_pool, 0))
{
size_t i;
for (i = 0; i < nmap; i++)
{
map[i].alias += new_pool - string_space;
map[i].value += new_pool - string_space;
}
}
string_space = new_pool;
string_space_max = new_size;
}
map[nmap].alias = memcpy (&string_space[string_space_act],
alias, alias_len);
string_space_act += alias_len;
map[nmap].value = memcpy (&string_space[string_space_act],
value, value_len);
string_space_act += value_len;
++nmap;
++added;
}
}
/* Possibly not the whole line fits into the buffer. Ignore
the rest of the line. */
while (strchr (buf, '\n') == NULL)
if (FGETS (buf, sizeof buf, fp) == NULL)
/* Make sure the inner loop will be left. The outer loop
will exit at the `feof' test. */
break;
}
/* Should we test for ferror()? I think we have to silently ignore
errors. --drepper */
fclose (fp);
if (added > 0)
qsort (map, nmap, sizeof (struct alias_map),
(int (*) PARAMS ((const void *, const void *))) alias_compare);
return added;
}
static int
extend_alias_table ()
{
size_t new_size;
struct alias_map *new_map;
new_size = maxmap == 0 ? 100 : 2 * maxmap;
new_map = (struct alias_map *) realloc (map, (new_size
* sizeof (struct alias_map)));
if (new_map == NULL)
/* Simply don't extend: we don't have any more core. */
return -1;
map = new_map;
maxmap = new_size;
return 0;
}
static int
alias_compare (map1, map2)
const struct alias_map *map1;
const struct alias_map *map2;
{
#if defined _LIBC || defined HAVE_STRCASECMP
return strcasecmp (map1->alias, map2->alias);
#else
const unsigned char *p1 = (const unsigned char *) map1->alias;
const unsigned char *p2 = (const unsigned char *) map2->alias;
unsigned char c1, c2;
if (p1 == p2)
return 0;
do
{
/* I know this seems to be odd but the tolower() function in
some systems libc cannot handle nonalpha characters. */
c1 = isupper (*p1) ? tolower (*p1) : *p1;
c2 = isupper (*p2) ? tolower (*p2) : *p2;
if (c1 == '\0')
break;
++p1;
++p2;
}
while (c1 == c2);
return c1 - c2;
#endif
}
@@ -1,69 +0,0 @@
/* Implementation of ngettext(3) function.
Copyright (C) 1995, 1997, 2000, 2001, 2002 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef _LIBC
# define __need_NULL
# include <stddef.h>
#else
# include <stdlib.h> /* Just for NULL. */
#endif
#include "gettextP.h"
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
#include <locale.h>
/* @@ end of prolog @@ */
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define NGETTEXT __ngettext
# define DCNGETTEXT __dcngettext
#else
# define NGETTEXT libintl_ngettext
# define DCNGETTEXT libintl_dcngettext
#endif
/* Look up MSGID in the current default message catalog for the current
LC_MESSAGES locale. If not found, returns MSGID itself (the default
text). */
char *
NGETTEXT (msgid1, msgid2, n)
const char *msgid1;
const char *msgid2;
unsigned long int n;
{
return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES);
}
#ifdef _LIBC
/* Alias for function name in GNU C Library. */
weak_alias (__ngettext, ngettext);
#endif
@@ -1,101 +0,0 @@
/* Plural expression evaluation.
Copyright (C) 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. */
static unsigned long int plural_eval (struct expression *pexp,
unsigned long int n)
internal_function;
static unsigned long int
internal_function
plural_eval (pexp, n)
struct expression *pexp;
unsigned long int n;
{
switch (pexp->nargs)
{
case 0:
switch (pexp->operation)
{
case var:
return n;
case num:
return pexp->val.num;
default:
break;
}
/* NOTREACHED */
break;
case 1:
{
/* pexp->operation must be lnot. */
unsigned long int arg = plural_eval (pexp->val.args[0], n);
return ! arg;
}
case 2:
{
unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
if (pexp->operation == lor)
return leftarg || plural_eval (pexp->val.args[1], n);
else if (pexp->operation == land)
return leftarg && plural_eval (pexp->val.args[1], n);
else
{
unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
switch (pexp->operation)
{
case mult:
return leftarg * rightarg;
case divide:
return leftarg / rightarg;
case module:
return leftarg % rightarg;
case plus:
return leftarg + rightarg;
case minus:
return leftarg - rightarg;
case less_than:
return leftarg < rightarg;
case greater_than:
return leftarg > rightarg;
case less_or_equal:
return leftarg <= rightarg;
case greater_or_equal:
return leftarg >= rightarg;
case equal:
return leftarg == rightarg;
case not_equal:
return leftarg != rightarg;
default:
break;
}
}
/* NOTREACHED */
break;
}
case 3:
{
/* pexp->operation must be qmop. */
unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
}
}
/* NOTREACHED */
return 0;
}
@@ -1,157 +0,0 @@
/* Expression parsing for plural form selection.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "plural-exp.h"
#if (defined __GNUC__ && !defined __APPLE_CC__) \
|| (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
/* These structs are the constant expression for the germanic plural
form determination. It represents the expression "n != 1". */
static const struct expression plvar =
{
.nargs = 0,
.operation = var,
};
static const struct expression plone =
{
.nargs = 0,
.operation = num,
.val =
{
.num = 1
}
};
struct expression GERMANIC_PLURAL =
{
.nargs = 2,
.operation = not_equal,
.val =
{
.args =
{
[0] = (struct expression *) &plvar,
[1] = (struct expression *) &plone
}
}
};
# define INIT_GERMANIC_PLURAL()
#else
/* For compilers without support for ISO C 99 struct/union initializers:
Initialization at run-time. */
static struct expression plvar;
static struct expression plone;
struct expression GERMANIC_PLURAL;
static void
init_germanic_plural ()
{
if (plone.val.num == 0)
{
plvar.nargs = 0;
plvar.operation = var;
plone.nargs = 0;
plone.operation = num;
plone.val.num = 1;
GERMANIC_PLURAL.nargs = 2;
GERMANIC_PLURAL.operation = not_equal;
GERMANIC_PLURAL.val.args[0] = &plvar;
GERMANIC_PLURAL.val.args[1] = &plone;
}
}
# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
#endif
void
internal_function
EXTRACT_PLURAL_EXPRESSION (nullentry, pluralp, npluralsp)
const char *nullentry;
struct expression **pluralp;
unsigned long int *npluralsp;
{
if (nullentry != NULL)
{
const char *plural;
const char *nplurals;
plural = strstr (nullentry, "plural=");
nplurals = strstr (nullentry, "nplurals=");
if (plural == NULL || nplurals == NULL)
goto no_plural;
else
{
char *endp;
unsigned long int n;
struct parse_args args;
/* First get the number. */
nplurals += 9;
while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
++nplurals;
if (!(*nplurals >= '0' && *nplurals <= '9'))
goto no_plural;
#if defined HAVE_STRTOUL || defined _LIBC
n = strtoul (nplurals, &endp, 10);
#else
for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
n = n * 10 + (*endp - '0');
#endif
if (nplurals == endp)
goto no_plural;
*npluralsp = n;
/* Due to the restrictions bison imposes onto the interface of the
scanner function we have to put the input string and the result
passed up from the parser into the same structure which address
is passed down to the parser. */
plural += 7;
args.cp = plural;
if (PLURAL_PARSE (&args) != 0)
goto no_plural;
*pluralp = args.res;
}
}
else
{
/* By default we are using the Germanic form: singular form only
for `one', the plural form otherwise. Yes, this is also what
English is using since English is a Germanic language. */
no_plural:
INIT_GERMANIC_PLURAL ();
*pluralp = &GERMANIC_PLURAL;
*npluralsp = 2;
}
}
@@ -1,127 +0,0 @@
/* Expression parsing and evaluation for plural form selection.
Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
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. */
#ifndef _PLURAL_EXP_H
#define _PLURAL_EXP_H
#ifndef PARAMS
# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
# define PARAMS(args) args
# else
# define PARAMS(args) ()
# endif
#endif
#ifndef internal_function
# define internal_function
#endif
#ifndef attribute_hidden
# define attribute_hidden
#endif
/* This is the representation of the expressions to determine the
plural form. */
struct expression
{
int nargs; /* Number of arguments. */
enum operator
{
/* Without arguments: */
var, /* The variable "n". */
num, /* Decimal number. */
/* Unary operators: */
lnot, /* Logical NOT. */
/* Binary operators: */
mult, /* Multiplication. */
divide, /* Division. */
module, /* Modulo operation. */
plus, /* Addition. */
minus, /* Subtraction. */
less_than, /* Comparison. */
greater_than, /* Comparison. */
less_or_equal, /* Comparison. */
greater_or_equal, /* Comparison. */
equal, /* Comparison for equality. */
not_equal, /* Comparison for inequality. */
land, /* Logical AND. */
lor, /* Logical OR. */
/* Ternary operators: */
qmop /* Question mark operator. */
} operation;
union
{
unsigned long int num; /* Number value for `num'. */
struct expression *args[3]; /* Up to three arguments. */
} val;
};
/* This is the data structure to pass information to the parser and get
the result in a thread-safe way. */
struct parse_args
{
const char *cp;
struct expression *res;
};
/* Names for the libintl functions are a problem. This source code is used
1. in the GNU C Library library,
2. in the GNU libintl library,
3. in the GNU gettext tools.
The function names in each situation must be different, to allow for
binary incompatible changes in 'struct expression'. Furthermore,
1. in the GNU C Library library, the names have a __ prefix,
2.+3. in the GNU libintl library and in the GNU gettext tools, the names
must follow ANSI C and not start with __.
So we have to distinguish the three cases. */
#ifdef _LIBC
# define FREE_EXPRESSION __gettext_free_exp
# define PLURAL_PARSE __gettextparse
# define GERMANIC_PLURAL __gettext_germanic_plural
# define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural
#elif defined (IN_LIBINTL)
# define FREE_EXPRESSION libintl_gettext_free_exp
# define PLURAL_PARSE libintl_gettextparse
# define GERMANIC_PLURAL libintl_gettext_germanic_plural
# define EXTRACT_PLURAL_EXPRESSION libintl_gettext_extract_plural
#else
# define FREE_EXPRESSION free_plural_expression
# define PLURAL_PARSE parse_plural_expression
# define GERMANIC_PLURAL germanic_plural
# define EXTRACT_PLURAL_EXPRESSION extract_plural_expression
#endif
extern void FREE_EXPRESSION PARAMS ((struct expression *exp))
internal_function;
extern int PLURAL_PARSE PARAMS ((void *arg));
extern struct expression GERMANIC_PLURAL attribute_hidden;
extern void EXTRACT_PLURAL_EXPRESSION PARAMS ((const char *nullentry,
struct expression **pluralp,
unsigned long int *npluralsp))
internal_function;
#if !defined (_LIBC) && !defined (IN_LIBINTL)
extern unsigned long int plural_eval PARAMS ((struct expression *pexp,
unsigned long int n));
#endif
#endif /* _PLURAL_EXP_H */
File diff suppressed because it is too large Load Diff
@@ -1,409 +0,0 @@
%{
/* Expression parsing for plural form selection.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <[email protected]>, 2000.
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. */
/* The bison generated parser uses alloca. AIX 3 forces us to put this
declaration at the beginning of the file. The declaration in bison's
skeleton file comes too late. This must come before <config.h>
because <config.h> may include arbitrary system headers. */
#if defined _AIX && !defined __GNUC__
#pragma alloca
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stddef.h>
#include <stdlib.h>
#include "plural-exp.h"
/* The main function generated by the parser is called __gettextparse,
but we want it to be called PLURAL_PARSE. */
#ifndef _LIBC
# define __gettextparse PLURAL_PARSE
#endif
#define YYLEX_PARAM &((struct parse_args *) arg)->cp
#define YYPARSE_PARAM arg
%}
%pure_parser
%expect 7
%union {
unsigned long int num;
enum operator op;
struct expression *exp;
}
%{
/* Prototypes for local functions. */
static struct expression *new_exp PARAMS ((int nargs, enum operator op,
struct expression * const *args));
static inline struct expression *new_exp_0 PARAMS ((enum operator op));
static inline struct expression *new_exp_1 PARAMS ((enum operator op,
struct expression *right));
static struct expression *new_exp_2 PARAMS ((enum operator op,
struct expression *left,
struct expression *right));
static inline struct expression *new_exp_3 PARAMS ((enum operator op,
struct expression *bexp,
struct expression *tbranch,
struct expression *fbranch));
static int yylex PARAMS ((YYSTYPE *lval, const char **pexp));
static void yyerror PARAMS ((const char *str));
/* Allocation of expressions. */
static struct expression *
new_exp (nargs, op, args)
int nargs;
enum operator op;
struct expression * const *args;
{
int i;
struct expression *newp;
/* If any of the argument could not be malloc'ed, just return NULL. */
for (i = nargs - 1; i >= 0; i--)
if (args[i] == NULL)
goto fail;
/* Allocate a new expression. */
newp = (struct expression *) malloc (sizeof (*newp));
if (newp != NULL)
{
newp->nargs = nargs;
newp->operation = op;
for (i = nargs - 1; i >= 0; i--)
newp->val.args[i] = args[i];
return newp;
}
fail:
for (i = nargs - 1; i >= 0; i--)
FREE_EXPRESSION (args[i]);
return NULL;
}
static inline struct expression *
new_exp_0 (op)
enum operator op;
{
return new_exp (0, op, NULL);
}
static inline struct expression *
new_exp_1 (op, right)
enum operator op;
struct expression *right;
{
struct expression *args[1];
args[0] = right;
return new_exp (1, op, args);
}
static struct expression *
new_exp_2 (op, left, right)
enum operator op;
struct expression *left;
struct expression *right;
{
struct expression *args[2];
args[0] = left;
args[1] = right;
return new_exp (2, op, args);
}
static inline struct expression *
new_exp_3 (op, bexp, tbranch, fbranch)
enum operator op;
struct expression *bexp;
struct expression *tbranch;
struct expression *fbranch;
{
struct expression *args[3];
args[0] = bexp;
args[1] = tbranch;
args[2] = fbranch;
return new_exp (3, op, args);
}
%}
/* This declares that all operators have the same associativity and the
precedence order as in C. See [Harbison, Steele: C, A Reference Manual].
There is no unary minus and no bitwise operators.
Operators with the same syntactic behaviour have been merged into a single
token, to save space in the array generated by bison. */
%right '?' /* ? */
%left '|' /* || */
%left '&' /* && */
%left EQUOP2 /* == != */
%left CMPOP2 /* < > <= >= */
%left ADDOP2 /* + - */
%left MULOP2 /* * / % */
%right '!' /* ! */
%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
%token <num> NUMBER
%type <exp> exp
%%
start: exp
{
if ($1 == NULL)
YYABORT;
((struct parse_args *) arg)->res = $1;
}
;
exp: exp '?' exp ':' exp
{
$$ = new_exp_3 (qmop, $1, $3, $5);
}
| exp '|' exp
{
$$ = new_exp_2 (lor, $1, $3);
}
| exp '&' exp
{
$$ = new_exp_2 (land, $1, $3);
}
| exp EQUOP2 exp
{
$$ = new_exp_2 ($2, $1, $3);
}
| exp CMPOP2 exp
{
$$ = new_exp_2 ($2, $1, $3);
}
| exp ADDOP2 exp
{
$$ = new_exp_2 ($2, $1, $3);
}
| exp MULOP2 exp
{
$$ = new_exp_2 ($2, $1, $3);
}
| '!' exp
{
$$ = new_exp_1 (lnot, $2);
}
| 'n'
{
$$ = new_exp_0 (var);
}
| NUMBER
{
if (($$ = new_exp_0 (num)) != NULL)
$$->val.num = $1;
}
| '(' exp ')'
{
$$ = $2;
}
;
%%
void
internal_function
FREE_EXPRESSION (exp)
struct expression *exp;
{
if (exp == NULL)
return;
/* Handle the recursive case. */
switch (exp->nargs)
{
case 3:
FREE_EXPRESSION (exp->val.args[2]);
/* FALLTHROUGH */
case 2:
FREE_EXPRESSION (exp->val.args[1]);
/* FALLTHROUGH */
case 1:
FREE_EXPRESSION (exp->val.args[0]);
/* FALLTHROUGH */
default:
break;
}
free (exp);
}
static int
yylex (lval, pexp)
YYSTYPE *lval;
const char **pexp;
{
const char *exp = *pexp;
int result;
while (1)
{
if (exp[0] == '\0')
{
*pexp = exp;
return YYEOF;
}
if (exp[0] != ' ' && exp[0] != '\t')
break;
++exp;
}
result = *exp++;
switch (result)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
unsigned long int n = result - '0';
while (exp[0] >= '0' && exp[0] <= '9')
{
n *= 10;
n += exp[0] - '0';
++exp;
}
lval->num = n;
result = NUMBER;
}
break;
case '=':
if (exp[0] == '=')
{
++exp;
lval->op = equal;
result = EQUOP2;
}
else
result = YYERRCODE;
break;
case '!':
if (exp[0] == '=')
{
++exp;
lval->op = not_equal;
result = EQUOP2;
}
break;
case '&':
case '|':
if (exp[0] == result)
++exp;
else
result = YYERRCODE;
break;
case '<':
if (exp[0] == '=')
{
++exp;
lval->op = less_or_equal;
}
else
lval->op = less_than;
result = CMPOP2;
break;
case '>':
if (exp[0] == '=')
{
++exp;
lval->op = greater_or_equal;
}
else
lval->op = greater_than;
result = CMPOP2;
break;
case '*':
lval->op = mult;
result = MULOP2;
break;
case '/':
lval->op = divide;
result = MULOP2;
break;
case '%':
lval->op = module;
result = MULOP2;
break;
case '+':
lval->op = plus;
result = ADDOP2;
break;
case '-':
lval->op = minus;
result = ADDOP2;
break;
case 'n':
case '?':
case ':':
case '(':
case ')':
/* Nothing, just return the character. */
break;
case ';':
case '\n':
case '\0':
/* Be safe and let the user call this function again. */
--exp;
result = YYEOF;
break;
default:
result = YYERRCODE;
#if YYDEBUG != 0
--exp;
#endif
break;
}
*pexp = exp;
return result;
}
static void
yyerror (str)
const char *str;
{
/* Do nothing. We don't print error messages here. */
}
@@ -1,70 +0,0 @@
# po2test.sed - Convert Uniforum style .po file to C code for testing.
# Copyright (C) 2000 Free Software Foundation, Inc.
# Ulrich Drepper <[email protected]>, 2000.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
# We copy the original message as a comment into the .msg file. But enclose
# them with INPUT ( ).
#
/^msgid/ {
s/msgid[ ]*"\(.*\)"/INPUT ("\1")/
# Clear flag from last substitution.
tb
# Append the next line.
:b
N
# Look whether second part is a continuation line.
s/\(.*\)")\(\n\)"\(.*\)"/\1\\\2\3")/
# Yes, then branch.
ta
P
D
# Note that `D' includes a jump to the start!!
# We found a continuation line. But before printing insert '\'.
:a
s/\(.*\)")\(\n.*\)/\1\\\2/
P
# We cannot use the sed command `D' here
s/.*\n\(.*\)/\1/
tb
}
#
# Copy the translations as well and enclose them with OUTPUT ( ).
#
/^msgstr/ {
s/msgstr[ ]*"\(.*\)"/OUTPUT ("\1")/
# Clear flag from last substitution.
tb
# Append the next line.
:b
N
# Look whether second part is a continuation line.
s/\(.*\)")\(\n\)"\(.*\)"/\1\\\2\3")/
# Yes, then branch.
ta
P
D
# Note that `D' includes a jump to the start!!
# We found a continuation line. But before printing insert '\'.
:a
s/\(.*\)")\(\n.*\)/\1\\\2/
P
# We cannot use the sed command `D' here
s/.*\n\(.*\)/\1/
tb
}
d
@@ -1,143 +0,0 @@
/* Implementation of the textdomain(3) function.
Copyright (C) 1995-1998, 2000, 2001, 2002 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#ifdef _LIBC
# include <libintl.h>
#else
# include "libgnuintl.h"
#endif
#include "gettextP.h"
#ifdef _LIBC
/* We have to handle multi-threaded applications. */
# include <bits/libc-lock.h>
#else
/* Provide dummy implementation if this is outside glibc. */
# define __libc_rwlock_define(CLASS, NAME)
# define __libc_rwlock_wrlock(NAME)
# define __libc_rwlock_unlock(NAME)
#endif
/* The internal variables in the standalone libintl.a must have different
names than the internal variables in GNU libc, otherwise programs
using libintl.a cannot be linked statically. */
#if !defined _LIBC
# define _nl_default_default_domain libintl_nl_default_default_domain
# define _nl_current_default_domain libintl_nl_current_default_domain
#endif
/* @@ end of prolog @@ */
/* Name of the default text domain. */
extern const char _nl_default_default_domain[] attribute_hidden;
/* Default text domain in which entries for gettext(3) are to be found. */
extern const char *_nl_current_default_domain attribute_hidden;
/* Names for the libintl functions are a problem. They must not clash
with existing names and they should follow ANSI C. But this source
code is also used in GNU C Library where the names have a __
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define TEXTDOMAIN __textdomain
# ifndef strdup
# define strdup(str) __strdup (str)
# endif
#else
# define TEXTDOMAIN libintl_textdomain
#endif
/* Lock variable to protect the global data in the gettext implementation. */
__libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
/* Set the current default message catalog to DOMAINNAME.
If DOMAINNAME is null, return the current default.
If DOMAINNAME is "", reset to the default of "messages". */
char *
TEXTDOMAIN (domainname)
const char *domainname;
{
char *new_domain;
char *old_domain;
/* A NULL pointer requests the current setting. */
if (domainname == NULL)
return (char *) _nl_current_default_domain;
__libc_rwlock_wrlock (_nl_state_lock);
old_domain = (char *) _nl_current_default_domain;
/* If domain name is the null string set to default domain "messages". */
if (domainname[0] == '\0'
|| strcmp (domainname, _nl_default_default_domain) == 0)
{
_nl_current_default_domain = _nl_default_default_domain;
new_domain = (char *) _nl_current_default_domain;
}
else if (strcmp (domainname, old_domain) == 0)
/* This can happen and people will use it to signal that some
environment variable changed. */
new_domain = old_domain;
else
{
/* If the following malloc fails `_nl_current_default_domain'
will be NULL. This value will be returned and so signals we
are out of core. */
#if defined _LIBC || defined HAVE_STRDUP
new_domain = strdup (domainname);
#else
size_t len = strlen (domainname) + 1;
new_domain = (char *) malloc (len);
if (new_domain != NULL)
memcpy (new_domain, domainname, len);
#endif
if (new_domain != NULL)
_nl_current_default_domain = new_domain;
}
/* We use this possibility to signal a change of the loaded catalogs
since this is most likely the case and there is no other easy we
to do it. Do it only when the call was successful. */
if (new_domain != NULL)
{
++_nl_msg_cat_cntr;
if (old_domain != new_domain && old_domain != _nl_default_default_domain)
free (old_domain);
}
__libc_rwlock_unlock (_nl_state_lock);
return new_domain;
}
#ifdef _LIBC
/* Alias for function name in GNU C Library. */
weak_alias (__textdomain, textdomain);
#endif
@@ -1,9 +0,0 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=ISO-8859-1\n"
msgid "test"
msgstr "«© Æß»"
msgid "onemore"
msgstr "½*½=¼"
@@ -1,58 +0,0 @@
/* Test of bind_textdomain_codeset.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Bruno Haible <haible@clisp.cons.org>, 2001.
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. */
#include <libintl.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main (void)
{
char *s;
int result = 0;
unsetenv ("LANGUAGE");
unsetenv ("OUTPUT_CHARSET");
setlocale (LC_ALL, "de_DE.ISO-8859-1");
textdomain ("codeset");
bindtextdomain ("codeset", OBJPFX "domaindir");
/* Here we expect output in ISO-8859-1. */
s = gettext ("cheese");
if (strcmp (s, "K\344se"))
{
printf ("call 1 returned: %s\n", s);
result = 1;
}
bind_textdomain_codeset ("codeset", "UTF-8");
/* Here we expect output in UTF-8. */
s = gettext ("cheese");
if (strcmp (s, "K\303\244se"))
{
printf ("call 2 returned: %s\n", s);
result = 1;
}
return result;
}
@@ -1,44 +0,0 @@
#! /bin/sh
# Test of bind_textdomain_codeset.
# Copyright (C) 2001, 2002 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.
common_objpfx=$1
objpfx=$2
LC_ALL=C
export LC_ALL
# Generate the test data.
test -d ${objpfx}domaindir || mkdir ${objpfx}domaindir
# Create the domain directories.
test -d ${objpfx}domaindir/de_DE || mkdir ${objpfx}domaindir/de_DE
test -d ${objpfx}domaindir/de_DE/LC_MESSAGES || mkdir ${objpfx}domaindir/de_DE/LC_MESSAGES
# Populate them.
msgfmt -o ${objpfx}domaindir/de_DE/LC_MESSAGES/codeset.mo tstcodeset.po
GCONV_PATH=${common_objpfx}iconvdata
export GCONV_PATH
LOCPATH=${common_objpfx}localedata
export LOCPATH
${common_objpfx}elf/ld.so --library-path $common_objpfx \
${objpfx}tst-codeset > ${objpfx}tst-codeset.out
exit $?

Some files were not shown because too many files have changed in this diff Show More