# Munged source names: list of C++, O etc files for Frontend
PARTSUFF=_fe
-GL_FE_CXX=$(shell cd $(GLUE) ; ls *$(PARTSUFF).cpp)
+GL_FE_CXX=$(notdir $(wildcard $(GLUE)/*$(PARTSUFF).cpp))
GL_FE_FILES=$(GL_FE_CXX:%.cpp=$(GLUE)/%.cpp)
GL_FE_O=$(GL_FE_CPP:%.cpp=%.o)
GL_PARTS=$(GL_FE_CXX:%$(PARTSUFF).cpp=%)
# for each version.. build all OTHER FE files
# TODO: check is unnecessary, not permitted.
# TODO: change to depend instead of for list.
+ @echo GL_PARTS=$(GL_PARTS)
+ @echo GL_FE_CXX=$(GL_FE_CXX)
+ @echo PARTSUFF=$(PARTSUFF)
@for ver in $(PLUGLIB_AVAILABLE) ; \
do \
echo building $$ver for $(PLUGLIB) ; \
$(BUILD)/%/$(GLUREN_H): $(BUILD)/%/ok Makefile makegluren.sh
-mkdir -p $(BUILD)/$*/$(GLUREN)
env SRC="$(SRC)" SOURCE="$(SOURCE)" GLUE="$(GLUE)" ./makegluren.sh $@ $*
+ @fgrep -q OICU_ $@ || ( echo "Error: $@: no OICU_ symbols found. Removing gluren.h " ; rm -f $@ ; exit 1)
$(BUILD)/%/config/$(ICU_CONFIG): $(BUILD)/%/config/$(ICU_CONFIG_ORIG) icu-config.sed $(BUILD)/%/ok
sed -f icu-config.sed < $(BUILD)/$*/config/$(ICU_CONFIG_ORIG) > $(BUILD)/$*/config/$(ICU_CONFIG) && chmod a+rx $(BUILD)/$*/config/$(ICU_CONFIG)
@echo "Available plugins: $(PROVIDER_AVAILABLE) ($(PLUGLIB_AVAILABLE))"
@echo "Available keywords:"
@for ver in $(PROVIDER_AVAILABLE); do \
- echo " ...@provider=icu"`echo $$ver | cut -d. -f1-2 | tr -d .`; \
+ echo " ...@provider=icu"`echo $$ver | ./icu2symver.sh`; \
done
@echo "Plugin library will be $(PLUGLIB_NAME)"
@echo
@echo "/* Generated file. */" > $@
@echo "const char *provider_version[] = {" >> $@
@for ver in $(PROVIDER_AVAILABLE); do \
- echo '"'`echo $$ver | cut -d. -f1-2 | tr -d .`'",' >> $@ ; \
+ echo VER $$ver ; \
+ sym=`echo $$ver | ./icu2symver.sh` ; \
+ echo SYM $$sym ; \
+ echo "\"$$sym\"", >> $@ ; \
done
@echo " }; " >> $@
@echo "#define PROVIDER_COUNT (sizeof(provider_version)/sizeof(provider_version[0]))" >> $@
#
-# Copyright (C) 2008-2010 IBM Corporation and Others. All Rights Reserved
+# Copyright (C) 2008-2012 IBM Corporation and Others. All Rights Reserved
# local definitions must go in Makefile.local
# example:
## These two are REQUIRED.
##
-# The version of ICU you will build against, such as:
-# EXAMPLE: 4.4.2
-PROVIDER_TARGET=4.4.2
+# The version of ICU you will build against (which API you will use). Note, 49.1 is required for collation support, and for date support.
+# EXAMPLE: 49.1
+PROVIDER_TARGET=49.1
# The versions of ICU you want to have available in the plugin. Space separated. Don't include the PROVIDER_TARGET version.
# EXAMPLE: 3.8.1 4.2.0.1
/*
*******************************************************************************
*
-* Copyright (C) 2009-2011, International Business Machines
+* Copyright (C) 2009-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
}
if(diffs==0) {
+#if (U_ICU_VERSION_MAJOR_NUM < 49)
+ printf("ERROR: 0 differences found between platforms. ICU " U_ICU_VERSION " does not support collator plugins properly (not until 49)\n");
+#else
printf("ERROR: 0 differences found between platforms.. are the platforms installed? Try 'icuinfo -L'\n");
+#endif
return 1;
} else {
printf("%d differences found among provider versions!\n", diffs);
}
int main(int /* argc*/ , const char * /*argv*/ []) {
+#if (U_ICU_VERSION_MAJOR_NUM < 49)
+ fprintf(stderr, "Warning: ICU %s doesn't support date providers. Need at least 49.\n", U_ICU_VERSION );
+ return 0;
+#else
UErrorCode status = U_ZERO_ERROR;
int diffs = 0;
int gbaddiffs =0;
int expected = PROVIDER_COUNT;
- for(int s=0;s<sizeof(styles)/sizeof(styles[0]);s++) {
+ for(uint32_t s=0;s<sizeof(styles)/sizeof(styles[0]);s++) {
for(int l=0;l<LOCALE_COUNT;l++) {
printf("\n");
UChar oldChars[200];
printf("Success!\n");
return 0;
+#endif
}
#include <stdio.h>
#include "unicode/ustring.h"
+#if COLL_FE_DEBUG
+#define debugfprintf(x) fprintf x
+#else
+#define debugfprintf(x)
+#endif
-
+/*
+ * Before ICU 50.0.2 (50m2) - there was a different collator signature.
+ * see: ticket:9460 ticket:9346
+ */
+#if (U_ICU_VERSION_MAJOR_NUM < 50) || ((U_ICU_VERSION_MAJOR_NUM==50)&&(U_ICU_VERSION_MINOR_NUM==0)&&(U_ICU_VERSION_PATCHLEVEL_NUM<2))
+#define PRE_50_0_2_COLLATOR
+#define CONST_BEFORE_50_0_2 const
+#define CONST_AFTER_50_0_2
+#define REF_AFTER_50_0_2
+#else
+/* "current" API */
+#define CONST_BEFORE_50_0_2
+#define CONST_AFTER_50_0_2 const
+#define REF_AFTER_50_0_2 &
+#endif
/**
* Macro to define the Collator_glue_4_2 class
virtual CollationKey& getCollationKey(const UnicodeString&, CollationKey&, UErrorCode&) const; \
virtual CollationKey& getCollationKey(const UChar*, int32_t, CollationKey&, UErrorCode&) const; \
virtual int32_t hashCode() const; \
- virtual const Locale getLocale(ULocDataLocaleType, UErrorCode&) const; \
+ virtual CONST_BEFORE_50_0_2 Locale getLocale(ULocDataLocaleType, UErrorCode&) const; \
virtual ECollationStrength getStrength() const; \
virtual void setStrength(ECollationStrength); \
virtual void getVersion(uint8_t*) const; \
- virtual void setAttribute(UColAttribute, UColAttributeValue, UErrorCode&); \
- virtual UColAttributeValue getAttribute(UColAttribute, UErrorCode&); \
+ virtual void setAttribute(UColAttribute, UColAttributeValue, UErrorCode&) ; \
+ virtual UColAttributeValue getAttribute(UColAttribute, UErrorCode&) CONST_AFTER_50_0_2; \
virtual uint32_t setVariableTop(const UChar*, int32_t, UErrorCode&); \
- virtual uint32_t setVariableTop(UnicodeString, UErrorCode&); \
+ virtual uint32_t setVariableTop(const UnicodeString REF_AFTER_50_0_2, UErrorCode&); \
virtual void setVariableTop(uint32_t, UErrorCode&); \
virtual uint32_t getVariableTop(UErrorCode&) const; \
- virtual Collator* safeClone(); \
+ virtual Collator* safeClone() CONST_AFTER_50_0_2 ; \
virtual int32_t getSortKey(const UnicodeString&, uint8_t*, int32_t) const; \
virtual int32_t getSortKey(const UChar*, int32_t, uint8_t*, int32_t) const; \
public: static int32_t countAvailable(); \
}
-const Locale GLUE_SYM ( Collator ) :: getLocale(ULocDataLocaleType, UErrorCode&) const {
+CONST_BEFORE_50_0_2 Locale GLUE_SYM ( Collator ) :: getLocale(ULocDataLocaleType, UErrorCode&) const {
return Locale();
}
}
-void GLUE_SYM ( Collator ) :: setAttribute(UColAttribute, UColAttributeValue, UErrorCode&) {
+void GLUE_SYM ( Collator ) :: setAttribute(UColAttribute, UColAttributeValue, UErrorCode&) {
}
-UColAttributeValue GLUE_SYM ( Collator ) :: getAttribute(UColAttribute, UErrorCode&) {
+UColAttributeValue GLUE_SYM ( Collator ) :: getAttribute(UColAttribute, UErrorCode&) CONST_AFTER_50_0_2 {
return (UColAttributeValue)0;
}
}
-uint32_t GLUE_SYM ( Collator ) :: setVariableTop(UnicodeString, UErrorCode&) {
+uint32_t GLUE_SYM ( Collator ) :: setVariableTop(const UnicodeString REF_AFTER_50_0_2, UErrorCode&) {
return 0;
}
}
-Collator* GLUE_SYM ( Collator ) :: safeClone() {
+Collator* GLUE_SYM ( Collator ) :: safeClone() CONST_AFTER_50_0_2 {
return clone();
}
char *p = buffer+strlen(buffer);
strncat(p,"_PICU",5);
p +=5 ;
- *(p++) = ICUGLUE_VER_STR[0];
- *(p++) = ICUGLUE_VER_STR[2];
+ CPY_VERSTR(p, ICUGLUE_VER_STR);
+ p +=2;
if(remainCap>0) {
*(p++)=0;
}
for(int j=0;j<avail;j++) {
strs[i+j].append(OICU_ucol_getAvailable(j));
strs[i+j].append("@sp=icu");
- strs[i+j].append( ICUGLUE_VER_STR[0] ); // X_y
- strs[i+j].append( ICUGLUE_VER_STR[2] ); // x_Y
+
+ if(IS_OLD_VERSTR(ICUGLUE_VER_STR)) {
+ strs[i+j].append( ICUGLUE_VER_STR[OLD_VERSTR_MAJ] ); // X_y
+ strs[i+j].append( ICUGLUE_VER_STR[OLD_VERSTR_MIN] ); // x_Y
+ } else {
+ strs[i+j].append( ICUGLUE_VER_STR[NEW_VERSTR_MAJ] ); // Xy_
+ strs[i+j].append( ICUGLUE_VER_STR[NEW_VERSTR_MIN] ); // xY_
+ }
+
#if COLL_FE_DEBUG
{
char foo[999];
const UChar *ss = strs[i+j].getTerminatedBuffer();
u_austrcpy(foo, ss);
- // fprintf(stderr, "VCF " ICUGLUE_VER_STR " appending [%d+%d=%d] <<%s>>\n", i, j, i+j, foo);
+ debugfprintf((stderr, "VCF " ICUGLUE_VER_STR " appending [%d+%d=%d] <<%s>>\n", i, j, i+j, foo));
}
#endif
}
#if defined(GLUE_VER)
#undef GLUE_VER
#endif
-#define GLUE_VER(x) /*printf("%c/%c|%c/%c\n", icuver[0],(#x)[0],icuver[1],(#x)[2]);*/ if(icuver[0]== (#x)[0] && icuver[1]==(#x)[2]) { Collator *c = glue ## Collator ## x :: create(loc, icuver); /*fprintf(stderr, "VCF::CC %s -> %p\n", loc.getName(), c);*/ return c; }
+
+#define GLUE_VER(x) \
+ debugfprintf((stderr,"%c/%c|%c/%c\n", icuver[0],(#x)[0],icuver[1],(#x)[2])); \
+ if(CMP_VERSTR(icuver, (#x))) { \
+ Collator *c = glue ## Collator ## x :: create(loc, icuver); \
+ debugfprintf((stderr, "VCF::CC %s -> %p\n", loc.getName(), c)); \
+ return c; \
+ }
+
#include "icuglue/glver.h"
#if COLL_FE_DEBUG
fprintf(stderr, "VCF:CC %s failed\n", loc.getName());
const UChar *pattern,
int32_t patternLength,
UErrorCode *status,
- const Locale &loc, const char */*ver*/) {
+ const Locale &loc, const char */*ver*/) {
// TODO: save version
- char locBuf[200];
- char kwvBuf[200];
+ //char locBuf[200];
+ //char kwvBuf[200];
UDateFormat * uc = OICU_udat_open( timeStyle, dateStyle, locale,
tzID,
tzIDLength,
#else
/** ==================================== The following code runs inside the 'provider' version (i.e. current ICU) ========== **/
+#if (U_ICU_VERSION_MAJOR_NUM < 49)
+#define DATE_PROVIDER_UNSUPPORTED
+#endif
+
+#ifndef DATE_PROVIDER_UNSUPPORTED
// define Collator_XX
#include "icuglue/glver.h"
udat_unregisterOpener(versionDateFormatOpener, &status);
}
+#else
+
+/* no op- this ICU doesn't support date providers */
+
+void date_provider_register(UErrorCode &) {
+ // not supported
+}
+
+void date_provider_unregister(UErrorCode &) {
+ // not supported
+}
+
+#endif
+
/* Plugin- only ICU 4.4+ */
#if (U_ICU_VERSION_MAJOR_NUM > 4) || ((U_ICU_VERSION_MAJOR_NUM==4)&&(U_ICU_VERSION_MINOR_NUM>3))
#include "unicode/icuplug.h"
/*
*******************************************************************************
*
-* Copyright (C) 2009-2010, International Business Machines
+* Copyright (C) 2009-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
#define GLUE_SYM_V(x, v) glue ## x ## v
+/**
+ * how to parse a version string.
+ * old: 3_6_X, 3_8_X, 4_4_X, 4_8_X
+ * new: 49_X, 50_X, 51_X, ...
+ *
+ * example use:
+ * char *str = "50_0_0", str1="49_1_2",str2="4_8_1_1";
+ * if(IS_OLD_VERSION(str)) {
+ * maj = str[OLD_VERSTR_MAJ];
+ * min = str[OLD_VERSTR_MIN];
+ * } else {
+ * maj = str[NEW_VERSTR_MAJ];
+ * min = str[NEW_VERSTR_MIN];
+ * }
+ */
+#define IS_OLD_VERSTR(x) ((x[0]<'4') || ((x[0]=='4') && (x[2]<'9') && (x[2]>='0')))
+#define OLD_VERSTR_MAJ 0
+#define OLD_VERSTR_MIN 2
+#define NEW_VERSTR_MAJ 0
+#define NEW_VERSTR_MIN 1
+
+/**
+ * copy version into dst[0] and dst[1]
+ * does not modify dst ptr
+ */
+#define CPY_VERSTR(dst,ver) if(IS_OLD_VERSTR(ver)) \
+ { \
+ (dst)[0]=ver[OLD_VERSTR_MAJ]; \
+ (dst)[1]=ver[OLD_VERSTR_MIN]; \
+ } else { \
+ (dst)[0]=ver[NEW_VERSTR_MAJ]; \
+ (dst)[1]=ver[NEW_VERSTR_MIN]; \
+ }
+
+/**
+ * compare a verstr to a string
+ * @param str a 2 char string such as "50", "44", "49"
+ * @param ver a verstr such as "50_0_2", "4_8_1_1", etc
+ * @return true or false
+ */
+
+#define CMP_VERSTR(str,ver) \
+ ( (IS_OLD_VERSTR(ver)) ? \
+ ( \
+ (str)[0]==ver[OLD_VERSTR_MAJ] && \
+ (str)[1]==ver[OLD_VERSTR_MIN] \
+ ):( \
+ (str)[0]==ver[NEW_VERSTR_MAJ]&& \
+ (str)[1]==ver[NEW_VERSTR_MIN] \
+ ) \
+ )
+
#endif
#!/bin/sh
# Copyright (C) 2010-2012 IBM Corporation and Others, All Rights Reserved.
+PRE44=0
+
+# output 4_0 instead of 40
+if [ "$1" == "--pre44sym" ];
+then
+ PRE44=1
+ shift
+fi
+
INVER="0.0"
if [ $# -eq 0 ];
then
MIN1=`echo ${UND} | cut -d_ -f2`
if [ ${MAJ0} -lt 49 ];
then
- # pre 50: paste together "4" and "8" to get 48
- echo -n "${MAJ0}${MIN1}"
+ if [ ${PRE44} -eq 0 ];
+ then
+ # pre 50: paste together "4" and "8" to get 48
+ echo -n "${MAJ0}${MIN1}"
+ else
+ # pre 50: 4_8
+ echo -n "${MAJ0}_${MIN1}"
+ fi
else
# post 50: just use the first #
echo -n "${MAJ0}"
fi
-exit 0
\ No newline at end of file
+exit 0
shift
TINY=`./icu2symver.sh $VER`
+OLDSYM=`./icu2symver.sh --pre44sym $VER`
echo "$0: Building ${OUT} for ${TINY} ------- " >&2
+echo "oldsym = ${OLDSYM}"
#set -x
-
+URENAME=${SRC}/${VER}/${SOURCE}/common/unicode/urename.h
(
cat ${GLUE}/gluren-top.h
+ echo "/* Generated from ${URENAME} by ${0} */"
echo "#define GLUREN_VER" ${TINY}
echo "#define GLUREN_TINY" ${TINY}
echo
echo '/* old style (<4.4)*/'
- grep "^#define.*${TINY}$" ${SRC}/${VER}/${SOURCE}/common/unicode/urename.h | fgrep -v '*' | sed -e "s@^#define \([^ ]*\) \([^ ]*\)@#define OICU_\1 \2@"
+ grep "^#define.*${OLDSYM}$" ${URENAME} | fgrep -v '*' | sed -e "s@^#define \([^ ]*\) \([^ ]*\)@#define OICU_\1 \2@"
echo '/* new style (4.4+) */'
- fgrep " U_ICU_ENTRY_POINT_RENAME(" ${SRC}/${VER}/${SOURCE}/common/unicode/urename.h | sed -e "s@^#define \([^ ]*\) .*@#define OICU_\1 \1_${TINY}@"
+ fgrep " U_ICU_ENTRY_POINT_RENAME(" ${URENAME} | sed -e "s@^#define \([^ ]*\) .*@#define OICU_\1 \1_${TINY}@"
cat ${GLUE}/gluren-bottom.h
) |
cat > ${OUT}
1c. Copy the ICUs (named as they were downloaded) into the ../../packages/ directory relative to this readme.
-2a. Copy the file "Makefile-local.sample" into a new file "Makefile.local".
+2a. Copy the file "Makefile.local-sample" into a new file "Makefile.local".
2b. Edit the Makefile.local to modify the PROVIDER_TARGET and
PROVIDER_AVAILABLE settings.
+---------------------------
+THEORY (INTERNAL USE ONLY!)
+
+For discussion: assume TARGET 50.0.2 and PROVIDER 4.0.1
+
+i. GENERAL
+
+ The "front end" for each module (date, collator, ..) is built once for the target version, and the "back end" glue is built once for each provider version. (TODO: fix wording here.)
+
+ The oicu.h header, combined with the generated gluren.h, provides a "renamed" symbol such as (literally) OICU_ucol_strcoll which is #defined to some specific version, such as ucol_strcoll_4_0. So, you can call the OICU_ version meaning "Old ICU". Thus, you have the ICU 4.0 function defined as an extern, by its explicit name, within the ICU 50 space.
+
+ The icuglue/glver.h header file contains multiple calls to, for example, GLUE_VER(4_0_1) GLUE_VER(49_1_2) ...
+ A module can redefine GLUE_VER in order to do some "each-version" process. Thus, glver.h can be #included multiple times..
+
+ Generally, a locale such as en_US@sp=icu40 will refer to an ICU 4.0 provider.
+
+ There are lots of version-specific #ifdefs used to deal with the vagaries of a decade of ICU changes.
+
+ii. COLLATORS
+
+ For each back end, there's an icu_50::Collator class named, say, glueCollator4_0_1 which is implemented in the TARGET space. However, each function of this class, such as "compare", is implemented by calling, for example, OICU_ucol_strcoll. As noted above, this is directly calling ucol_strcoll_4_0. This is where the cross-version calls happen. Such glue code must be very careful not to, for example, call ucol_open_4_0 and pass the result to ucol_close_50 !
+
+ The FE builds a CollatorFactory subclass, VersionCollatorFactory. It registers a collator for every localeid it can support. This is done by calling each glueCollator* subclass's static ::countAvailable and appendAvailable functions directly.
+
+ The plugin simply registers and unregisters the VCF. Such collators are available to both C++ and C API, including the shortstring interface, using the _PICU## short string tag.
+
+iii. DATE FORMATTERS
+
+ Date formatters work in a similar fashion to collators. DateFormat subclasses are registered which are implemented in terms of OICU_udat_* functions. A "DateFormatOpener" (factory equivalent) is registered to allow udat_open to process correctly. C++ date format registration is not addressed as of this writing.
+
+