From: Steven R. Loomis Date: Tue, 18 Sep 2012 02:02:43 +0000 (+0000) Subject: ICU-9329 document internals and usage. work with ICU 50. X-Git-Tag: milestone-59-0-1~3551 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3b5c1fb3cd46827f3d44aa429e6c9d678ef62099;p=icu ICU-9329 document internals and usage. work with ICU 50. X-SVN-Rev: 32401 --- diff --git a/tools/multi/proj/provider/Makefile b/tools/multi/proj/provider/Makefile index 04e06da6658..8825a60e18c 100644 --- a/tools/multi/proj/provider/Makefile +++ b/tools/multi/proj/provider/Makefile @@ -98,7 +98,7 @@ MAKE_INSTALL_XTRA_OPTS=$(MAKE_XTRA_OPTS) # 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=%) @@ -146,6 +146,9 @@ $(GLOUT)/$(PLUGLIB)/obj-$(OK): $(GLOUT) glurens $(PLUGLIB_ICU_CONFIG) $(GL_FE_F # 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) ; \ @@ -249,6 +252,7 @@ glurens: $(GLUREN_ICU) $(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) @@ -302,7 +306,7 @@ info help: @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 @@ -314,7 +318,10 @@ $(OUT)/$(PLUGLIB)/provider_version.h: Makefile.local Makefile @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]))" >> $@ diff --git a/tools/multi/proj/provider/Makefile.local-sample b/tools/multi/proj/provider/Makefile.local-sample index 88e8c8ac175..34a36ce56f5 100644 --- a/tools/multi/proj/provider/Makefile.local-sample +++ b/tools/multi/proj/provider/Makefile.local-sample @@ -1,5 +1,5 @@ # -# 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: @@ -8,9 +8,9 @@ ## 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 diff --git a/tools/multi/proj/provider/coldiff.cpp b/tools/multi/proj/provider/coldiff.cpp index 563816cc0a3..a45cfc70da2 100644 --- a/tools/multi/proj/provider/coldiff.cpp +++ b/tools/multi/proj/provider/coldiff.cpp @@ -1,7 +1,7 @@ /* ******************************************************************************* * -* Copyright (C) 2009-2011, International Business Machines +* Copyright (C) 2009-2012, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -164,7 +164,11 @@ int main(int /* argc*/ , const char * /*argv*/ []) { } 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); diff --git a/tools/multi/proj/provider/datediff.cpp b/tools/multi/proj/provider/datediff.cpp index 0a21997772d..0f69b906ff4 100644 --- a/tools/multi/proj/provider/datediff.cpp +++ b/tools/multi/proj/provider/datediff.cpp @@ -39,6 +39,10 @@ void setup(UErrorCode &status) { } 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; @@ -48,7 +52,7 @@ int main(int /* argc*/ , const char * /*argv*/ []) { int expected = PROVIDER_COUNT; - for(int s=0;s #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 @@ -40,17 +59,17 @@ 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(); \ @@ -209,7 +228,7 @@ int32_t GLUE_SYM ( Collator ) :: hashCode() const { } -const Locale GLUE_SYM ( Collator ) :: getLocale(ULocDataLocaleType, UErrorCode&) const { +CONST_BEFORE_50_0_2 Locale GLUE_SYM ( Collator ) :: getLocale(ULocDataLocaleType, UErrorCode&) const { return Locale(); } @@ -229,11 +248,11 @@ void GLUE_SYM ( Collator ) :: getVersion(uint8_t*) const { } -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; } @@ -243,7 +262,7 @@ return 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; } @@ -257,7 +276,7 @@ return 0; } -Collator* GLUE_SYM ( Collator ) :: safeClone() { +Collator* GLUE_SYM ( Collator ) :: safeClone() CONST_AFTER_50_0_2 { return clone(); } @@ -292,8 +311,8 @@ int32_t GLUE_SYM (Collator ) :: internalGetShortDefinitionString(const char *lo 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; } @@ -319,14 +338,21 @@ int32_t GLUE_SYM ( Collator ) :: appendAvailable(UnicodeString* strs, int32_t i, for(int j=0;j>\n", i, j, i+j, foo); + debugfprintf((stderr, "VCF " ICUGLUE_VER_STR " appending [%d+%d=%d] <<%s>>\n", i, j, i+j, foo)); } #endif } @@ -380,7 +406,15 @@ Collator *VersionCollatorFactory::createCollator(const Locale &loc) { #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()); diff --git a/tools/multi/proj/provider/glue/date_fe.cpp b/tools/multi/proj/provider/glue/date_fe.cpp index 7042b22adc4..6e3c1f040b5 100644 --- a/tools/multi/proj/provider/glue/date_fe.cpp +++ b/tools/multi/proj/provider/glue/date_fe.cpp @@ -90,10 +90,10 @@ GLUE_SYM ( DateFormat ) :: create(UDateFormatStyle timeStyle, 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, @@ -185,6 +185,11 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION( GLUE_SYM( DateFormat ) ) #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" @@ -324,6 +329,20 @@ void date_provider_unregister(UErrorCode &status) { 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" diff --git a/tools/multi/proj/provider/glue/include/icuglue/icuglue.h b/tools/multi/proj/provider/glue/include/icuglue/icuglue.h index 8d916c5efac..61485618bae 100644 --- a/tools/multi/proj/provider/glue/include/icuglue/icuglue.h +++ b/tools/multi/proj/provider/glue/include/icuglue/icuglue.h @@ -1,7 +1,7 @@ /* ******************************************************************************* * -* Copyright (C) 2009-2010, International Business Machines +* Copyright (C) 2009-2012, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* @@ -15,4 +15,56 @@ #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 diff --git a/tools/multi/proj/provider/icu2symver.sh b/tools/multi/proj/provider/icu2symver.sh index 597325f729f..27cdddd3e97 100755 --- a/tools/multi/proj/provider/icu2symver.sh +++ b/tools/multi/proj/provider/icu2symver.sh @@ -1,6 +1,15 @@ #!/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 @@ -18,11 +27,17 @@ MAJ0=`echo ${UND} | cut -d_ -f1` 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 diff --git a/tools/multi/proj/provider/makegluren.sh b/tools/multi/proj/provider/makegluren.sh index 6343f752fcc..3b3deaf9afa 100755 --- a/tools/multi/proj/provider/makegluren.sh +++ b/tools/multi/proj/provider/makegluren.sh @@ -9,19 +9,22 @@ VER=$1 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} diff --git a/tools/multi/proj/provider/readme.txt b/tools/multi/proj/provider/readme.txt index 91f36a7b33c..1e7d3e4b81e 100644 --- a/tools/multi/proj/provider/readme.txt +++ b/tools/multi/proj/provider/readme.txt @@ -21,7 +21,7 @@ the provider interface). As of this writing, 49, 4.8.1.1, 4.6.x, 4.4.x, 4.2.0.1 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. @@ -77,3 +77,34 @@ format, but only through 'udat_open'. +--------------------------- +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. + +