* 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
|
libmail.so libmedia.so libmidi.so libmidi2.so
|
||||||
libnetwork.so
|
libnetwork.so
|
||||||
libpng.so
|
libpng.so
|
||||||
<revisioned>libroot.so
|
<revisioned>libroot.so libroot-addon-icu.so
|
||||||
libscreensaver.so
|
libscreensaver.so
|
||||||
libtextencoding.so libtiff.so libtracker.so libtranslation.so
|
libtextencoding.so libtiff.so libtracker.so libtranslation.so
|
||||||
libz.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 n_sep_by_space;
|
||||||
char p_sign_posn;
|
char p_sign_posn;
|
||||||
char n_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
|
#define LC_ALL 0
|
||||||
@@ -34,6 +40,11 @@ struct lconv {
|
|||||||
#define LC_NUMERIC 4
|
#define LC_NUMERIC 4
|
||||||
#define LC_TIME 5
|
#define LC_TIME 5
|
||||||
#define LC_MESSAGES 6
|
#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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
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_MIN 0x00000000UL
|
||||||
#define WCHAR_MAX 0x7FFFFFFFUL
|
#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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
typedef const int *wctrans_t;
|
typedef int wctrans_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -28,7 +28,7 @@ extern int iswupper(wint_t wc);
|
|||||||
extern int iswxdigit(wint_t wc);
|
extern int iswxdigit(wint_t wc);
|
||||||
|
|
||||||
extern int iswctype(wint_t wc, wctype_t charClass);
|
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 towlower(wint_t wc);
|
||||||
extern wint_t towupper(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 $
|
* $FreeBSD: /repoman/r/ncvs/src/lib/libc/stdtime/timelocal.h,v 1.11 2002/01/24 15:07:44 phantom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _TIMELOCAL_H_
|
#ifndef _TIMELOCAL_H_
|
||||||
#define _TIMELOCAL_H_
|
#define _TIMELOCAL_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private header file for the strftime and strptime localization
|
* Private header file for the strftime and strptime localization
|
||||||
* stuff.
|
* stuff.
|
||||||
*/
|
*/
|
||||||
struct lc_time_T {
|
struct lc_time_t {
|
||||||
const char *mon[12];
|
const char* mon[12];
|
||||||
const char *month[12];
|
const char* month[12];
|
||||||
const char *wday[7];
|
const char* wday[7];
|
||||||
const char *weekday[7];
|
const char* weekday[7];
|
||||||
const char *X_fmt;
|
const char* X_fmt;
|
||||||
const char *x_fmt;
|
const char* x_fmt;
|
||||||
const char *c_fmt;
|
const char* c_fmt;
|
||||||
const char *am;
|
const char* am;
|
||||||
const char *pm;
|
const char* pm;
|
||||||
const char *date_fmt;
|
const char* date_fmt;
|
||||||
const char *alt_month[12];
|
const char* alt_month[12];
|
||||||
const char *md_order;
|
const char* md_order;
|
||||||
const char *ampm_fmt;
|
const char* ampm_fmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lc_time_T *__get_current_time_locale(void);
|
__BEGIN_DECLS
|
||||||
int __time_load_locale(const char *);
|
const struct lc_time_t* __get_current_time_locale(void);
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
|
||||||
#endif /* !_TIMELOCAL_H_ */
|
#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 =
|
local librootFunctions =
|
||||||
abs.o
|
abs.o
|
||||||
ctype.o
|
ctype.o
|
||||||
|
LocaleData.o
|
||||||
qsort.o
|
qsort.o
|
||||||
kernel_vsprintf.o
|
kernel_vsprintf.o
|
||||||
memcmp.o
|
memcmp.o
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src system kernel lib ;
|
SubDir HAIKU_TOP src system kernel lib ;
|
||||||
|
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
|
UsePrivateHeaders [ FDirName libroot locale ] ;
|
||||||
|
|
||||||
# kernel libroot os files
|
# kernel libroot os files
|
||||||
|
|
||||||
@@ -41,8 +42,9 @@ KernelMergeObject kernel_lib_posix.o :
|
|||||||
poll.c
|
poll.c
|
||||||
utime.c
|
utime.c
|
||||||
# locale
|
# locale
|
||||||
ctype.c
|
ctype.cpp
|
||||||
localeconv.c
|
localeconv.cpp
|
||||||
|
LocaleData.cpp
|
||||||
# stdio (this subdir)
|
# stdio (this subdir)
|
||||||
kernel_vsprintf.cpp
|
kernel_vsprintf.cpp
|
||||||
# stdlib
|
# stdlib
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ local librootObjects =
|
|||||||
posix_gnu_stdlib.o
|
posix_gnu_stdlib.o
|
||||||
posix_gnu_string.o
|
posix_gnu_string.o
|
||||||
posix_gnu_wcsmbs.o
|
posix_gnu_wcsmbs.o
|
||||||
posix_gnu_wctype.o
|
|
||||||
posix_stdlib.o
|
posix_stdlib.o
|
||||||
posix_string.o
|
posix_string.o
|
||||||
posix_string_arch_$(TARGET_ARCH).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 os ;
|
||||||
SubInclude HAIKU_TOP src system libroot posix ;
|
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 stdlib ;
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc string ;
|
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 wcsmbs ;
|
||||||
SubInclude HAIKU_TOP src system libroot posix glibc wctype ;
|
|
||||||
|
|||||||
@@ -21,32 +21,11 @@
|
|||||||
|
|
||||||
#include <features.h>
|
#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
|
__BEGIN_DECLS
|
||||||
|
|
||||||
/* Message catalog descriptor type. */
|
|
||||||
typedef void *nl_catd;
|
|
||||||
|
|
||||||
/* Type used by `nl_langinfo'. */
|
/* Type used by `nl_langinfo'. */
|
||||||
typedef int nl_item;
|
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
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* nl_types.h */
|
#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 ;
|
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ;
|
||||||
|
|
||||||
MergeObject posix_gnu_ctype.o :
|
MergeObject posix_gnu_ctype.o :
|
||||||
ctype_l.c
|
|
||||||
ctype.c
|
|
||||||
ctype-extn.c
|
|
||||||
ctype-info.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)
|
#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] =
|
const char *__ctype32_wctype[12] =
|
||||||
{
|
{
|
||||||
b(char, class_upper, 32),
|
b(char, class_upper, 32),
|
||||||
@@ -68,4 +62,3 @@ const char *__ctype32_wctrans[2] =
|
|||||||
b(char, map_toupper, 0),
|
b(char, map_toupper, 0),
|
||||||
b(char, map_tolower, 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 ctype ;
|
||||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc iconv ;
|
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 locale ;
|
||||||
#SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc string ;
|
|
||||||
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ;
|
SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ;
|
||||||
|
|
||||||
SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ;
|
SubDirCcFlags -D_GNU_SOURCE -DUSE_IN_LIBIO ;
|
||||||
@@ -18,7 +17,6 @@ MergeObject posix_gnu_iconv.o :
|
|||||||
gconv_cache.c
|
gconv_cache.c
|
||||||
gconv_conf.c
|
gconv_conf.c
|
||||||
gconv_db.c
|
gconv_db.c
|
||||||
# gconv_dl.c
|
|
||||||
gconv_simple.c
|
gconv_simple.c
|
||||||
gconv_trans.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 <[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 <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 <[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. */
|
|
||||||
|
|
||||||
#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 <[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. */
|
|
||||||
|
|
||||||
/* 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 <[email protected]>, 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 <[email protected]>, 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