* reintegrated posix-locale
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37725 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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" {
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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" {
|
||||
|
||||
@@ -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
|
||||
+22
-17
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
SubDir HAIKU_TOP src system libroot add-ons ;
|
||||
|
||||
SubInclude HAIKU_TOP src system libroot add-ons icu ;
|
||||
@@ -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) ;
|
||||
@@ -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, ©len);
|
||||
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 */
|
||||
@@ -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
Reference in New Issue
Block a user