[sword-svn] r214 - in trunk: . source source/common source/common/unicode source/config source/extra/uconv source/i18n source/i18n/unicode source/layout source/samples/layout source/tools/ctestfw source/tools/ctestfw/unicode source/tools/pkgdata source/tools/toolutil

chrislit at crosswire.org chrislit at crosswire.org
Thu Jul 2 12:32:01 MST 2009


Author: chrislit
Date: 2009-07-02 12:32:00 -0700 (Thu, 02 Jul 2009)
New Revision: 214

Removed:
   trunk/source/common/unicode/uspoof.h
   trunk/source/layout/HindiFeatureTags.h
Modified:
   trunk/readme.html
   trunk/source/common/dtintrv.cpp
   trunk/source/common/mutex.cpp
   trunk/source/common/uloc.c
   trunk/source/common/unicode/dtintrv.h
   trunk/source/common/unicode/uversion.h
   trunk/source/config/gmakever.mk
   trunk/source/config/make2sh.sed
   trunk/source/config/pkgdataMakefile.in
   trunk/source/configure.mk
   trunk/source/extra/uconv/pkgdataMakefile.in
   trunk/source/extra/uconv/uconv.vcproj
   trunk/source/i18n/currpinf.cpp
   trunk/source/i18n/dtitv_impl.h
   trunk/source/i18n/dtitvfmt.cpp
   trunk/source/i18n/dtitvinf.cpp
   trunk/source/i18n/dtptngen.cpp
   trunk/source/i18n/tmunit.cpp
   trunk/source/i18n/tmutamt.cpp
   trunk/source/i18n/tmutfmt.cpp
   trunk/source/i18n/unicode/currpinf.h
   trunk/source/i18n/unicode/dtitvfmt.h
   trunk/source/i18n/unicode/dtitvinf.h
   trunk/source/i18n/unicode/dtptngen.h
   trunk/source/i18n/unicode/smpdtfmt.h
   trunk/source/i18n/unicode/tmunit.h
   trunk/source/i18n/unicode/tmutamt.h
   trunk/source/i18n/unicode/tmutfmt.h
   trunk/source/i18n/uspoof_impl.cpp
   trunk/source/samples/layout/cgnomelayout.c
   trunk/source/tools/ctestfw/ctest.c
   trunk/source/tools/ctestfw/tstdtmod.cpp
   trunk/source/tools/ctestfw/unicode/ctest.h
   trunk/source/tools/pkgdata/pkgdata.cpp
   trunk/source/tools/toolutil/pkg_genc.c
   trunk/source/tools/toolutil/pkg_genc.h
   trunk/source/tools/toolutil/pkg_gencmn.c
   trunk/source/tools/toolutil/pkg_gencmn.h
   trunk/source/tools/toolutil/pkg_icu.cpp
   trunk/source/tools/toolutil/pkg_icu.h
   trunk/source/tools/toolutil/toolutil.c
Log:
ICU 4.2.1 update, sixth pass


Modified: trunk/readme.html
===================================================================
--- trunk/readme.html	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/readme.html	2009-07-02 19:32:00 UTC (rev 214)
@@ -17,9 +17,9 @@
 
   <body class="readme">
     <h1>International Components for Unicode<br />
-     <abbr title="International Components for Unicode">ICU</abbr> 4.2.0.1 ReadMe</h1>
+     <abbr title="International Components for Unicode">ICU</abbr> 4.2.1 ReadMe</h1>
 
-    <p>Version: 2009 May 20th<br />
+    <p>Version: 2009 July 1st<br />
      Copyright &copy; 1997-2009 International Business Machines Corporation and
     others. All Rights Reserved.</p>
     <!-- Remember that there is a copyright at the end too -->
@@ -200,9 +200,45 @@
     <h2><a name="News" href="#News" id="News">What is new in this release?</a></h2>
     
 
-    <p>ICU for C/C++ version 4.2.0.1 is a an update release of 4.2, containing selected platform and build related bug fixes. It does
-     not introduce new API or functionality. These changes will be rolled into the next release of ICU.  
-     	The overall ticket used for this release is <a href="http://bugs.icu-project.org/trac/ticket/6953">#6953</a>.
+    <p>ICU for C/C++ version 4.2.1 is a maintenance release of 4.2, containing fixes and updates in both code and data. It does
+     not introduce new API or functionality relative to 4.2. These changes will be rolled into the next release of ICU.  
+     	The overall ticket used for the 4.2.1 release is <a href="http://bugs.icu-project.org/trac/ticket/7018">#7018</a>.
+     	 Here is a list of the bug fixes included in 4.2.1, and the revisions used  4.2.1:
+     </p>
+     <ul>
+     	<li>
+     		<a href="http://bugs.icu-project.org/trac/ticket/6905">#6905</a> 
+     		<a href="http://bugs.icu-project.org/trac/changeset/26084">r26084</a> &mdash;
+     		Make sure cintltst and intltest pass w/o data
+     	</li>
+     	<li>
+     		<a href="http://bugs.icu-project.org/trac/ticket/6919">#6919</a> 
+     		<a href="http://bugs.icu-project.org/trac/changeset/26063">r26063</a> &mdash;
+     		icu-config generation errors
+     	</li>
+     	<li>
+     		<a href="http://bugs.icu-project.org/trac/ticket/6979">#6979</a> 
+     		<a href="http://bugs.icu-project.org/trac/changeset/26138">r26138</a> &mdash;
+     		Integrate CLDR 1.7.1
+     	</li>
+     	<li>
+     		<a href="http://bugs.icu-project.org/trac/ticket/6980">#6980</a> 
+     		<a href="http://bugs.icu-project.org/trac/changeset/26005">r26005</a> &mdash;
+     		SimpleDateFormat serious compilation warnings
+     	</li>
+     	<li>
+     		<a href="http://bugs.icu-project.org/trac/ticket/6908">#6908</a> 
+     		<a href="http://bugs.icu-project.org/trac/changeset/25978">r25978</a> &mdash;
+     		Numbering Systems - Malayalam msising digit 5
+     	</li>
+     	<li>
+     		<a href="http://bugs.icu-project.org/trac/ticket/6990">#6990</a> 
+     		<a href="http://bugs.icu-project.org/trac/changeset/26002">r26164</a> &mdash;
+     		Update time zone data to version 2009j
+     	</li>
+     </ul>
+    <p> 
+     	The overall ticket used for the 4.2.0.1 release was <a href="http://bugs.icu-project.org/trac/ticket/6953">#6953</a>.
      	 Here is a list of the bug fixes included in 4.2.0.1, and the revisions used to patch 4.2.0.1:
      </p>
      <ul>

Modified: trunk/source/common/dtintrv.cpp
===================================================================
--- trunk/source/common/dtintrv.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/common/dtintrv.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,61 +1,61 @@
-/*******************************************************************************
-* Copyright (C) 2008, International Business Machines Corporation and
-* others. All Rights Reserved.
-*******************************************************************************
-*
-* File DTINTRV.CPP 
-*
-*******************************************************************************
-*/
-
-
-
-#include "unicode/dtintrv.h"
-
-
-U_NAMESPACE_BEGIN
-
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateInterval)
-
-//DateInterval::DateInterval(){}
-
-
-DateInterval::DateInterval(UDate from, UDate to)
-:   fromDate(from),
-    toDate(to)
-{}
-
-
-DateInterval::~DateInterval(){}
-
-
-DateInterval::DateInterval(const DateInterval& other)
-: UObject(other) {
-    *this = other;
-}   
-
-
-DateInterval&
-DateInterval::operator=(const DateInterval& other) {
-    if ( this != &other ) {
-        fromDate = other.fromDate;
-        toDate = other.toDate;
-    }
-    return *this;
-}
-
-
-DateInterval* 
-DateInterval::clone() const {
-    return new DateInterval(*this);
-}
-
-
-UBool 
-DateInterval::operator==(const DateInterval& other) const { 
-    return ( fromDate == other.fromDate && toDate == other.toDate );
-}
-
-
-U_NAMESPACE_END
-
+/*******************************************************************************
+* Copyright (C) 2008, International Business Machines Corporation and
+* others. All Rights Reserved.
+*******************************************************************************
+*
+* File DTINTRV.CPP 
+*
+*******************************************************************************
+*/
+
+
+
+#include "unicode/dtintrv.h"
+
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateInterval)
+
+//DateInterval::DateInterval(){}
+
+
+DateInterval::DateInterval(UDate from, UDate to)
+:   fromDate(from),
+    toDate(to)
+{}
+
+
+DateInterval::~DateInterval(){}
+
+
+DateInterval::DateInterval(const DateInterval& other)
+: UObject(other) {
+    *this = other;
+}   
+
+
+DateInterval&
+DateInterval::operator=(const DateInterval& other) {
+    if ( this != &other ) {
+        fromDate = other.fromDate;
+        toDate = other.toDate;
+    }
+    return *this;
+}
+
+
+DateInterval* 
+DateInterval::clone() const {
+    return new DateInterval(*this);
+}
+
+
+UBool 
+DateInterval::operator==(const DateInterval& other) const { 
+    return ( fromDate == other.fromDate && toDate == other.toDate );
+}
+
+
+U_NAMESPACE_END
+

Modified: trunk/source/common/mutex.cpp
===================================================================
--- trunk/source/common/mutex.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/common/mutex.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,18 +1,18 @@
-/**
-*******************************************************************************
-* Copyright (C) 2008, International Business Machines Corporation.       *
-* All Rights Reserved.                                                        *
-*******************************************************************************
-*/
-
-#include "unicode/utypes.h"
-
-#if UCONFIG_NO_SERVICE
-
-/* If UCONFIG_NO_SERVICE, then there is no invocation of Mutex elsewhere in
-   common, so add one here to force an export */
-#include "mutex.h"
-static Mutex *aMutex = 0;
-
-/* UCONFIG_NO_SERVICE */
-#endif
+/**
+*******************************************************************************
+* Copyright (C) 2008, International Business Machines Corporation.       *
+* All Rights Reserved.                                                        *
+*******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+
+#if UCONFIG_NO_SERVICE
+
+/* If UCONFIG_NO_SERVICE, then there is no invocation of Mutex elsewhere in
+   common, so add one here to force an export */
+#include "mutex.h"
+static Mutex *aMutex = 0;
+
+/* UCONFIG_NO_SERVICE */
+#endif

Modified: trunk/source/common/uloc.c
===================================================================
--- trunk/source/common/uloc.c	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/common/uloc.c	2009-07-02 19:32:00 UTC (rev 214)
@@ -146,7 +146,7 @@
     "lah", "lam", "lb",  "lez", "lg",  "li",  "ln",  "lo",  "lol",
     "loz", "lt",  "lu",  "lua", "lui", "lun", "luo", "lus",
     "lv",  "mad", "mag", "mai", "mak", "man", "map", "mas",
-    "mdf", "mdr", "men", "mg",  "mga", "mh",  "mi",  "mic", "min",
+    "mdf", "mdr", "men", "mfe", "mg",  "mga", "mh",  "mi",  "mic", "min",
     "mis", "mk",  "mkh", "ml",  "mn",  "mnc", "mni", "mno",
     "mo",  "moh", "mos", "mr",  "ms",  "mt",  "mul", "mun",
     "mus", "mwl", "mwr", "my",  "myn", "myv", "na",  "nah", "nai", "nap",
@@ -262,8 +262,8 @@
     "loz", "lit", "lub", "lua", "lui", "lun", "luo", "lus",
 /*  "lv",  "mad", "mag", "mai", "mak", "man", "map", "mas",    */
     "lav", "mad", "mag", "mai", "mak", "man", "map", "mas",
-/*  "mdf", "mdr", "men", "mg",  "mga", "mh",  "mi",  "mic", "min",    */
-    "mdf", "mdr", "men", "mlg", "mga", "mah", "mri", "mic", "min",
+/*  "mdf", "mdr", "men", "mfe", "mg",  "mga", "mh",  "mi",  "mic", "min",    */
+    "mdf", "mdr", "men", "mfe", "mlg", "mga", "mah", "mri", "mic", "min",
 /*  "mis", "mk",  "mkh", "ml",  "mn",  "mnc", "mni", "mno",    */
     "mis", "mkd", "mkh", "mal", "mon", "mnc", "mni", "mno",
 /*  "mo",  "moh", "mos", "mr",  "ms",  "mt",  "mul", "mun",    */

Modified: trunk/source/common/unicode/dtintrv.h
===================================================================
--- trunk/source/common/unicode/dtintrv.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/common/unicode/dtintrv.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,158 +1,158 @@
-/*
-*******************************************************************************
-* Copyright (C) 2008-2009, International Business Machines Corporation and
-* others. All Rights Reserved.
-*******************************************************************************
-*
-* File DTINTRV.H 
-*
-*******************************************************************************
-*/
-
-#ifndef __DTINTRV_H__
-#define __DTINTRV_H__
-
-#include "unicode/utypes.h"
-#include "unicode/uobject.h"
-
-/**
- * \file
- * \brief C++ API: Date Interval data type
- */
-
-
-U_NAMESPACE_BEGIN
-
-
-/**
- * This class represents a date interval.
- * It is a pair of UDate representing from UDate 1 to UDate 2.
- * @stable ICU 4.0
-**/
-class U_COMMON_API DateInterval : public UObject {
-public:
-
-    /** 
-     * Construct a DateInterval given a from date and a to date.
-     * @param fromDate  The from date in date interval.
-     * @param toDate    The to date in date interval.
-     * @stable ICU 4.0
-     */
-    DateInterval(UDate fromDate, UDate toDate);
-
-    /**
-     * destructor
-     * @stable ICU 4.0
-     */
-    virtual ~DateInterval();
- 
-    /** 
-     * Get the from date.
-     * @return  the from date in dateInterval.
-     * @stable ICU 4.0
-     */
-    UDate getFromDate() const;
-
-    /** 
-     * Get the to date.
-     * @return  the to date in dateInterval.
-     * @stable ICU 4.0
-     */
-    UDate getToDate() const;
-
-
-    /**
-     * Return the class ID for this class. This is useful only for comparing to
-     * a return value from getDynamicClassID(). For example:
-     * <pre>
-     * .   Base* polymorphic_pointer = createPolymorphicObject();
-     * .   if (polymorphic_pointer->getDynamicClassID() ==
-     * .       erived::getStaticClassID()) ...
-     * </pre>
-     * @return          The class ID for all objects of this class.
-     * @stable ICU 4.0
-     */
-    static UClassID U_EXPORT2 getStaticClassID(void);
-
-    /**
-     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
-     * method is to implement a simple version of RTTI, since not all C++
-     * compilers support genuine RTTI. Polymorphic operator==() and clone()
-     * methods call this method.
-     *
-     * @return          The class ID for this object. All objects of a
-     *                  given class have the same class ID.  Objects of
-     *                  other classes have different class IDs.
-     * @stable ICU 4.0
-     */
-    virtual UClassID getDynamicClassID(void) const;
-
-    
-    /**
-     * Copy constructor.
-     * @stable ICU 4.0
-     */
-    DateInterval(const DateInterval& other);
-
-    /**
-     * Default assignment operator
-     * @stable ICU 4.0
-     */
-    DateInterval& operator=(const DateInterval&);
-
-    /**
-     * Equality operator.
-     * @return TRUE if the two DateIntervals are the same
-     * @stable ICU 4.0
-     */
-    virtual UBool operator==(const DateInterval& other) const;
-
-    /**
-     * Non-equality operator
-     * @return TRUE if the two DateIntervals are not the same
-     * @stable ICU 4.0
-     */
-    UBool operator!=(const DateInterval& other) const;
-
-
-    /**
-     * clone this object. 
-     * The caller owns the result and should delete it when done.
-     * @return a cloned DateInterval
-     * @stable ICU 4.0
-     */
-     virtual DateInterval* clone() const;
-
-private:
-    /** 
-     * Default constructor, not implemented.
-     */
-    DateInterval();
-
-    UDate fromDate;
-    UDate toDate;
-
-} ;// end class DateInterval
-
-
-inline UDate 
-DateInterval::getFromDate() const { 
-    return fromDate; 
-}
-
-
-inline UDate 
-DateInterval::getToDate() const { 
-    return toDate; 
-}
-
-
-inline UBool 
-DateInterval::operator!=(const DateInterval& other) const { 
-    return ( !operator==(other) );
-}
-
-
-U_NAMESPACE_END
-
-#endif
+/*
+*******************************************************************************
+* Copyright (C) 2008-2009, International Business Machines Corporation and
+* others. All Rights Reserved.
+*******************************************************************************
+*
+* File DTINTRV.H 
+*
+*******************************************************************************
+*/
+
+#ifndef __DTINTRV_H__
+#define __DTINTRV_H__
+
+#include "unicode/utypes.h"
+#include "unicode/uobject.h"
+
+/**
+ * \file
+ * \brief C++ API: Date Interval data type
+ */
+
+
+U_NAMESPACE_BEGIN
+
+
+/**
+ * This class represents a date interval.
+ * It is a pair of UDate representing from UDate 1 to UDate 2.
+ * @stable ICU 4.0
+**/
+class U_COMMON_API DateInterval : public UObject {
+public:
+
+    /** 
+     * Construct a DateInterval given a from date and a to date.
+     * @param fromDate  The from date in date interval.
+     * @param toDate    The to date in date interval.
+     * @stable ICU 4.0
+     */
+    DateInterval(UDate fromDate, UDate toDate);
+
+    /**
+     * destructor
+     * @stable ICU 4.0
+     */
+    virtual ~DateInterval();
+ 
+    /** 
+     * Get the from date.
+     * @return  the from date in dateInterval.
+     * @stable ICU 4.0
+     */
+    UDate getFromDate() const;
+
+    /** 
+     * Get the to date.
+     * @return  the to date in dateInterval.
+     * @stable ICU 4.0
+     */
+    UDate getToDate() const;
+
+
+    /**
+     * Return the class ID for this class. This is useful only for comparing to
+     * a return value from getDynamicClassID(). For example:
+     * <pre>
+     * .   Base* polymorphic_pointer = createPolymorphicObject();
+     * .   if (polymorphic_pointer->getDynamicClassID() ==
+     * .       erived::getStaticClassID()) ...
+     * </pre>
+     * @return          The class ID for all objects of this class.
+     * @stable ICU 4.0
+     */
+    static UClassID U_EXPORT2 getStaticClassID(void);
+
+    /**
+     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
+     * method is to implement a simple version of RTTI, since not all C++
+     * compilers support genuine RTTI. Polymorphic operator==() and clone()
+     * methods call this method.
+     *
+     * @return          The class ID for this object. All objects of a
+     *                  given class have the same class ID.  Objects of
+     *                  other classes have different class IDs.
+     * @stable ICU 4.0
+     */
+    virtual UClassID getDynamicClassID(void) const;
+
+    
+    /**
+     * Copy constructor.
+     * @stable ICU 4.0
+     */
+    DateInterval(const DateInterval& other);
+
+    /**
+     * Default assignment operator
+     * @stable ICU 4.0
+     */
+    DateInterval& operator=(const DateInterval&);
+
+    /**
+     * Equality operator.
+     * @return TRUE if the two DateIntervals are the same
+     * @stable ICU 4.0
+     */
+    virtual UBool operator==(const DateInterval& other) const;
+
+    /**
+     * Non-equality operator
+     * @return TRUE if the two DateIntervals are not the same
+     * @stable ICU 4.0
+     */
+    UBool operator!=(const DateInterval& other) const;
+
+
+    /**
+     * clone this object. 
+     * The caller owns the result and should delete it when done.
+     * @return a cloned DateInterval
+     * @stable ICU 4.0
+     */
+     virtual DateInterval* clone() const;
+
+private:
+    /** 
+     * Default constructor, not implemented.
+     */
+    DateInterval();
+
+    UDate fromDate;
+    UDate toDate;
+
+} ;// end class DateInterval
+
+
+inline UDate 
+DateInterval::getFromDate() const { 
+    return fromDate; 
+}
+
+
+inline UDate 
+DateInterval::getToDate() const { 
+    return toDate; 
+}
+
+
+inline UBool 
+DateInterval::operator!=(const DateInterval& other) const { 
+    return ( !operator==(other) );
+}
+
+
+U_NAMESPACE_END
+
+#endif

Deleted: trunk/source/common/unicode/uspoof.h
===================================================================
--- trunk/source/common/unicode/uspoof.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/common/unicode/uspoof.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,553 +0,0 @@
-/*
-***************************************************************************
-* Copyright (C) 2008, International Business Machines Corporation
-* and others. All Rights Reserved.
-***************************************************************************
-*   file name:  uspoof.h
-*   encoding:   US-ASCII
-*   tab size:   8 (not used)
-*   indentation:4
-*
-*   created on: 2008Feb13
-*   created by: Andy Heninger
-*
-*   Unicode Spoof Detection
-*/
-
-/**
- * \file
- * \brief C API: Unicode Spoof Detection
- *
- * <p>C API for Unicode Security and Spoofing Detection</p>
- *
- * These functions are intended to check strings, typically
- * identifiers or URLs, for the presence of combinations of
- * characters that are likely to be visually confusing - 
- * for cases where the displayed form of an identifier may
- * not be what it appears to be.
- *
- * Unicode security considerations, and descriptions of the checks
- * performed by these functions, are describe in 
- * Unicode Technical Report #36, http://unicode.org/reports/tr36, and
- * Unicode Technical Standard #39, http://unicode.org/reports/tr39
- */
-#ifndef USPOOF_H
-#define USPOOF_H
-
-#include "unicode/utypes.h"
-#include "unicode/uset.h"
-
-#ifdef XP_CPLUSPLUS
-#include "unicode/unistr.h"
-#include "unicode/uniset.h"
-#endif
-
-
-struct USpoofChecker;
-typedef struct USpoofChecker USpoofChecker;
-
-/**
- * Enum for the kinds of checks that USpoofChecker can perform.
- * These enum values are used both to select the set of checks that
- * will be performed, and to report results from the check function.
- *
- * @draft ICU 4.0
- */
-typedef enum USpoofChecks {
-    USPOOF_SINGLE_SCRIPT_CONFUSABLE =  1,
-    USPOOF_MIXED_SCRIPT_CONFUSABLE  =  2,
-    USPOOF_WHOLE_SCRIPT_CONFUSABLE  =  4,
-    USPOOF_SECURE_ID                =  8,
-    USPOOF_MIXED_SCRIPT             = 16,
-    USPOOF_LOCALE_LIMIT             = 32,
-    USPOOF_CHAR_LIMIT               = 64,
-    USPOOF_ALL_CHECKS               = 0x7f
-    };
-    
-    
-/**
- *  Create a Unicode Spoof Checker, configured to perform all 
- *  checks except for USPOOF_LOCALE_LIMIT and USPOOF_CHAR_LIMIT.
- *  Note that additional checks may be added in the future,
- *  resulting in the changes to the default checking behavior.
- *
- *  @param status  The error code, set if this function encounters a problem.
- *  @return        the newly created Spoof Checker
- *  @draft  ICU 4.0
- */
-U_DRAFT USpoofChecker * U_EXPORT2
-uspoof_open(UErrorCode *status);
-
-
-/**
- * Specify the set of checks that will be performed by the check
- * functions of this Spoof Checker.
- *
- * 
- * @param sc       The USpoofChecker
- * @checks         The set of checks that this spoof checker will perform.
- *                 The value is a bit set, obtained by OR-ing together
- *                 values from enum USpoofChecks.
- * @param status   The error code, set if this function encounters a problem.
- * @draft  ICU 4.0
- *
- */
-U_DRAFT void U_EXPORT2
-uspoof_setChecks(USpoofChecker *sc, int32_t checks, UErrorCode *status);
-
-/**
- * Get the set of checks that this Spoof Checker has been configured to perform.
- * 
- * @param sc       The USpoofChecker
- * @param status   The error code, set if this function encounters a problem.
- * @return         The set of checks that this spoof checker will perform.
- *                 The value is a bit set, obtained by OR-ing together
- *                 values from enum USpoofChecks.
- * @draft  ICU 4.0
- *
- */
-U_DRAFT int32_t U_EXPORT2
-uspoof_getChecks(const USpoofChecker sc, UErrorCode *status);
-
-/**
- * Limit characters that are acceptable in identifiers being checked to those 
- * normally used with the languages associated with the specified locales.
- * Any previously specified list of locales is replaced by the new settings.
- *
- * A set of languages is determined from the locale(s), and
- * from those a set of acceptable Unicode scripts is determined.
- * Characters from this set of scripts, along with characters from
- * the "common" and "inherited" Unicode Script categories
- * will be permitted.
- *
- * Supplying an empty string removes all restrictions;
- * characters from any script will be allowed.
- *
- * The USPOOF_LOCALE_LIMIT test is automatically enabled for this
- * USpoofChecker when calling this function with a non-empty set
- * of locales.
- *
- * @param sc           The USpoofChecker 
- * @param localesList  A list list of locales, from which the language
- *                     and associated script are extracted.  The list
- *                     list has the format of an HTTP Accept-Language
- *                     header, and .
- * @param status       The error code, set if this function encounters a problem.
- * @draft  ICU 4.0
- */
-U_DRAFT void U_EXPORT2
-uspoof_setAllowedLocales(USpoofChecker *sc, const char *localesList, UErrorCode *status);
-
-/**
- * Get a list of locales for the scripts that are acceptable in strings
- *  to be checked.  If no limitations on scripts have been specified,
- *  an empty string will be returned.
- *
- *  The format of the returned list is that of an HTTP Accept-Language
- *  header field, but it may not be identical to the original string passed
- *  to uspoof_setAllowedLocales();  the string may be
- *  reformatted, and information other than languages from the originally
- *  specified HTTP header may be omitted.
- *
- * @param sc           The USpoofChecker 
- * @param status       The error code, set if this function encounters a problem.
- * @return             A string containing a list of  locales corresponding
- *                     to the acceptable scripts, formatted like an
- *                     HTTP Accept Language value.
- *  
- * @draft ICU 4.0
- */
-U_DRAFT const char * U_EXPORT2
-uspoof_getAllowedLocales(USpoofChecker *sc, UErrorCode *status);
-
-
-/**
- * Limit the acceptable characters to those specified by a Unicode Set.
- *   Any previously specified character limit is
- *   is replaced by the new settings.
- *
- * The USPOOF_CHAR_LIMIT test is automatically enabled for this
- * USpoofChecker by this function.
- *
- * @param sc       The USpoofChecker 
- * @param chars    A Unicode Set containing the list of
- *                 charcters that are permitted.  Ownership of the set
- *                 remains with the caller.  The incoming set is cloned by
- *                 this function, so there are no restrictions on modifying
- *                 or deleting the USet after calling this function.
- * @param status   The error code, set if this function encounters a problem.
- */
-U_DRAFT void U_EXPORT2
-uspoof_setAllowedChars(USpoofChecker *sc, const USet *chars, UErrorCode *status);
-
-
-/**
- * Get a USet for the characters permitted in an identifier.
- * This corresponds to the limits imposed by the Set Allowed Characters
- * functions. Limitations imposed by other checks will not be
- * reflected in the set returned by this function.
- *
- * The returned set will be frozen, meaning that it cannot be modified
- * by the caller.
- *
- * Ownership of the returned set remains with the Spoof Detector.  The
- * returned set will become invalid if the spoof detector is closed,
- * or if a new set of allowed characters is specified.
- *
- *
- * @param sc       The USpoofChecker 
- * @param chars    A Unicode Set containing the complete list of
- *                 charcters that are permitted.  Ownership of the set
- *                 remains with the caller.  The incoming set is cloned by
- *                 this function, so there are no restrictions on modifying
- *                 or deleting the USet after calling this function.
- * @param status   The error code, set if this function encounters a problem.
- * @return         A USet containing the characters that are permitted by
- *                 the USPOOF_CHAR_LIMIT test.
- */
-U_DRAFT const USet * U_EXPORT2
-uspoof_getAllowedChars(USpoofChecker *sc, UErrorCode *status);
-
-
-#ifdef XP_CPLUSPLUS
-/**
- * Limit the acceptable characters to those specified by a Unicode Set.
- *   Any previously specified character limit is
- *   is replaced by the new settings.
- *
- * The USPOOF_CHAR_LIMIT test is automatically enabled for this
- * USoofChecker by this function.
- *
- * @param sc       The USpoofChecker 
- * @param chars    A Unicode Set containing the list of
- *                 charcters that are permitted.  Ownership of the set
- *                 remains with the caller.  The incoming set is cloned by
- *                 this function, so there are no restrictions on modifying
- *                 or deleting the USet after calling this function.
- * @param status   The error code, set if this function encounters a problem.
- */
-U_DRAFT void U_EXPORT2
-uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const UnicodeSet *chars, UErrorCode *status);
-
-
-/**
- * Get a UnicodeSet for the characters permitted in an identifier.
- * This corresponds to the limits imposed by the Set Allowed Characters / 
- * UnicodeSet functions. Limitations imposed by other checks will not be
- * reflected in the set returned by this function.
- *
- * The returned set will be frozen, meaning that it cannot be modified
- * by the caller.
- *
- * Ownership of the returned set remains with the Spoof Detector.  The
- * returned set will become invalid if the spoof detector is closed,
- * or if a new set of allowed characters is specified.
- *
- *
- * @param sc       The USpoofChecker 
- * @param status   The error code, set if this function encounters a problem.
- * @return         A UnicodeSet containing the characters that are permitted by
- *                 the USPOOF_CHAR_LIMIT test.
- */
-U_DRAFT const UnicodeSet * U_EXPORT2
-uspoof_getAllowedUnicodeSet(USpoofChecker *sc, UErrorCode *status);
-#endif
-
-
-/**
- * Check the specified string for possible security issues.
- * The text to be checked will typically be an indentifier of some sort.
- * The set of checks to be performed is specified with uspoof_setChecks().
- * 
- * @param sc      The USpoofChecker 
- * @param text    The string to be checked for possible security issues,
- *                in UTF-16 format.
- * @param length  the length of the string to be checked, expressed in
- *                16 bit UTF-16 code units, or -1 if the string is 
- *                zero terminated.
- * @param status  The error code, set if an error occured while attempting to
- *                perform the check.
- *                Spoofing or security issues detected with the input string are
- *                not reported here, but through the function's return value.
- * @return        An integer value with bits set for any potential security
- *                or spoofing issues detected.  The bits are defined by
- *                enum USpoofChecks.  Zero is returned if no issues
- *                are found with the input string.
- * @draft ICU 4.0
- */
-U_DRAFT int32_t U_EXPORT2
-uspoof_check(const USpoofChecker *sc, const UChar *text, int32_t length, UErrorCode *status);
-
-/**
- * Check the specified string for possible security issues.
- * The text to be checked will typically be an indentifier of some sort.
- * The set of checks to be performed is specified with uspoof_setChecks().
- * 
- * @param sc      The USpoofChecker 
- * @param text    The string to be checked for possible security issues,
- *                in UTF-16 format.
- * @param length  the length of the string to be checked, expressed in
- *                16 bit UTF-16 code units, or -1 if the string is 
- *                zero terminated.
- * @param status  The error code, set if an error occured while attempting to
- *                perform the check.
- *                Spoofing or security issues detected with the input string are
- *                not reported here, but through the function's return value.
- * @return        An integer value with bits set for any potential security
- *                or spoofing issues detected.  The bits are defined by
- *                enum USpoofChecks.  Zero is returned if no issues
- *                are found with the input string.
- * @draft ICU 4.0
- */
-U_DRAFT int32_t U_EXPORT2
-uspoof_check(const USpoofChecker *sc, const UChar *text, int32_t length, UErrorCode *status);
-
-
-/**
- * Check the specified string for possible security issues.
- * The text to be checked will typically be an indentifier of some sort.
- * The set of checks to be performed is specified with uspoof_setChecks().
- * 
- * @param sc      The USpoofChecker 
- * @param text    A UTF-8 string to be checked for possible security issues.
- * @param length  the length of the string to be checked, or -1 if the string is 
- *                zero terminated.
- * @param status  The error code, set if an error occured while attempting to
- *                perform the check.
- *                Spoofing or security issues detected with the input string are
- *                not reported here, but through the function's return value.
- * @return        An integer value with bits set for any potential security
- *                or spoofing issues detected.  The bits are defined by
- *                enum USpoofChecks.  Zero is returned if no issues
- *                are found with the input string.
- * @draft ICU 4.0
- */
-U_DRAFT int32_t U_EXPORT2
-uspoof_checkUTF8(const USpoofChecker *sc, const char *text, int32_t length, UErrorCode *status);
-
-
-#ifdef XP_CPLUSPLUS
-/**
- * Check the specified string for possible security issues.
- * The text to be checked will typically be an indentifier of some sort.
- * The set of checks to be performed is specified with uspoof_setChecks().
- * 
- * @param sc      The USpoofChecker 
- * @param text    A UnicodeString to be checked for possible security issues.
- * @param status  The error code, set if an error occured while attempting to
- *                perform the check.
- *                Spoofing or security issues detected with the input string are
- *                not reported here, but through the function's return value.
- * @return        An integer value with bits set for any potential security
- *                or spoofing issues detected.  The bits are defined by
- *                enum USpoofChecks.  Zero is returned if no issues
- *                are found with the input string.
- * @draft ICU 4.0
- */
-U_DRAFT int32_t U_EXPORT2
-uspoof_checkUnicodeString(const USpoofChecker *sc,
-                          const U_NAMESPACE_QUALIFIER UnicodeString &text, 
-                          int32_t length, UErrorCode *status);
-
-#endif
-
-
-/**
- * Check the whether two specified strings are visually confusable.
- * The types of confusability to be tested - single script, mixed script,
- * or whole script - are determined by the check options set for the
- * USpoofChecker.
- *
- * @param sc      The USpoofChecker
- * @param s1      The first of the two strings to be compared for 
- *                confusability.  The strings are in UTF-16 format.
- * @param length1 the length of the first string, expressed in
- *                16 bit UTF-16 code units, or -1 if the string is 
- *                zero terminated.
- * @param s2      The second of the two strings to be compared for 
- *                confusability.  The strings are in UTF-16 format.
- * @param length2 The length of the second string, expressed in
- *                16 bit UTF-16 code units, or -1 if the string is 
- *                zero terminated.
- * @param status  The error code, set if an error occured while attempting to
- *                perform the check.
- *                Confusability of the strings is not reported here,
- *                but through this function's return value.
- * @return        An integer value with bit(s) set corresponding to
- *                the type of confusability found, as defined by
- *                enum USpoofChecks.  Zero is returned if the strings
- *                are not confusable.
- * @draft ICU 4.0
- */
-U_DRAFT int32_t U_EXPORT2
-uspoof_areConfusable(const USpoofChecker *sc,
-                     const UChar *s1, int32_t length1,
-                     const UChar *s2, int32_t length2,
-                     UErrorCode *status);
-
-
-
-/**
- * Check the whether two specified strings are visually confusable.
- * The types of confusability to be tested - single script, mixed script,
- * or whole script - are determined by the check options set for the
- * USpoofChecker.
- *
- * @param sc      The USpoofChecker
- * @param s1      The first of the two strings to be compared for 
- *                confusability.  The strings are in UTF-8 format.
- * @param length1 the length of the first string, in bytes, or -1 
- *                if the string is zero terminated.
- * @param s2      The second of the two strings to be compared for 
- *                confusability.  The strings are in UTF-18 format.
- * @param length2 The length of the second string in bytes, or -1 
- *                if the string is zero terminated.
- * @param status  The error code, set if an error occured while attempting to
- *                perform the check.
- *                Confusability of the strings is not reported here,
- *                but through this function's return value.
- * @return        An integer value with bit(s) set corresponding to
- *                the type of confusability found, as defined by
- *                enum USpoofChecks.  Zero is returned if the strings
- *                are not confusable.
- * @draft ICU 4.0
- */
-U_DRAFT int32_t U_EXPORT2
-uspoof_areConfusableUTF8(const USpoofChecker *sc,
-                         const char *s1, int32_t length1,
-                         const char *s2, int32_t length2,
-                         UErrorCode *status);
-
-
-
-
-#ifdef XP_CPLUSPLUS
-/**
- * Check the whether two specified strings are visually confusable.
- * The types of confusability to be tested - single script, mixed script,
- * or whole script - are determined by the check options set for the
- * USpoofChecker.
- *
- * @param sc      The USpoofChecker
- * @param s1      The first of the two strings to be compared for 
- *                confusability.  The strings are in UTF-8 format.
- * @param s2      The second of the two strings to be compared for 
- *                confusability.  The strings are in UTF-18 format.
- * @param status  The error code, set if an error occured while attempting to
- *                perform the check.
- *                Confusability of the strings is not reported here,
- *                but through this function's return value.
- * @return        An integer value with bit(s) set corresponding to
- *                the type of confusability found, as defined by
- *                enum USpoofChecks.  Zero is returned if the strings
- *                are not confusable.
- * @draft ICU 4.0
- */
-U_DRAFT int32_t U_EXPORT2
-uspoof_areConfusableUnicodeString(const USpoofChecker *sc,
-                                  const U_NAMESPACE_QUALIFIER UnicodeString &s1,
-                                  const U_NAMESPACE_QUALIFIER UnicodeString &s2,
-                                  UErrorCode *status);
-#endif
-
-
-/**
-  *  Get the "skeleton" for an identifier string.
-  *  Skeletons are a transformation of the input string;
-  *  Two strings are confusable if their skeletons are identical.
-  *  See Unicode UAX 39 for additional information.
-  *
-  *  Using skeletons directly makes it possible to quickly check
-  *  whether an identifier is confusable with any of some large
-  *  set of existing identifiers, by creating an efficiently
-  *  searchable collection of the skeletons.
-  *
-  * @param sc      The USpoofChecker 
-  * @param s       The input string whose skeleton will be computed.
-  * @param length  The length of the input string, expressed in 16 bit
-  *                UTF-16 code units, or -1 if the string is zero terminated.
-  * @param dest    The output buffer, to receive the skeleton string.
-  * @param destCapacity  The length of the output buffer, in 16 bit units.
-  *                The destCapacity may be zero, in which case the function will
-  *                return the actual length of the skeleton.
-  * @param status  The error code, set if an error occured while attempting to
-  *                perform the check.
-  * @return        The length of the skeleton string.  The returned length
-  *                is always that of the complete skeleton, even when the
-  *                supplied buffer is too small (or of zero length)
-  *                
-  * @draft ICU 4.0
-  */
-U_DRAFT int32_t U_EXPORT2
-uspoof_getSkeleton(const USpoofChecker *sc,
-                   const UChar *s,  int32_t length,
-                   UChar *dest, int32_t destCapacity,
-                   UErrorCode *status);
-    
-/**
-  *  Get the "skeleton" for an identifier string.
-  *  Skeletons are a transformation of the input string;
-  *  Two strings are confusable if their skeletons are identical.
-  *  See Unicode UAX 39 for additional information.
-  *
-  *  Using skeletons directly makes it possible to quickly check
-  *  whether an identifier is confusable with any of some large
-  *  set of existing identifiers, by creating an efficiently
-  *  searchable collection of the skeletons.
-  *
-  * @param sc      The USpoofChecker 
-  * @param s       The UTF-8 format input string whose skeleton will be computed.
-  * @param length  The length of the input string, in bytes,
-  *                or -1 if the string is zero terminated.
-  * @param dest    The output buffer, to receive the skeleton string.
-  * @param destCapacity  The length of the output buffer, in bytes.
-  *                The destCapacity may be zero, in which case the function will
-  *                return the actual length of the skeleton.
-  * @param status  The error code, set if an error occured while attempting to
-  *                perform the check.
-  * @return        The length of the skeleton string, in bytes.  The returned length
-  *                is always that of the complete skeleton, even when the
-  *                supplied buffer is too small (or of zero length)
-  *                
-  * @draft ICU 4.0
-  */   
-U_DRAFT int32_t U_EXPORT2
-uspoof_getSkeletonUTF8(const USpoofChecker *sc,
-                   const char *s,  int32_t length,
-                   char *dest, int32_t destCapacity,
-                   UErrorCode *status);
-    
-#ifdef XP_CPLUSPLUS
-/**
-  *  Get the "skeleton" for an identifier string.
-  *  Skeletons are a transformation of the input string;
-  *  Two strings are confusable if their skeletons are identical.
-  *  See Unicode UAX 39 for additional information.
-  *
-  *  Using skeletons directly makes it possible to quickly check
-  *  whether an identifier is confusable with any of some large
-  *  set of existing identifiers, by creating an efficiently
-  *  searchable collection of the skeletons.
-  *
-  * @param sc      The USpoofChecker 
-  * @param s       The input string whose skeleton will be computed.
-  * @param dest    The output string, to receive the skeleton string.
-  * @param destCapacity  The length of the output buffer, in bytes.
-  *                The destCapacity may be zero, in which case the function will
-  *                return the actual length of the skeleton.
-  * @param status  The error code, set if an error occured while attempting to
-  *                perform the check.
-  * @return        A reference to the destination (skeleton) string.
-  *                
-  * @draft ICU 4.0
-  */   
-U_DRAFT UnicodeString & U_EXPORT2
-uspoof_getSkeletonUnicodeString(const USpoofChecker *sc,
-                                const UnicodeString &s,
-                                UnicodeString &dest,
-                                UErrorCode *status);
-#endif
-
-#endif
-
-

Modified: trunk/source/common/unicode/uversion.h
===================================================================
--- trunk/source/common/unicode/uversion.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/common/unicode/uversion.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -74,14 +74,14 @@
  *  This value will change in the subsequent releases of ICU
  *  @stable ICU 2.4
  */
-#define U_ICU_VERSION_PATCHLEVEL_NUM 0
+#define U_ICU_VERSION_PATCHLEVEL_NUM 1
 
 /** The current ICU build level version as an integer.  
  *  This value is for use by ICU clients. It defaults to 0.
  *  @stable ICU 4.0
  */
 #ifndef U_ICU_VERSION_BUILDLEVEL_NUM
-#define U_ICU_VERSION_BUILDLEVEL_NUM 1
+#define U_ICU_VERSION_BUILDLEVEL_NUM 0
 #endif
 
 /** Glued version suffix for renamers 
@@ -95,7 +95,7 @@
  *  This value will change in the subsequent releases of ICU
  *  @stable ICU 2.4
  */
-#define U_ICU_VERSION "4.2.0.1"
+#define U_ICU_VERSION "4.2.1"
 
 /** The current ICU library major/minor version as a string without dots, for library name suffixes. 
  *  This value will change in the subsequent releases of ICU

Modified: trunk/source/config/gmakever.mk
===================================================================
--- trunk/source/config/gmakever.mk	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/config/gmakever.mk	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,20 +1,20 @@
-## -*-makefile-*-
-#******************************************************************************
-#   Copyright (C) 2008-2009, International Business Machines
-#   Corporation and others.  All Rights Reserved.
-#******************************************************************************
-# Make sure we have the right version of Make.
-
-at_least=3.80
-latest_a=$(firstword $(sort $(MAKE_VERSION) $(at_least)))
-
-ifneq ($(at_least),$(latest_a))
-err:
-	@echo "ERROR: $(MAKE_VERSION) - too old, please upgrade to at least $(at_least)"
-	@false
-else
-ok:
-	@echo "$(MAKE_VERSION) (we wanted at least $(at_least))"
-	@true
-endif
-
+## -*-makefile-*-
+#******************************************************************************
+#   Copyright (C) 2008-2009, International Business Machines
+#   Corporation and others.  All Rights Reserved.
+#******************************************************************************
+# Make sure we have the right version of Make.
+
+at_least=3.80
+latest_a=$(firstword $(sort $(MAKE_VERSION) $(at_least)))
+
+ifneq ($(at_least),$(latest_a))
+err:
+	@echo "ERROR: $(MAKE_VERSION) - too old, please upgrade to at least $(at_least)"
+	@false
+else
+ok:
+	@echo "$(MAKE_VERSION) (we wanted at least $(at_least))"
+	@true
+endif
+

Modified: trunk/source/config/make2sh.sed
===================================================================
--- trunk/source/config/make2sh.sed	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/config/make2sh.sed	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,4 +1,4 @@
-# Copyright (C) 1999-2006, International Business Machines  Corporation and others.  All Rights Reserved.
+# Copyright (C) 1999-2009, International Business Machines  Corporation and others.  All Rights Reserved.
 s%^\([a-zA-Z\._-]*\)[ 	]*+=%\1=$(\1) %
 s%^[A-Z]*_SO_TARG*%## &%
 s%^SHARED_OBJECT.*%## &%
@@ -9,6 +9,7 @@
 s@^\([a-zA-Z][-.a-zA-Z_0-9-]*\)[	 ]*=[ 	]*\(.*\)@\1="\2"@
 s@^\([a-zA-Z][-a-zA-Z_0-9-]*\)\.\([a-zA-Z_0-9-]*\)[	 ]*=[ 	]*\(.*\)@\1_\2=\3@
 s@^\([a-zA-Z][-a-zA-Z_0-9-]*\)\-\([a-zA-Z_0-9-]*\)[	 ]*=[ 	]*\(.*\)@\1_\2=\3@
+s@\${\([a-zA-Z][-a-zA-Z_0-9-]*\)\.\([a-zA-Z_0-9-]*\)}@${\1_\2}@g
 s@^\(prefix\)=\(.*\)@default_\1=\2\
 if [ "x${\1}" = "x" ]; then \1="$default_\1"; fi@
 s@^\(ENABLE_RPATH\)=\(.*\)@default_\1=\2\

Modified: trunk/source/config/pkgdataMakefile.in
===================================================================
--- trunk/source/config/pkgdataMakefile.in	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/config/pkgdataMakefile.in	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,40 +1,40 @@
-## pkgdataMakefile.in for ICU data
-## Copyright (c) 2008, International Business Machines Corporation and
-## others. All Rights Reserved.
-
-## Source directory information
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-
-# So that you have $(top_builddir)/config.status
-top_builddir = ..
-
-## All the flags and other definitions are included here.
-include $(top_builddir)/icudefs.mk
-
-OUTPUTFILE=pkgdata.inc
-MIDDLE_SO_TARGET=
-
-all : clean 
-	@echo GENCCODE_ASSEMBLY_TYPE=$(GENCCODE_ASSEMBLY) >> $(OUTPUTFILE)
-	@echo SO=$(SO) >> $(OUTPUTFILE)
-	@echo SOBJ=$(SOBJ) >> $(OUTPUTFILE)
-	@echo A=$(A) >> $(OUTPUTFILE)
-	@echo LIBPREFIX=$(LIBPREFIX) >> $(OUTPUTFILE)
-	@echo LIB_EXT_ORDER=$(FINAL_SO_TARGET) >> $(OUTPUTFILE)
-	@echo COMPILE="$(COMPILE.c)" >> $(OUTPUTFILE)
-	@echo LIBFLAGS="-I$(prefix)/include $(SHAREDLIBCPPFLAGS) $(SHAREDLIBCFLAGS)" >> $(OUTPUTFILE)
-	@echo GENLIB="$(SHLIB.c)" >> $(OUTPUTFILE)
-	@echo LDICUDTFLAGS=$(LDFLAGSICUDT) >> $(OUTPUTFILE)
-	@echo LD_SONAME=$(LD_SONAME) >> $(OUTPUTFILE)
-	@echo RPATH_FLAGS=$(RPATH_FLAGS) >> $(OUTPUTFILE)
-	@echo BIR_LDFLAGS=$(BIR_LDFLAGS) >> $(OUTPUTFILE)
-	@echo AR=$(AR) >> $(OUTPUTFILE)
-	@echo ARFLAGS=$(ARFLAGS) >> $(OUTPUTFILE)
-	@echo RANLIB=$(RANLIB) >> $(OUTPUTFILE)
-	@echo INSTALL_CMD=$(INSTALL-L) >> $(OUTPUTFILE)
-
-
-clean : 
-	$(RMV) $(OUTPUTFILE)
-
+## pkgdataMakefile.in for ICU data
+## Copyright (c) 2008, International Business Machines Corporation and
+## others. All Rights Reserved.
+
+## Source directory information
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+# So that you have $(top_builddir)/config.status
+top_builddir = ..
+
+## All the flags and other definitions are included here.
+include $(top_builddir)/icudefs.mk
+
+OUTPUTFILE=pkgdata.inc
+MIDDLE_SO_TARGET=
+
+all : clean 
+	@echo GENCCODE_ASSEMBLY_TYPE=$(GENCCODE_ASSEMBLY) >> $(OUTPUTFILE)
+	@echo SO=$(SO) >> $(OUTPUTFILE)
+	@echo SOBJ=$(SOBJ) >> $(OUTPUTFILE)
+	@echo A=$(A) >> $(OUTPUTFILE)
+	@echo LIBPREFIX=$(LIBPREFIX) >> $(OUTPUTFILE)
+	@echo LIB_EXT_ORDER=$(FINAL_SO_TARGET) >> $(OUTPUTFILE)
+	@echo COMPILE="$(COMPILE.c)" >> $(OUTPUTFILE)
+	@echo LIBFLAGS="-I$(prefix)/include $(SHAREDLIBCPPFLAGS) $(SHAREDLIBCFLAGS)" >> $(OUTPUTFILE)
+	@echo GENLIB="$(SHLIB.c)" >> $(OUTPUTFILE)
+	@echo LDICUDTFLAGS=$(LDFLAGSICUDT) >> $(OUTPUTFILE)
+	@echo LD_SONAME=$(LD_SONAME) >> $(OUTPUTFILE)
+	@echo RPATH_FLAGS=$(RPATH_FLAGS) >> $(OUTPUTFILE)
+	@echo BIR_LDFLAGS=$(BIR_LDFLAGS) >> $(OUTPUTFILE)
+	@echo AR=$(AR) >> $(OUTPUTFILE)
+	@echo ARFLAGS=$(ARFLAGS) >> $(OUTPUTFILE)
+	@echo RANLIB=$(RANLIB) >> $(OUTPUTFILE)
+	@echo INSTALL_CMD=$(INSTALL-L) >> $(OUTPUTFILE)
+
+
+clean : 
+	$(RMV) $(OUTPUTFILE)
+

Modified: trunk/source/configure.mk
===================================================================
--- trunk/source/configure.mk	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/configure.mk	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,11 +1,11 @@
-#  Copyright (c) 2008-2009, International Business Machines Corporation and others. All Rights Reserved.
-# 
-#
-# Makefile for regenerating configure in the face of a bad ^M
-# This should become unnecessary for autoconf past 2.63
-# 
-# Usage:    MAKE -f configure.mk configure
-
-configure:	configure.in ./aclocal.m4
-	( autoconf && mv configure configure.tmp && sed -e 's%^ac_cr=.*%ac_cr=`echo X |tr X "\\015"`%'  < configure.tmp > configure && chmod a+rx $@ && rm configure.tmp ) || ( rm $@ ; "echo configure build failed" ; /usr/bin/false  )
-
+#  Copyright (c) 2008-2009, International Business Machines Corporation and others. All Rights Reserved.
+# 
+#
+# Makefile for regenerating configure in the face of a bad ^M
+# This should become unnecessary for autoconf past 2.63
+# 
+# Usage:    MAKE -f configure.mk configure
+
+configure:	configure.in ./aclocal.m4
+	( autoconf && mv configure configure.tmp && sed -e 's%^ac_cr=.*%ac_cr=`echo X |tr X "\\015"`%'  < configure.tmp > configure && chmod a+rx $@ && rm configure.tmp ) || ( rm $@ ; "echo configure build failed" ; /usr/bin/false  )
+

Modified: trunk/source/extra/uconv/pkgdataMakefile.in
===================================================================
--- trunk/source/extra/uconv/pkgdataMakefile.in	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/extra/uconv/pkgdataMakefile.in	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,40 +1,40 @@
-## pkgdataMakefile.in for ICU data
-## Copyright (c) 2008-2009, International Business Machines Corporation and
-## others. All Rights Reserved.
-
-## Source directory information
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-
-# So that you have $(top_builddir)/config.status
-top_builddir = ../..
-
-## All the flags and other definitions are included here.
-include $(top_builddir)/icudefs.mk
-
-MIDDLE_SO_TARGET=
-
-OUTPUTFILE=pkgdata.inc
-
-all : clean 
-	@echo GENCCODE_ASSEMBLY_TYPE=$(GENCCODE_ASSEMBLY) >> $(OUTPUTFILE)
-	@echo SO=$(SO) >> $(OUTPUTFILE)
-	@echo SOBJ=$(SOBJ) >> $(OUTPUTFILE)
-	@echo A=$(A) >> $(OUTPUTFILE)
-	@echo LIBPREFIX=$(LIBPREFIX) >> $(OUTPUTFILE)
-	@echo LIB_EXT_ORDER=$(FINAL_SO_TARGET) >> $(OUTPUTFILE)
-	@echo COMPILE="$(COMPILE.c)" >> $(OUTPUTFILE)
-	@echo LIBFLAGS="-I$(top_srcdir)/common -I$(top_builddir)/common $(SHAREDLIBCPPFLAGS) $(SHAREDLIBCFLAGS)" >> $(OUTPUTFILE)
-	@echo GENLIB="$(SHLIB.c)" >> $(OUTPUTFILE)
-	@echo LDICUDTFLAGS=$(LDFLAGSICUDT) >> $(OUTPUTFILE)
-	@echo LD_SONAME=$(LD_SONAME) >> $(OUTPUTFILE)
-	@echo RPATH_FLAGS=$(RPATH_FLAGS) >> $(OUTPUTFILE)
-	@echo BIR_LDFLAGS=$(BIR_LDFLAGS) >> $(OUTPUTFILE)
-	@echo AR=$(AR) >> $(OUTPUTFILE)
-	@echo ARFLAGS=$(ARFLAGS) >> $(OUTPUTFILE)
-	@echo RANLIB=$(RANLIB) >> $(OUTPUTFILE)
-	@echo INSTALL_CMD=$(INSTALL_DATA) >> $(OUTPUTFILE)
-
-clean : 
-	$(RMV) $(OUTPUTFILE)
-
+## pkgdataMakefile.in for ICU data
+## Copyright (c) 2008-2009, International Business Machines Corporation and
+## others. All Rights Reserved.
+
+## Source directory information
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+
+# So that you have $(top_builddir)/config.status
+top_builddir = ../..
+
+## All the flags and other definitions are included here.
+include $(top_builddir)/icudefs.mk
+
+MIDDLE_SO_TARGET=
+
+OUTPUTFILE=pkgdata.inc
+
+all : clean 
+	@echo GENCCODE_ASSEMBLY_TYPE=$(GENCCODE_ASSEMBLY) >> $(OUTPUTFILE)
+	@echo SO=$(SO) >> $(OUTPUTFILE)
+	@echo SOBJ=$(SOBJ) >> $(OUTPUTFILE)
+	@echo A=$(A) >> $(OUTPUTFILE)
+	@echo LIBPREFIX=$(LIBPREFIX) >> $(OUTPUTFILE)
+	@echo LIB_EXT_ORDER=$(FINAL_SO_TARGET) >> $(OUTPUTFILE)
+	@echo COMPILE="$(COMPILE.c)" >> $(OUTPUTFILE)
+	@echo LIBFLAGS="-I$(top_srcdir)/common -I$(top_builddir)/common $(SHAREDLIBCPPFLAGS) $(SHAREDLIBCFLAGS)" >> $(OUTPUTFILE)
+	@echo GENLIB="$(SHLIB.c)" >> $(OUTPUTFILE)
+	@echo LDICUDTFLAGS=$(LDFLAGSICUDT) >> $(OUTPUTFILE)
+	@echo LD_SONAME=$(LD_SONAME) >> $(OUTPUTFILE)
+	@echo RPATH_FLAGS=$(RPATH_FLAGS) >> $(OUTPUTFILE)
+	@echo BIR_LDFLAGS=$(BIR_LDFLAGS) >> $(OUTPUTFILE)
+	@echo AR=$(AR) >> $(OUTPUTFILE)
+	@echo ARFLAGS=$(ARFLAGS) >> $(OUTPUTFILE)
+	@echo RANLIB=$(RANLIB) >> $(OUTPUTFILE)
+	@echo INSTALL_CMD=$(INSTALL_DATA) >> $(OUTPUTFILE)
+
+clean : 
+	$(RMV) $(OUTPUTFILE)
+

Modified: trunk/source/extra/uconv/uconv.vcproj
===================================================================
--- trunk/source/extra/uconv/uconv.vcproj	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/extra/uconv/uconv.vcproj	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,485 +1,485 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="9.00"
-	Name="uconv"
-	ProjectGUID="{DBA4088D-F6F9-4F8F-8820-082A4765C16C}"
-	TargetFrameworkVersion="131072"
-	>
-	<Platforms>
-		<Platform
-			Name="Win32"
-		/>
-		<Platform
-			Name="x64"
-		/>
-	</Platforms>
-	<ToolFiles>
-	</ToolFiles>
-	<Configurations>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory=".\x86\Release"
-			IntermediateDirectory=".\x86\Release"
-			ConfigurationType="1"
-			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-				CommandLine="copy &quot;$(TargetPath)&quot; ..\..\..\bin&#x0D;&#x0A;"
-				Outputs="$(ProjectDir)..\..\..\bin\$(TargetFileName)"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TypeLibraryName=".\x86\Release/uconv.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\..\..\include;..\..\common"
-				PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;UCONVMSG_LINK"
-				StringPooling="true"
-				RuntimeLibrary="2"
-				EnableFunctionLevelLinking="true"
-				DisableLanguageExtensions="true"
-				TreatWChar_tAsBuiltInType="true"
-				PrecompiledHeaderFile=".\x86\Release/uconv.pch"
-				AssemblerListingLocation=".\x86\Release/"
-				ObjectFile=".\x86\Release/"
-				ProgramDataBaseFileName=".\x86\Release/"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				CompileAs="0"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1033"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="uconvmsg.lib"
-				OutputFile=".\x86\Release/uconv.exe"
-				LinkIncremental="1"
-				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="x86\Release"
-				ProgramDatabaseFile=".\x86\Release/uconv.pdb"
-				SubSystem="1"
-				RandomizedBaseAddress="1"
-				DataExecutionPrevention="0"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory=".\x86\Debug"
-			IntermediateDirectory=".\x86\Debug"
-			ConfigurationType="1"
-			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-				CommandLine="copy &quot;$(TargetPath)&quot; ..\..\..\bin&#x0D;&#x0A;"
-				Outputs="$(ProjectDir)..\..\..\bin\$(TargetFileName)"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TypeLibraryName=".\x86\Debug/uconv.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\include;..\..\common"
-				PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;UCONVMSG_LINK"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="true"
-				DisableLanguageExtensions="true"
-				TreatWChar_tAsBuiltInType="true"
-				PrecompiledHeaderFile=".\x86\Debug/uconv.pch"
-				AssemblerListingLocation=".\x86\Debug/"
-				ObjectFile=".\x86\Debug/"
-				ProgramDataBaseFileName=".\x86\Debug/"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				DebugInformationFormat="4"
-				CompileAs="0"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG"
-				Culture="1033"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="uconvmsg.lib"
-				OutputFile=".\x86\Debug/uconv.exe"
-				LinkIncremental="2"
-				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="x86\Debug"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile=".\x86\Debug/uconv.pdb"
-				SubSystem="1"
-				RandomizedBaseAddress="1"
-				DataExecutionPrevention="0"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-				UseFAT32Workaround="true"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Release|x64"
-			OutputDirectory=".\x64\Release"
-			IntermediateDirectory=".\x64\Release"
-			ConfigurationType="1"
-			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-				CommandLine="copy &quot;$(TargetPath)&quot; ..\..\..\bin64&#x0D;&#x0A;"
-				Outputs="$(ProjectDir)..\..\..\bin64\$(TargetFileName)"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-				TypeLibraryName=".\x64\Release/uconv.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories="..\..\..\include;..\..\common"
-				PreprocessorDefinitions="WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;UCONVMSG_LINK"
-				StringPooling="true"
-				RuntimeLibrary="2"
-				EnableFunctionLevelLinking="true"
-				DisableLanguageExtensions="true"
-				TreatWChar_tAsBuiltInType="true"
-				PrecompiledHeaderFile=".\x64\Release/uconv.pch"
-				AssemblerListingLocation=".\x64\Release/"
-				ObjectFile=".\x64\Release/"
-				ProgramDataBaseFileName=".\x64\Release/"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				CompileAs="0"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="NDEBUG"
-				Culture="1033"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="uconvmsg.lib"
-				OutputFile=".\x64\Release/uconv.exe"
-				LinkIncremental="1"
-				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="x64\Release"
-				ProgramDatabaseFile=".\x64\Release/uconv.pdb"
-				SubSystem="1"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debug|x64"
-			OutputDirectory=".\x64\Debug"
-			IntermediateDirectory=".\x64\Debug"
-			ConfigurationType="1"
-			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
-			UseOfMFC="0"
-			ATLMinimizesCRunTimeLibraryUsage="false"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-				CommandLine="copy &quot;$(TargetPath)&quot; ..\..\..\bin64&#x0D;&#x0A;"
-				Outputs="$(ProjectDir)..\..\..\bin64\$(TargetFileName)"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-				TargetEnvironment="3"
-				TypeLibraryName=".\x64\Debug/uconv.tlb"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="..\..\..\include;..\..\common"
-				PreprocessorDefinitions="WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;UCONVMSG_LINK"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="3"
-				BufferSecurityCheck="true"
-				DisableLanguageExtensions="true"
-				TreatWChar_tAsBuiltInType="true"
-				PrecompiledHeaderFile=".\x64\Debug/uconv.pch"
-				AssemblerListingLocation=".\x64\Debug/"
-				ObjectFile=".\x64\Debug/"
-				ProgramDataBaseFileName=".\x64\Debug/"
-				WarningLevel="3"
-				SuppressStartupBanner="true"
-				DebugInformationFormat="3"
-				CompileAs="0"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-				PreprocessorDefinitions="_DEBUG"
-				Culture="1033"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="uconvmsg.lib"
-				OutputFile=".\x64\Debug/uconv.exe"
-				LinkIncremental="2"
-				SuppressStartupBanner="true"
-				AdditionalLibraryDirectories="x64\Debug"
-				GenerateDebugInformation="true"
-				ProgramDatabaseFile=".\x64\Debug/uconv.pdb"
-				SubSystem="1"
-				TargetMachine="17"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-				UseFAT32Workaround="true"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-			>
-			<File
-				RelativePath=".\uconv.cpp"
-				>
-			</File>
-			<File
-				RelativePath=".\uwmsg.c"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl"
-			>
-			<File
-				RelativePath=".\unicode\uwmsg.h"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Resource Bundles"
-			Filter="txt"
-			>
-			<File
-				RelativePath=".\resources\fr.txt"
-				>
-			</File>
-			<File
-				RelativePath=".\resources\root.txt"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="Build Scripts"
-			Filter="mak;mk;bat"
-			>
-			<File
-				RelativePath=".\makedata.mak"
-				>
-				<FileConfiguration
-					Name="Release|Win32"
-					>
-					<Tool
-						Name="VCCustomBuildTool"
-						CommandLine="nmake /nologo /f $(InputName).mak icup=&quot;$(ProjectDir)..\..\..&quot; CFG=x86\Release&#x0D;&#x0A;"
-						Outputs="x86\Release/uconvmsg.lib"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|Win32"
-					>
-					<Tool
-						Name="VCCustomBuildTool"
-						CommandLine="nmake /nologo /f $(InputName).mak icup=&quot;$(ProjectDir)..\..\..&quot; CFG=x86\Debug&#x0D;&#x0A;"
-						Outputs="x86\Debug/uconvmsg.lib"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Release|x64"
-					>
-					<Tool
-						Name="VCCustomBuildTool"
-						CommandLine="nmake /nologo /f $(InputName).mak icup=&quot;$(ProjectDir)..\..\..&quot; CFG=x64\Release&#x0D;&#x0A;"
-						Outputs="x64\Release/uconvmsg.lib"
-					/>
-				</FileConfiguration>
-				<FileConfiguration
-					Name="Debug|x64"
-					>
-					<Tool
-						Name="VCCustomBuildTool"
-						CommandLine="nmake /nologo /f $(InputName).mak icup=&quot;$(ProjectDir)..\..\..&quot; CFG=x64\Debug&#x0D;&#x0A;"
-						Outputs="x64\Debug/uconvmsg.lib"
-					/>
-				</FileConfiguration>
-			</File>
-			<File
-				RelativePath=".\resfiles.mk"
-				>
-			</File>
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="uconv"
+	ProjectGUID="{DBA4088D-F6F9-4F8F-8820-082A4765C16C}"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+		<Platform
+			Name="x64"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory=".\x86\Release"
+			IntermediateDirectory=".\x86\Release"
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+				CommandLine="copy &quot;$(TargetPath)&quot; ..\..\..\bin&#x0D;&#x0A;"
+				Outputs="$(ProjectDir)..\..\..\bin\$(TargetFileName)"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TypeLibraryName=".\x86\Release/uconv.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\..\include;..\..\common"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;UCONVMSG_LINK"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				DisableLanguageExtensions="true"
+				TreatWChar_tAsBuiltInType="true"
+				PrecompiledHeaderFile=".\x86\Release/uconv.pch"
+				AssemblerListingLocation=".\x86\Release/"
+				ObjectFile=".\x86\Release/"
+				ProgramDataBaseFileName=".\x86\Release/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="uconvmsg.lib"
+				OutputFile=".\x86\Release/uconv.exe"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="x86\Release"
+				ProgramDatabaseFile=".\x86\Release/uconv.pdb"
+				SubSystem="1"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory=".\x86\Debug"
+			IntermediateDirectory=".\x86\Debug"
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+				CommandLine="copy &quot;$(TargetPath)&quot; ..\..\..\bin&#x0D;&#x0A;"
+				Outputs="$(ProjectDir)..\..\..\bin\$(TargetFileName)"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TypeLibraryName=".\x86\Debug/uconv.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..\include;..\..\common"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;UCONVMSG_LINK"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="true"
+				DisableLanguageExtensions="true"
+				TreatWChar_tAsBuiltInType="true"
+				PrecompiledHeaderFile=".\x86\Debug/uconv.pch"
+				AssemblerListingLocation=".\x86\Debug/"
+				ObjectFile=".\x86\Debug/"
+				ProgramDataBaseFileName=".\x86\Debug/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="4"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="uconvmsg.lib"
+				OutputFile=".\x86\Debug/uconv.exe"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="x86\Debug"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile=".\x86\Debug/uconv.pdb"
+				SubSystem="1"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+				UseFAT32Workaround="true"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory=".\x64\Release"
+			IntermediateDirectory=".\x64\Release"
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+				CommandLine="copy &quot;$(TargetPath)&quot; ..\..\..\bin64&#x0D;&#x0A;"
+				Outputs="$(ProjectDir)..\..\..\bin64\$(TargetFileName)"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+				TypeLibraryName=".\x64\Release/uconv.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\..\..\include;..\..\common"
+				PreprocessorDefinitions="WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;UCONVMSG_LINK"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				DisableLanguageExtensions="true"
+				TreatWChar_tAsBuiltInType="true"
+				PrecompiledHeaderFile=".\x64\Release/uconv.pch"
+				AssemblerListingLocation=".\x64\Release/"
+				ObjectFile=".\x64\Release/"
+				ProgramDataBaseFileName=".\x64\Release/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="uconvmsg.lib"
+				OutputFile=".\x64\Release/uconv.exe"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="x64\Release"
+				ProgramDatabaseFile=".\x64\Release/uconv.pdb"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory=".\x64\Debug"
+			IntermediateDirectory=".\x64\Debug"
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+				CommandLine="copy &quot;$(TargetPath)&quot; ..\..\..\bin64&#x0D;&#x0A;"
+				Outputs="$(ProjectDir)..\..\..\bin64\$(TargetFileName)"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				TargetEnvironment="3"
+				TypeLibraryName=".\x64\Debug/uconv.tlb"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\..\include;..\..\common"
+				PreprocessorDefinitions="WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;UCONVMSG_LINK"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				BufferSecurityCheck="true"
+				DisableLanguageExtensions="true"
+				TreatWChar_tAsBuiltInType="true"
+				PrecompiledHeaderFile=".\x64\Debug/uconv.pch"
+				AssemblerListingLocation=".\x64\Debug/"
+				ObjectFile=".\x64\Debug/"
+				ProgramDataBaseFileName=".\x64\Debug/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+				CompileAs="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="uconvmsg.lib"
+				OutputFile=".\x64\Debug/uconv.exe"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				AdditionalLibraryDirectories="x64\Debug"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile=".\x64\Debug/uconv.pdb"
+				SubSystem="1"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+				UseFAT32Workaround="true"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+			>
+			<File
+				RelativePath=".\uconv.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\uwmsg.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl"
+			>
+			<File
+				RelativePath=".\unicode\uwmsg.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Bundles"
+			Filter="txt"
+			>
+			<File
+				RelativePath=".\resources\fr.txt"
+				>
+			</File>
+			<File
+				RelativePath=".\resources\root.txt"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Build Scripts"
+			Filter="mak;mk;bat"
+			>
+			<File
+				RelativePath=".\makedata.mak"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						CommandLine="nmake /nologo /f $(InputName).mak icup=&quot;$(ProjectDir)..\..\..&quot; CFG=x86\Release&#x0D;&#x0A;"
+						Outputs="x86\Release/uconvmsg.lib"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						CommandLine="nmake /nologo /f $(InputName).mak icup=&quot;$(ProjectDir)..\..\..&quot; CFG=x86\Debug&#x0D;&#x0A;"
+						Outputs="x86\Debug/uconvmsg.lib"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						CommandLine="nmake /nologo /f $(InputName).mak icup=&quot;$(ProjectDir)..\..\..&quot; CFG=x64\Release&#x0D;&#x0A;"
+						Outputs="x64\Release/uconvmsg.lib"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					>
+					<Tool
+						Name="VCCustomBuildTool"
+						CommandLine="nmake /nologo /f $(InputName).mak icup=&quot;$(ProjectDir)..\..\..&quot; CFG=x64\Debug&#x0D;&#x0A;"
+						Outputs="x64\Debug/uconvmsg.lib"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\resfiles.mk"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

Modified: trunk/source/i18n/currpinf.cpp
===================================================================
--- trunk/source/i18n/currpinf.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/currpinf.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,370 +1,372 @@
-/*
- *******************************************************************************
- * Copyright (C) 2009, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-#include "unicode/currpinf.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-//#define CURRENCY_PLURAL_INFO_DEBUG 1
-
-#ifdef CURRENCY_PLURAL_INFO_DEBUG
-#include <iostream>
-#endif
-
-
-#include "unicode/locid.h"
-#include "unicode/plurrule.h"
-#include "unicode/ures.h"
-#include "cstring.h"
-#include "hash.h"
-#include "uresimp.h"
-
-U_NAMESPACE_BEGIN
-
-
-static const UChar gNumberPatternSeparator = 0x3B; // ;
-
-U_CDECL_BEGIN
-
-/**
- * @internal ICU 4.2
- */
-static UBool U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2);
-
-U_CDECL_END
-
-UBool
-U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2) {
-    const UnicodeString* affix_1 = (UnicodeString*)val1.pointer;
-    const UnicodeString* affix_2 = (UnicodeString*)val2.pointer;
-    return  *affix_1 == *affix_2;
-}
-
-
-
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyPluralInfo)
-
-static const UChar gDefaultCurrencyPluralPattern[] = {'0', '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4, 0};
-static const UChar gTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
-static const UChar gPluralCountOther[] = {0x6F, 0x74, 0x68, 0x65, 0x72, 0};
-static const UChar gPart0[] = {0x7B, 0x30, 0x7D, 0};
-static const UChar gPart1[] = {0x7B, 0x31, 0x7D, 0};
-
-static const char gNumberPatternsTag[]="NumberPatterns";
-static const char gCurrUnitPtnTag[]="CurrencyUnitPatterns";
-
-CurrencyPluralInfo::CurrencyPluralInfo(UErrorCode& status)
-:   fPluralCountToCurrencyUnitPattern(NULL),
-    fPluralRules(NULL),
-    fLocale(NULL) {
-    initialize(Locale::getDefault(), status);
-}
-
-CurrencyPluralInfo::CurrencyPluralInfo(const Locale& locale, UErrorCode& status)
-:   fPluralCountToCurrencyUnitPattern(NULL),
-    fPluralRules(NULL),
-    fLocale(NULL) {
-    initialize(locale, status);
-}
-
-CurrencyPluralInfo::CurrencyPluralInfo(const CurrencyPluralInfo& info) 
-:   UObject(info),
-    fPluralCountToCurrencyUnitPattern(NULL),
-    fPluralRules(NULL),
-    fLocale(NULL) {
-    *this = info;
-}
-
-
-CurrencyPluralInfo&
-CurrencyPluralInfo::operator=(const CurrencyPluralInfo& info) {
-    if (this == &info) {
-        return *this;
-    }
-
-    deleteHash(fPluralCountToCurrencyUnitPattern);
-    UErrorCode status = U_ZERO_ERROR;
-    fPluralCountToCurrencyUnitPattern = initHash(status);
-    copyHash(info.fPluralCountToCurrencyUnitPattern, 
-             fPluralCountToCurrencyUnitPattern, status);
-    if ( U_FAILURE(status) ) {
-        return *this;
-    }
-
-    delete fPluralRules;
-    delete fLocale;
-    if (info.fPluralRules) {
-        fPluralRules = info.fPluralRules->clone();
-    } else {
-        fPluralRules = NULL;
-    }
-    if (info.fLocale) {
-        fLocale = info.fLocale->clone();
-    } else {
-        fLocale = NULL;
-    }
-    return *this;
-}
-
-
-CurrencyPluralInfo::~CurrencyPluralInfo() {
-    deleteHash(fPluralCountToCurrencyUnitPattern);
-    fPluralCountToCurrencyUnitPattern = NULL;
-    delete fPluralRules;
-    delete fLocale;
-    fPluralRules = NULL;
-    fLocale = NULL;
-}
-
-UBool
-CurrencyPluralInfo::operator==(const CurrencyPluralInfo& info) const {
-#ifdef CURRENCY_PLURAL_INFO_DEBUG
-    if (*fPluralRules == *info.fPluralRules) {
-        std::cout << "same plural rules\n";
-    }
-    if (*fLocale == *info.fLocale) {
-        std::cout << "same locale\n";
-    }
-    if (fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern)) {
-        std::cout << "same pattern\n";
-    }
-#endif
-    return *fPluralRules == *info.fPluralRules &&
-           *fLocale == *info.fLocale &&
-           fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern);
-}
-
-
-CurrencyPluralInfo*
-CurrencyPluralInfo::clone() const {
-    return new CurrencyPluralInfo(*this);
-}
-
-const PluralRules* 
-CurrencyPluralInfo::getPluralRules() const {
-    return fPluralRules;
-}
-
-UnicodeString&
-CurrencyPluralInfo::getCurrencyPluralPattern(const UnicodeString&  pluralCount,
-                                             UnicodeString& result) const {
-    const UnicodeString* currencyPluralPattern = 
-        (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(pluralCount);
-    if (currencyPluralPattern == NULL) {
-        // fall back to "other"
-        if (pluralCount.compare(gPluralCountOther)) {
-            currencyPluralPattern = 
-                (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(gPluralCountOther);
-        }
-        if (currencyPluralPattern == NULL) {
-            // no currencyUnitPatterns defined, 
-            // fallback to predefined defult.
-            // This should never happen when ICU resource files are
-            // available, since currencyUnitPattern of "other" is always
-            // defined in root.
-            result = UnicodeString(gDefaultCurrencyPluralPattern);
-            return result;
-        }
-    }
-    result = *currencyPluralPattern;
-    return result;
-}
-
-const Locale&
-CurrencyPluralInfo::getLocale() const {
-    return *fLocale;
-}
-
-void
-CurrencyPluralInfo::setPluralRules(const UnicodeString& ruleDescription,
-                                   UErrorCode& status) {
-    if (U_SUCCESS(status)) {
-        fPluralRules = PluralRules::createRules(ruleDescription, status);
-    }
-}
-
-
-void
-CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount,
-                                             const UnicodeString& pattern,
-                                             UErrorCode& status) {
-    if (U_SUCCESS(status)) {
-        fPluralCountToCurrencyUnitPattern->put(pluralCount, new UnicodeString(pattern), status);
-    }
-}
-
-
-void
-CurrencyPluralInfo::setLocale(const Locale& loc, UErrorCode& status) {
-    initialize(loc, status);
-}
-
-
-void 
-CurrencyPluralInfo::initialize(const Locale& loc, UErrorCode& status) {
-    if (U_FAILURE(status)) {
-        return;
-    }
-    delete fLocale;
-    fLocale = loc.clone();
-    fPluralRules = PluralRules::forLocale(loc, status);
-    setupCurrencyPluralPattern(loc, status);
-}
-
-   
-void
-CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) {
-    if (U_FAILURE(status)) {
-        return;
-    }
-
-    fPluralCountToCurrencyUnitPattern = initHash(status);
-    if (U_FAILURE(status)) {
-        return;
-    }
-
-    UErrorCode ec = U_ZERO_ERROR;
-    UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec);
-    UResourceBundle *numberPatterns = ures_getByKey(rb, gNumberPatternsTag, NULL, &ec);
-    int32_t ptnLen;
-    // TODO: 0 to be NumberFormat::fNumberStyle
-    const UChar* numberStylePattern = ures_getStringByIndex(numberPatterns, 0, 
-                                                            &ptnLen, &ec);
-    int32_t numberStylePatternLen = ptnLen;
-    const UChar* negNumberStylePattern = NULL;
-    int32_t negNumberStylePatternLen = 0;
-    // TODO: Java
-    // parse to check whether there is ";" separator in the numberStylePattern
-    UBool hasSeparator = false;
-    for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) {
-        if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) {
-            hasSeparator = true;
-            // split the number style pattern into positive and negative
-            negNumberStylePattern = numberStylePattern + styleCharIndex + 1;
-            negNumberStylePatternLen = ptnLen - styleCharIndex - 1;
-            numberStylePatternLen = styleCharIndex;
-        }
-    }
-    ures_close(numberPatterns);
-
-    if (U_FAILURE(ec)) {
-        ures_close(rb);
-        return;
-    }
-
-    UResourceBundle *currencyRes = ures_getByKeyWithFallback(rb, gCurrUnitPtnTag, NULL, &ec);
-    
-#ifdef CURRENCY_PLURAL_INFO_DEBUG
-    std::cout << "in set up\n";
-#endif
-    StringEnumeration* keywords = fPluralRules->getKeywords(ec);
-    if (U_SUCCESS(ec)) {
-        const char* pluralCount;
-        while ((pluralCount = keywords->next(NULL, ec)) != NULL) {
-            if ( U_SUCCESS(ec) ) {
-                int32_t ptnLen;
-                UErrorCode err = U_ZERO_ERROR;
-                const UChar* patternChars = ures_getStringByKeyWithFallback(
-                    currencyRes, pluralCount, &ptnLen, &err);
-                if (U_SUCCESS(err) && ptnLen > 0) {
-                    UnicodeString* pattern = new UnicodeString(patternChars, ptnLen);
-#ifdef CURRENCY_PLURAL_INFO_DEBUG
-                    char result_1[1000];
-                    pattern->extract(0, pattern->length(), result_1, "UTF-8");
-                    std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
-#endif
-                    pattern->findAndReplace(gPart0, 
-                      UnicodeString(numberStylePattern, numberStylePatternLen));
-                    pattern->findAndReplace(gPart1, gTripleCurrencySign);
-
-                    if (hasSeparator) {
-                        UnicodeString negPattern(patternChars, ptnLen);
-                        negPattern.findAndReplace(gPart0, 
-                          UnicodeString(negNumberStylePattern, negNumberStylePatternLen));
-                        negPattern.findAndReplace(gPart1, gTripleCurrencySign);
-                        pattern->append(gNumberPatternSeparator);
-                        pattern->append(negPattern);
-                    }
-#ifdef CURRENCY_PLURAL_INFO_DEBUG
-                    pattern->extract(0, pattern->length(), result_1, "UTF-8");
-                    std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
-#endif
-
-                    fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount), pattern, status);
-                }
-            }
-        }
-    }
-    delete keywords;
-    ures_close(currencyRes);
-    ures_close(rb);
-}
-
-
-
-void
-CurrencyPluralInfo::deleteHash(Hashtable* hTable) 
-{
-    if ( hTable == NULL ) {
-        return;
-    }
-    int32_t pos = -1;
-    const UHashElement* element = NULL;
-    while ( (element = hTable->nextElement(pos)) != NULL ) {
-        const UHashTok keyTok = element->key;
-        const UHashTok valueTok = element->value;
-        const UnicodeString* value = (UnicodeString*)valueTok.pointer;
-        delete value;
-    }
-    delete hTable;
-    hTable = NULL;
-}
-
-
-Hashtable*
-CurrencyPluralInfo::initHash(UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return NULL;
-    }
-    Hashtable* hTable;
-    if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
-        status = U_MEMORY_ALLOCATION_ERROR;
-        return NULL;
-    }
-    hTable->setValueCompartor(ValueComparator);
-    return hTable;
-}
-
-
-void
-CurrencyPluralInfo::copyHash(const Hashtable* source,
-                           Hashtable* target,
-                           UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    int32_t pos = -1;
-    const UHashElement* element = NULL;
-    if ( source ) {
-        while ( (element = source->nextElement(pos)) != NULL ) {
-            const UHashTok keyTok = element->key;
-            const UnicodeString* key = (UnicodeString*)keyTok.pointer;
-            const UHashTok valueTok = element->value;
-            const UnicodeString* value = (UnicodeString*)valueTok.pointer;
-            UnicodeString* copy = new UnicodeString(*value);
-            target->put(UnicodeString(*key), copy, status);
-            if ( U_FAILURE(status) ) {
-                return;
-            }
-        }
-    }
-}
-
-
-U_NAMESPACE_END
-
-#endif
+/*
+ *******************************************************************************
+ * Copyright (C) 2009, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+#include "unicode/currpinf.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+//#define CURRENCY_PLURAL_INFO_DEBUG 1
+
+#ifdef CURRENCY_PLURAL_INFO_DEBUG
+#include <iostream>
+#endif
+
+
+#include "unicode/locid.h"
+#include "unicode/plurrule.h"
+#include "unicode/ures.h"
+#include "cstring.h"
+#include "hash.h"
+#include "uresimp.h"
+
+U_NAMESPACE_BEGIN
+
+
+static const UChar gNumberPatternSeparator = 0x3B; // ;
+
+U_CDECL_BEGIN
+
+/**
+ * @internal ICU 4.2
+ */
+static UBool U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2);
+
+U_CDECL_END
+
+UBool
+U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2) {
+    const UnicodeString* affix_1 = (UnicodeString*)val1.pointer;
+    const UnicodeString* affix_2 = (UnicodeString*)val2.pointer;
+    return  *affix_1 == *affix_2;
+}
+
+
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyPluralInfo)
+
+static const UChar gDefaultCurrencyPluralPattern[] = {'0', '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4, 0};
+static const UChar gTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
+static const UChar gPluralCountOther[] = {0x6F, 0x74, 0x68, 0x65, 0x72, 0};
+static const UChar gPart0[] = {0x7B, 0x30, 0x7D, 0};
+static const UChar gPart1[] = {0x7B, 0x31, 0x7D, 0};
+
+static const char gNumberPatternsTag[]="NumberPatterns";
+static const char gCurrUnitPtnTag[]="CurrencyUnitPatterns";
+
+CurrencyPluralInfo::CurrencyPluralInfo(UErrorCode& status)
+:   fPluralCountToCurrencyUnitPattern(NULL),
+    fPluralRules(NULL),
+    fLocale(NULL) {
+    initialize(Locale::getDefault(), status);
+}
+
+CurrencyPluralInfo::CurrencyPluralInfo(const Locale& locale, UErrorCode& status)
+:   fPluralCountToCurrencyUnitPattern(NULL),
+    fPluralRules(NULL),
+    fLocale(NULL) {
+    initialize(locale, status);
+}
+
+CurrencyPluralInfo::CurrencyPluralInfo(const CurrencyPluralInfo& info) 
+:   UObject(info),
+    fPluralCountToCurrencyUnitPattern(NULL),
+    fPluralRules(NULL),
+    fLocale(NULL) {
+    *this = info;
+}
+
+
+CurrencyPluralInfo&
+CurrencyPluralInfo::operator=(const CurrencyPluralInfo& info) {
+    if (this == &info) {
+        return *this;
+    }
+
+    deleteHash(fPluralCountToCurrencyUnitPattern);
+    UErrorCode status = U_ZERO_ERROR;
+    fPluralCountToCurrencyUnitPattern = initHash(status);
+    copyHash(info.fPluralCountToCurrencyUnitPattern, 
+             fPluralCountToCurrencyUnitPattern, status);
+    if ( U_FAILURE(status) ) {
+        return *this;
+    }
+
+    delete fPluralRules;
+    delete fLocale;
+    if (info.fPluralRules) {
+        fPluralRules = info.fPluralRules->clone();
+    } else {
+        fPluralRules = NULL;
+    }
+    if (info.fLocale) {
+        fLocale = info.fLocale->clone();
+    } else {
+        fLocale = NULL;
+    }
+    return *this;
+}
+
+
+CurrencyPluralInfo::~CurrencyPluralInfo() {
+    deleteHash(fPluralCountToCurrencyUnitPattern);
+    fPluralCountToCurrencyUnitPattern = NULL;
+    delete fPluralRules;
+    delete fLocale;
+    fPluralRules = NULL;
+    fLocale = NULL;
+}
+
+UBool
+CurrencyPluralInfo::operator==(const CurrencyPluralInfo& info) const {
+#ifdef CURRENCY_PLURAL_INFO_DEBUG
+    if (*fPluralRules == *info.fPluralRules) {
+        std::cout << "same plural rules\n";
+    }
+    if (*fLocale == *info.fLocale) {
+        std::cout << "same locale\n";
+    }
+    if (fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern)) {
+        std::cout << "same pattern\n";
+    }
+#endif
+    return *fPluralRules == *info.fPluralRules &&
+           *fLocale == *info.fLocale &&
+           fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern);
+}
+
+
+CurrencyPluralInfo*
+CurrencyPluralInfo::clone() const {
+    return new CurrencyPluralInfo(*this);
+}
+
+const PluralRules* 
+CurrencyPluralInfo::getPluralRules() const {
+    return fPluralRules;
+}
+
+UnicodeString&
+CurrencyPluralInfo::getCurrencyPluralPattern(const UnicodeString&  pluralCount,
+                                             UnicodeString& result) const {
+    const UnicodeString* currencyPluralPattern = 
+        (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(pluralCount);
+    if (currencyPluralPattern == NULL) {
+        // fall back to "other"
+        if (pluralCount.compare(gPluralCountOther)) {
+            currencyPluralPattern = 
+                (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(gPluralCountOther);
+        }
+        if (currencyPluralPattern == NULL) {
+            // no currencyUnitPatterns defined, 
+            // fallback to predefined defult.
+            // This should never happen when ICU resource files are
+            // available, since currencyUnitPattern of "other" is always
+            // defined in root.
+            result = UnicodeString(gDefaultCurrencyPluralPattern);
+            return result;
+        }
+    }
+    result = *currencyPluralPattern;
+    return result;
+}
+
+const Locale&
+CurrencyPluralInfo::getLocale() const {
+    return *fLocale;
+}
+
+void
+CurrencyPluralInfo::setPluralRules(const UnicodeString& ruleDescription,
+                                   UErrorCode& status) {
+    if (U_SUCCESS(status)) {
+        fPluralRules = PluralRules::createRules(ruleDescription, status);
+    }
+}
+
+
+void
+CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount,
+                                             const UnicodeString& pattern,
+                                             UErrorCode& status) {
+    if (U_SUCCESS(status)) {
+        fPluralCountToCurrencyUnitPattern->put(pluralCount, new UnicodeString(pattern), status);
+    }
+}
+
+
+void
+CurrencyPluralInfo::setLocale(const Locale& loc, UErrorCode& status) {
+    initialize(loc, status);
+}
+
+
+void 
+CurrencyPluralInfo::initialize(const Locale& loc, UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return;
+    }
+    delete fLocale;
+    fLocale = loc.clone();
+    fPluralRules = PluralRules::forLocale(loc, status);
+    setupCurrencyPluralPattern(loc, status);
+}
+
+   
+void
+CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return;
+    }
+
+    fPluralCountToCurrencyUnitPattern = initHash(status);
+    if (U_FAILURE(status)) {
+        return;
+    }
+
+    UErrorCode ec = U_ZERO_ERROR;
+    UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec);
+    UResourceBundle *numberPatterns = ures_getByKey(rb, gNumberPatternsTag, NULL, &ec);
+    int32_t ptnLen;
+    // TODO: 0 to be NumberFormat::fNumberStyle
+    const UChar* numberStylePattern = ures_getStringByIndex(numberPatterns, 0, 
+                                                            &ptnLen, &ec);
+    int32_t numberStylePatternLen = ptnLen;
+    const UChar* negNumberStylePattern = NULL;
+    int32_t negNumberStylePatternLen = 0;
+    // TODO: Java
+    // parse to check whether there is ";" separator in the numberStylePattern
+    UBool hasSeparator = false;
+    if (U_SUCCESS(ec)) {
+        for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) {
+            if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) {
+                hasSeparator = true;
+                // split the number style pattern into positive and negative
+                negNumberStylePattern = numberStylePattern + styleCharIndex + 1;
+                negNumberStylePatternLen = ptnLen - styleCharIndex - 1;
+                numberStylePatternLen = styleCharIndex;
+            }
+        }
+    }
+    ures_close(numberPatterns);
+
+    if (U_FAILURE(ec)) {
+        ures_close(rb);
+        return;
+    }
+
+    UResourceBundle *currencyRes = ures_getByKeyWithFallback(rb, gCurrUnitPtnTag, NULL, &ec);
+    
+#ifdef CURRENCY_PLURAL_INFO_DEBUG
+    std::cout << "in set up\n";
+#endif
+    StringEnumeration* keywords = fPluralRules->getKeywords(ec);
+    if (U_SUCCESS(ec)) {
+        const char* pluralCount;
+        while ((pluralCount = keywords->next(NULL, ec)) != NULL) {
+            if ( U_SUCCESS(ec) ) {
+                int32_t ptnLen;
+                UErrorCode err = U_ZERO_ERROR;
+                const UChar* patternChars = ures_getStringByKeyWithFallback(
+                    currencyRes, pluralCount, &ptnLen, &err);
+                if (U_SUCCESS(err) && ptnLen > 0) {
+                    UnicodeString* pattern = new UnicodeString(patternChars, ptnLen);
+#ifdef CURRENCY_PLURAL_INFO_DEBUG
+                    char result_1[1000];
+                    pattern->extract(0, pattern->length(), result_1, "UTF-8");
+                    std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
+#endif
+                    pattern->findAndReplace(gPart0, 
+                      UnicodeString(numberStylePattern, numberStylePatternLen));
+                    pattern->findAndReplace(gPart1, gTripleCurrencySign);
+
+                    if (hasSeparator) {
+                        UnicodeString negPattern(patternChars, ptnLen);
+                        negPattern.findAndReplace(gPart0, 
+                          UnicodeString(negNumberStylePattern, negNumberStylePatternLen));
+                        negPattern.findAndReplace(gPart1, gTripleCurrencySign);
+                        pattern->append(gNumberPatternSeparator);
+                        pattern->append(negPattern);
+                    }
+#ifdef CURRENCY_PLURAL_INFO_DEBUG
+                    pattern->extract(0, pattern->length(), result_1, "UTF-8");
+                    std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
+#endif
+
+                    fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount), pattern, status);
+                }
+            }
+        }
+    }
+    delete keywords;
+    ures_close(currencyRes);
+    ures_close(rb);
+}
+
+
+
+void
+CurrencyPluralInfo::deleteHash(Hashtable* hTable) 
+{
+    if ( hTable == NULL ) {
+        return;
+    }
+    int32_t pos = -1;
+    const UHashElement* element = NULL;
+    while ( (element = hTable->nextElement(pos)) != NULL ) {
+        const UHashTok keyTok = element->key;
+        const UHashTok valueTok = element->value;
+        const UnicodeString* value = (UnicodeString*)valueTok.pointer;
+        delete value;
+    }
+    delete hTable;
+    hTable = NULL;
+}
+
+
+Hashtable*
+CurrencyPluralInfo::initHash(UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return NULL;
+    }
+    Hashtable* hTable;
+    if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return NULL;
+    }
+    hTable->setValueCompartor(ValueComparator);
+    return hTable;
+}
+
+
+void
+CurrencyPluralInfo::copyHash(const Hashtable* source,
+                           Hashtable* target,
+                           UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    int32_t pos = -1;
+    const UHashElement* element = NULL;
+    if ( source ) {
+        while ( (element = source->nextElement(pos)) != NULL ) {
+            const UHashTok keyTok = element->key;
+            const UnicodeString* key = (UnicodeString*)keyTok.pointer;
+            const UHashTok valueTok = element->value;
+            const UnicodeString* value = (UnicodeString*)valueTok.pointer;
+            UnicodeString* copy = new UnicodeString(*value);
+            target->put(UnicodeString(*key), copy, status);
+            if ( U_FAILURE(status) ) {
+                return;
+            }
+        }
+    }
+}
+
+
+U_NAMESPACE_END
+
+#endif

Modified: trunk/source/i18n/dtitv_impl.h
===================================================================
--- trunk/source/i18n/dtitv_impl.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/dtitv_impl.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,93 +1,93 @@
-/*
-*******************************************************************************
-* Copyright (C) 2007-2008, International Business Machines Corporation and
-* others. All Rights Reserved.
-*******************************************************************************
-*
-* File DTITV_IMPL.H
-*
-*******************************************************************************
-*/
-
-
-#ifndef DTITV_IMPL_H__
-#define DTITV_IMPL_H__
-
-/**
- * \file
- * \brief C++ API: Defines macros for interval format implementation
- */
- 
-#if !UCONFIG_NO_FORMATTING
-
-#include "unicode/unistr.h"
-
-
-#define QUOTE             ((UChar)0x0027)
-#define LOW_LINE          ((UChar)0x005F)
-#define COLON             ((UChar)0x003A)
-#define LEFT_CURLY_BRACKET  ((UChar)0x007B)
-#define RIGHT_CURLY_BRACKET ((UChar)0x007D)
-#define SPACE             ((UChar)0x0020)
-#define EN_DASH           ((UChar)0x2013)
-
-#define DIGIT_ZERO        ((UChar)0x0030)
-#define DIGIT_ONE         ((UChar)0x0031)
-
-#define LOW_A             ((UChar)0x0061)
-#define LOW_B             ((UChar)0x0062)
-#define LOW_C             ((UChar)0x0063)
-#define LOW_D             ((UChar)0x0064)
-#define LOW_E             ((UChar)0x0065)
-#define LOW_F             ((UChar)0x0066)
-#define LOW_G             ((UChar)0x0067)
-#define LOW_H             ((UChar)0x0068)
-#define LOW_I             ((UChar)0x0069)
-#define LOW_J             ((UChar)0x006a)
-#define LOW_K             ((UChar)0x006B)
-#define LOW_L             ((UChar)0x006C)
-#define LOW_M             ((UChar)0x006D)
-#define LOW_N             ((UChar)0x006E)
-#define LOW_O             ((UChar)0x006F)
-#define LOW_P             ((UChar)0x0070)
-#define LOW_Q             ((UChar)0x0071)
-#define LOW_R             ((UChar)0x0072)
-#define LOW_S             ((UChar)0x0073)
-#define LOW_T             ((UChar)0x0074)
-#define LOW_U             ((UChar)0x0075)
-#define LOW_V             ((UChar)0x0076)
-#define LOW_W             ((UChar)0x0077)
-#define LOW_Y             ((UChar)0x0079)
-#define LOW_Z             ((UChar)0x007A)
-
-#define CAP_A             ((UChar)0x0041)
-#define CAP_C             ((UChar)0x0043)
-#define CAP_D             ((UChar)0x0044)
-#define CAP_E             ((UChar)0x0045)
-#define CAP_F             ((UChar)0x0046)
-#define CAP_G             ((UChar)0x0047)
-#define CAP_H             ((UChar)0x0048)
-#define CAP_K             ((UChar)0x004B)
-#define CAP_L             ((UChar)0x004C)
-#define CAP_M             ((UChar)0x004D)
-#define CAP_O             ((UChar)0x004F)
-#define CAP_Q             ((UChar)0x0051)
-#define CAP_S             ((UChar)0x0053)
-#define CAP_T             ((UChar)0x0054)
-#define CAP_V             ((UChar)0x0056)
-#define CAP_W             ((UChar)0x0057)
-#define CAP_Y             ((UChar)0x0059)
-#define CAP_Z             ((UChar)0x005A)
-
-//#define MINIMUM_SUPPORTED_CALENDAR_FIELD    UCAL_MINUTE
-
-#define MAX_E_COUNT      5
-#define MAX_M_COUNT      5
-//#define MAX_INTERVAL_INDEX 4
-#define MAX_POSITIVE_INT  56632;
-
-
-#endif /* #if !UCONFIG_NO_FORMATTING */
-
-#endif 
-//eof
+/*
+*******************************************************************************
+* Copyright (C) 2007-2008, International Business Machines Corporation and
+* others. All Rights Reserved.
+*******************************************************************************
+*
+* File DTITV_IMPL.H
+*
+*******************************************************************************
+*/
+
+
+#ifndef DTITV_IMPL_H__
+#define DTITV_IMPL_H__
+
+/**
+ * \file
+ * \brief C++ API: Defines macros for interval format implementation
+ */
+ 
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/unistr.h"
+
+
+#define QUOTE             ((UChar)0x0027)
+#define LOW_LINE          ((UChar)0x005F)
+#define COLON             ((UChar)0x003A)
+#define LEFT_CURLY_BRACKET  ((UChar)0x007B)
+#define RIGHT_CURLY_BRACKET ((UChar)0x007D)
+#define SPACE             ((UChar)0x0020)
+#define EN_DASH           ((UChar)0x2013)
+
+#define DIGIT_ZERO        ((UChar)0x0030)
+#define DIGIT_ONE         ((UChar)0x0031)
+
+#define LOW_A             ((UChar)0x0061)
+#define LOW_B             ((UChar)0x0062)
+#define LOW_C             ((UChar)0x0063)
+#define LOW_D             ((UChar)0x0064)
+#define LOW_E             ((UChar)0x0065)
+#define LOW_F             ((UChar)0x0066)
+#define LOW_G             ((UChar)0x0067)
+#define LOW_H             ((UChar)0x0068)
+#define LOW_I             ((UChar)0x0069)
+#define LOW_J             ((UChar)0x006a)
+#define LOW_K             ((UChar)0x006B)
+#define LOW_L             ((UChar)0x006C)
+#define LOW_M             ((UChar)0x006D)
+#define LOW_N             ((UChar)0x006E)
+#define LOW_O             ((UChar)0x006F)
+#define LOW_P             ((UChar)0x0070)
+#define LOW_Q             ((UChar)0x0071)
+#define LOW_R             ((UChar)0x0072)
+#define LOW_S             ((UChar)0x0073)
+#define LOW_T             ((UChar)0x0074)
+#define LOW_U             ((UChar)0x0075)
+#define LOW_V             ((UChar)0x0076)
+#define LOW_W             ((UChar)0x0077)
+#define LOW_Y             ((UChar)0x0079)
+#define LOW_Z             ((UChar)0x007A)
+
+#define CAP_A             ((UChar)0x0041)
+#define CAP_C             ((UChar)0x0043)
+#define CAP_D             ((UChar)0x0044)
+#define CAP_E             ((UChar)0x0045)
+#define CAP_F             ((UChar)0x0046)
+#define CAP_G             ((UChar)0x0047)
+#define CAP_H             ((UChar)0x0048)
+#define CAP_K             ((UChar)0x004B)
+#define CAP_L             ((UChar)0x004C)
+#define CAP_M             ((UChar)0x004D)
+#define CAP_O             ((UChar)0x004F)
+#define CAP_Q             ((UChar)0x0051)
+#define CAP_S             ((UChar)0x0053)
+#define CAP_T             ((UChar)0x0054)
+#define CAP_V             ((UChar)0x0056)
+#define CAP_W             ((UChar)0x0057)
+#define CAP_Y             ((UChar)0x0059)
+#define CAP_Z             ((UChar)0x005A)
+
+//#define MINIMUM_SUPPORTED_CALENDAR_FIELD    UCAL_MINUTE
+
+#define MAX_E_COUNT      5
+#define MAX_M_COUNT      5
+//#define MAX_INTERVAL_INDEX 4
+#define MAX_POSITIVE_INT  56632;
+
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif 
+//eof

Modified: trunk/source/i18n/dtitvfmt.cpp
===================================================================
--- trunk/source/i18n/dtitvfmt.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/dtitvfmt.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,1423 +1,1423 @@
-/*******************************************************************************
-* Copyright (C) 2008-2009, International Business Machines Corporation and
-* others. All Rights Reserved.
-*******************************************************************************
-*
-* File DTITVFMT.CPP 
-*
-*******************************************************************************
-*/
-
-#include "unicode/dtitvfmt.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-//TODO: put in compilation
-//#define DTITVFMT_DEBUG 1
-
-#include "cstring.h"
-#include "unicode/msgfmt.h"
-#include "unicode/dtptngen.h"
-#include "unicode/dtitvinf.h"
-#include "unicode/calendar.h"
-#include "dtitv_impl.h"
-
-#ifdef DTITVFMT_DEBUG 
-#include <iostream>
-#include "cstring.h"
-#endif
-
-#include "gregoimp.h"
-
-U_NAMESPACE_BEGIN
-
-
-
-#ifdef DTITVFMT_DEBUG 
-#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
-#endif
-
-
-static const UChar gDateFormatSkeleton[][11] = {
-//yMMMMEEEEd
-{LOW_Y, CAP_M, CAP_M, CAP_M, CAP_M, CAP_E, CAP_E, CAP_E, CAP_E, LOW_D, 0},
-//yMMMMd
-{LOW_Y, CAP_M, CAP_M, CAP_M, CAP_M, LOW_D, 0},
-//yMMMd
-{LOW_Y, CAP_M, CAP_M, CAP_M, LOW_D, 0},
-//yMd
-{LOW_Y, CAP_M, LOW_D, 0} };
-
-
-static const char gDateTimePatternsTag[]="DateTimePatterns";
-
-
-// latestFirst:
-static const UChar gLaterFirstPrefix[] = {LOW_L, LOW_A, LOW_T, LOW_E, LOW_S,LOW_T, CAP_F, LOW_I, LOW_R, LOW_S, LOW_T, COLON};
-
-// earliestFirst:
-static const UChar gEarlierFirstPrefix[] = {LOW_E, LOW_A, LOW_R, LOW_L, LOW_I, LOW_E, LOW_S, LOW_T, CAP_F, LOW_I, LOW_R, LOW_S, LOW_T, COLON};
-
-
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalFormat)
-
-
-
-DateIntervalFormat* U_EXPORT2
-DateIntervalFormat::createInstance(const UnicodeString& skeleton, 
-                                   UErrorCode& status) {
-    return createInstance(skeleton, Locale::getDefault(), status);
-}
-
-
-DateIntervalFormat* U_EXPORT2
-DateIntervalFormat::createInstance(const UnicodeString& skeleton, 
-                                   const Locale& locale, 
-                                   UErrorCode& status) {
-#ifdef DTITVFMT_DEBUG
-    char result[1000];
-    char result_1[1000];
-    char mesg[2000];
-    skeleton.extract(0,  skeleton.length(), result, "UTF-8");
-    UnicodeString pat;
-    ((SimpleDateFormat*)dtfmt)->toPattern(pat);
-    pat.extract(0,  pat.length(), result_1, "UTF-8");
-    sprintf(mesg, "skeleton: %s; pattern: %s\n", result, result_1);
-    PRINTMESG(mesg)
-#endif
-
-    DateIntervalInfo* dtitvinf = new DateIntervalInfo(locale, status);
-    return create(locale, dtitvinf, &skeleton, status);
-}
-
-
-
-DateIntervalFormat* U_EXPORT2
-DateIntervalFormat::createInstance(const UnicodeString& skeleton,
-                                   const DateIntervalInfo& dtitvinf,
-                                   UErrorCode& status) {
-    return createInstance(skeleton, Locale::getDefault(), dtitvinf, status);
-}
-
-
-DateIntervalFormat* U_EXPORT2
-DateIntervalFormat::createInstance(const UnicodeString& skeleton,
-                                   const Locale& locale,
-                                   const DateIntervalInfo& dtitvinf,
-                                   UErrorCode& status) {
-    DateIntervalInfo* ptn = dtitvinf.clone();
-    return create(locale, ptn, &skeleton, status);
-}
-
-
-DateIntervalFormat::DateIntervalFormat()
-:   fInfo(NULL),
-    fDateFormat(NULL),
-    fFromCalendar(NULL),
-    fToCalendar(NULL),
-    fDtpng(NULL)
-{}
-
-
-DateIntervalFormat::DateIntervalFormat(const DateIntervalFormat& itvfmt)
-:   Format(itvfmt),
-    fInfo(NULL),
-    fDateFormat(NULL),
-    fFromCalendar(NULL),
-    fToCalendar(NULL),
-    fDtpng(NULL) {
-    *this = itvfmt;
-}
-
-
-DateIntervalFormat&
-DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) {
-    if ( this != &itvfmt ) {
-        delete fDateFormat;
-        delete fInfo;
-        delete fFromCalendar;
-        delete fToCalendar;
-        delete fDtpng;
-        if ( itvfmt.fDateFormat ) {
-            fDateFormat = (SimpleDateFormat*)itvfmt.fDateFormat->clone();
-        } else {
-            fDateFormat = NULL;
-        }
-        if ( itvfmt.fInfo ) {
-            fInfo = itvfmt.fInfo->clone();
-        } else {
-            fInfo = NULL;
-        }
-        if ( itvfmt.fFromCalendar ) {
-            fFromCalendar = itvfmt.fFromCalendar->clone();
-        } else {
-            fFromCalendar = NULL;
-        }
-        if ( itvfmt.fToCalendar ) {
-            fToCalendar = itvfmt.fToCalendar->clone();
-        } else {
-            fToCalendar = NULL;
-        }
-        fSkeleton = itvfmt.fSkeleton;
-        int8_t i;
-        for ( i = 0; i< DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
-            fIntervalPatterns[i] = itvfmt.fIntervalPatterns[i];
-        }
-        if (itvfmt.fDtpng) {
-            fDtpng = itvfmt.fDtpng->clone();
-        }
-    }
-    return *this;
-}
-
-
-DateIntervalFormat::~DateIntervalFormat() {
-    delete fInfo;
-    delete fDateFormat;
-    delete fFromCalendar;
-    delete fToCalendar;
-    delete fDtpng;
-}
-
-
-Format*
-DateIntervalFormat::clone(void) const {
-    return new DateIntervalFormat(*this);
-}
-
-
-UBool
-DateIntervalFormat::operator==(const Format& other) const {
-    if ( other.getDynamicClassID() == DateIntervalFormat::getStaticClassID() ) {
-        DateIntervalFormat* fmt = (DateIntervalFormat*)&other;
-#ifdef DTITVFMT_DEBUG
-    UBool equal;
-    equal = (this == fmt);
-    
-    equal = (*fInfo == *fmt->fInfo);
-    equal = (*fDateFormat == *fmt->fDateFormat);
-    equal = fFromCalendar->isEquivalentTo(*fmt->fFromCalendar) ;
-    equal = fToCalendar->isEquivalentTo(*fmt->fToCalendar) ;
-    equal = (fSkeleton == fmt->fSkeleton);
-#endif
-        UBool res;
-        res =  ( this == fmt ) ||
-               ( Format::operator==(other) && 
-                 fInfo && 
-                 ( *fInfo == *fmt->fInfo ) &&
-                 fDateFormat &&
-                 ( *fDateFormat == *fmt->fDateFormat ) &&
-                 fFromCalendar &&
-                 fFromCalendar->isEquivalentTo(*fmt->fFromCalendar) &&
-                 fToCalendar &&
-                 fToCalendar->isEquivalentTo(*fmt->fToCalendar) &&
-                 fSkeleton == fmt->fSkeleton &&
-                 fDtpng &&
-                 (*fDtpng == *fmt->fDtpng) );
-        int8_t i;
-        for (i = 0; i< DateIntervalInfo::kIPI_MAX_INDEX && res == TRUE; ++i ) {
-            res =   ( fIntervalPatterns[i].firstPart ==
-                      fmt->fIntervalPatterns[i].firstPart) &&
-                    ( fIntervalPatterns[i].secondPart ==
-                      fmt->fIntervalPatterns[i].secondPart ) &&
-                    ( fIntervalPatterns[i].laterDateFirst ==
-                      fmt->fIntervalPatterns[i].laterDateFirst) ;
-        }
-        return res;
-    } 
-    return FALSE;
-}
-
-
-
-UnicodeString&
-DateIntervalFormat::format(const Formattable& obj,
-                           UnicodeString& appendTo,
-                           FieldPosition& fieldPosition,
-                           UErrorCode& status) const {
-    if ( U_FAILURE(status) ) {
-        return appendTo;
-    }
-
-    if ( obj.getType() == Formattable::kObject ) {
-        const UObject* formatObj = obj.getObject();
-        if (formatObj->getDynamicClassID() == DateInterval::getStaticClassID()){
-            return format((DateInterval*)formatObj, appendTo, fieldPosition, status);
-        }
-    }
-    status = U_ILLEGAL_ARGUMENT_ERROR;
-    return appendTo;
-}
-
-
-UnicodeString&
-DateIntervalFormat::format(const DateInterval* dtInterval,
-                           UnicodeString& appendTo,
-                           FieldPosition& fieldPosition,
-                           UErrorCode& status) const {
-    if ( U_FAILURE(status) ) {
-        return appendTo;
-    }
-
-    if ( fFromCalendar != NULL && fToCalendar != NULL && 
-         fDateFormat != NULL && fInfo != NULL ) {
-        fFromCalendar->setTime(dtInterval->getFromDate(), status);
-        fToCalendar->setTime(dtInterval->getToDate(), status);
-        if ( U_SUCCESS(status) ) {
-            return format(*fFromCalendar, *fToCalendar, appendTo,fieldPosition, status);
-        }
-    }
-    return appendTo;
-}
-
-
-UnicodeString&
-DateIntervalFormat::format(Calendar& fromCalendar,
-                           Calendar& toCalendar,
-                           UnicodeString& appendTo,
-                           FieldPosition& pos,
-                           UErrorCode& status) const {
-    if ( U_FAILURE(status) ) {
-        return appendTo;
-    }
-
-    // not support different calendar types and time zones
-    //if ( fromCalendar.getType() != toCalendar.getType() ) {
-    if ( !fromCalendar.isEquivalentTo(toCalendar) ||
-         uprv_strcmp(fromCalendar.getType(), "gregorian") ) {
-        status = U_ILLEGAL_ARGUMENT_ERROR;
-        return appendTo;
-    }
-
-    // First, find the largest different calendar field.
-    UCalendarDateFields field = UCAL_FIELD_COUNT;
-
-    if ( fromCalendar.get(UCAL_ERA,status) != toCalendar.get(UCAL_ERA,status)) {
-        field = UCAL_ERA;
-    } else if ( fromCalendar.get(UCAL_YEAR, status) != 
-                toCalendar.get(UCAL_YEAR, status) ) {
-        field = UCAL_YEAR;
-    } else if ( fromCalendar.get(UCAL_MONTH, status) !=
-                toCalendar.get(UCAL_MONTH, status) ) {
-        field = UCAL_MONTH;
-    } else if ( fromCalendar.get(UCAL_DATE, status) !=
-                toCalendar.get(UCAL_DATE, status) ) {
-        field = UCAL_DATE;
-    } else if ( fromCalendar.get(UCAL_AM_PM, status) !=
-                toCalendar.get(UCAL_AM_PM, status) ) {
-        field = UCAL_AM_PM;
-    } else if ( fromCalendar.get(UCAL_HOUR, status) !=
-                toCalendar.get(UCAL_HOUR, status) ) {
-        field = UCAL_HOUR;
-    } else if ( fromCalendar.get(UCAL_MINUTE, status) !=
-                toCalendar.get(UCAL_MINUTE, status) ) {
-        field = UCAL_MINUTE;
-    }
-
-    if ( U_FAILURE(status) ) {
-        return appendTo;
-    }
-    if ( field == UCAL_FIELD_COUNT ) {
-        /* ignore the second/millisecond etc. small fields' difference.
-         * use single date when all the above are the same.
-         */
-        return fDateFormat->format(fromCalendar, appendTo, pos);
-    }
-    
-    // following call should not set wrong status,
-    // all the pass-in fields are valid till here
-    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
-                                                                        status);
-    const PatternInfo& intervalPattern = fIntervalPatterns[itvPtnIndex];
-
-    if ( intervalPattern.firstPart.isEmpty() &&
-         intervalPattern.secondPart.isEmpty() ) {
-        if ( fDateFormat->isFieldUnitIgnored(field) ) {
-            /* the largest different calendar field is small than
-             * the smallest calendar field in pattern,
-             * return single date format.
-             */
-            return fDateFormat->format(fromCalendar, appendTo, pos);
-        }
-        return fallbackFormat(fromCalendar, toCalendar, appendTo, pos, status);
-    }
-    // If the first part in interval pattern is empty, 
-    // the 2nd part of it saves the full-pattern used in fall-back.
-    // For a 'real' interval pattern, the first part will never be empty.
-    if ( intervalPattern.firstPart.isEmpty() ) {
-        // fall back
-        UnicodeString originalPattern;
-        fDateFormat->toPattern(originalPattern);
-        fDateFormat->applyPattern(intervalPattern.secondPart);
-        appendTo = fallbackFormat(fromCalendar, toCalendar, appendTo, pos, status);
-        fDateFormat->applyPattern(originalPattern);
-        return appendTo;
-    }
-    Calendar* firstCal;
-    Calendar* secondCal;
-    if ( intervalPattern.laterDateFirst ) {
-        firstCal = &toCalendar;
-        secondCal = &fromCalendar;
-    } else {
-        firstCal = &fromCalendar;
-        secondCal = &toCalendar;
-    }
-    // break the interval pattern into 2 parts,
-    // first part should not be empty, 
-    UnicodeString originalPattern;
-    fDateFormat->toPattern(originalPattern);
-    fDateFormat->applyPattern(intervalPattern.firstPart);
-    fDateFormat->format(*firstCal, appendTo, pos);
-    if ( !intervalPattern.secondPart.isEmpty() ) {
-        fDateFormat->applyPattern(intervalPattern.secondPart);
-        fDateFormat->format(*secondCal, appendTo, pos);
-    }
-    fDateFormat->applyPattern(originalPattern);
-    return appendTo;
-}
-
-
-
-void
-DateIntervalFormat::parseObject(const UnicodeString& /* source */, 
-                                Formattable& /* result */,
-                                ParsePosition& /* parse_pos */) const {
-    // parseObject(const UnicodeString&, Formattable&, UErrorCode&) const
-    // will set status as U_INVALID_FORMAT_ERROR if 
-    // parse_pos is still 0
-}
-
-
-
-
-const DateIntervalInfo*
-DateIntervalFormat::getDateIntervalInfo() const {
-    return fInfo;
-}
-
-
-void
-DateIntervalFormat::setDateIntervalInfo(const DateIntervalInfo& newItvPattern,
-                                        UErrorCode& status) {
-    delete fInfo;
-    fInfo = new DateIntervalInfo(newItvPattern);
-    if ( fDateFormat ) {
-        initializePattern(status);
-    }
-}
-
-
- 
-const DateFormat*
-DateIntervalFormat::getDateFormat() const {
-    return fDateFormat;
-}
-
-
-DateIntervalFormat::DateIntervalFormat(const Locale& locale,
-                                       DateIntervalInfo* dtItvInfo,
-                                       const UnicodeString* skeleton,
-                                       UErrorCode& status) 
-:   fInfo(NULL),
-    fDateFormat(NULL),
-    fFromCalendar(NULL),
-    fToCalendar(NULL),
-    fDtpng(NULL)
-{
-    if ( U_FAILURE(status) ) {
-        delete dtItvInfo;
-        return;
-    }
-    fDtpng = DateTimePatternGenerator::createInstance(locale, status);
-    SimpleDateFormat* dtfmt = createSDFPatternInstance(*skeleton, locale, 
-                                                    fDtpng, status);
-    if ( U_FAILURE(status) ) {
-        delete dtItvInfo;
-        delete fDtpng;
-        delete dtfmt;
-        return;
-    }
-    if ( dtfmt == NULL || dtItvInfo == NULL || fDtpng == NULL ) {
-        status = U_MEMORY_ALLOCATION_ERROR;
-        // safe to delete NULL
-        delete dtfmt;
-        delete dtItvInfo;
-        delete fDtpng;
-        return;
-    }
-    if ( skeleton ) {
-        fSkeleton = *skeleton;
-    }
-    fInfo = dtItvInfo;
-    fDateFormat = dtfmt;
-    if ( dtfmt->getCalendar() ) {
-        fFromCalendar = dtfmt->getCalendar()->clone();
-        fToCalendar = dtfmt->getCalendar()->clone();
-    } else {
-        fFromCalendar = NULL;
-        fToCalendar = NULL;
-    }
-    initializePattern(status);
-}
-
-
-SimpleDateFormat* U_EXPORT2
-DateIntervalFormat::createSDFPatternInstance(const UnicodeString& skeleton,
-                                             const Locale& locale,
-                                             DateTimePatternGenerator* dtpng,
-                                             UErrorCode& status)
-{
-    if ( U_FAILURE(status) ) {
-        return NULL;
-    }
-
-    const UnicodeString pattern = dtpng->getBestPattern(skeleton, status);
-    if ( U_FAILURE(status) ) {
-        return NULL;
-    }
-    SimpleDateFormat* dtfmt = new SimpleDateFormat(pattern, locale, status);
-    if ( U_FAILURE(status) ) {
-        delete dtfmt;
-        return NULL;
-    }
-    return dtfmt;
-}
-
-
-DateIntervalFormat* U_EXPORT2
-DateIntervalFormat::create(const Locale& locale,
-                           DateIntervalInfo* dtitvinf,
-                           const UnicodeString* skeleton,
-                           UErrorCode& status) {
-    DateIntervalFormat* f = new DateIntervalFormat(locale, dtitvinf, 
-                                                   skeleton, status);
-    if ( f == NULL ) {
-        status = U_MEMORY_ALLOCATION_ERROR;
-        delete dtitvinf;
-    } else if ( U_FAILURE(status) ) {
-        // safe to delete f, although nothing acutally is saved
-        delete f;
-        f = 0;
-    }
-    return f;
-}
-
-
-
-/** 
- * Initialize interval patterns locale to this formatter
- * 
- * This code is a bit complicated since 
- * 1. the interval patterns saved in resource bundle files are interval
- *    patterns based on date or time only.
- *    It does not have interval patterns based on both date and time.
- *    Interval patterns on both date and time are algorithm generated.
- *
- *    For example, it has interval patterns on skeleton "dMy" and "hm",
- *    but it does not have interval patterns on skeleton "dMyhm".
- *    
- *    The rule to genearte interval patterns for both date and time skeleton are
- *    1) when the year, month, or day differs, concatenate the two original 
- *    expressions with a separator between, 
- *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
- *    to "Jan 11, 2007 10:10am" is 
- *    "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 
- *
- *    2) otherwise, present the date followed by the range expression 
- *    for the time.
- *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
- *    to "Jan 10, 2007 11:10am" is 
- *    "Jan 10, 2007 10:10 am - 11:10am" 
- *
- * 2. even a pattern does not request a certion calendar field,
- *    the interval pattern needs to include such field if such fields are
- *    different between 2 dates.
- *    For example, a pattern/skeleton is "hm", but the interval pattern 
- *    includes year, month, and date when year, month, and date differs.
- * 
- * @param status          output param set to success/failure code on exit
- * @stable ICU 4.0 
- */
-void 
-DateIntervalFormat::initializePattern(UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    const Locale& locale = fDateFormat->getSmpFmtLocale();
-    if ( fSkeleton.isEmpty() ) {
-        UnicodeString fullPattern;
-        fDateFormat->toPattern(fullPattern);
-#ifdef DTITVFMT_DEBUG
-    char result[1000];
-    char result_1[1000];
-    char mesg[2000];
-    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
-    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
-    PRINTMESG(mesg)
-#endif
-        // fSkeleton is already set by createDateIntervalInstance()
-        // or by createInstance(UnicodeString skeleton, .... )
-        fSkeleton = fDtpng->getSkeleton(fullPattern, status);
-        if ( U_FAILURE(status) ) {
-            return;    
-        }
-    }
-
-    // initialize the fIntervalPattern ordering
-    int8_t i;
-    for ( i = 0; i < DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
-        fIntervalPatterns[i].laterDateFirst = fInfo->getDefaultOrder();
-    }
-
-    /* Check whether the skeleton is a combination of date and time.
-     * For the complication reason 1 explained above.
-     */
-    UnicodeString dateSkeleton;
-    UnicodeString timeSkeleton;
-    UnicodeString normalizedTimeSkeleton;
-    UnicodeString normalizedDateSkeleton;
-
-
-    /* the difference between time skeleton and normalizedTimeSkeleton are:
-     * 1. both 'H' and 'h' are normalized as 'h' in normalized time skeleton,
-     * 2. 'a' is omitted in normalized time skeleton.
-     * 3. there is only one appearance for 'h', 'm','v', 'z' in normalized 
-     *    time skeleton
-     *
-     * The difference between date skeleton and normalizedDateSkeleton are:
-     * 1. both 'y' and 'd' appear only once in normalizeDateSkeleton
-     * 2. 'E' and 'EE' are normalized into 'EEE'
-     * 3. 'MM' is normalized into 'M'
-     */
-    getDateTimeSkeleton(fSkeleton, dateSkeleton, normalizedDateSkeleton,
-                        timeSkeleton, normalizedTimeSkeleton);
-
-#ifdef DTITVFMT_DEBUG
-    char result[1000];
-    char result_1[1000];
-    char mesg[2000];
-    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
-    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
-    PRINTMESG(mesg)
-#endif
-
-
-    UBool found = setSeparateDateTimePtn(normalizedDateSkeleton, 
-                                         normalizedTimeSkeleton);
-
-    if ( found == false ) {
-        // use fallback
-        // TODO: if user asks "m"(minute), but "d"(day) differ
-        if ( timeSkeleton.length() != 0 ) {
-            if ( dateSkeleton.length() == 0 ) {
-                // prefix with yMd
-                timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort]);
-                UnicodeString pattern = fDtpng->getBestPattern(timeSkeleton, status);
-                if ( U_FAILURE(status) ) {
-                    return;    
-                }
-                // for fall back interval patterns,
-                // the first part of the pattern is empty,
-                // the second part of the pattern is the full-pattern
-                // should be used in fall-back.
-                setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); 
-                setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); 
-                setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); 
-            } else {
-                // TODO: fall back
-            }
-        } else {
-            // TODO: fall back
-        }
-        return;
-    } // end of skeleton not found
-    // interval patterns for skeleton are found in resource 
-    if ( timeSkeleton.length() == 0 ) {
-        // done
-    } else if ( dateSkeleton.length() == 0 ) {
-        // prefix with yMd
-        timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort]);
-        UnicodeString pattern = fDtpng->getBestPattern(timeSkeleton, status);
-        if ( U_FAILURE(status) ) {
-            return;    
-        }
-        // for fall back interval patterns,
-        // the first part of the pattern is empty,
-        // the second part of the pattern is the full-pattern
-        // should be used in fall-back.
-        setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); 
-        setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); 
-        setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); 
-    } else {
-        /* if both present,
-         * 1) when the year, month, or day differs, 
-         * concatenate the two original expressions with a separator between, 
-         * 2) otherwise, present the date followed by the 
-         * range expression for the time. 
-         */
-        /*
-         * 1) when the year, month, or day differs, 
-         * concatenate the two original expressions with a separator between, 
-         */
-        // if field exists, use fall back
-        UnicodeString skeleton = fSkeleton;
-        if ( !fieldExistsInSkeleton(UCAL_DATE, dateSkeleton) ) {
-            // prefix skeleton with 'd'
-            skeleton.insert(0, LOW_D);
-            setFallbackPattern(UCAL_DATE, skeleton, status);
-        }
-        if ( !fieldExistsInSkeleton(UCAL_MONTH, dateSkeleton) ) {
-            // then prefix skeleton with 'M'
-            skeleton.insert(0, CAP_M);
-            setFallbackPattern(UCAL_MONTH, skeleton, status);
-        }
-        if ( !fieldExistsInSkeleton(UCAL_YEAR, dateSkeleton) ) {
-            // then prefix skeleton with 'y'
-            skeleton.insert(0, LOW_Y);
-            setFallbackPattern(UCAL_YEAR, skeleton, status);
-        }
-        
-        /*
-         * 2) otherwise, present the date followed by the 
-         * range expression for the time. 
-         */
-        // Need the Date/Time pattern for concatnation the date with
-        // the time interval.
-        // The date/time pattern ( such as {0} {1} ) is saved in
-        // calendar, that is why need to get the CalendarData here.
-        CalendarData* calData = new CalendarData(locale, NULL, status);
-
-        if ( U_FAILURE(status) ) {
-            delete calData;
-            return;
-        }
-
-        if ( calData == NULL ) {
-            status = U_MEMORY_ALLOCATION_ERROR;
-            return;
-        }
-       
-        const UResourceBundle* dateTimePatternsRes = calData->getByKey(
-                                           gDateTimePatternsTag, status);
-        int32_t dateTimeFormatLength;
-        const UChar* dateTimeFormat = ures_getStringByIndex(
-                                            dateTimePatternsRes,
-                                            (int32_t)DateFormat::kDateTime,
-                                            &dateTimeFormatLength, &status);
-        if ( U_FAILURE(status) ) {
-            return;
-        }
-
-        UnicodeString datePattern = fDtpng->getBestPattern(dateSkeleton, status);
-
-        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
-                                      datePattern, UCAL_AM_PM, status);
-        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
-                                      datePattern, UCAL_HOUR, status);
-        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
-                                      datePattern, UCAL_MINUTE, status);
-        delete calData;
-    }
-}
-
-
-
-void  U_EXPORT2 
-DateIntervalFormat::getDateTimeSkeleton(const UnicodeString& skeleton, 
-                                        UnicodeString& dateSkeleton, 
-                                        UnicodeString& normalizedDateSkeleton, 
-                                        UnicodeString& timeSkeleton,
-                                        UnicodeString& normalizedTimeSkeleton) {
-    // dateSkeleton follows the sequence of y*M*E*d*
-    // timeSkeleton follows the sequence of hm*[v|z]?
-    int32_t ECount = 0;
-    int32_t dCount = 0;
-    int32_t MCount = 0;
-    int32_t yCount = 0;
-    int32_t hCount = 0;
-    int32_t mCount = 0;
-    int32_t vCount = 0;
-    int32_t zCount = 0;
-    int32_t i;
-
-    for (i = 0; i < skeleton.length(); ++i) {
-        UChar ch = skeleton[i];
-        switch ( ch ) {
-          case CAP_E:
-            dateSkeleton.append(ch);
-            ++ECount;
-            break;
-          case LOW_D:
-            dateSkeleton.append(ch);
-            ++dCount;
-            break;
-          case CAP_M:
-            dateSkeleton.append(ch);
-            ++MCount;
-            break;
-          case LOW_Y:
-            dateSkeleton.append(ch);
-            ++yCount;
-            break;
-          case CAP_G:
-          case CAP_Y:
-          case LOW_U:
-          case CAP_Q:
-          case LOW_Q:
-          case CAP_L:
-          case LOW_L:
-          case CAP_W:
-          case LOW_W:
-          case CAP_D:
-          case CAP_F:
-          case LOW_G:
-          case LOW_E:
-          case LOW_C:
-            normalizedDateSkeleton.append(ch);
-            dateSkeleton.append(ch);
-            break;
-          case LOW_A:
-            // 'a' is implicitly handled 
-            timeSkeleton.append(ch);
-            break;
-          case LOW_H:
-          case CAP_H:
-            timeSkeleton.append(ch);
-            ++hCount;
-            break;
-          case LOW_M:
-            timeSkeleton.append(ch);
-            ++mCount;
-            break;
-          case LOW_Z:
-            ++zCount;
-            timeSkeleton.append(ch);
-            break;
-          case LOW_V:
-            ++vCount;
-            timeSkeleton.append(ch);
-            break;
-          case CAP_V:
-          case CAP_Z:
-          case LOW_K:
-          case CAP_K:
-          case LOW_J:
-          case LOW_S:
-          case CAP_S:
-          case CAP_A:
-            timeSkeleton.append(ch);
-            normalizedTimeSkeleton.append(ch);
-            break;     
-        }
-    }
-
-    /* generate normalized form for date*/
-    if ( yCount != 0 ) {
-        normalizedDateSkeleton.append(LOW_Y);
-    }
-    if ( MCount != 0 ) {
-        if ( MCount < 3 ) {
-            normalizedDateSkeleton.append(CAP_M);
-        } else {
-            int32_t i;
-            for ( i = 0; i < MCount && i < MAX_M_COUNT; ++i ) {
-                 normalizedDateSkeleton.append(CAP_M);
-            }
-        }
-    }
-    if ( ECount != 0 ) {
-        if ( ECount <= 3 ) {
-            normalizedDateSkeleton.append(CAP_E);
-        } else {
-            int32_t i;
-            for ( i = 0; i < ECount && i < MAX_E_COUNT; ++i ) {
-                 normalizedDateSkeleton.append(CAP_E);
-            }
-        }
-    }
-    if ( dCount != 0 ) {
-        normalizedDateSkeleton.append(LOW_D);
-    }
-
-    /* generate normalized form for time */
-    if ( hCount != 0 ) {
-        normalizedTimeSkeleton.append(LOW_H);
-    }
-    if ( mCount != 0 ) {
-        normalizedTimeSkeleton.append(LOW_M);
-    }
-    if ( zCount != 0 ) {
-        normalizedTimeSkeleton.append(LOW_Z);
-    }
-    if ( vCount != 0 ) {
-        normalizedTimeSkeleton.append(LOW_V);
-    }
-}
-
-
-/**
- * Generate date or time interval pattern from resource,
- * and set them into the interval pattern locale to this formatter.
- *
- * It needs to handle the following: 
- * 1. need to adjust field width.
- *    For example, the interval patterns saved in DateIntervalInfo
- *    includes "dMMMy", but not "dMMMMy".
- *    Need to get interval patterns for dMMMMy from dMMMy.
- *    Another example, the interval patterns saved in DateIntervalInfo
- *    includes "hmv", but not "hmz".
- *    Need to get interval patterns for "hmz' from 'hmv'
- *
- * 2. there might be no pattern for 'y' differ for skeleton "Md",
- *    in order to get interval patterns for 'y' differ,
- *    need to look for it from skeleton 'yMd'
- *
- * @param dateSkeleton   normalized date skeleton
- * @param timeSkeleton   normalized time skeleton
- * @return               whether the resource is found for the skeleton.
- *                       TRUE if interval pattern found for the skeleton,
- *                       FALSE otherwise.
- * @stable ICU 4.0
- */
-UBool 
-DateIntervalFormat::setSeparateDateTimePtn(
-                                 const UnicodeString& dateSkeleton,
-                                 const UnicodeString& timeSkeleton) {
-    const UnicodeString* skeleton;
-    // if both date and time skeleton present,
-    // the final interval pattern might include time interval patterns
-    // ( when, am_pm, hour, minute differ ),
-    // but not date interval patterns ( when year, month, day differ ).
-    // For year/month/day differ, it falls back to fall-back pattern.
-    if ( timeSkeleton.length() != 0  ) {
-        skeleton = &timeSkeleton;
-    } else {
-        skeleton = &dateSkeleton;
-    }
-
-    /* interval patterns for skeleton "dMMMy" (but not "dMMMMy") 
-     * are defined in resource,
-     * interval patterns for skeleton "dMMMMy" are calculated by
-     * 1. get the best match skeleton for "dMMMMy", which is "dMMMy"
-     * 2. get the interval patterns for "dMMMy",
-     * 3. extend "MMM" to "MMMM" in above interval patterns for "dMMMMy" 
-     * getBestSkeleton() is step 1.
-     */
-    // best skeleton, and the difference information
-    int8_t differenceInfo = 0;
-    const UnicodeString* bestSkeleton = fInfo->getBestSkeleton(*skeleton, 
-                                                               differenceInfo);
-    /* best skeleton could be NULL.
-       For example: in "ca" resource file,
-       interval format is defined as following
-           intervalFormats{
-                fallback{"{0} - {1}"}
-            }
-       there is no skeletons/interval patterns defined,
-       and the best skeleton match could be NULL
-     */
-    if ( bestSkeleton == NULL ) {
-        return false; 
-    } 
-   
-    // difference:
-    // 0 means the best matched skeleton is the same as input skeleton
-    // 1 means the fields are the same, but field width are different
-    // 2 means the only difference between fields are v/z,
-    // -1 means there are other fields difference 
-    if ( differenceInfo == -1 ) { 
-        // skeleton has different fields, not only  v/z difference
-        return false;
-    }
-
-    if ( timeSkeleton.length() == 0 ) {
-        UnicodeString extendedSkeleton;
-        UnicodeString extendedBestSkeleton;
-        // only has date skeleton
-        setIntervalPattern(UCAL_DATE, skeleton, bestSkeleton, differenceInfo,
-                           &extendedSkeleton, &extendedBestSkeleton);
-
-        UBool extended = setIntervalPattern(UCAL_MONTH, skeleton, bestSkeleton, 
-                                     differenceInfo,
-                                     &extendedSkeleton, &extendedBestSkeleton);
-                                              
-        if ( extended ) {
-            bestSkeleton = &extendedBestSkeleton;
-            skeleton = &extendedSkeleton;
-        }
-        setIntervalPattern(UCAL_YEAR, skeleton, bestSkeleton, differenceInfo,
-                           &extendedSkeleton, &extendedBestSkeleton);
-    } else {
-        setIntervalPattern(UCAL_MINUTE, skeleton, bestSkeleton, differenceInfo);
-        setIntervalPattern(UCAL_HOUR, skeleton, bestSkeleton, differenceInfo);
-        setIntervalPattern(UCAL_AM_PM, skeleton, bestSkeleton, differenceInfo);
-    }
-    return true;
-}
-
-
-
-void
-DateIntervalFormat::setFallbackPattern(UCalendarDateFields field,
-                                       const UnicodeString& skeleton,
-                                       UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    UnicodeString pattern = fDtpng->getBestPattern(skeleton, status);
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    setPatternInfo(field, NULL, &pattern, fInfo->getDefaultOrder());
-}
-
-
-
-
-void
-DateIntervalFormat::setPatternInfo(UCalendarDateFields field, 
-                                   const UnicodeString* firstPart,
-                                   const UnicodeString* secondPart, 
-                                   UBool laterDateFirst) {
-    // for fall back interval patterns,
-    // the first part of the pattern is empty,
-    // the second part of the pattern is the full-pattern
-    // should be used in fall-back.
-    UErrorCode status = U_ZERO_ERROR;
-    // following should not set any wrong status.
-    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
-                                                                        status);
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    PatternInfo& ptn = fIntervalPatterns[itvPtnIndex];
-    if ( firstPart ) {
-        ptn.firstPart = *firstPart;
-    }
-    if ( secondPart ) {
-        ptn.secondPart = *secondPart;
-    }
-    ptn.laterDateFirst = laterDateFirst;
-}
-
-void
-DateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
-                                       const UnicodeString& intervalPattern) {
-    UBool order = fInfo->getDefaultOrder();
-    setIntervalPattern(field, intervalPattern, order);
-}
-
-
-void
-DateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
-                                       const UnicodeString& intervalPattern,
-                                       UBool laterDateFirst) {
-    const UnicodeString* pattern = &intervalPattern;
-    UBool order = laterDateFirst;
-    // check for "latestFirst:" or "earliestFirst:" prefix
-    int8_t prefixLength = sizeof(gLaterFirstPrefix)/sizeof(gLaterFirstPrefix[0]);
-    int8_t earliestFirstLength = sizeof(gEarlierFirstPrefix)/sizeof(gEarlierFirstPrefix[0]);
-    UnicodeString realPattern;
-    if ( intervalPattern.startsWith(gLaterFirstPrefix, prefixLength) ) {
-        order = true;
-        intervalPattern.extract(prefixLength, 
-                                intervalPattern.length() - prefixLength,
-                                realPattern);
-        pattern = &realPattern;
-    } else if ( intervalPattern.startsWith(gEarlierFirstPrefix,
-                                           earliestFirstLength) ) {
-        order = false;
-        intervalPattern.extract(earliestFirstLength,
-                                intervalPattern.length() - earliestFirstLength,
-                                realPattern);
-        pattern = &realPattern;
-    }
-
-    int32_t splitPoint = splitPatternInto2Part(*pattern);
-    
-    UnicodeString firstPart;
-    UnicodeString secondPart;
-    pattern->extract(0, splitPoint, firstPart);
-    if ( splitPoint < pattern->length() ) {
-        pattern->extract(splitPoint, pattern->length()-splitPoint, secondPart);
-    }
-    setPatternInfo(field, &firstPart, &secondPart, order);
-}
-
-
-
-
-/**
- * Generate interval pattern from existing resource
- *
- * It not only save the interval patterns,
- * but also return the extended skeleton and its best match skeleton.
- *
- * @param field           largest different calendar field
- * @param skeleton        skeleton
- * @param bestSkeleton    the best match skeleton which has interval pattern
- *                        defined in resource
- * @param differenceInfo  the difference between skeleton and best skeleton
- *         0 means the best matched skeleton is the same as input skeleton
- *         1 means the fields are the same, but field width are different
- *         2 means the only difference between fields are v/z,
- *        -1 means there are other fields difference 
- *
- * @param extendedSkeleton      extended skeleton
- * @param extendedBestSkeleton  extended best match skeleton
- * @return                      whether the interval pattern is found 
- *                              through extending skeleton or not.
- *                              TRUE if interval pattern is found by
- *                              extending skeleton, FALSE otherwise.
- * @stable ICU 4.0
- */
-UBool
-DateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
-                                       const UnicodeString* skeleton,
-                                       const UnicodeString* bestSkeleton,
-                                       int8_t differenceInfo,
-                                       UnicodeString* extendedSkeleton,
-                                       UnicodeString* extendedBestSkeleton) {
-    UErrorCode status = U_ZERO_ERROR;
-    // following getIntervalPattern() should not generate error status
-    UnicodeString pattern;
-    fInfo->getIntervalPattern(*bestSkeleton, field, pattern, status);
-    if ( pattern.isEmpty() ) {
-        // single date
-        if ( SimpleDateFormat::isFieldUnitIgnored(*bestSkeleton, field) ) {
-            // do nothing, format will handle it
-            return false;
-        }
-
-        // for 24 hour system, interval patterns in resource file
-        // might not include pattern when am_pm differ, 
-        // which should be the same as hour differ.
-        // add it here for simplicity
-        if ( field == UCAL_AM_PM ) {
-            fInfo->getIntervalPattern(*bestSkeleton, UCAL_HOUR, pattern,status);
-            if ( !pattern.isEmpty() ) {
-                setIntervalPattern(field, pattern);
-            }
-            return false;
-        } 
-        // else, looking for pattern when 'y' differ for 'dMMMM' skeleton,
-        // first, get best match pattern "MMMd",
-        // since there is no pattern for 'y' differs for skeleton 'MMMd',
-        // need to look for it from skeleton 'yMMMd',
-        // if found, adjust field width in interval pattern from
-        // "MMM" to "MMMM".
-        UChar fieldLetter = fgCalendarFieldToPatternLetter[field];
-        if ( extendedSkeleton ) {
-            *extendedSkeleton = *skeleton;
-            *extendedBestSkeleton = *bestSkeleton;
-            extendedSkeleton->insert(0, fieldLetter);
-            extendedBestSkeleton->insert(0, fieldLetter);
-            // for example, looking for patterns when 'y' differ for
-            // skeleton "MMMM". 
-            fInfo->getIntervalPattern(*extendedBestSkeleton,field,pattern,status);
-            if ( pattern.isEmpty() && differenceInfo == 0 ) {
-                // if there is no skeleton "yMMMM" defined,
-                // look for the best match skeleton, for example: "yMMM" 
-                const UnicodeString* tmpBest = fInfo->getBestSkeleton(
-                                        *extendedBestSkeleton, differenceInfo);
-                if ( tmpBest != 0 && differenceInfo != -1 ) {
-                    fInfo->getIntervalPattern(*tmpBest, field, pattern, status);
-                    bestSkeleton = tmpBest;
-                }
-            }
-        }
-    } 
-    if ( !pattern.isEmpty() ) {
-        if ( differenceInfo != 0 ) {
-            UnicodeString adjustIntervalPattern;
-            adjustFieldWidth(*skeleton, *bestSkeleton, pattern, differenceInfo,
-                              adjustIntervalPattern);
-            setIntervalPattern(field, adjustIntervalPattern);
-        } else {
-            setIntervalPattern(field, pattern);
-        }
-        if ( extendedSkeleton && !extendedSkeleton->isEmpty() ) {
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-
-
-int32_t  U_EXPORT2 
-DateIntervalFormat::splitPatternInto2Part(const UnicodeString& intervalPattern) {
-    UBool inQuote = false;
-    UChar prevCh = 0;
-    int32_t count = 0;
-
-    /* repeatedPattern used to record whether a pattern has already seen.
-       It is a pattern applies to first calendar if it is first time seen,
-       otherwise, it is a pattern applies to the second calendar
-     */
-    UBool patternRepeated[] = 
-    {
-    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
-             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   P   Q   R   S   T   U   V   W   X   Y   Z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
-    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   p   q   r   s   t   u   v   w   x   y   z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
-    };
-
-    int8_t PATTERN_CHAR_BASE = 0x41;
-    
-    /* loop through the pattern string character by character looking for
-     * the first repeated pattern letter, which breaks the interval pattern
-     * into 2 parts. 
-     */
-    int32_t i;
-    UBool foundRepetition = false;
-    for (i = 0; i < intervalPattern.length(); ++i) {
-        UChar ch = intervalPattern.charAt(i);
-        
-        if (ch != prevCh && count > 0) {
-            // check the repeativeness of pattern letter
-            UBool repeated = patternRepeated[(int)(prevCh - PATTERN_CHAR_BASE)];
-            if ( repeated == FALSE ) {
-                patternRepeated[prevCh - PATTERN_CHAR_BASE] = TRUE;
-            } else {
-                foundRepetition = true;
-                break;
-            }
-            count = 0;
-        }
-        if (ch == '\'') {
-            // Consecutive single quotes are a single quote literal,
-            // either outside of quotes or between quotes
-            if ((i+1) < intervalPattern.length() && 
-                intervalPattern.charAt(i+1) == '\'') {
-                ++i;
-            } else {
-                inQuote = ! inQuote;
-            }
-        } 
-        else if (!inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
-                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
-            // ch is a date-time pattern character 
-            prevCh = ch;
-            ++count;
-        }
-    }
-    // check last pattern char, distinguish
-    // "dd MM" ( no repetition ), 
-    // "d-d"(last char repeated ), and 
-    // "d-d MM" ( repetition found )
-    if ( count > 0 && foundRepetition == FALSE ) {
-        if ( patternRepeated[(int)(prevCh - PATTERN_CHAR_BASE)] == FALSE ) {
-            count = 0;
-        }
-    }
-    return (i - count);
-}
-
-
-
-UnicodeString& 
-DateIntervalFormat::fallbackFormat(Calendar& fromCalendar,
-                                   Calendar& toCalendar,
-                                   UnicodeString& appendTo,
-                                   FieldPosition& pos,
-                                   UErrorCode& status) const {
-    if ( U_FAILURE(status) ) {
-        return appendTo;
-    }
-    // the fall back
-    // no need delete earlierDate and laterDate since they are adopted
-    UnicodeString* earlierDate = new UnicodeString();
-    *earlierDate = fDateFormat->format(fromCalendar, *earlierDate, pos);
-    UnicodeString* laterDate = new UnicodeString();
-    *laterDate = fDateFormat->format(toCalendar, *laterDate, pos);
-    UnicodeString fallbackPattern;
-    fInfo->getFallbackIntervalPattern(fallbackPattern);
-    Formattable fmtArray[2];
-    fmtArray[0].adoptString(earlierDate);
-    fmtArray[1].adoptString(laterDate);
-    
-    UnicodeString fallback;
-    MessageFormat::format(fallbackPattern, fmtArray, 2, fallback, status);
-    if ( U_SUCCESS(status) ) {
-        appendTo.append(fallback);
-    }
-    return appendTo;
-}
-
-
-
-
-UBool  U_EXPORT2 
-DateIntervalFormat::fieldExistsInSkeleton(UCalendarDateFields field,
-                                          const UnicodeString& skeleton)
-{
-    const UChar fieldChar = fgCalendarFieldToPatternLetter[field];
-    return ( (skeleton.indexOf(fieldChar) == -1)?FALSE:TRUE ) ;
-}
-
-
-
-void  U_EXPORT2 
-DateIntervalFormat::adjustFieldWidth(const UnicodeString& inputSkeleton,
-                 const UnicodeString& bestMatchSkeleton,
-                 const UnicodeString& bestIntervalPattern,
-                 int8_t differenceInfo,
-                 UnicodeString& adjustedPtn) {
-    adjustedPtn = bestIntervalPattern;
-    int32_t inputSkeletonFieldWidth[] = 
-    {
-    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
-             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   P   Q   R   S   T   U   V   W   X   Y   Z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
-    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   p   q   r   s   t   u   v   w   x   y   z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
-    };
-
-    int32_t bestMatchSkeletonFieldWidth[] = 
-    {
-    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
-             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   P   Q   R   S   T   U   V   W   X   Y   Z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
-    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   p   q   r   s   t   u   v   w   x   y   z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
-    };
-
-    DateIntervalInfo::parseSkeleton(inputSkeleton, inputSkeletonFieldWidth);
-    DateIntervalInfo::parseSkeleton(bestMatchSkeleton, bestMatchSkeletonFieldWidth);
-    if ( differenceInfo == 2 ) {
-        adjustedPtn.findAndReplace("v", "z");
-    }
-
-    UBool inQuote = false;
-    UChar prevCh = 0;
-    int32_t count = 0;
-
-    const int8_t PATTERN_CHAR_BASE = 0x41;
-    
-    // loop through the pattern string character by character 
-    int32_t adjustedPtnLength = adjustedPtn.length();
-    int32_t i;
-    for (i = 0; i < adjustedPtnLength; ++i) {
-        UChar ch = adjustedPtn.charAt(i);
-        if (ch != prevCh && count > 0) {
-            // check the repeativeness of pattern letter
-            UChar skeletonChar = prevCh;
-            if ( skeletonChar ==  CAP_L ) {
-                // there is no "L" (always be "M") in skeleton, 
-                // but there is "L" in pattern.
-                // for skeleton "M+", the pattern might be "...L..." 
-                skeletonChar = CAP_M;
-            }
-            int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
-            int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
-            if ( fieldCount == count && inputFieldCount > fieldCount ) {
-                count = inputFieldCount - fieldCount;
-                int32_t j;
-                for ( j = 0; j < count; ++j ) {
-                    adjustedPtn.insert(i, prevCh);    
-                }                    
-                i += count;
-                adjustedPtnLength += count;
-            }
-            count = 0;
-        }
-        if (ch == '\'') {
-            // Consecutive single quotes are a single quote literal,
-            // either outside of quotes or between quotes
-            if ((i+1) < adjustedPtn.length() && adjustedPtn.charAt(i+1) == '\'') {
-                ++i;
-            } else {
-                inQuote = ! inQuote;
-            }
-        } 
-        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/) 
-                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
-            // ch is a date-time pattern character 
-            prevCh = ch;
-            ++count;
-        }
-    }
-    if ( count > 0 ) {
-        // last item
-        // check the repeativeness of pattern letter
-        UChar skeletonChar = prevCh;
-        if ( skeletonChar == CAP_L ) {
-            // there is no "L" (always be "M") in skeleton, 
-            // but there is "L" in pattern.
-            // for skeleton "M+", the pattern might be "...L..." 
-            skeletonChar = CAP_M;
-        }
-        int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
-        int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
-        if ( fieldCount == count && inputFieldCount > fieldCount ) {
-            count = inputFieldCount - fieldCount;
-            int32_t j;
-            for ( j = 0; j < count; ++j ) {
-                adjustedPtn.append(prevCh);    
-            }                    
-        }
-    }
-}
-
-
-
-void 
-DateIntervalFormat::concatSingleDate2TimeInterval(const UChar* format,
-                                              int32_t formatLen,
-                                              const UnicodeString& datePattern,
-                                              UCalendarDateFields field,
-                                              UErrorCode& status) {
-    // following should not set wrong status
-    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
-                                                                        status);
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    PatternInfo&  timeItvPtnInfo = fIntervalPatterns[itvPtnIndex];
-    if ( !timeItvPtnInfo.firstPart.isEmpty() ) {
-        // UnicodeString allocated here is adopted, so no need to delete
-        UnicodeString* timeIntervalPattern = new UnicodeString(timeItvPtnInfo.firstPart);
-        timeIntervalPattern->append(timeItvPtnInfo.secondPart);
-        UnicodeString* dateStr = new UnicodeString(datePattern);
-        Formattable fmtArray[2];
-        fmtArray[0].adoptString(timeIntervalPattern);
-        fmtArray[1].adoptString(dateStr);
-        UnicodeString combinedPattern;
-        MessageFormat::format(UnicodeString(TRUE, format, formatLen),
-                              fmtArray, 2, combinedPattern, status);
-        if ( U_FAILURE(status) ) {
-            return;
-        }
-        setIntervalPattern(field, combinedPattern, timeItvPtnInfo.laterDateFirst);
-    } 
-    // else: fall back
-    // it should not happen if the interval format defined is valid
-}
-
-
-
-const UChar
-DateIntervalFormat::fgCalendarFieldToPatternLetter[] =
-{
-    /*GyM*/ CAP_G, LOW_Y, CAP_M,
-    /*wWd*/ LOW_W, CAP_W, LOW_D,
-    /*DEF*/ CAP_D, CAP_E, CAP_F,
-    /*ahH*/ LOW_A, LOW_H, CAP_H,
-    /*m..*/ LOW_M,
-};
-
-
-U_NAMESPACE_END
-
-#endif
+/*******************************************************************************
+* Copyright (C) 2008-2009, International Business Machines Corporation and
+* others. All Rights Reserved.
+*******************************************************************************
+*
+* File DTITVFMT.CPP 
+*
+*******************************************************************************
+*/
+
+#include "unicode/dtitvfmt.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+//TODO: put in compilation
+//#define DTITVFMT_DEBUG 1
+
+#include "cstring.h"
+#include "unicode/msgfmt.h"
+#include "unicode/dtptngen.h"
+#include "unicode/dtitvinf.h"
+#include "unicode/calendar.h"
+#include "dtitv_impl.h"
+
+#ifdef DTITVFMT_DEBUG 
+#include <iostream>
+#include "cstring.h"
+#endif
+
+#include "gregoimp.h"
+
+U_NAMESPACE_BEGIN
+
+
+
+#ifdef DTITVFMT_DEBUG 
+#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
+#endif
+
+
+static const UChar gDateFormatSkeleton[][11] = {
+//yMMMMEEEEd
+{LOW_Y, CAP_M, CAP_M, CAP_M, CAP_M, CAP_E, CAP_E, CAP_E, CAP_E, LOW_D, 0},
+//yMMMMd
+{LOW_Y, CAP_M, CAP_M, CAP_M, CAP_M, LOW_D, 0},
+//yMMMd
+{LOW_Y, CAP_M, CAP_M, CAP_M, LOW_D, 0},
+//yMd
+{LOW_Y, CAP_M, LOW_D, 0} };
+
+
+static const char gDateTimePatternsTag[]="DateTimePatterns";
+
+
+// latestFirst:
+static const UChar gLaterFirstPrefix[] = {LOW_L, LOW_A, LOW_T, LOW_E, LOW_S,LOW_T, CAP_F, LOW_I, LOW_R, LOW_S, LOW_T, COLON};
+
+// earliestFirst:
+static const UChar gEarlierFirstPrefix[] = {LOW_E, LOW_A, LOW_R, LOW_L, LOW_I, LOW_E, LOW_S, LOW_T, CAP_F, LOW_I, LOW_R, LOW_S, LOW_T, COLON};
+
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalFormat)
+
+
+
+DateIntervalFormat* U_EXPORT2
+DateIntervalFormat::createInstance(const UnicodeString& skeleton, 
+                                   UErrorCode& status) {
+    return createInstance(skeleton, Locale::getDefault(), status);
+}
+
+
+DateIntervalFormat* U_EXPORT2
+DateIntervalFormat::createInstance(const UnicodeString& skeleton, 
+                                   const Locale& locale, 
+                                   UErrorCode& status) {
+#ifdef DTITVFMT_DEBUG
+    char result[1000];
+    char result_1[1000];
+    char mesg[2000];
+    skeleton.extract(0,  skeleton.length(), result, "UTF-8");
+    UnicodeString pat;
+    ((SimpleDateFormat*)dtfmt)->toPattern(pat);
+    pat.extract(0,  pat.length(), result_1, "UTF-8");
+    sprintf(mesg, "skeleton: %s; pattern: %s\n", result, result_1);
+    PRINTMESG(mesg)
+#endif
+
+    DateIntervalInfo* dtitvinf = new DateIntervalInfo(locale, status);
+    return create(locale, dtitvinf, &skeleton, status);
+}
+
+
+
+DateIntervalFormat* U_EXPORT2
+DateIntervalFormat::createInstance(const UnicodeString& skeleton,
+                                   const DateIntervalInfo& dtitvinf,
+                                   UErrorCode& status) {
+    return createInstance(skeleton, Locale::getDefault(), dtitvinf, status);
+}
+
+
+DateIntervalFormat* U_EXPORT2
+DateIntervalFormat::createInstance(const UnicodeString& skeleton,
+                                   const Locale& locale,
+                                   const DateIntervalInfo& dtitvinf,
+                                   UErrorCode& status) {
+    DateIntervalInfo* ptn = dtitvinf.clone();
+    return create(locale, ptn, &skeleton, status);
+}
+
+
+DateIntervalFormat::DateIntervalFormat()
+:   fInfo(NULL),
+    fDateFormat(NULL),
+    fFromCalendar(NULL),
+    fToCalendar(NULL),
+    fDtpng(NULL)
+{}
+
+
+DateIntervalFormat::DateIntervalFormat(const DateIntervalFormat& itvfmt)
+:   Format(itvfmt),
+    fInfo(NULL),
+    fDateFormat(NULL),
+    fFromCalendar(NULL),
+    fToCalendar(NULL),
+    fDtpng(NULL) {
+    *this = itvfmt;
+}
+
+
+DateIntervalFormat&
+DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) {
+    if ( this != &itvfmt ) {
+        delete fDateFormat;
+        delete fInfo;
+        delete fFromCalendar;
+        delete fToCalendar;
+        delete fDtpng;
+        if ( itvfmt.fDateFormat ) {
+            fDateFormat = (SimpleDateFormat*)itvfmt.fDateFormat->clone();
+        } else {
+            fDateFormat = NULL;
+        }
+        if ( itvfmt.fInfo ) {
+            fInfo = itvfmt.fInfo->clone();
+        } else {
+            fInfo = NULL;
+        }
+        if ( itvfmt.fFromCalendar ) {
+            fFromCalendar = itvfmt.fFromCalendar->clone();
+        } else {
+            fFromCalendar = NULL;
+        }
+        if ( itvfmt.fToCalendar ) {
+            fToCalendar = itvfmt.fToCalendar->clone();
+        } else {
+            fToCalendar = NULL;
+        }
+        fSkeleton = itvfmt.fSkeleton;
+        int8_t i;
+        for ( i = 0; i< DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
+            fIntervalPatterns[i] = itvfmt.fIntervalPatterns[i];
+        }
+        if (itvfmt.fDtpng) {
+            fDtpng = itvfmt.fDtpng->clone();
+        }
+    }
+    return *this;
+}
+
+
+DateIntervalFormat::~DateIntervalFormat() {
+    delete fInfo;
+    delete fDateFormat;
+    delete fFromCalendar;
+    delete fToCalendar;
+    delete fDtpng;
+}
+
+
+Format*
+DateIntervalFormat::clone(void) const {
+    return new DateIntervalFormat(*this);
+}
+
+
+UBool
+DateIntervalFormat::operator==(const Format& other) const {
+    if ( other.getDynamicClassID() == DateIntervalFormat::getStaticClassID() ) {
+        DateIntervalFormat* fmt = (DateIntervalFormat*)&other;
+#ifdef DTITVFMT_DEBUG
+    UBool equal;
+    equal = (this == fmt);
+    
+    equal = (*fInfo == *fmt->fInfo);
+    equal = (*fDateFormat == *fmt->fDateFormat);
+    equal = fFromCalendar->isEquivalentTo(*fmt->fFromCalendar) ;
+    equal = fToCalendar->isEquivalentTo(*fmt->fToCalendar) ;
+    equal = (fSkeleton == fmt->fSkeleton);
+#endif
+        UBool res;
+        res =  ( this == fmt ) ||
+               ( Format::operator==(other) && 
+                 fInfo && 
+                 ( *fInfo == *fmt->fInfo ) &&
+                 fDateFormat &&
+                 ( *fDateFormat == *fmt->fDateFormat ) &&
+                 fFromCalendar &&
+                 fFromCalendar->isEquivalentTo(*fmt->fFromCalendar) &&
+                 fToCalendar &&
+                 fToCalendar->isEquivalentTo(*fmt->fToCalendar) &&
+                 fSkeleton == fmt->fSkeleton &&
+                 fDtpng &&
+                 (*fDtpng == *fmt->fDtpng) );
+        int8_t i;
+        for (i = 0; i< DateIntervalInfo::kIPI_MAX_INDEX && res == TRUE; ++i ) {
+            res =   ( fIntervalPatterns[i].firstPart ==
+                      fmt->fIntervalPatterns[i].firstPart) &&
+                    ( fIntervalPatterns[i].secondPart ==
+                      fmt->fIntervalPatterns[i].secondPart ) &&
+                    ( fIntervalPatterns[i].laterDateFirst ==
+                      fmt->fIntervalPatterns[i].laterDateFirst) ;
+        }
+        return res;
+    } 
+    return FALSE;
+}
+
+
+
+UnicodeString&
+DateIntervalFormat::format(const Formattable& obj,
+                           UnicodeString& appendTo,
+                           FieldPosition& fieldPosition,
+                           UErrorCode& status) const {
+    if ( U_FAILURE(status) ) {
+        return appendTo;
+    }
+
+    if ( obj.getType() == Formattable::kObject ) {
+        const UObject* formatObj = obj.getObject();
+        if (formatObj->getDynamicClassID() == DateInterval::getStaticClassID()){
+            return format((DateInterval*)formatObj, appendTo, fieldPosition, status);
+        }
+    }
+    status = U_ILLEGAL_ARGUMENT_ERROR;
+    return appendTo;
+}
+
+
+UnicodeString&
+DateIntervalFormat::format(const DateInterval* dtInterval,
+                           UnicodeString& appendTo,
+                           FieldPosition& fieldPosition,
+                           UErrorCode& status) const {
+    if ( U_FAILURE(status) ) {
+        return appendTo;
+    }
+
+    if ( fFromCalendar != NULL && fToCalendar != NULL && 
+         fDateFormat != NULL && fInfo != NULL ) {
+        fFromCalendar->setTime(dtInterval->getFromDate(), status);
+        fToCalendar->setTime(dtInterval->getToDate(), status);
+        if ( U_SUCCESS(status) ) {
+            return format(*fFromCalendar, *fToCalendar, appendTo,fieldPosition, status);
+        }
+    }
+    return appendTo;
+}
+
+
+UnicodeString&
+DateIntervalFormat::format(Calendar& fromCalendar,
+                           Calendar& toCalendar,
+                           UnicodeString& appendTo,
+                           FieldPosition& pos,
+                           UErrorCode& status) const {
+    if ( U_FAILURE(status) ) {
+        return appendTo;
+    }
+
+    // not support different calendar types and time zones
+    //if ( fromCalendar.getType() != toCalendar.getType() ) {
+    if ( !fromCalendar.isEquivalentTo(toCalendar) ||
+         uprv_strcmp(fromCalendar.getType(), "gregorian") ) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return appendTo;
+    }
+
+    // First, find the largest different calendar field.
+    UCalendarDateFields field = UCAL_FIELD_COUNT;
+
+    if ( fromCalendar.get(UCAL_ERA,status) != toCalendar.get(UCAL_ERA,status)) {
+        field = UCAL_ERA;
+    } else if ( fromCalendar.get(UCAL_YEAR, status) != 
+                toCalendar.get(UCAL_YEAR, status) ) {
+        field = UCAL_YEAR;
+    } else if ( fromCalendar.get(UCAL_MONTH, status) !=
+                toCalendar.get(UCAL_MONTH, status) ) {
+        field = UCAL_MONTH;
+    } else if ( fromCalendar.get(UCAL_DATE, status) !=
+                toCalendar.get(UCAL_DATE, status) ) {
+        field = UCAL_DATE;
+    } else if ( fromCalendar.get(UCAL_AM_PM, status) !=
+                toCalendar.get(UCAL_AM_PM, status) ) {
+        field = UCAL_AM_PM;
+    } else if ( fromCalendar.get(UCAL_HOUR, status) !=
+                toCalendar.get(UCAL_HOUR, status) ) {
+        field = UCAL_HOUR;
+    } else if ( fromCalendar.get(UCAL_MINUTE, status) !=
+                toCalendar.get(UCAL_MINUTE, status) ) {
+        field = UCAL_MINUTE;
+    }
+
+    if ( U_FAILURE(status) ) {
+        return appendTo;
+    }
+    if ( field == UCAL_FIELD_COUNT ) {
+        /* ignore the second/millisecond etc. small fields' difference.
+         * use single date when all the above are the same.
+         */
+        return fDateFormat->format(fromCalendar, appendTo, pos);
+    }
+    
+    // following call should not set wrong status,
+    // all the pass-in fields are valid till here
+    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
+                                                                        status);
+    const PatternInfo& intervalPattern = fIntervalPatterns[itvPtnIndex];
+
+    if ( intervalPattern.firstPart.isEmpty() &&
+         intervalPattern.secondPart.isEmpty() ) {
+        if ( fDateFormat->isFieldUnitIgnored(field) ) {
+            /* the largest different calendar field is small than
+             * the smallest calendar field in pattern,
+             * return single date format.
+             */
+            return fDateFormat->format(fromCalendar, appendTo, pos);
+        }
+        return fallbackFormat(fromCalendar, toCalendar, appendTo, pos, status);
+    }
+    // If the first part in interval pattern is empty, 
+    // the 2nd part of it saves the full-pattern used in fall-back.
+    // For a 'real' interval pattern, the first part will never be empty.
+    if ( intervalPattern.firstPart.isEmpty() ) {
+        // fall back
+        UnicodeString originalPattern;
+        fDateFormat->toPattern(originalPattern);
+        fDateFormat->applyPattern(intervalPattern.secondPart);
+        appendTo = fallbackFormat(fromCalendar, toCalendar, appendTo, pos, status);
+        fDateFormat->applyPattern(originalPattern);
+        return appendTo;
+    }
+    Calendar* firstCal;
+    Calendar* secondCal;
+    if ( intervalPattern.laterDateFirst ) {
+        firstCal = &toCalendar;
+        secondCal = &fromCalendar;
+    } else {
+        firstCal = &fromCalendar;
+        secondCal = &toCalendar;
+    }
+    // break the interval pattern into 2 parts,
+    // first part should not be empty, 
+    UnicodeString originalPattern;
+    fDateFormat->toPattern(originalPattern);
+    fDateFormat->applyPattern(intervalPattern.firstPart);
+    fDateFormat->format(*firstCal, appendTo, pos);
+    if ( !intervalPattern.secondPart.isEmpty() ) {
+        fDateFormat->applyPattern(intervalPattern.secondPart);
+        fDateFormat->format(*secondCal, appendTo, pos);
+    }
+    fDateFormat->applyPattern(originalPattern);
+    return appendTo;
+}
+
+
+
+void
+DateIntervalFormat::parseObject(const UnicodeString& /* source */, 
+                                Formattable& /* result */,
+                                ParsePosition& /* parse_pos */) const {
+    // parseObject(const UnicodeString&, Formattable&, UErrorCode&) const
+    // will set status as U_INVALID_FORMAT_ERROR if 
+    // parse_pos is still 0
+}
+
+
+
+
+const DateIntervalInfo*
+DateIntervalFormat::getDateIntervalInfo() const {
+    return fInfo;
+}
+
+
+void
+DateIntervalFormat::setDateIntervalInfo(const DateIntervalInfo& newItvPattern,
+                                        UErrorCode& status) {
+    delete fInfo;
+    fInfo = new DateIntervalInfo(newItvPattern);
+    if ( fDateFormat ) {
+        initializePattern(status);
+    }
+}
+
+
+ 
+const DateFormat*
+DateIntervalFormat::getDateFormat() const {
+    return fDateFormat;
+}
+
+
+DateIntervalFormat::DateIntervalFormat(const Locale& locale,
+                                       DateIntervalInfo* dtItvInfo,
+                                       const UnicodeString* skeleton,
+                                       UErrorCode& status) 
+:   fInfo(NULL),
+    fDateFormat(NULL),
+    fFromCalendar(NULL),
+    fToCalendar(NULL),
+    fDtpng(NULL)
+{
+    if ( U_FAILURE(status) ) {
+        delete dtItvInfo;
+        return;
+    }
+    fDtpng = DateTimePatternGenerator::createInstance(locale, status);
+    SimpleDateFormat* dtfmt = createSDFPatternInstance(*skeleton, locale, 
+                                                    fDtpng, status);
+    if ( U_FAILURE(status) ) {
+        delete dtItvInfo;
+        delete fDtpng;
+        delete dtfmt;
+        return;
+    }
+    if ( dtfmt == NULL || dtItvInfo == NULL || fDtpng == NULL ) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        // safe to delete NULL
+        delete dtfmt;
+        delete dtItvInfo;
+        delete fDtpng;
+        return;
+    }
+    if ( skeleton ) {
+        fSkeleton = *skeleton;
+    }
+    fInfo = dtItvInfo;
+    fDateFormat = dtfmt;
+    if ( dtfmt->getCalendar() ) {
+        fFromCalendar = dtfmt->getCalendar()->clone();
+        fToCalendar = dtfmt->getCalendar()->clone();
+    } else {
+        fFromCalendar = NULL;
+        fToCalendar = NULL;
+    }
+    initializePattern(status);
+}
+
+
+SimpleDateFormat* U_EXPORT2
+DateIntervalFormat::createSDFPatternInstance(const UnicodeString& skeleton,
+                                             const Locale& locale,
+                                             DateTimePatternGenerator* dtpng,
+                                             UErrorCode& status)
+{
+    if ( U_FAILURE(status) ) {
+        return NULL;
+    }
+
+    const UnicodeString pattern = dtpng->getBestPattern(skeleton, status);
+    if ( U_FAILURE(status) ) {
+        return NULL;
+    }
+    SimpleDateFormat* dtfmt = new SimpleDateFormat(pattern, locale, status);
+    if ( U_FAILURE(status) ) {
+        delete dtfmt;
+        return NULL;
+    }
+    return dtfmt;
+}
+
+
+DateIntervalFormat* U_EXPORT2
+DateIntervalFormat::create(const Locale& locale,
+                           DateIntervalInfo* dtitvinf,
+                           const UnicodeString* skeleton,
+                           UErrorCode& status) {
+    DateIntervalFormat* f = new DateIntervalFormat(locale, dtitvinf, 
+                                                   skeleton, status);
+    if ( f == NULL ) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        delete dtitvinf;
+    } else if ( U_FAILURE(status) ) {
+        // safe to delete f, although nothing acutally is saved
+        delete f;
+        f = 0;
+    }
+    return f;
+}
+
+
+
+/** 
+ * Initialize interval patterns locale to this formatter
+ * 
+ * This code is a bit complicated since 
+ * 1. the interval patterns saved in resource bundle files are interval
+ *    patterns based on date or time only.
+ *    It does not have interval patterns based on both date and time.
+ *    Interval patterns on both date and time are algorithm generated.
+ *
+ *    For example, it has interval patterns on skeleton "dMy" and "hm",
+ *    but it does not have interval patterns on skeleton "dMyhm".
+ *    
+ *    The rule to genearte interval patterns for both date and time skeleton are
+ *    1) when the year, month, or day differs, concatenate the two original 
+ *    expressions with a separator between, 
+ *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
+ *    to "Jan 11, 2007 10:10am" is 
+ *    "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 
+ *
+ *    2) otherwise, present the date followed by the range expression 
+ *    for the time.
+ *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
+ *    to "Jan 10, 2007 11:10am" is 
+ *    "Jan 10, 2007 10:10 am - 11:10am" 
+ *
+ * 2. even a pattern does not request a certion calendar field,
+ *    the interval pattern needs to include such field if such fields are
+ *    different between 2 dates.
+ *    For example, a pattern/skeleton is "hm", but the interval pattern 
+ *    includes year, month, and date when year, month, and date differs.
+ * 
+ * @param status          output param set to success/failure code on exit
+ * @stable ICU 4.0 
+ */
+void 
+DateIntervalFormat::initializePattern(UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    const Locale& locale = fDateFormat->getSmpFmtLocale();
+    if ( fSkeleton.isEmpty() ) {
+        UnicodeString fullPattern;
+        fDateFormat->toPattern(fullPattern);
+#ifdef DTITVFMT_DEBUG
+    char result[1000];
+    char result_1[1000];
+    char mesg[2000];
+    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
+    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
+    PRINTMESG(mesg)
+#endif
+        // fSkeleton is already set by createDateIntervalInstance()
+        // or by createInstance(UnicodeString skeleton, .... )
+        fSkeleton = fDtpng->getSkeleton(fullPattern, status);
+        if ( U_FAILURE(status) ) {
+            return;    
+        }
+    }
+
+    // initialize the fIntervalPattern ordering
+    int8_t i;
+    for ( i = 0; i < DateIntervalInfo::kIPI_MAX_INDEX; ++i ) {
+        fIntervalPatterns[i].laterDateFirst = fInfo->getDefaultOrder();
+    }
+
+    /* Check whether the skeleton is a combination of date and time.
+     * For the complication reason 1 explained above.
+     */
+    UnicodeString dateSkeleton;
+    UnicodeString timeSkeleton;
+    UnicodeString normalizedTimeSkeleton;
+    UnicodeString normalizedDateSkeleton;
+
+
+    /* the difference between time skeleton and normalizedTimeSkeleton are:
+     * 1. both 'H' and 'h' are normalized as 'h' in normalized time skeleton,
+     * 2. 'a' is omitted in normalized time skeleton.
+     * 3. there is only one appearance for 'h', 'm','v', 'z' in normalized 
+     *    time skeleton
+     *
+     * The difference between date skeleton and normalizedDateSkeleton are:
+     * 1. both 'y' and 'd' appear only once in normalizeDateSkeleton
+     * 2. 'E' and 'EE' are normalized into 'EEE'
+     * 3. 'MM' is normalized into 'M'
+     */
+    getDateTimeSkeleton(fSkeleton, dateSkeleton, normalizedDateSkeleton,
+                        timeSkeleton, normalizedTimeSkeleton);
+
+#ifdef DTITVFMT_DEBUG
+    char result[1000];
+    char result_1[1000];
+    char mesg[2000];
+    fSkeleton.extract(0,  fSkeleton.length(), result, "UTF-8");
+    sprintf(mesg, "in getBestSkeleton: fSkeleton: %s; \n", result);
+    PRINTMESG(mesg)
+#endif
+
+
+    UBool found = setSeparateDateTimePtn(normalizedDateSkeleton, 
+                                         normalizedTimeSkeleton);
+
+    if ( found == false ) {
+        // use fallback
+        // TODO: if user asks "m"(minute), but "d"(day) differ
+        if ( timeSkeleton.length() != 0 ) {
+            if ( dateSkeleton.length() == 0 ) {
+                // prefix with yMd
+                timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort]);
+                UnicodeString pattern = fDtpng->getBestPattern(timeSkeleton, status);
+                if ( U_FAILURE(status) ) {
+                    return;    
+                }
+                // for fall back interval patterns,
+                // the first part of the pattern is empty,
+                // the second part of the pattern is the full-pattern
+                // should be used in fall-back.
+                setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); 
+                setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); 
+                setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); 
+            } else {
+                // TODO: fall back
+            }
+        } else {
+            // TODO: fall back
+        }
+        return;
+    } // end of skeleton not found
+    // interval patterns for skeleton are found in resource 
+    if ( timeSkeleton.length() == 0 ) {
+        // done
+    } else if ( dateSkeleton.length() == 0 ) {
+        // prefix with yMd
+        timeSkeleton.insert(0, gDateFormatSkeleton[DateFormat::kShort]);
+        UnicodeString pattern = fDtpng->getBestPattern(timeSkeleton, status);
+        if ( U_FAILURE(status) ) {
+            return;    
+        }
+        // for fall back interval patterns,
+        // the first part of the pattern is empty,
+        // the second part of the pattern is the full-pattern
+        // should be used in fall-back.
+        setPatternInfo(UCAL_DATE, NULL, &pattern, fInfo->getDefaultOrder()); 
+        setPatternInfo(UCAL_MONTH, NULL, &pattern, fInfo->getDefaultOrder()); 
+        setPatternInfo(UCAL_YEAR, NULL, &pattern, fInfo->getDefaultOrder()); 
+    } else {
+        /* if both present,
+         * 1) when the year, month, or day differs, 
+         * concatenate the two original expressions with a separator between, 
+         * 2) otherwise, present the date followed by the 
+         * range expression for the time. 
+         */
+        /*
+         * 1) when the year, month, or day differs, 
+         * concatenate the two original expressions with a separator between, 
+         */
+        // if field exists, use fall back
+        UnicodeString skeleton = fSkeleton;
+        if ( !fieldExistsInSkeleton(UCAL_DATE, dateSkeleton) ) {
+            // prefix skeleton with 'd'
+            skeleton.insert(0, LOW_D);
+            setFallbackPattern(UCAL_DATE, skeleton, status);
+        }
+        if ( !fieldExistsInSkeleton(UCAL_MONTH, dateSkeleton) ) {
+            // then prefix skeleton with 'M'
+            skeleton.insert(0, CAP_M);
+            setFallbackPattern(UCAL_MONTH, skeleton, status);
+        }
+        if ( !fieldExistsInSkeleton(UCAL_YEAR, dateSkeleton) ) {
+            // then prefix skeleton with 'y'
+            skeleton.insert(0, LOW_Y);
+            setFallbackPattern(UCAL_YEAR, skeleton, status);
+        }
+        
+        /*
+         * 2) otherwise, present the date followed by the 
+         * range expression for the time. 
+         */
+        // Need the Date/Time pattern for concatnation the date with
+        // the time interval.
+        // The date/time pattern ( such as {0} {1} ) is saved in
+        // calendar, that is why need to get the CalendarData here.
+        CalendarData* calData = new CalendarData(locale, NULL, status);
+
+        if ( U_FAILURE(status) ) {
+            delete calData;
+            return;
+        }
+
+        if ( calData == NULL ) {
+            status = U_MEMORY_ALLOCATION_ERROR;
+            return;
+        }
+       
+        const UResourceBundle* dateTimePatternsRes = calData->getByKey(
+                                           gDateTimePatternsTag, status);
+        int32_t dateTimeFormatLength;
+        const UChar* dateTimeFormat = ures_getStringByIndex(
+                                            dateTimePatternsRes,
+                                            (int32_t)DateFormat::kDateTime,
+                                            &dateTimeFormatLength, &status);
+        if ( U_FAILURE(status) ) {
+            return;
+        }
+
+        UnicodeString datePattern = fDtpng->getBestPattern(dateSkeleton, status);
+
+        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
+                                      datePattern, UCAL_AM_PM, status);
+        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
+                                      datePattern, UCAL_HOUR, status);
+        concatSingleDate2TimeInterval(dateTimeFormat, dateTimeFormatLength,
+                                      datePattern, UCAL_MINUTE, status);
+        delete calData;
+    }
+}
+
+
+
+void  U_EXPORT2 
+DateIntervalFormat::getDateTimeSkeleton(const UnicodeString& skeleton, 
+                                        UnicodeString& dateSkeleton, 
+                                        UnicodeString& normalizedDateSkeleton, 
+                                        UnicodeString& timeSkeleton,
+                                        UnicodeString& normalizedTimeSkeleton) {
+    // dateSkeleton follows the sequence of y*M*E*d*
+    // timeSkeleton follows the sequence of hm*[v|z]?
+    int32_t ECount = 0;
+    int32_t dCount = 0;
+    int32_t MCount = 0;
+    int32_t yCount = 0;
+    int32_t hCount = 0;
+    int32_t mCount = 0;
+    int32_t vCount = 0;
+    int32_t zCount = 0;
+    int32_t i;
+
+    for (i = 0; i < skeleton.length(); ++i) {
+        UChar ch = skeleton[i];
+        switch ( ch ) {
+          case CAP_E:
+            dateSkeleton.append(ch);
+            ++ECount;
+            break;
+          case LOW_D:
+            dateSkeleton.append(ch);
+            ++dCount;
+            break;
+          case CAP_M:
+            dateSkeleton.append(ch);
+            ++MCount;
+            break;
+          case LOW_Y:
+            dateSkeleton.append(ch);
+            ++yCount;
+            break;
+          case CAP_G:
+          case CAP_Y:
+          case LOW_U:
+          case CAP_Q:
+          case LOW_Q:
+          case CAP_L:
+          case LOW_L:
+          case CAP_W:
+          case LOW_W:
+          case CAP_D:
+          case CAP_F:
+          case LOW_G:
+          case LOW_E:
+          case LOW_C:
+            normalizedDateSkeleton.append(ch);
+            dateSkeleton.append(ch);
+            break;
+          case LOW_A:
+            // 'a' is implicitly handled 
+            timeSkeleton.append(ch);
+            break;
+          case LOW_H:
+          case CAP_H:
+            timeSkeleton.append(ch);
+            ++hCount;
+            break;
+          case LOW_M:
+            timeSkeleton.append(ch);
+            ++mCount;
+            break;
+          case LOW_Z:
+            ++zCount;
+            timeSkeleton.append(ch);
+            break;
+          case LOW_V:
+            ++vCount;
+            timeSkeleton.append(ch);
+            break;
+          case CAP_V:
+          case CAP_Z:
+          case LOW_K:
+          case CAP_K:
+          case LOW_J:
+          case LOW_S:
+          case CAP_S:
+          case CAP_A:
+            timeSkeleton.append(ch);
+            normalizedTimeSkeleton.append(ch);
+            break;     
+        }
+    }
+
+    /* generate normalized form for date*/
+    if ( yCount != 0 ) {
+        normalizedDateSkeleton.append(LOW_Y);
+    }
+    if ( MCount != 0 ) {
+        if ( MCount < 3 ) {
+            normalizedDateSkeleton.append(CAP_M);
+        } else {
+            int32_t i;
+            for ( i = 0; i < MCount && i < MAX_M_COUNT; ++i ) {
+                 normalizedDateSkeleton.append(CAP_M);
+            }
+        }
+    }
+    if ( ECount != 0 ) {
+        if ( ECount <= 3 ) {
+            normalizedDateSkeleton.append(CAP_E);
+        } else {
+            int32_t i;
+            for ( i = 0; i < ECount && i < MAX_E_COUNT; ++i ) {
+                 normalizedDateSkeleton.append(CAP_E);
+            }
+        }
+    }
+    if ( dCount != 0 ) {
+        normalizedDateSkeleton.append(LOW_D);
+    }
+
+    /* generate normalized form for time */
+    if ( hCount != 0 ) {
+        normalizedTimeSkeleton.append(LOW_H);
+    }
+    if ( mCount != 0 ) {
+        normalizedTimeSkeleton.append(LOW_M);
+    }
+    if ( zCount != 0 ) {
+        normalizedTimeSkeleton.append(LOW_Z);
+    }
+    if ( vCount != 0 ) {
+        normalizedTimeSkeleton.append(LOW_V);
+    }
+}
+
+
+/**
+ * Generate date or time interval pattern from resource,
+ * and set them into the interval pattern locale to this formatter.
+ *
+ * It needs to handle the following: 
+ * 1. need to adjust field width.
+ *    For example, the interval patterns saved in DateIntervalInfo
+ *    includes "dMMMy", but not "dMMMMy".
+ *    Need to get interval patterns for dMMMMy from dMMMy.
+ *    Another example, the interval patterns saved in DateIntervalInfo
+ *    includes "hmv", but not "hmz".
+ *    Need to get interval patterns for "hmz' from 'hmv'
+ *
+ * 2. there might be no pattern for 'y' differ for skeleton "Md",
+ *    in order to get interval patterns for 'y' differ,
+ *    need to look for it from skeleton 'yMd'
+ *
+ * @param dateSkeleton   normalized date skeleton
+ * @param timeSkeleton   normalized time skeleton
+ * @return               whether the resource is found for the skeleton.
+ *                       TRUE if interval pattern found for the skeleton,
+ *                       FALSE otherwise.
+ * @stable ICU 4.0
+ */
+UBool 
+DateIntervalFormat::setSeparateDateTimePtn(
+                                 const UnicodeString& dateSkeleton,
+                                 const UnicodeString& timeSkeleton) {
+    const UnicodeString* skeleton;
+    // if both date and time skeleton present,
+    // the final interval pattern might include time interval patterns
+    // ( when, am_pm, hour, minute differ ),
+    // but not date interval patterns ( when year, month, day differ ).
+    // For year/month/day differ, it falls back to fall-back pattern.
+    if ( timeSkeleton.length() != 0  ) {
+        skeleton = &timeSkeleton;
+    } else {
+        skeleton = &dateSkeleton;
+    }
+
+    /* interval patterns for skeleton "dMMMy" (but not "dMMMMy") 
+     * are defined in resource,
+     * interval patterns for skeleton "dMMMMy" are calculated by
+     * 1. get the best match skeleton for "dMMMMy", which is "dMMMy"
+     * 2. get the interval patterns for "dMMMy",
+     * 3. extend "MMM" to "MMMM" in above interval patterns for "dMMMMy" 
+     * getBestSkeleton() is step 1.
+     */
+    // best skeleton, and the difference information
+    int8_t differenceInfo = 0;
+    const UnicodeString* bestSkeleton = fInfo->getBestSkeleton(*skeleton, 
+                                                               differenceInfo);
+    /* best skeleton could be NULL.
+       For example: in "ca" resource file,
+       interval format is defined as following
+           intervalFormats{
+                fallback{"{0} - {1}"}
+            }
+       there is no skeletons/interval patterns defined,
+       and the best skeleton match could be NULL
+     */
+    if ( bestSkeleton == NULL ) {
+        return false; 
+    } 
+   
+    // difference:
+    // 0 means the best matched skeleton is the same as input skeleton
+    // 1 means the fields are the same, but field width are different
+    // 2 means the only difference between fields are v/z,
+    // -1 means there are other fields difference 
+    if ( differenceInfo == -1 ) { 
+        // skeleton has different fields, not only  v/z difference
+        return false;
+    }
+
+    if ( timeSkeleton.length() == 0 ) {
+        UnicodeString extendedSkeleton;
+        UnicodeString extendedBestSkeleton;
+        // only has date skeleton
+        setIntervalPattern(UCAL_DATE, skeleton, bestSkeleton, differenceInfo,
+                           &extendedSkeleton, &extendedBestSkeleton);
+
+        UBool extended = setIntervalPattern(UCAL_MONTH, skeleton, bestSkeleton, 
+                                     differenceInfo,
+                                     &extendedSkeleton, &extendedBestSkeleton);
+                                              
+        if ( extended ) {
+            bestSkeleton = &extendedBestSkeleton;
+            skeleton = &extendedSkeleton;
+        }
+        setIntervalPattern(UCAL_YEAR, skeleton, bestSkeleton, differenceInfo,
+                           &extendedSkeleton, &extendedBestSkeleton);
+    } else {
+        setIntervalPattern(UCAL_MINUTE, skeleton, bestSkeleton, differenceInfo);
+        setIntervalPattern(UCAL_HOUR, skeleton, bestSkeleton, differenceInfo);
+        setIntervalPattern(UCAL_AM_PM, skeleton, bestSkeleton, differenceInfo);
+    }
+    return true;
+}
+
+
+
+void
+DateIntervalFormat::setFallbackPattern(UCalendarDateFields field,
+                                       const UnicodeString& skeleton,
+                                       UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    UnicodeString pattern = fDtpng->getBestPattern(skeleton, status);
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    setPatternInfo(field, NULL, &pattern, fInfo->getDefaultOrder());
+}
+
+
+
+
+void
+DateIntervalFormat::setPatternInfo(UCalendarDateFields field, 
+                                   const UnicodeString* firstPart,
+                                   const UnicodeString* secondPart, 
+                                   UBool laterDateFirst) {
+    // for fall back interval patterns,
+    // the first part of the pattern is empty,
+    // the second part of the pattern is the full-pattern
+    // should be used in fall-back.
+    UErrorCode status = U_ZERO_ERROR;
+    // following should not set any wrong status.
+    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
+                                                                        status);
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    PatternInfo& ptn = fIntervalPatterns[itvPtnIndex];
+    if ( firstPart ) {
+        ptn.firstPart = *firstPart;
+    }
+    if ( secondPart ) {
+        ptn.secondPart = *secondPart;
+    }
+    ptn.laterDateFirst = laterDateFirst;
+}
+
+void
+DateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
+                                       const UnicodeString& intervalPattern) {
+    UBool order = fInfo->getDefaultOrder();
+    setIntervalPattern(field, intervalPattern, order);
+}
+
+
+void
+DateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
+                                       const UnicodeString& intervalPattern,
+                                       UBool laterDateFirst) {
+    const UnicodeString* pattern = &intervalPattern;
+    UBool order = laterDateFirst;
+    // check for "latestFirst:" or "earliestFirst:" prefix
+    int8_t prefixLength = sizeof(gLaterFirstPrefix)/sizeof(gLaterFirstPrefix[0]);
+    int8_t earliestFirstLength = sizeof(gEarlierFirstPrefix)/sizeof(gEarlierFirstPrefix[0]);
+    UnicodeString realPattern;
+    if ( intervalPattern.startsWith(gLaterFirstPrefix, prefixLength) ) {
+        order = true;
+        intervalPattern.extract(prefixLength, 
+                                intervalPattern.length() - prefixLength,
+                                realPattern);
+        pattern = &realPattern;
+    } else if ( intervalPattern.startsWith(gEarlierFirstPrefix,
+                                           earliestFirstLength) ) {
+        order = false;
+        intervalPattern.extract(earliestFirstLength,
+                                intervalPattern.length() - earliestFirstLength,
+                                realPattern);
+        pattern = &realPattern;
+    }
+
+    int32_t splitPoint = splitPatternInto2Part(*pattern);
+    
+    UnicodeString firstPart;
+    UnicodeString secondPart;
+    pattern->extract(0, splitPoint, firstPart);
+    if ( splitPoint < pattern->length() ) {
+        pattern->extract(splitPoint, pattern->length()-splitPoint, secondPart);
+    }
+    setPatternInfo(field, &firstPart, &secondPart, order);
+}
+
+
+
+
+/**
+ * Generate interval pattern from existing resource
+ *
+ * It not only save the interval patterns,
+ * but also return the extended skeleton and its best match skeleton.
+ *
+ * @param field           largest different calendar field
+ * @param skeleton        skeleton
+ * @param bestSkeleton    the best match skeleton which has interval pattern
+ *                        defined in resource
+ * @param differenceInfo  the difference between skeleton and best skeleton
+ *         0 means the best matched skeleton is the same as input skeleton
+ *         1 means the fields are the same, but field width are different
+ *         2 means the only difference between fields are v/z,
+ *        -1 means there are other fields difference 
+ *
+ * @param extendedSkeleton      extended skeleton
+ * @param extendedBestSkeleton  extended best match skeleton
+ * @return                      whether the interval pattern is found 
+ *                              through extending skeleton or not.
+ *                              TRUE if interval pattern is found by
+ *                              extending skeleton, FALSE otherwise.
+ * @stable ICU 4.0
+ */
+UBool
+DateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
+                                       const UnicodeString* skeleton,
+                                       const UnicodeString* bestSkeleton,
+                                       int8_t differenceInfo,
+                                       UnicodeString* extendedSkeleton,
+                                       UnicodeString* extendedBestSkeleton) {
+    UErrorCode status = U_ZERO_ERROR;
+    // following getIntervalPattern() should not generate error status
+    UnicodeString pattern;
+    fInfo->getIntervalPattern(*bestSkeleton, field, pattern, status);
+    if ( pattern.isEmpty() ) {
+        // single date
+        if ( SimpleDateFormat::isFieldUnitIgnored(*bestSkeleton, field) ) {
+            // do nothing, format will handle it
+            return false;
+        }
+
+        // for 24 hour system, interval patterns in resource file
+        // might not include pattern when am_pm differ, 
+        // which should be the same as hour differ.
+        // add it here for simplicity
+        if ( field == UCAL_AM_PM ) {
+            fInfo->getIntervalPattern(*bestSkeleton, UCAL_HOUR, pattern,status);
+            if ( !pattern.isEmpty() ) {
+                setIntervalPattern(field, pattern);
+            }
+            return false;
+        } 
+        // else, looking for pattern when 'y' differ for 'dMMMM' skeleton,
+        // first, get best match pattern "MMMd",
+        // since there is no pattern for 'y' differs for skeleton 'MMMd',
+        // need to look for it from skeleton 'yMMMd',
+        // if found, adjust field width in interval pattern from
+        // "MMM" to "MMMM".
+        UChar fieldLetter = fgCalendarFieldToPatternLetter[field];
+        if ( extendedSkeleton ) {
+            *extendedSkeleton = *skeleton;
+            *extendedBestSkeleton = *bestSkeleton;
+            extendedSkeleton->insert(0, fieldLetter);
+            extendedBestSkeleton->insert(0, fieldLetter);
+            // for example, looking for patterns when 'y' differ for
+            // skeleton "MMMM". 
+            fInfo->getIntervalPattern(*extendedBestSkeleton,field,pattern,status);
+            if ( pattern.isEmpty() && differenceInfo == 0 ) {
+                // if there is no skeleton "yMMMM" defined,
+                // look for the best match skeleton, for example: "yMMM" 
+                const UnicodeString* tmpBest = fInfo->getBestSkeleton(
+                                        *extendedBestSkeleton, differenceInfo);
+                if ( tmpBest != 0 && differenceInfo != -1 ) {
+                    fInfo->getIntervalPattern(*tmpBest, field, pattern, status);
+                    bestSkeleton = tmpBest;
+                }
+            }
+        }
+    } 
+    if ( !pattern.isEmpty() ) {
+        if ( differenceInfo != 0 ) {
+            UnicodeString adjustIntervalPattern;
+            adjustFieldWidth(*skeleton, *bestSkeleton, pattern, differenceInfo,
+                              adjustIntervalPattern);
+            setIntervalPattern(field, adjustIntervalPattern);
+        } else {
+            setIntervalPattern(field, pattern);
+        }
+        if ( extendedSkeleton && !extendedSkeleton->isEmpty() ) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+
+
+int32_t  U_EXPORT2 
+DateIntervalFormat::splitPatternInto2Part(const UnicodeString& intervalPattern) {
+    UBool inQuote = false;
+    UChar prevCh = 0;
+    int32_t count = 0;
+
+    /* repeatedPattern used to record whether a pattern has already seen.
+       It is a pattern applies to first calendar if it is first time seen,
+       otherwise, it is a pattern applies to the second calendar
+     */
+    UBool patternRepeated[] = 
+    {
+    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   P   Q   R   S   T   U   V   W   X   Y   Z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
+    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   p   q   r   s   t   u   v   w   x   y   z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    };
+
+    int8_t PATTERN_CHAR_BASE = 0x41;
+    
+    /* loop through the pattern string character by character looking for
+     * the first repeated pattern letter, which breaks the interval pattern
+     * into 2 parts. 
+     */
+    int32_t i;
+    UBool foundRepetition = false;
+    for (i = 0; i < intervalPattern.length(); ++i) {
+        UChar ch = intervalPattern.charAt(i);
+        
+        if (ch != prevCh && count > 0) {
+            // check the repeativeness of pattern letter
+            UBool repeated = patternRepeated[(int)(prevCh - PATTERN_CHAR_BASE)];
+            if ( repeated == FALSE ) {
+                patternRepeated[prevCh - PATTERN_CHAR_BASE] = TRUE;
+            } else {
+                foundRepetition = true;
+                break;
+            }
+            count = 0;
+        }
+        if (ch == '\'') {
+            // Consecutive single quotes are a single quote literal,
+            // either outside of quotes or between quotes
+            if ((i+1) < intervalPattern.length() && 
+                intervalPattern.charAt(i+1) == '\'') {
+                ++i;
+            } else {
+                inQuote = ! inQuote;
+            }
+        } 
+        else if (!inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/)
+                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
+            // ch is a date-time pattern character 
+            prevCh = ch;
+            ++count;
+        }
+    }
+    // check last pattern char, distinguish
+    // "dd MM" ( no repetition ), 
+    // "d-d"(last char repeated ), and 
+    // "d-d MM" ( repetition found )
+    if ( count > 0 && foundRepetition == FALSE ) {
+        if ( patternRepeated[(int)(prevCh - PATTERN_CHAR_BASE)] == FALSE ) {
+            count = 0;
+        }
+    }
+    return (i - count);
+}
+
+
+
+UnicodeString& 
+DateIntervalFormat::fallbackFormat(Calendar& fromCalendar,
+                                   Calendar& toCalendar,
+                                   UnicodeString& appendTo,
+                                   FieldPosition& pos,
+                                   UErrorCode& status) const {
+    if ( U_FAILURE(status) ) {
+        return appendTo;
+    }
+    // the fall back
+    // no need delete earlierDate and laterDate since they are adopted
+    UnicodeString* earlierDate = new UnicodeString();
+    *earlierDate = fDateFormat->format(fromCalendar, *earlierDate, pos);
+    UnicodeString* laterDate = new UnicodeString();
+    *laterDate = fDateFormat->format(toCalendar, *laterDate, pos);
+    UnicodeString fallbackPattern;
+    fInfo->getFallbackIntervalPattern(fallbackPattern);
+    Formattable fmtArray[2];
+    fmtArray[0].adoptString(earlierDate);
+    fmtArray[1].adoptString(laterDate);
+    
+    UnicodeString fallback;
+    MessageFormat::format(fallbackPattern, fmtArray, 2, fallback, status);
+    if ( U_SUCCESS(status) ) {
+        appendTo.append(fallback);
+    }
+    return appendTo;
+}
+
+
+
+
+UBool  U_EXPORT2 
+DateIntervalFormat::fieldExistsInSkeleton(UCalendarDateFields field,
+                                          const UnicodeString& skeleton)
+{
+    const UChar fieldChar = fgCalendarFieldToPatternLetter[field];
+    return ( (skeleton.indexOf(fieldChar) == -1)?FALSE:TRUE ) ;
+}
+
+
+
+void  U_EXPORT2 
+DateIntervalFormat::adjustFieldWidth(const UnicodeString& inputSkeleton,
+                 const UnicodeString& bestMatchSkeleton,
+                 const UnicodeString& bestIntervalPattern,
+                 int8_t differenceInfo,
+                 UnicodeString& adjustedPtn) {
+    adjustedPtn = bestIntervalPattern;
+    int32_t inputSkeletonFieldWidth[] = 
+    {
+    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   P   Q   R   S   T   U   V   W   X   Y   Z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
+    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   p   q   r   s   t   u   v   w   x   y   z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    };
+
+    int32_t bestMatchSkeletonFieldWidth[] = 
+    {
+    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   P   Q   R   S   T   U   V   W   X   Y   Z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
+    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   p   q   r   s   t   u   v   w   x   y   z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    };
+
+    DateIntervalInfo::parseSkeleton(inputSkeleton, inputSkeletonFieldWidth);
+    DateIntervalInfo::parseSkeleton(bestMatchSkeleton, bestMatchSkeletonFieldWidth);
+    if ( differenceInfo == 2 ) {
+        adjustedPtn.findAndReplace("v", "z");
+    }
+
+    UBool inQuote = false;
+    UChar prevCh = 0;
+    int32_t count = 0;
+
+    const int8_t PATTERN_CHAR_BASE = 0x41;
+    
+    // loop through the pattern string character by character 
+    int32_t adjustedPtnLength = adjustedPtn.length();
+    int32_t i;
+    for (i = 0; i < adjustedPtnLength; ++i) {
+        UChar ch = adjustedPtn.charAt(i);
+        if (ch != prevCh && count > 0) {
+            // check the repeativeness of pattern letter
+            UChar skeletonChar = prevCh;
+            if ( skeletonChar ==  CAP_L ) {
+                // there is no "L" (always be "M") in skeleton, 
+                // but there is "L" in pattern.
+                // for skeleton "M+", the pattern might be "...L..." 
+                skeletonChar = CAP_M;
+            }
+            int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
+            int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
+            if ( fieldCount == count && inputFieldCount > fieldCount ) {
+                count = inputFieldCount - fieldCount;
+                int32_t j;
+                for ( j = 0; j < count; ++j ) {
+                    adjustedPtn.insert(i, prevCh);    
+                }                    
+                i += count;
+                adjustedPtnLength += count;
+            }
+            count = 0;
+        }
+        if (ch == '\'') {
+            // Consecutive single quotes are a single quote literal,
+            // either outside of quotes or between quotes
+            if ((i+1) < adjustedPtn.length() && adjustedPtn.charAt(i+1) == '\'') {
+                ++i;
+            } else {
+                inQuote = ! inQuote;
+            }
+        } 
+        else if ( ! inQuote && ((ch >= 0x0061 /*'a'*/ && ch <= 0x007A /*'z'*/) 
+                    || (ch >= 0x0041 /*'A'*/ && ch <= 0x005A /*'Z'*/))) {
+            // ch is a date-time pattern character 
+            prevCh = ch;
+            ++count;
+        }
+    }
+    if ( count > 0 ) {
+        // last item
+        // check the repeativeness of pattern letter
+        UChar skeletonChar = prevCh;
+        if ( skeletonChar == CAP_L ) {
+            // there is no "L" (always be "M") in skeleton, 
+            // but there is "L" in pattern.
+            // for skeleton "M+", the pattern might be "...L..." 
+            skeletonChar = CAP_M;
+        }
+        int32_t fieldCount = bestMatchSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
+        int32_t inputFieldCount = inputSkeletonFieldWidth[(int)(skeletonChar - PATTERN_CHAR_BASE)];
+        if ( fieldCount == count && inputFieldCount > fieldCount ) {
+            count = inputFieldCount - fieldCount;
+            int32_t j;
+            for ( j = 0; j < count; ++j ) {
+                adjustedPtn.append(prevCh);    
+            }                    
+        }
+    }
+}
+
+
+
+void 
+DateIntervalFormat::concatSingleDate2TimeInterval(const UChar* format,
+                                              int32_t formatLen,
+                                              const UnicodeString& datePattern,
+                                              UCalendarDateFields field,
+                                              UErrorCode& status) {
+    // following should not set wrong status
+    int32_t itvPtnIndex = DateIntervalInfo::calendarFieldToIntervalIndex(field,
+                                                                        status);
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    PatternInfo&  timeItvPtnInfo = fIntervalPatterns[itvPtnIndex];
+    if ( !timeItvPtnInfo.firstPart.isEmpty() ) {
+        // UnicodeString allocated here is adopted, so no need to delete
+        UnicodeString* timeIntervalPattern = new UnicodeString(timeItvPtnInfo.firstPart);
+        timeIntervalPattern->append(timeItvPtnInfo.secondPart);
+        UnicodeString* dateStr = new UnicodeString(datePattern);
+        Formattable fmtArray[2];
+        fmtArray[0].adoptString(timeIntervalPattern);
+        fmtArray[1].adoptString(dateStr);
+        UnicodeString combinedPattern;
+        MessageFormat::format(UnicodeString(TRUE, format, formatLen),
+                              fmtArray, 2, combinedPattern, status);
+        if ( U_FAILURE(status) ) {
+            return;
+        }
+        setIntervalPattern(field, combinedPattern, timeItvPtnInfo.laterDateFirst);
+    } 
+    // else: fall back
+    // it should not happen if the interval format defined is valid
+}
+
+
+
+const UChar
+DateIntervalFormat::fgCalendarFieldToPatternLetter[] =
+{
+    /*GyM*/ CAP_G, LOW_Y, CAP_M,
+    /*wWd*/ LOW_W, CAP_W, LOW_D,
+    /*DEF*/ CAP_D, CAP_E, CAP_F,
+    /*ahH*/ LOW_A, LOW_H, CAP_H,
+    /*m..*/ LOW_M,
+};
+
+
+U_NAMESPACE_END
+
+#endif

Modified: trunk/source/i18n/dtitvinf.cpp
===================================================================
--- trunk/source/i18n/dtitvinf.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/dtitvinf.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,642 +1,642 @@
-/*******************************************************************************
-* Copyright (C) 2008-2009, International Business Machines Corporation and
-* others. All Rights Reserved.
-*******************************************************************************
-*
-* File DTITVINF.CPP 
-*
-*******************************************************************************
-*/
-
-#include "unicode/dtitvinf.h"
-
-
-#if !UCONFIG_NO_FORMATTING
-
-//TODO: define it in compiler time
-//#define DTITVINF_DEBUG 1
-
-
-#ifdef DTITVINF_DEBUG 
-#include <iostream>
-#endif
-
-#include "cstring.h"
-#include "unicode/msgfmt.h"
-#include "dtitv_impl.h"
-#include "hash.h"
-#include "gregoimp.h"
-#include "uresimp.h"
-#include "hash.h"
-#include "gregoimp.h"
-#include "uresimp.h"
-
-
-U_NAMESPACE_BEGIN
-
-
-#ifdef DTITVINF_DEBUG 
-#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
-#endif
-
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalInfo)
-
-static const char gCalendarTag[]="calendar";
-static const char gGregorianTag[]="gregorian";
-static const char gIntervalDateTimePatternTag[]="intervalFormats";
-static const char gFallbackPatternTag[]="fallback";
-
-// {0}
-static const UChar gFirstPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET};
-// {1}
-static const UChar gSecondPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ONE, RIGHT_CURLY_BRACKET};
-
-// default fall-back
-static const UChar gDefaultFallbackPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, EN_DASH, SPACE, LEFT_CURLY_BRACKET, DIGIT_ONE, RIGHT_CURLY_BRACKET, 0};
-
-
-
-DateIntervalInfo::DateIntervalInfo(UErrorCode& status) 
-:   fFallbackIntervalPattern(gDefaultFallbackPattern),
-    fFirstDateInPtnIsLaterDate(false),
-    fIntervalPatterns(NULL)
-{
-    fIntervalPatterns = initHash(status);
-}
-
-
-
-DateIntervalInfo::DateIntervalInfo(const Locale& locale, UErrorCode& status)
-:   fFallbackIntervalPattern(gDefaultFallbackPattern),
-    fFirstDateInPtnIsLaterDate(false),
-    fIntervalPatterns(NULL)
-{
-    initializeData(locale, status);
-}
-
-
-
-void
-DateIntervalInfo::setIntervalPattern(const UnicodeString& skeleton,
-                                     UCalendarDateFields lrgDiffCalUnit,
-                                     const UnicodeString& intervalPattern,
-                                     UErrorCode& status) {
-    
-    if ( lrgDiffCalUnit == UCAL_HOUR_OF_DAY ) {
-        setIntervalPatternInternally(skeleton, UCAL_AM_PM, intervalPattern, status);
-        setIntervalPatternInternally(skeleton, UCAL_HOUR, intervalPattern, status);
-    } else if ( lrgDiffCalUnit == UCAL_DAY_OF_MONTH ||
-                lrgDiffCalUnit == UCAL_DAY_OF_WEEK ) {
-        setIntervalPatternInternally(skeleton, UCAL_DATE, intervalPattern, status);
-    } else {
-        setIntervalPatternInternally(skeleton, lrgDiffCalUnit, intervalPattern, status);
-    }
-}
-
-
-void
-DateIntervalInfo::setFallbackIntervalPattern(
-                                    const UnicodeString& fallbackPattern,
-                                    UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    int32_t firstPatternIndex = fallbackPattern.indexOf(gFirstPattern, 
-                        sizeof(gFirstPattern)/sizeof(gFirstPattern[0]), 0);
-    int32_t secondPatternIndex = fallbackPattern.indexOf(gSecondPattern, 
-                        sizeof(gSecondPattern)/sizeof(gSecondPattern[0]), 0);
-    if ( firstPatternIndex == -1 || secondPatternIndex == -1 ) {
-        status = U_ILLEGAL_ARGUMENT_ERROR;
-        return;
-    }
-    if ( firstPatternIndex > secondPatternIndex ) { 
-        fFirstDateInPtnIsLaterDate = true;
-    }
-    fFallbackIntervalPattern = fallbackPattern;
-}
-
-
-
-DateIntervalInfo::DateIntervalInfo(const DateIntervalInfo& dtitvinf)
-:   UObject(dtitvinf),
-    fIntervalPatterns(NULL)
-{
-    *this = dtitvinf;
-}
-    
-
-
-DateIntervalInfo&
-DateIntervalInfo::operator=(const DateIntervalInfo& dtitvinf) {
-    if ( this == &dtitvinf ) {
-        return *this;
-    }
-    
-    UErrorCode status = U_ZERO_ERROR;
-    deleteHash(fIntervalPatterns);
-    fIntervalPatterns = initHash(status);
-    copyHash(dtitvinf.fIntervalPatterns, fIntervalPatterns, status);
-    if ( U_FAILURE(status) ) {
-        return *this;
-    } 
-
-    fFallbackIntervalPattern = dtitvinf.fFallbackIntervalPattern;
-    fFirstDateInPtnIsLaterDate = dtitvinf.fFirstDateInPtnIsLaterDate;
-    return *this;
-}
-
-
-DateIntervalInfo*
-DateIntervalInfo::clone() const {
-    return new DateIntervalInfo(*this);
-}
-
-
-DateIntervalInfo::~DateIntervalInfo() {
-    deleteHash(fIntervalPatterns);
-    fIntervalPatterns = NULL;
-}
-
-
-UBool
-DateIntervalInfo::operator==(const DateIntervalInfo& other) const {
-    UBool equal = ( 
-      fFallbackIntervalPattern == other.fFallbackIntervalPattern &&
-      fFirstDateInPtnIsLaterDate == other.fFirstDateInPtnIsLaterDate );
-
-    if ( equal == TRUE ) {
-        equal = fIntervalPatterns->equals(*(other.fIntervalPatterns));
-    }
-
-    return equal;
-}
-
-
-UnicodeString&
-DateIntervalInfo::getIntervalPattern(const UnicodeString& skeleton,
-                                     UCalendarDateFields field,
-                                     UnicodeString& result,
-                                     UErrorCode& status) const {
-    if ( U_FAILURE(status) ) {
-        return result;
-    }
-   
-    const UnicodeString* patternsOfOneSkeleton = (UnicodeString*) fIntervalPatterns->get(skeleton);
-    if ( patternsOfOneSkeleton != NULL ) {
-        IntervalPatternIndex index = calendarFieldToIntervalIndex(field, status);
-        if ( U_FAILURE(status) ) {
-            return result;
-        }
-        const UnicodeString& intervalPattern =  patternsOfOneSkeleton[index];
-        if ( !intervalPattern.isEmpty() ) {
-            result = intervalPattern;
-        }
-    }
-    return result;
-}
-
-
-UBool
-DateIntervalInfo::getDefaultOrder() const {
-    return fFirstDateInPtnIsLaterDate;
-}
-
-
-UnicodeString&
-DateIntervalInfo::getFallbackIntervalPattern(UnicodeString& result) const {
-    result = fFallbackIntervalPattern;
-    return result;
-}
-
-
-void 
-DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& err)
-{
-  fIntervalPatterns = initHash(err);
-  if ( U_FAILURE(err) ) {
-      return;
-  }
-  const char *locName = locale.getName();
-  char parentLocale[ULOC_FULLNAME_CAPACITY];
-  int32_t locNameLen;
-  uprv_strcpy(parentLocale, locName);
-  UErrorCode status = U_ZERO_ERROR;
-  Hashtable skeletonSet(TRUE, status);
-  if ( U_FAILURE(status) ) {
-      return;
-  }
-  do {
-    UResourceBundle *rb, *calBundle, *gregorianBundle, *itvDtPtnResource;
-    rb = ures_open(NULL, parentLocale, &status);
-    calBundle = ures_getByKey(rb, gCalendarTag, NULL, &status); 
-    gregorianBundle = ures_getByKey(calBundle, gGregorianTag, NULL, &status);
-    itvDtPtnResource = ures_getByKeyWithFallback(gregorianBundle, 
-                         gIntervalDateTimePatternTag, NULL, &status);
-
-    if ( U_SUCCESS(status) ) {
-        // look for fallback first, since it establishes the default order
-        const UChar* resStr;
-        int32_t resStrLen = 0;
-        resStr = ures_getStringByKeyWithFallback(itvDtPtnResource, 
-                                             gFallbackPatternTag, 
-                                             &resStrLen, &status);
-        if ( U_SUCCESS(status) ) {
-            UnicodeString pattern = UnicodeString(TRUE, resStr, resStrLen);
-            setFallbackIntervalPattern(pattern, status);
-        }
-
-        int32_t size = ures_getSize(itvDtPtnResource);
-        int32_t index;
-        for ( index = 0; index < size; ++index ) {
-            UResourceBundle* oneRes = ures_getByIndex(itvDtPtnResource, index, 
-                                                     NULL, &status);
-            if ( U_SUCCESS(status) ) {
-                const char* skeleton = ures_getKey(oneRes);
-                if ( skeleton == NULL || 
-                     skeletonSet.geti(UnicodeString(skeleton)) == 1 ) {
-                    ures_close(oneRes);
-                    continue;
-                }
-                skeletonSet.puti(UnicodeString(skeleton), 1, status);
-                if ( uprv_strcmp(skeleton, gFallbackPatternTag) == 0 ) {
-                    ures_close(oneRes);
-                    continue;  // fallback
-                }
-    
-                UResourceBundle* intervalPatterns = ures_getByKey(
-                                     itvDtPtnResource, skeleton, NULL, &status);
-    
-                if ( U_FAILURE(status) ) {
-                    ures_close(intervalPatterns);
-                    ures_close(oneRes);
-                    break;
-                }
-                if ( intervalPatterns == NULL ) {
-                    ures_close(intervalPatterns);
-                    ures_close(oneRes);
-                    continue;
-                }
-    
-                const UChar* pattern;
-                const char* key;
-                int32_t ptLength;
-                int32_t ptnNum = ures_getSize(intervalPatterns);
-                int32_t ptnIndex;
-                for ( ptnIndex = 0; ptnIndex < ptnNum; ++ptnIndex ) {
-                    pattern = ures_getNextString(intervalPatterns, &ptLength, &key,
-                                                 &status);
-                    if ( U_FAILURE(status) ) {
-                        break;
-                    }
-        
-                    UCalendarDateFields calendarField = UCAL_FIELD_COUNT;
-                    if ( !uprv_strcmp(key, "y") ) {
-                        calendarField = UCAL_YEAR;
-                    } else if ( !uprv_strcmp(key, "M") ) {
-                        calendarField = UCAL_MONTH;
-                    } else if ( !uprv_strcmp(key, "d") ) {
-                        calendarField = UCAL_DATE;
-                    } else if ( !uprv_strcmp(key, "a") ) {
-                        calendarField = UCAL_AM_PM;
-                    } else if ( !uprv_strcmp(key, "h") ) {
-                        calendarField = UCAL_HOUR;
-                    } else if ( !uprv_strcmp(key, "m") ) {
-                        calendarField = UCAL_MINUTE;
-                    }
-                    if ( calendarField != UCAL_FIELD_COUNT ) {
-                        setIntervalPatternInternally(skeleton, calendarField, pattern,status);
-                    }
-                }
-                ures_close(intervalPatterns);
-            }
-            ures_close(oneRes);
-        }
-    }
-    ures_close(itvDtPtnResource);
-    ures_close(gregorianBundle);
-    ures_close(calBundle);
-    ures_close(rb);
-    status = U_ZERO_ERROR;
-    locNameLen = uloc_getParent(parentLocale, parentLocale,
-                                ULOC_FULLNAME_CAPACITY,&status);
-  } while ( locNameLen > 0 );
-}
-
-
-
-void
-DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton,
-                                      UCalendarDateFields lrgDiffCalUnit,
-                                      const UnicodeString& intervalPattern,
-                                      UErrorCode& status) {
-    IntervalPatternIndex index = calendarFieldToIntervalIndex(lrgDiffCalUnit,status);
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(fIntervalPatterns->get(skeleton));
-    UBool emptyHash = false;
-    if ( patternsOfOneSkeleton == NULL ) {
-        patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX];
-        emptyHash = true;
-    }
-    
-    patternsOfOneSkeleton[index] = intervalPattern;
-    if ( emptyHash == TRUE ) {
-        fIntervalPatterns->put(skeleton, patternsOfOneSkeleton, status);
-    }
-}
-
-
-
-void 
-DateIntervalInfo::parseSkeleton(const UnicodeString& skeleton, 
-                                int32_t* skeletonFieldWidth) {
-    const int8_t PATTERN_CHAR_BASE = 0x41;
-    int32_t i;
-    for ( i = 0; i < skeleton.length(); ++i ) {
-        // it is an ASCII char in skeleton
-        int8_t ch = (int8_t)skeleton.charAt(i);  
-        ++skeletonFieldWidth[ch - PATTERN_CHAR_BASE];
-    }
-}
-
-
-
-UBool 
-DateIntervalInfo::stringNumeric(int32_t fieldWidth, int32_t anotherFieldWidth,
-                                char patternLetter) {
-    if ( patternLetter == 'M' ) {
-        if ( fieldWidth <= 2 && anotherFieldWidth > 2 ||
-             fieldWidth > 2 && anotherFieldWidth <= 2 ) {
-            return true;
-        }
-    }
-    return false;
-}
-
-
-
-const UnicodeString* 
-DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton,
-                                  int8_t& bestMatchDistanceInfo) const {
-#ifdef DTITVINF_DEBUG
-    char result[1000];
-    char result_1[1000];
-    char mesg[2000];
-    skeleton.extract(0,  skeleton.length(), result, "UTF-8");
-    sprintf(mesg, "in getBestSkeleton: skeleton: %s; \n", result);
-    PRINTMESG(mesg)
-#endif
-
-
-    int32_t inputSkeletonFieldWidth[] =
-    {
-    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
-             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   P   Q   R   S   T   U   V   W   X   Y   Z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
-    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   p   q   r   s   t   u   v   w   x   y   z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
-    };
-
-    int32_t skeletonFieldWidth[] =
-    {
-    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
-             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   P   Q   R   S   T   U   V   W   X   Y   Z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
-    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-    //   p   q   r   s   t   u   v   w   x   y   z
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
-    };
-
-    const int32_t DIFFERENT_FIELD = 0x1000;
-    const int32_t STRING_NUMERIC_DIFFERENCE = 0x100;
-    const int32_t BASE = 0x41;
-    const UChar CHAR_V = 0x0076;
-    const UChar CHAR_Z = 0x007A;
-
-    // hack for 'v' and 'z'.
-    // resource bundle only have time skeletons ending with 'v',
-    // but not for time skeletons ending with 'z'.
-    UBool replaceZWithV = false;
-    const UnicodeString* inputSkeleton = &skeleton; 
-    UnicodeString copySkeleton;
-    if ( skeleton.indexOf(CHAR_Z) != -1 ) {
-        UChar zstr[2];
-        UChar vstr[2]; 
-        zstr[0]=CHAR_Z;
-        vstr[0]=CHAR_V;
-        zstr[1]=0;
-        vstr[1]=0;
-        copySkeleton = skeleton;
-        copySkeleton.findAndReplace(zstr, vstr);
-        inputSkeleton = &copySkeleton;
-        replaceZWithV = true;
-    }
-
-    parseSkeleton(*inputSkeleton, inputSkeletonFieldWidth);
-    int32_t bestDistance = MAX_POSITIVE_INT;
-    const UnicodeString* bestSkeleton = NULL;
-
-    // 0 means exact the same skeletons;
-    // 1 means having the same field, but with different length,
-    // 2 means only z/v differs
-    // -1 means having different field.
-    bestMatchDistanceInfo = 0;
-    int8_t fieldLength = sizeof(skeletonFieldWidth)/sizeof(skeletonFieldWidth[0]);
-
-    int32_t pos = -1;
-    const UHashElement* elem = NULL;
-    while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) {
-        const UHashTok keyTok = elem->key;
-        UnicodeString* skeleton = (UnicodeString*)keyTok.pointer;
-#ifdef DTITVINF_DEBUG
-    skeleton->extract(0,  skeleton->length(), result, "UTF-8");
-    sprintf(mesg, "available skeletons: skeleton: %s; \n", result);
-    PRINTMESG(mesg)
-#endif
-
-        // clear skeleton field width
-        int8_t i;
-        for ( i = 0; i < fieldLength; ++i ) {
-            skeletonFieldWidth[i] = 0;    
-        }
-        parseSkeleton(*skeleton, skeletonFieldWidth);
-        // calculate distance
-        int32_t distance = 0;
-        int8_t fieldDifference = 1;
-        for ( i = 0; i < fieldLength; ++i ) {
-            int32_t inputFieldWidth = inputSkeletonFieldWidth[i];
-            int32_t fieldWidth = skeletonFieldWidth[i];
-            if ( inputFieldWidth == fieldWidth ) {
-                continue;
-            }
-            if ( inputFieldWidth == 0 ) {
-                fieldDifference = -1;
-                distance += DIFFERENT_FIELD;
-            } else if ( fieldWidth == 0 ) {
-                fieldDifference = -1;
-                distance += DIFFERENT_FIELD;
-            } else if (stringNumeric(inputFieldWidth, fieldWidth, 
-                                     (char)(i+BASE) ) ) {
-                distance += STRING_NUMERIC_DIFFERENCE;
-            } else {
-                distance += (inputFieldWidth > fieldWidth) ? 
-                            (inputFieldWidth - fieldWidth) : 
-                            (fieldWidth - inputFieldWidth);
-            }
-        }
-        if ( distance < bestDistance ) {
-            bestSkeleton = skeleton;
-            bestDistance = distance;
-            bestMatchDistanceInfo = fieldDifference;
-        }
-        if ( distance == 0 ) {
-            bestMatchDistanceInfo = 0;
-            break;
-        }
-    }
-    if ( replaceZWithV && bestMatchDistanceInfo != -1 ) {
-        bestMatchDistanceInfo = 2;
-    }
-    return bestSkeleton;
-}
-
-
-
-DateIntervalInfo::IntervalPatternIndex
-DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field, 
-                                               UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return kIPI_MAX_INDEX;
-    }
-    IntervalPatternIndex index = kIPI_MAX_INDEX;
-    switch ( field ) {
-      case UCAL_ERA:
-        index = kIPI_ERA;
-        break;
-      case UCAL_YEAR:
-        index = kIPI_YEAR;
-        break;
-      case UCAL_MONTH:
-        index = kIPI_MONTH;
-        break;
-      case UCAL_DATE:
-      case UCAL_DAY_OF_WEEK:
-      //case UCAL_DAY_OF_MONTH:
-        index = kIPI_DATE;
-        break;
-      case UCAL_AM_PM:
-        index = kIPI_AM_PM;
-        break;
-      case UCAL_HOUR:
-      case UCAL_HOUR_OF_DAY:
-        index = kIPI_HOUR;
-        break;
-      case UCAL_MINUTE:
-        index = kIPI_MINUTE;
-        break;
-      default:
-        status = U_ILLEGAL_ARGUMENT_ERROR;
-    }
-    return index;
-}
-
-
-
-void
-DateIntervalInfo::deleteHash(Hashtable* hTable) 
-{
-    if ( hTable == NULL ) {
-        return;
-    }
-    int32_t pos = -1;
-    const UHashElement* element = NULL;
-    while ( (element = hTable->nextElement(pos)) != NULL ) {
-        const UHashTok keyTok = element->key;
-        const UHashTok valueTok = element->value;
-        const UnicodeString* value = (UnicodeString*)valueTok.pointer;
-        delete[] value;
-    }
-    delete fIntervalPatterns;
-}
-
-
-U_CDECL_BEGIN 
-
-/**
- * set hash table value comparator
- *
- * @param val1  one value in comparison
- * @param val2  the other value in comparison
- * @return      TRUE if 2 values are the same, FALSE otherwise
- */
-UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2);
-
-U_CDECL_END
-
-UBool 
-U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) {
-    const UnicodeString* pattern1 = (UnicodeString*)val1.pointer;
-    const UnicodeString* pattern2 = (UnicodeString*)val2.pointer;
-    UBool ret = TRUE;
-    int8_t i;
-    for ( i = 0; i < DateIntervalInfo::kIPI_MAX_INDEX && ret == TRUE; ++i ) {
-        ret = (pattern1[i] == pattern2[i]);
-    }
-    return ret;
-}
-
-
-
-Hashtable*
-DateIntervalInfo::initHash(UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return NULL;
-    }
-    Hashtable* hTable;
-    if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
-        status = U_MEMORY_ALLOCATION_ERROR;
-        return NULL;
-    }
-    hTable->setValueCompartor(dtitvinfHashTableValueComparator);
-    return hTable;
-}
-
-
-void
-DateIntervalInfo::copyHash(const Hashtable* source,
-                           Hashtable* target,
-                           UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    int32_t pos = -1;
-    const UHashElement* element = NULL;
-    if ( source ) {
-        while ( (element = source->nextElement(pos)) != NULL ) {
-            const UHashTok keyTok = element->key;
-            const UnicodeString* key = (UnicodeString*)keyTok.pointer;
-            const UHashTok valueTok = element->value;
-            const UnicodeString* value = (UnicodeString*)valueTok.pointer;
-            UnicodeString* copy = new UnicodeString[kIPI_MAX_INDEX];
-            int8_t i;
-            for ( i = 0; i < kIPI_MAX_INDEX; ++i ) {
-                copy[i] = value[i];
-            }
-            target->put(UnicodeString(*key), copy, status);
-            if ( U_FAILURE(status) ) {
-                return;
-            }
-        }
-    }
-}
-
-
-U_NAMESPACE_END
-
-#endif
+/*******************************************************************************
+* Copyright (C) 2008-2009, International Business Machines Corporation and
+* others. All Rights Reserved.
+*******************************************************************************
+*
+* File DTITVINF.CPP 
+*
+*******************************************************************************
+*/
+
+#include "unicode/dtitvinf.h"
+
+
+#if !UCONFIG_NO_FORMATTING
+
+//TODO: define it in compiler time
+//#define DTITVINF_DEBUG 1
+
+
+#ifdef DTITVINF_DEBUG 
+#include <iostream>
+#endif
+
+#include "cstring.h"
+#include "unicode/msgfmt.h"
+#include "dtitv_impl.h"
+#include "hash.h"
+#include "gregoimp.h"
+#include "uresimp.h"
+#include "hash.h"
+#include "gregoimp.h"
+#include "uresimp.h"
+
+
+U_NAMESPACE_BEGIN
+
+
+#ifdef DTITVINF_DEBUG 
+#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
+#endif
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalInfo)
+
+static const char gCalendarTag[]="calendar";
+static const char gGregorianTag[]="gregorian";
+static const char gIntervalDateTimePatternTag[]="intervalFormats";
+static const char gFallbackPatternTag[]="fallback";
+
+// {0}
+static const UChar gFirstPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET};
+// {1}
+static const UChar gSecondPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ONE, RIGHT_CURLY_BRACKET};
+
+// default fall-back
+static const UChar gDefaultFallbackPattern[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, EN_DASH, SPACE, LEFT_CURLY_BRACKET, DIGIT_ONE, RIGHT_CURLY_BRACKET, 0};
+
+
+
+DateIntervalInfo::DateIntervalInfo(UErrorCode& status) 
+:   fFallbackIntervalPattern(gDefaultFallbackPattern),
+    fFirstDateInPtnIsLaterDate(false),
+    fIntervalPatterns(NULL)
+{
+    fIntervalPatterns = initHash(status);
+}
+
+
+
+DateIntervalInfo::DateIntervalInfo(const Locale& locale, UErrorCode& status)
+:   fFallbackIntervalPattern(gDefaultFallbackPattern),
+    fFirstDateInPtnIsLaterDate(false),
+    fIntervalPatterns(NULL)
+{
+    initializeData(locale, status);
+}
+
+
+
+void
+DateIntervalInfo::setIntervalPattern(const UnicodeString& skeleton,
+                                     UCalendarDateFields lrgDiffCalUnit,
+                                     const UnicodeString& intervalPattern,
+                                     UErrorCode& status) {
+    
+    if ( lrgDiffCalUnit == UCAL_HOUR_OF_DAY ) {
+        setIntervalPatternInternally(skeleton, UCAL_AM_PM, intervalPattern, status);
+        setIntervalPatternInternally(skeleton, UCAL_HOUR, intervalPattern, status);
+    } else if ( lrgDiffCalUnit == UCAL_DAY_OF_MONTH ||
+                lrgDiffCalUnit == UCAL_DAY_OF_WEEK ) {
+        setIntervalPatternInternally(skeleton, UCAL_DATE, intervalPattern, status);
+    } else {
+        setIntervalPatternInternally(skeleton, lrgDiffCalUnit, intervalPattern, status);
+    }
+}
+
+
+void
+DateIntervalInfo::setFallbackIntervalPattern(
+                                    const UnicodeString& fallbackPattern,
+                                    UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    int32_t firstPatternIndex = fallbackPattern.indexOf(gFirstPattern, 
+                        sizeof(gFirstPattern)/sizeof(gFirstPattern[0]), 0);
+    int32_t secondPatternIndex = fallbackPattern.indexOf(gSecondPattern, 
+                        sizeof(gSecondPattern)/sizeof(gSecondPattern[0]), 0);
+    if ( firstPatternIndex == -1 || secondPatternIndex == -1 ) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return;
+    }
+    if ( firstPatternIndex > secondPatternIndex ) { 
+        fFirstDateInPtnIsLaterDate = true;
+    }
+    fFallbackIntervalPattern = fallbackPattern;
+}
+
+
+
+DateIntervalInfo::DateIntervalInfo(const DateIntervalInfo& dtitvinf)
+:   UObject(dtitvinf),
+    fIntervalPatterns(NULL)
+{
+    *this = dtitvinf;
+}
+    
+
+
+DateIntervalInfo&
+DateIntervalInfo::operator=(const DateIntervalInfo& dtitvinf) {
+    if ( this == &dtitvinf ) {
+        return *this;
+    }
+    
+    UErrorCode status = U_ZERO_ERROR;
+    deleteHash(fIntervalPatterns);
+    fIntervalPatterns = initHash(status);
+    copyHash(dtitvinf.fIntervalPatterns, fIntervalPatterns, status);
+    if ( U_FAILURE(status) ) {
+        return *this;
+    } 
+
+    fFallbackIntervalPattern = dtitvinf.fFallbackIntervalPattern;
+    fFirstDateInPtnIsLaterDate = dtitvinf.fFirstDateInPtnIsLaterDate;
+    return *this;
+}
+
+
+DateIntervalInfo*
+DateIntervalInfo::clone() const {
+    return new DateIntervalInfo(*this);
+}
+
+
+DateIntervalInfo::~DateIntervalInfo() {
+    deleteHash(fIntervalPatterns);
+    fIntervalPatterns = NULL;
+}
+
+
+UBool
+DateIntervalInfo::operator==(const DateIntervalInfo& other) const {
+    UBool equal = ( 
+      fFallbackIntervalPattern == other.fFallbackIntervalPattern &&
+      fFirstDateInPtnIsLaterDate == other.fFirstDateInPtnIsLaterDate );
+
+    if ( equal == TRUE ) {
+        equal = fIntervalPatterns->equals(*(other.fIntervalPatterns));
+    }
+
+    return equal;
+}
+
+
+UnicodeString&
+DateIntervalInfo::getIntervalPattern(const UnicodeString& skeleton,
+                                     UCalendarDateFields field,
+                                     UnicodeString& result,
+                                     UErrorCode& status) const {
+    if ( U_FAILURE(status) ) {
+        return result;
+    }
+   
+    const UnicodeString* patternsOfOneSkeleton = (UnicodeString*) fIntervalPatterns->get(skeleton);
+    if ( patternsOfOneSkeleton != NULL ) {
+        IntervalPatternIndex index = calendarFieldToIntervalIndex(field, status);
+        if ( U_FAILURE(status) ) {
+            return result;
+        }
+        const UnicodeString& intervalPattern =  patternsOfOneSkeleton[index];
+        if ( !intervalPattern.isEmpty() ) {
+            result = intervalPattern;
+        }
+    }
+    return result;
+}
+
+
+UBool
+DateIntervalInfo::getDefaultOrder() const {
+    return fFirstDateInPtnIsLaterDate;
+}
+
+
+UnicodeString&
+DateIntervalInfo::getFallbackIntervalPattern(UnicodeString& result) const {
+    result = fFallbackIntervalPattern;
+    return result;
+}
+
+
+void 
+DateIntervalInfo::initializeData(const Locale& locale, UErrorCode& err)
+{
+  fIntervalPatterns = initHash(err);
+  if ( U_FAILURE(err) ) {
+      return;
+  }
+  const char *locName = locale.getName();
+  char parentLocale[ULOC_FULLNAME_CAPACITY];
+  int32_t locNameLen;
+  uprv_strcpy(parentLocale, locName);
+  UErrorCode status = U_ZERO_ERROR;
+  Hashtable skeletonSet(TRUE, status);
+  if ( U_FAILURE(status) ) {
+      return;
+  }
+  do {
+    UResourceBundle *rb, *calBundle, *gregorianBundle, *itvDtPtnResource;
+    rb = ures_open(NULL, parentLocale, &status);
+    calBundle = ures_getByKey(rb, gCalendarTag, NULL, &status); 
+    gregorianBundle = ures_getByKey(calBundle, gGregorianTag, NULL, &status);
+    itvDtPtnResource = ures_getByKeyWithFallback(gregorianBundle, 
+                         gIntervalDateTimePatternTag, NULL, &status);
+
+    if ( U_SUCCESS(status) ) {
+        // look for fallback first, since it establishes the default order
+        const UChar* resStr;
+        int32_t resStrLen = 0;
+        resStr = ures_getStringByKeyWithFallback(itvDtPtnResource, 
+                                             gFallbackPatternTag, 
+                                             &resStrLen, &status);
+        if ( U_SUCCESS(status) ) {
+            UnicodeString pattern = UnicodeString(TRUE, resStr, resStrLen);
+            setFallbackIntervalPattern(pattern, status);
+        }
+
+        int32_t size = ures_getSize(itvDtPtnResource);
+        int32_t index;
+        for ( index = 0; index < size; ++index ) {
+            UResourceBundle* oneRes = ures_getByIndex(itvDtPtnResource, index, 
+                                                     NULL, &status);
+            if ( U_SUCCESS(status) ) {
+                const char* skeleton = ures_getKey(oneRes);
+                if ( skeleton == NULL || 
+                     skeletonSet.geti(UnicodeString(skeleton)) == 1 ) {
+                    ures_close(oneRes);
+                    continue;
+                }
+                skeletonSet.puti(UnicodeString(skeleton), 1, status);
+                if ( uprv_strcmp(skeleton, gFallbackPatternTag) == 0 ) {
+                    ures_close(oneRes);
+                    continue;  // fallback
+                }
+    
+                UResourceBundle* intervalPatterns = ures_getByKey(
+                                     itvDtPtnResource, skeleton, NULL, &status);
+    
+                if ( U_FAILURE(status) ) {
+                    ures_close(intervalPatterns);
+                    ures_close(oneRes);
+                    break;
+                }
+                if ( intervalPatterns == NULL ) {
+                    ures_close(intervalPatterns);
+                    ures_close(oneRes);
+                    continue;
+                }
+    
+                const UChar* pattern;
+                const char* key;
+                int32_t ptLength;
+                int32_t ptnNum = ures_getSize(intervalPatterns);
+                int32_t ptnIndex;
+                for ( ptnIndex = 0; ptnIndex < ptnNum; ++ptnIndex ) {
+                    pattern = ures_getNextString(intervalPatterns, &ptLength, &key,
+                                                 &status);
+                    if ( U_FAILURE(status) ) {
+                        break;
+                    }
+        
+                    UCalendarDateFields calendarField = UCAL_FIELD_COUNT;
+                    if ( !uprv_strcmp(key, "y") ) {
+                        calendarField = UCAL_YEAR;
+                    } else if ( !uprv_strcmp(key, "M") ) {
+                        calendarField = UCAL_MONTH;
+                    } else if ( !uprv_strcmp(key, "d") ) {
+                        calendarField = UCAL_DATE;
+                    } else if ( !uprv_strcmp(key, "a") ) {
+                        calendarField = UCAL_AM_PM;
+                    } else if ( !uprv_strcmp(key, "h") ) {
+                        calendarField = UCAL_HOUR;
+                    } else if ( !uprv_strcmp(key, "m") ) {
+                        calendarField = UCAL_MINUTE;
+                    }
+                    if ( calendarField != UCAL_FIELD_COUNT ) {
+                        setIntervalPatternInternally(skeleton, calendarField, pattern,status);
+                    }
+                }
+                ures_close(intervalPatterns);
+            }
+            ures_close(oneRes);
+        }
+    }
+    ures_close(itvDtPtnResource);
+    ures_close(gregorianBundle);
+    ures_close(calBundle);
+    ures_close(rb);
+    status = U_ZERO_ERROR;
+    locNameLen = uloc_getParent(parentLocale, parentLocale,
+                                ULOC_FULLNAME_CAPACITY,&status);
+  } while ( locNameLen > 0 );
+}
+
+
+
+void
+DateIntervalInfo::setIntervalPatternInternally(const UnicodeString& skeleton,
+                                      UCalendarDateFields lrgDiffCalUnit,
+                                      const UnicodeString& intervalPattern,
+                                      UErrorCode& status) {
+    IntervalPatternIndex index = calendarFieldToIntervalIndex(lrgDiffCalUnit,status);
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    UnicodeString* patternsOfOneSkeleton = (UnicodeString*)(fIntervalPatterns->get(skeleton));
+    UBool emptyHash = false;
+    if ( patternsOfOneSkeleton == NULL ) {
+        patternsOfOneSkeleton = new UnicodeString[kIPI_MAX_INDEX];
+        emptyHash = true;
+    }
+    
+    patternsOfOneSkeleton[index] = intervalPattern;
+    if ( emptyHash == TRUE ) {
+        fIntervalPatterns->put(skeleton, patternsOfOneSkeleton, status);
+    }
+}
+
+
+
+void 
+DateIntervalInfo::parseSkeleton(const UnicodeString& skeleton, 
+                                int32_t* skeletonFieldWidth) {
+    const int8_t PATTERN_CHAR_BASE = 0x41;
+    int32_t i;
+    for ( i = 0; i < skeleton.length(); ++i ) {
+        // it is an ASCII char in skeleton
+        int8_t ch = (int8_t)skeleton.charAt(i);  
+        ++skeletonFieldWidth[ch - PATTERN_CHAR_BASE];
+    }
+}
+
+
+
+UBool 
+DateIntervalInfo::stringNumeric(int32_t fieldWidth, int32_t anotherFieldWidth,
+                                char patternLetter) {
+    if ( patternLetter == 'M' ) {
+        if ( fieldWidth <= 2 && anotherFieldWidth > 2 ||
+             fieldWidth > 2 && anotherFieldWidth <= 2 ) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
+
+const UnicodeString* 
+DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton,
+                                  int8_t& bestMatchDistanceInfo) const {
+#ifdef DTITVINF_DEBUG
+    char result[1000];
+    char result_1[1000];
+    char mesg[2000];
+    skeleton.extract(0,  skeleton.length(), result, "UTF-8");
+    sprintf(mesg, "in getBestSkeleton: skeleton: %s; \n", result);
+    PRINTMESG(mesg)
+#endif
+
+
+    int32_t inputSkeletonFieldWidth[] =
+    {
+    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   P   Q   R   S   T   U   V   W   X   Y   Z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
+    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   p   q   r   s   t   u   v   w   x   y   z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    };
+
+    int32_t skeletonFieldWidth[] =
+    {
+    //       A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   P   Q   R   S   T   U   V   W   X   Y   Z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0, 0,  0, 0, 0,
+    //       a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    //   p   q   r   s   t   u   v   w   x   y   z
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
+    };
+
+    const int32_t DIFFERENT_FIELD = 0x1000;
+    const int32_t STRING_NUMERIC_DIFFERENCE = 0x100;
+    const int32_t BASE = 0x41;
+    const UChar CHAR_V = 0x0076;
+    const UChar CHAR_Z = 0x007A;
+
+    // hack for 'v' and 'z'.
+    // resource bundle only have time skeletons ending with 'v',
+    // but not for time skeletons ending with 'z'.
+    UBool replaceZWithV = false;
+    const UnicodeString* inputSkeleton = &skeleton; 
+    UnicodeString copySkeleton;
+    if ( skeleton.indexOf(CHAR_Z) != -1 ) {
+        UChar zstr[2];
+        UChar vstr[2]; 
+        zstr[0]=CHAR_Z;
+        vstr[0]=CHAR_V;
+        zstr[1]=0;
+        vstr[1]=0;
+        copySkeleton = skeleton;
+        copySkeleton.findAndReplace(zstr, vstr);
+        inputSkeleton = &copySkeleton;
+        replaceZWithV = true;
+    }
+
+    parseSkeleton(*inputSkeleton, inputSkeletonFieldWidth);
+    int32_t bestDistance = MAX_POSITIVE_INT;
+    const UnicodeString* bestSkeleton = NULL;
+
+    // 0 means exact the same skeletons;
+    // 1 means having the same field, but with different length,
+    // 2 means only z/v differs
+    // -1 means having different field.
+    bestMatchDistanceInfo = 0;
+    int8_t fieldLength = sizeof(skeletonFieldWidth)/sizeof(skeletonFieldWidth[0]);
+
+    int32_t pos = -1;
+    const UHashElement* elem = NULL;
+    while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) {
+        const UHashTok keyTok = elem->key;
+        UnicodeString* skeleton = (UnicodeString*)keyTok.pointer;
+#ifdef DTITVINF_DEBUG
+    skeleton->extract(0,  skeleton->length(), result, "UTF-8");
+    sprintf(mesg, "available skeletons: skeleton: %s; \n", result);
+    PRINTMESG(mesg)
+#endif
+
+        // clear skeleton field width
+        int8_t i;
+        for ( i = 0; i < fieldLength; ++i ) {
+            skeletonFieldWidth[i] = 0;    
+        }
+        parseSkeleton(*skeleton, skeletonFieldWidth);
+        // calculate distance
+        int32_t distance = 0;
+        int8_t fieldDifference = 1;
+        for ( i = 0; i < fieldLength; ++i ) {
+            int32_t inputFieldWidth = inputSkeletonFieldWidth[i];
+            int32_t fieldWidth = skeletonFieldWidth[i];
+            if ( inputFieldWidth == fieldWidth ) {
+                continue;
+            }
+            if ( inputFieldWidth == 0 ) {
+                fieldDifference = -1;
+                distance += DIFFERENT_FIELD;
+            } else if ( fieldWidth == 0 ) {
+                fieldDifference = -1;
+                distance += DIFFERENT_FIELD;
+            } else if (stringNumeric(inputFieldWidth, fieldWidth, 
+                                     (char)(i+BASE) ) ) {
+                distance += STRING_NUMERIC_DIFFERENCE;
+            } else {
+                distance += (inputFieldWidth > fieldWidth) ? 
+                            (inputFieldWidth - fieldWidth) : 
+                            (fieldWidth - inputFieldWidth);
+            }
+        }
+        if ( distance < bestDistance ) {
+            bestSkeleton = skeleton;
+            bestDistance = distance;
+            bestMatchDistanceInfo = fieldDifference;
+        }
+        if ( distance == 0 ) {
+            bestMatchDistanceInfo = 0;
+            break;
+        }
+    }
+    if ( replaceZWithV && bestMatchDistanceInfo != -1 ) {
+        bestMatchDistanceInfo = 2;
+    }
+    return bestSkeleton;
+}
+
+
+
+DateIntervalInfo::IntervalPatternIndex
+DateIntervalInfo::calendarFieldToIntervalIndex(UCalendarDateFields field, 
+                                               UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return kIPI_MAX_INDEX;
+    }
+    IntervalPatternIndex index = kIPI_MAX_INDEX;
+    switch ( field ) {
+      case UCAL_ERA:
+        index = kIPI_ERA;
+        break;
+      case UCAL_YEAR:
+        index = kIPI_YEAR;
+        break;
+      case UCAL_MONTH:
+        index = kIPI_MONTH;
+        break;
+      case UCAL_DATE:
+      case UCAL_DAY_OF_WEEK:
+      //case UCAL_DAY_OF_MONTH:
+        index = kIPI_DATE;
+        break;
+      case UCAL_AM_PM:
+        index = kIPI_AM_PM;
+        break;
+      case UCAL_HOUR:
+      case UCAL_HOUR_OF_DAY:
+        index = kIPI_HOUR;
+        break;
+      case UCAL_MINUTE:
+        index = kIPI_MINUTE;
+        break;
+      default:
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+    }
+    return index;
+}
+
+
+
+void
+DateIntervalInfo::deleteHash(Hashtable* hTable) 
+{
+    if ( hTable == NULL ) {
+        return;
+    }
+    int32_t pos = -1;
+    const UHashElement* element = NULL;
+    while ( (element = hTable->nextElement(pos)) != NULL ) {
+        const UHashTok keyTok = element->key;
+        const UHashTok valueTok = element->value;
+        const UnicodeString* value = (UnicodeString*)valueTok.pointer;
+        delete[] value;
+    }
+    delete fIntervalPatterns;
+}
+
+
+U_CDECL_BEGIN 
+
+/**
+ * set hash table value comparator
+ *
+ * @param val1  one value in comparison
+ * @param val2  the other value in comparison
+ * @return      TRUE if 2 values are the same, FALSE otherwise
+ */
+UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2);
+
+U_CDECL_END
+
+UBool 
+U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) {
+    const UnicodeString* pattern1 = (UnicodeString*)val1.pointer;
+    const UnicodeString* pattern2 = (UnicodeString*)val2.pointer;
+    UBool ret = TRUE;
+    int8_t i;
+    for ( i = 0; i < DateIntervalInfo::kIPI_MAX_INDEX && ret == TRUE; ++i ) {
+        ret = (pattern1[i] == pattern2[i]);
+    }
+    return ret;
+}
+
+
+
+Hashtable*
+DateIntervalInfo::initHash(UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return NULL;
+    }
+    Hashtable* hTable;
+    if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return NULL;
+    }
+    hTable->setValueCompartor(dtitvinfHashTableValueComparator);
+    return hTable;
+}
+
+
+void
+DateIntervalInfo::copyHash(const Hashtable* source,
+                           Hashtable* target,
+                           UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    int32_t pos = -1;
+    const UHashElement* element = NULL;
+    if ( source ) {
+        while ( (element = source->nextElement(pos)) != NULL ) {
+            const UHashTok keyTok = element->key;
+            const UnicodeString* key = (UnicodeString*)keyTok.pointer;
+            const UHashTok valueTok = element->value;
+            const UnicodeString* value = (UnicodeString*)valueTok.pointer;
+            UnicodeString* copy = new UnicodeString[kIPI_MAX_INDEX];
+            int8_t i;
+            for ( i = 0; i < kIPI_MAX_INDEX; ++i ) {
+                copy[i] = value[i];
+            }
+            target->put(UnicodeString(*key), copy, status);
+            if ( U_FAILURE(status) ) {
+                return;
+            }
+        }
+    }
+}
+
+
+U_NAMESPACE_END
+
+#endif

Modified: trunk/source/i18n/dtptngen.cpp
===================================================================
--- trunk/source/i18n/dtptngen.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/dtptngen.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -385,7 +385,7 @@
     if (U_FAILURE(status)) {
         return;
     }
-    addCLDRData(locale);
+    addCLDRData(locale, status);
     setDateTimeFromCalendar(locale, status);
     setDecimalSymbols(locale, status);
 } // DateTimePatternGenerator::initData
@@ -497,8 +497,7 @@
 static const UChar hourFormatChars[] = { CAP_H, LOW_H, CAP_K, LOW_K, 0 }; // HhKk, the hour format characters
 
 void
-DateTimePatternGenerator::addCLDRData(const Locale& locale) {
-    UErrorCode err = U_ZERO_ERROR;
+DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& err) {
     UResourceBundle *rb, *calTypeBundle, *calBundle;
     UResourceBundle *patBundle, *fieldBundle, *fBundle;
     UnicodeString rbPattern, value, field;
@@ -509,6 +508,8 @@
 
     UnicodeString defaultItemFormat(TRUE, UDATPG_ItemFormat, LENGTHOF(UDATPG_ItemFormat)-1);  // Read-only alias.
 
+    err = U_ZERO_ERROR;
+    
     fDefaultHourFormatChar = 0;
     for (i=0; i<UDATPG_FIELD_COUNT; ++i ) {
         appendItemNames[i]=CAP_F;
@@ -524,6 +525,9 @@
     }
 
     rb = ures_open(NULL, locale.getName(), &err);
+    if (rb == NULL || U_FAILURE(err)) {
+        return;
+    }
     const char *curLocaleName=ures_getLocaleByType(rb, ULOC_ACTUAL_LOCALE, &err);
     const char * calendarTypeToUse = DT_DateTimeGregorianTag; // initial default
     char         calendarType[ULOC_KEYWORDS_CAPACITY]; // to be filled in with the type to use, if all goes well
@@ -570,7 +574,7 @@
                 }
             }
         }
-    };
+    }
     ures_close(patBundle);
 
     err = U_ZERO_ERROR;
@@ -596,7 +600,7 @@
         patBundle = ures_getByKeyWithFallback(fBundle, Resource_Fields[i], NULL, &err);
         fieldBundle = ures_getByKeyWithFallback(patBundle, "dn", NULL, &err);
         rbPattern = ures_getNextUnicodeString(fieldBundle, &key, &err);
-       ures_close(fieldBundle);
+        ures_close(fieldBundle);
         ures_close(patBundle);
         if (rbPattern.length()==0 ) {
             continue;

Modified: trunk/source/i18n/tmunit.cpp
===================================================================
--- trunk/source/i18n/tmunit.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/tmunit.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,115 +1,115 @@
-/*
- *******************************************************************************
- * Copyright (C) 2008, Google, International Business Machines Corporation and *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-#include "unicode/tmunit.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-U_NAMESPACE_BEGIN
-
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnit)
-
-
-/*
- * There are only 7 time units.
- * So, TimeUnit could be made as singleton 
- * (similar to uniset_props.cpp, or unorm.cpp,
- * in which a static TimeUnit* array is created, and 
- * the creatInstance() returns a const TimeUnit*).
- * But the constraint is TimeUnit is a data member of Measure.
- * But Measure (which is an existing API) does not expect it's "unit" member
- * as singleton. Meaure takes ownership of the "unit" member.
- * In its constructor, it does not take a const "unit" pointer.
- * Also, Measure can clone and destruct the "unit" pointer.
- * In order to preserve the old behavior and let Measure handle singleton "unit",  
- * 1. a flag need to be added in Measure; 
- * 2. a new constructor which takes const "unit" as parameter need to be added,
- *    and this new constructor will set the flag on.
- * 3. clone and destructor need to check upon this flag to distinguish on how
- *    to handle the "unit". 
- * 
- * Since TimeUnit is such a light weight object, comparing with the heavy weight
- * format operation, we decided to avoid the above complication.
- * 
- * So, both TimeUnit and CurrencyUnit (the 2 subclasses of MeasureUnit) are
- * immutable and non-singleton.
- *
- * Currently, TimeUnitAmount and CurrencyAmount are immutable.
- * If an application needs to create a long list of TimeUnitAmount on the same
- * time unit but different number, for example,
- * 1 hour, 2 hour, 3 hour, ................. 10,000 hour,
- * there might be performance hit because 10,000 TimeUnit object, 
- * although all are the same time unit, will be created in heap and deleted.
- *
- * To address this performance issue, if there is any in the future,
- * we should and need to change TimeUnitAmount and CurrencyAmount to be 
- * immutable by allowing a setter on the number.
- * Or we need to add 2 parallel mutable classes in order to 
- * preserve the existing API.
- * Or we can use freezable.
- */
-TimeUnit* U_EXPORT2 
-TimeUnit::createInstance(TimeUnit::UTimeUnitFields timeUnitField, 
-                         UErrorCode& status) {
-    if (U_FAILURE(status)) {
-        return NULL;
-    }
-    if (timeUnitField < 0 || timeUnitField >= UTIMEUNIT_FIELD_COUNT) {
-        status = U_ILLEGAL_ARGUMENT_ERROR;
-        return NULL;
-    }
-    return new TimeUnit(timeUnitField);
-}
-
-
-TimeUnit::TimeUnit(TimeUnit::UTimeUnitFields timeUnitField) {
-    fTimeUnitField = timeUnitField;
-}
-
-
-TimeUnit::TimeUnit(const TimeUnit& other) 
-:   MeasureUnit(other) {
-    *this = other;
-}
-
-
-UObject* 
-TimeUnit::clone() const {
-    return new TimeUnit(*this);
-}
-
-
-TimeUnit&
-TimeUnit::operator=(const TimeUnit& other) {
-    if (this == &other) {
-        return *this;
-    }
-    fTimeUnitField = other.fTimeUnitField;
-    return *this;
-}
-
-
-UBool 
-TimeUnit::operator==(const UObject& other) const {
-    return (other.getDynamicClassID() == TimeUnit::getStaticClassID() 
-            && fTimeUnitField == ((TimeUnit*)&other)->fTimeUnitField);
-}
-
-
-TimeUnit::UTimeUnitFields
-TimeUnit::getTimeUnitField() const {
-    return fTimeUnitField;
-}
-
-
-TimeUnit::~TimeUnit() {
-}
-
-
-U_NAMESPACE_END
-
-#endif
+/*
+ *******************************************************************************
+ * Copyright (C) 2008, Google, International Business Machines Corporation and *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+#include "unicode/tmunit.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnit)
+
+
+/*
+ * There are only 7 time units.
+ * So, TimeUnit could be made as singleton 
+ * (similar to uniset_props.cpp, or unorm.cpp,
+ * in which a static TimeUnit* array is created, and 
+ * the creatInstance() returns a const TimeUnit*).
+ * But the constraint is TimeUnit is a data member of Measure.
+ * But Measure (which is an existing API) does not expect it's "unit" member
+ * as singleton. Meaure takes ownership of the "unit" member.
+ * In its constructor, it does not take a const "unit" pointer.
+ * Also, Measure can clone and destruct the "unit" pointer.
+ * In order to preserve the old behavior and let Measure handle singleton "unit",  
+ * 1. a flag need to be added in Measure; 
+ * 2. a new constructor which takes const "unit" as parameter need to be added,
+ *    and this new constructor will set the flag on.
+ * 3. clone and destructor need to check upon this flag to distinguish on how
+ *    to handle the "unit". 
+ * 
+ * Since TimeUnit is such a light weight object, comparing with the heavy weight
+ * format operation, we decided to avoid the above complication.
+ * 
+ * So, both TimeUnit and CurrencyUnit (the 2 subclasses of MeasureUnit) are
+ * immutable and non-singleton.
+ *
+ * Currently, TimeUnitAmount and CurrencyAmount are immutable.
+ * If an application needs to create a long list of TimeUnitAmount on the same
+ * time unit but different number, for example,
+ * 1 hour, 2 hour, 3 hour, ................. 10,000 hour,
+ * there might be performance hit because 10,000 TimeUnit object, 
+ * although all are the same time unit, will be created in heap and deleted.
+ *
+ * To address this performance issue, if there is any in the future,
+ * we should and need to change TimeUnitAmount and CurrencyAmount to be 
+ * immutable by allowing a setter on the number.
+ * Or we need to add 2 parallel mutable classes in order to 
+ * preserve the existing API.
+ * Or we can use freezable.
+ */
+TimeUnit* U_EXPORT2 
+TimeUnit::createInstance(TimeUnit::UTimeUnitFields timeUnitField, 
+                         UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    if (timeUnitField < 0 || timeUnitField >= UTIMEUNIT_FIELD_COUNT) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return NULL;
+    }
+    return new TimeUnit(timeUnitField);
+}
+
+
+TimeUnit::TimeUnit(TimeUnit::UTimeUnitFields timeUnitField) {
+    fTimeUnitField = timeUnitField;
+}
+
+
+TimeUnit::TimeUnit(const TimeUnit& other) 
+:   MeasureUnit(other) {
+    *this = other;
+}
+
+
+UObject* 
+TimeUnit::clone() const {
+    return new TimeUnit(*this);
+}
+
+
+TimeUnit&
+TimeUnit::operator=(const TimeUnit& other) {
+    if (this == &other) {
+        return *this;
+    }
+    fTimeUnitField = other.fTimeUnitField;
+    return *this;
+}
+
+
+UBool 
+TimeUnit::operator==(const UObject& other) const {
+    return (other.getDynamicClassID() == TimeUnit::getStaticClassID() 
+            && fTimeUnitField == ((TimeUnit*)&other)->fTimeUnitField);
+}
+
+
+TimeUnit::UTimeUnitFields
+TimeUnit::getTimeUnitField() const {
+    return fTimeUnitField;
+}
+
+
+TimeUnit::~TimeUnit() {
+}
+
+
+U_NAMESPACE_END
+
+#endif

Modified: trunk/source/i18n/tmutamt.cpp
===================================================================
--- trunk/source/i18n/tmutamt.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/tmutamt.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,76 +1,76 @@
-/*
- *******************************************************************************
- * Copyright (C) 2008, Google, International Business Machines Corporation and *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */ 
-
-#include "unicode/tmutamt.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-U_NAMESPACE_BEGIN
-
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnitAmount)
-
-
-TimeUnitAmount::TimeUnitAmount(const Formattable& number, 
-                               TimeUnit::UTimeUnitFields timeUnitField,
-                               UErrorCode& status)
-:    Measure(number, TimeUnit::createInstance(timeUnitField, status), status) {
-}
-
-
-TimeUnitAmount::TimeUnitAmount(double amount, 
-                               TimeUnit::UTimeUnitFields timeUnitField,
-                               UErrorCode& status)
-:   Measure(Formattable(amount), 
-            TimeUnit::createInstance(timeUnitField, status),
-            status) {
-}
-
-
-TimeUnitAmount::TimeUnitAmount(const TimeUnitAmount& other)
-:   Measure(other)
-{
-}
-
-
-TimeUnitAmount& 
-TimeUnitAmount::operator=(const TimeUnitAmount& other) {
-    Measure::operator=(other);
-    return *this;
-}
-
-
-UBool
-TimeUnitAmount::operator==(const UObject& other) const {
-    return Measure::operator==(other);
-}
-
-UObject* 
-TimeUnitAmount::clone() const {
-    return new TimeUnitAmount(*this);
-}
-
-    
-TimeUnitAmount::~TimeUnitAmount() {
-}
-
-
-
-const TimeUnit&
-TimeUnitAmount::getTimeUnit() const {
-    return (const TimeUnit&) getUnit();
-}
-
-
-TimeUnit::UTimeUnitFields
-TimeUnitAmount::getTimeUnitField() const {
-    return getTimeUnit().getTimeUnitField();
-}
-    
-
-U_NAMESPACE_END
-
-#endif
+/*
+ *******************************************************************************
+ * Copyright (C) 2008, Google, International Business Machines Corporation and *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */ 
+
+#include "unicode/tmutamt.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnitAmount)
+
+
+TimeUnitAmount::TimeUnitAmount(const Formattable& number, 
+                               TimeUnit::UTimeUnitFields timeUnitField,
+                               UErrorCode& status)
+:    Measure(number, TimeUnit::createInstance(timeUnitField, status), status) {
+}
+
+
+TimeUnitAmount::TimeUnitAmount(double amount, 
+                               TimeUnit::UTimeUnitFields timeUnitField,
+                               UErrorCode& status)
+:   Measure(Formattable(amount), 
+            TimeUnit::createInstance(timeUnitField, status),
+            status) {
+}
+
+
+TimeUnitAmount::TimeUnitAmount(const TimeUnitAmount& other)
+:   Measure(other)
+{
+}
+
+
+TimeUnitAmount& 
+TimeUnitAmount::operator=(const TimeUnitAmount& other) {
+    Measure::operator=(other);
+    return *this;
+}
+
+
+UBool
+TimeUnitAmount::operator==(const UObject& other) const {
+    return Measure::operator==(other);
+}
+
+UObject* 
+TimeUnitAmount::clone() const {
+    return new TimeUnitAmount(*this);
+}
+
+    
+TimeUnitAmount::~TimeUnitAmount() {
+}
+
+
+
+const TimeUnit&
+TimeUnitAmount::getTimeUnit() const {
+    return (const TimeUnit&) getUnit();
+}
+
+
+TimeUnit::UTimeUnitFields
+TimeUnitAmount::getTimeUnitField() const {
+    return getTimeUnit().getTimeUnitField();
+}
+    
+
+U_NAMESPACE_END
+
+#endif

Modified: trunk/source/i18n/tmutfmt.cpp
===================================================================
--- trunk/source/i18n/tmutfmt.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/tmutfmt.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,859 +1,859 @@
-/*
- *******************************************************************************
- * Copyright (C) 2008-2009, Google, International Business Machines Corporation
- * and  others. All Rights Reserved.                                           
- *******************************************************************************
- */
-
-
-#include "unicode/tmutfmt.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-#include "cmemory.h"
-#include "cstring.h"
-#include "hash.h"
-#include "uresimp.h"
-#include "unicode/msgfmt.h"
-
-#define LEFT_CURLY_BRACKET  ((UChar)0x007B)
-#define RIGHT_CURLY_BRACKET ((UChar)0x007D)
-#define SPACE             ((UChar)0x0020)
-#define DIGIT_ZERO        ((UChar)0x0030)
-#define LOW_S             ((UChar)0x0073)
-#define LOW_M             ((UChar)0x006D)
-#define LOW_I             ((UChar)0x0069)
-#define LOW_N             ((UChar)0x006E)
-#define LOW_H             ((UChar)0x0068)
-#define LOW_W             ((UChar)0x0077)
-#define LOW_D             ((UChar)0x0064)
-#define LOW_Y             ((UChar)0x0079)
-#define LOW_Z             ((UChar)0x007A)
-#define LOW_E             ((UChar)0x0065)
-#define LOW_R             ((UChar)0x0072)
-#define LOW_O             ((UChar)0x006F)
-#define LOW_N             ((UChar)0x006E)
-#define LOW_T             ((UChar)0x0074)
-
-
-//TODO: define in compile time
-//#define TMUTFMT_DEBUG 1
-
-#ifdef TMUTFMT_DEBUG
-#include <iostream>
-#endif
-
-U_NAMESPACE_BEGIN
-
-
-
-UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnitFormat)
-
-static const char gUnitsTag[] = "units";
-static const char gShortUnitsTag[] = "unitsShort";
-static const char gTimeUnitYear[] = "year";
-static const char gTimeUnitMonth[] = "month";
-static const char gTimeUnitDay[] = "day";
-static const char gTimeUnitWeek[] = "week";
-static const char gTimeUnitHour[] = "hour";
-static const char gTimeUnitMinute[] = "minute";
-static const char gTimeUnitSecond[] = "second";
-static const char gPluralCountOther[] = "other";
-
-static const UChar DEFAULT_PATTERN_FOR_SECOND[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_S, 0};
-static const UChar DEFAULT_PATTERN_FOR_MINUTE[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_M, LOW_I, LOW_N, 0};
-static const UChar DEFAULT_PATTERN_FOR_HOUR[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_H, 0};
-static const UChar DEFAULT_PATTERN_FOR_WEEK[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_W, 0};
-static const UChar DEFAULT_PATTERN_FOR_DAY[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_D, 0};
-static const UChar DEFAULT_PATTERN_FOR_MONTH[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_M, 0};
-static const UChar DEFAULT_PATTERN_FOR_YEAR[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_Y, 0};
-
-static const UChar PLURAL_COUNT_ZERO[] = {LOW_Z, LOW_E, LOW_R, LOW_O, 0};
-static const UChar PLURAL_COUNT_ONE[] = {LOW_O, LOW_N, LOW_E, 0};
-static const UChar PLURAL_COUNT_TWO[] = {LOW_T, LOW_W, LOW_O, 0};
-
-
-TimeUnitFormat::TimeUnitFormat(UErrorCode& status)
-:   fNumberFormat(NULL),
-    fPluralRules(NULL) {
-    create(Locale::getDefault(), kFull, status);
-}
-
-
-TimeUnitFormat::TimeUnitFormat(const Locale& locale, UErrorCode& status)
-:   fNumberFormat(NULL),
-    fPluralRules(NULL) {
-    create(locale, kFull, status);
-}
-
-
-TimeUnitFormat::TimeUnitFormat(const Locale& locale, EStyle style, UErrorCode& status)
-:   fNumberFormat(NULL),
-    fPluralRules(NULL) {
-    create(locale, style, status);
-}
-
-
-TimeUnitFormat::TimeUnitFormat(const TimeUnitFormat& other)
-:   MeasureFormat(other),
-    fNumberFormat(NULL),
-    fPluralRules(NULL),
-    fStyle(kFull)
-{
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        fTimeUnitToCountToPatterns[i] = NULL;
-    }
-    *this = other;
-}
-
-
-TimeUnitFormat::~TimeUnitFormat() {
-    delete fNumberFormat;
-    fNumberFormat = NULL;
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        deleteHash(fTimeUnitToCountToPatterns[i]);
-        fTimeUnitToCountToPatterns[i] = NULL;
-    }
-    delete fPluralRules;
-    fPluralRules = NULL;
-}
-
-
-Format* 
-TimeUnitFormat::clone(void) const {
-    return new TimeUnitFormat(*this);
-}
-
-
-TimeUnitFormat& 
-TimeUnitFormat::operator=(const TimeUnitFormat& other) {
-    if (this == &other) {
-        return *this;
-    }
-    delete fNumberFormat;
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        deleteHash(fTimeUnitToCountToPatterns[i]);
-        fTimeUnitToCountToPatterns[i] = NULL;
-    }
-    delete fPluralRules;
-    if (other.fNumberFormat) {
-        fNumberFormat = (NumberFormat*)other.fNumberFormat->clone();
-    } else {
-        fNumberFormat = NULL;
-    }
-    fLocale = other.fLocale;
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        UErrorCode status = U_ZERO_ERROR;
-        fTimeUnitToCountToPatterns[i] = initHash(status);
-        if (U_SUCCESS(status)) {
-            copyHash(other.fTimeUnitToCountToPatterns[i], fTimeUnitToCountToPatterns[i], status);
-        } else {
-            delete fTimeUnitToCountToPatterns[i];
-            fTimeUnitToCountToPatterns[i] = NULL;
-        }
-    } 
-    if (other.fPluralRules) {
-        fPluralRules = (PluralRules*)other.fPluralRules->clone();
-    } else {
-        fPluralRules = NULL;
-    }
-    fStyle = other.fStyle;
-    return *this;
-}
-
-
-UBool 
-TimeUnitFormat::operator==(const Format& other) const {
-    if (other.getDynamicClassID() == TimeUnitFormat::getStaticClassID()) {
-        TimeUnitFormat* fmt = (TimeUnitFormat*)&other;
-        UBool ret =  ( (fNumberFormat && fmt->fNumberFormat && 
-                        *fNumberFormat == *fmt->fNumberFormat ||
-                        fNumberFormat == fmt->fNumberFormat ) &&
-                       fLocale == fmt->fLocale &&
-                       (fPluralRules && fmt->fPluralRules &&
-                        *fPluralRules == *fmt->fPluralRules ||
-                        fPluralRules == fmt->fPluralRules) &&
-                      fStyle == fmt->fStyle); 
-        if (ret) {
-            for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-                 i < TimeUnit::UTIMEUNIT_FIELD_COUNT && ret;
-                 i = (TimeUnit::UTimeUnitFields)(i+1)) {
-                ret = fTimeUnitToCountToPatterns[i]->equals(*(fmt->fTimeUnitToCountToPatterns[i]));
-            }
-        }
-        return ret;
-    }
-    return false;
-}
-
-
-UnicodeString& 
-TimeUnitFormat::format(const Formattable& obj, UnicodeString& toAppendTo,
-                       FieldPosition& pos, UErrorCode& status) const {
-    if (U_FAILURE(status)) {
-        return toAppendTo;
-    }
-    if (obj.getType() == Formattable::kObject) {
-        const UObject* formatObj = obj.getObject();
-        if (formatObj->getDynamicClassID() == TimeUnitAmount::getStaticClassID()){
-            TimeUnitAmount* amount = (TimeUnitAmount*)formatObj;
-            Hashtable* countToPattern = fTimeUnitToCountToPatterns[amount->getTimeUnitField()];
-            double number;
-            const Formattable& amtNumber = amount->getNumber();
-            if (amtNumber.getType() == Formattable::kDouble) {
-                number = amtNumber.getDouble();
-            } else if (amtNumber.getType() == Formattable::kLong) {
-                number = amtNumber.getLong();
-            } else {
-                status = U_ILLEGAL_ARGUMENT_ERROR;
-                return toAppendTo;
-            }
-            UnicodeString count = fPluralRules->select(number);
-#ifdef TMUTFMT_DEBUG
-            char result[1000];
-            count.extract(0, count.length(), result, "UTF-8");
-            std::cout << "number: " << number << "; format plural count: " << result << "\n";           
-#endif
-            MessageFormat* pattern = ((MessageFormat**)countToPattern->get(count))[fStyle];
-            Formattable formattable[1];
-            formattable[0].setDouble(number);
-            return pattern->format(formattable, 1, toAppendTo, pos, status);
-        }
-    }
-    status = U_ILLEGAL_ARGUMENT_ERROR;
-    return toAppendTo;
-}
-
-
-void 
-TimeUnitFormat::parseObject(const UnicodeString& source, 
-                            Formattable& result,
-                            ParsePosition& pos) const {
-    double resultNumber = -1; 
-    UBool withNumberFormat = false;
-    TimeUnit::UTimeUnitFields resultTimeUnit = TimeUnit::UTIMEUNIT_FIELD_COUNT;
-    int32_t oldPos = pos.getIndex();
-    int32_t newPos = -1;
-    int32_t longestParseDistance = 0;
-    UnicodeString* countOfLongestMatch = NULL;
-#ifdef TMUTFMT_DEBUG
-    char res[1000];
-    source.extract(0, source.length(), res, "UTF-8");
-    std::cout << "parse source: " << res << "\n";           
-#endif
-    // parse by iterating through all available patterns
-    // and looking for the longest match.
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
-        int32_t elemPos = -1;
-        const UHashElement* elem = NULL;
-        while ((elem = countToPatterns->nextElement(elemPos)) != NULL){
-            const UHashTok keyTok = elem->key;
-            UnicodeString* count = (UnicodeString*)keyTok.pointer;
-#ifdef TMUTFMT_DEBUG
-            count->extract(0, count->length(), res, "UTF-8");
-            std::cout << "parse plural count: " << res << "\n";           
-#endif
-            const UHashTok valueTok = elem->value;
-            // the value is a pair of MessageFormat*
-            MessageFormat** patterns = (MessageFormat**)valueTok.pointer;
-            for (EStyle style = kFull; style < kTotal; style = (EStyle)(style + 1)) {
-                MessageFormat* pattern = patterns[style];
-                pos.setErrorIndex(-1);
-                pos.setIndex(oldPos);
-                // see if we can parse
-                Formattable parsed;
-                pattern->parseObject(source, parsed, pos);
-                if (pos.getErrorIndex() != -1 || pos.getIndex() == oldPos) {
-                    continue;
-                }
-    #ifdef TMUTFMT_DEBUG
-                std::cout << "parsed.getType: " << parsed.getType() << "\n";
-    #endif
-                double tmpNumber = 0;
-                if (pattern->getArgTypeCount() != 0) {
-                    // pattern with Number as beginning, such as "{0} d".
-                    // check to make sure that the timeUnit is consistent
-                    Formattable& temp = parsed[0];
-                    if (temp.getType() == Formattable::kDouble) {
-                        tmpNumber = temp.getDouble();
-                    } else if (temp.getType() == Formattable::kLong) {
-                        tmpNumber = temp.getLong();
-                    } else {
-                        continue;
-                    }
-                    UnicodeString select = fPluralRules->select(tmpNumber);
-    #ifdef TMUTFMT_DEBUG
-                    select.extract(0, select.length(), res, "UTF-8");
-                    std::cout << "parse plural select count: " << res << "\n"; 
-    #endif
-                    if (*count != select) {
-                        continue;
-                    }
-                }
-                int32_t parseDistance = pos.getIndex() - oldPos;
-                if (parseDistance > longestParseDistance) {
-                    if (pattern->getArgTypeCount() != 0) {
-                        resultNumber = tmpNumber;
-                        withNumberFormat = true;
-                    } else {
-                        withNumberFormat = false;
-                    }
-                    resultTimeUnit = i;
-                    newPos = pos.getIndex();
-                    longestParseDistance = parseDistance;
-                    countOfLongestMatch = count;
-                }
-            }
-        }
-    }
-    /* After find the longest match, parse the number.
-     * Result number could be null for the pattern without number pattern.
-     * such as unit pattern in Arabic.
-     * When result number is null, use plural rule to set the number.
-     */
-    if (withNumberFormat == false && longestParseDistance != 0) {
-        // set the number using plurrual count
-        if ( *countOfLongestMatch == PLURAL_COUNT_ZERO ) {
-            resultNumber = 0;
-        } else if ( *countOfLongestMatch == PLURAL_COUNT_ONE ) {
-            resultNumber = 1;
-        } else if ( *countOfLongestMatch == PLURAL_COUNT_TWO ) {
-            resultNumber = 2;
-        } else {
-            // should not happen.
-            // TODO: how to handle?
-            resultNumber = 3;
-        }
-    }
-    if (longestParseDistance == 0) {
-        pos.setIndex(oldPos);
-        pos.setErrorIndex(0);
-    } else {
-        UErrorCode status = U_ZERO_ERROR;
-        TimeUnitAmount* tmutamt = new TimeUnitAmount(resultNumber, resultTimeUnit, status);
-        if (U_SUCCESS(status)) {
-            result.adoptObject(tmutamt);
-            pos.setIndex(newPos);
-            pos.setErrorIndex(-1);
-        } else {
-            pos.setIndex(oldPos);
-            pos.setErrorIndex(0);
-        }
-    }
-}
-
-
-void
-TimeUnitFormat::create(const Locale& locale, EStyle style, UErrorCode& status) {
-    if (U_FAILURE(status)) {
-        return;
-    }
-    if (style < kFull || style > kAbbreviate) {
-        status = U_ILLEGAL_ARGUMENT_ERROR;
-        return;
-    }
-    fStyle = style;
-    fLocale = locale;
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        fTimeUnitToCountToPatterns[i] = NULL;
-    }
-    //TODO: format() and parseObj() are const member functions,
-    //so, can not do lazy initialization in C++.
-    //setup has to be done in constructors.
-    //and here, the behavior is not consistent with Java.
-    //In Java, create an empty instance does not setup locale as
-    //default locale. If it followed by setNumberFormat(),
-    //in format(), the locale will set up as the locale in fNumberFormat.
-    //But in C++, this sets the locale as the default locale. 
-    setup(status);
-}
-
-void 
-TimeUnitFormat::setup(UErrorCode& err) {
-    initDataMembers(err);
-    readFromCurrentLocale(kFull, gUnitsTag, err);
-    checkConsistency(kFull, gUnitsTag, err);
-    readFromCurrentLocale(kAbbreviate, gShortUnitsTag, err);
-    checkConsistency(kAbbreviate, gShortUnitsTag, err);
-}
-
-
-void
-TimeUnitFormat::initDataMembers(UErrorCode& err){
-    if (U_FAILURE(err)) {
-        return;
-    }
-    if (fNumberFormat == NULL) {
-        fNumberFormat = NumberFormat::createInstance(fLocale, err);
-    }
-    delete fPluralRules;
-    fPluralRules = PluralRules::forLocale(fLocale, err);
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        deleteHash(fTimeUnitToCountToPatterns[i]);
-        fTimeUnitToCountToPatterns[i] = NULL;
-    }
-}
-
-
-
-
-void
-TimeUnitFormat::readFromCurrentLocale(EStyle style, const char* key, UErrorCode& err) {
-    if (U_FAILURE(err)) {
-        return;
-    }
-    // fill timeUnitToCountToPatterns from resource file
-    // err is used to indicate wrong status except missing resource.
-    // status is an error code used in resource lookup.
-    // status does not affect "err".
-    UErrorCode status = U_ZERO_ERROR;
-    UResourceBundle *rb, *unitsRes;
-    rb = ures_open(NULL, fLocale.getName(), &status);
-    unitsRes = ures_getByKey(rb, key, NULL, &status);
-    if (U_FAILURE(status)) {
-        ures_close(unitsRes);
-        ures_close(rb);
-        return;
-    }
-    int32_t size = ures_getSize(unitsRes);
-    for ( int32_t index = 0; index < size; ++index) {
-        // resource of one time unit
-        UResourceBundle* oneTimeUnit = ures_getByIndex(unitsRes, index,
-                                                       NULL, &status);
-        if (U_SUCCESS(status)) {
-            const char* timeUnitName = ures_getKey(oneTimeUnit);
-            if (timeUnitName == NULL) {
-                ures_close(oneTimeUnit);
-                continue;
-            }
-            UResourceBundle* countsToPatternRB = ures_getByKey(unitsRes, 
-                                                             timeUnitName, 
-                                                             NULL, &status);
-            if (countsToPatternRB == NULL || U_FAILURE(status)) {
-                ures_close(countsToPatternRB);
-                ures_close(oneTimeUnit);
-                continue;
-            }
-            TimeUnit::UTimeUnitFields timeUnitField = TimeUnit::UTIMEUNIT_FIELD_COUNT;
-            if ( uprv_strcmp(timeUnitName, gTimeUnitYear) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_YEAR;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitMonth) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_MONTH;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitDay) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_DAY;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitHour) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_HOUR;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitMinute) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_MINUTE;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitSecond) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_SECOND;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitWeek) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_WEEK;
-            } else {
-                ures_close(countsToPatternRB);
-                ures_close(oneTimeUnit);
-                continue;
-            }
-            Hashtable* countToPatterns = fTimeUnitToCountToPatterns[timeUnitField];
-            if (countToPatterns == NULL) {
-                countToPatterns = initHash(err);
-                if (U_FAILURE(err)) {
-                    ures_close(countsToPatternRB);
-                    ures_close(oneTimeUnit);
-                    delete countToPatterns;
-                    break;
-                }
-            }
-            int32_t count = ures_getSize(countsToPatternRB);
-            const UChar* pattern;
-            const char*  pluralCount;
-            int32_t ptLength; 
-            for ( int32_t pluralIndex = 0; pluralIndex < count; ++pluralIndex) {
-                // resource of count to pattern
-                pattern = ures_getNextString(countsToPatternRB, &ptLength,
-                                             &pluralCount, &status);
-                if (U_FAILURE(status)) {
-                    continue;
-                }
-                MessageFormat* messageFormat = new MessageFormat(pattern, fLocale, err);
-                if ( U_SUCCESS(err) ) {
-                  if (fNumberFormat != NULL) {
-                    messageFormat->setFormat(0, *fNumberFormat);
-                  }
-                  MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCount);
-                  if (formatters == NULL) {
-                    // formatters = new MessageFormat*[kTotal];
-                    formatters = (MessageFormat**)uprv_malloc(2*sizeof(MessageFormat*));
-                    formatters[kFull] = NULL;
-                    formatters[kAbbreviate] = NULL;
-                    countToPatterns->put(pluralCount, formatters, err);
-                    if (U_FAILURE(err)) {
-                        delete [] formatters;
-                    }
-                  } 
-                  if (U_SUCCESS(err)) {
-                      //delete formatters[style];
-                      formatters[style] = messageFormat;
-                  }
-                } 
-                if (U_FAILURE(err)) {
-                    ures_close(countsToPatternRB);
-                    ures_close(oneTimeUnit);
-                    ures_close(unitsRes);
-                    ures_close(rb);
-                    delete messageFormat;
-                    delete countToPatterns;
-                    return;
-                }
-            }
-            if (fTimeUnitToCountToPatterns[timeUnitField] == NULL) {
-                fTimeUnitToCountToPatterns[timeUnitField] = countToPatterns;
-            }
-            ures_close(countsToPatternRB);
-        }
-        ures_close(oneTimeUnit);
-    }
-    ures_close(unitsRes);
-    ures_close(rb);
-}
-
-
-void 
-TimeUnitFormat::checkConsistency(EStyle style, const char* key, UErrorCode& err) {
-    if (U_FAILURE(err)) {
-        return;
-    }
-    // there should be patterns for each plural rule in each time unit.
-    // For each time unit, 
-    //     for each plural rule, following is unit pattern fall-back rule:
-    //         ( for example: "one" hour )
-    //         look for its unit pattern in its locale tree.
-    //         if pattern is not found in its own locale, such as de_DE,
-    //         look for the pattern in its parent, such as de,
-    //         keep looking till found or till root.
-    //         if the pattern is not found in root either,
-    //         fallback to plural count "other",
-    //         look for the pattern of "other" in the locale tree:
-    //         "de_DE" to "de" to "root".
-    //         If not found, fall back to value of 
-    //         static variable DEFAULT_PATTERN_FOR_xxx, such as "{0} h". 
-    //
-    // Following is consistency check to create pattern for each
-    // plural rule in each time unit using above fall-back rule.
-    //
-    StringEnumeration* keywords = fPluralRules->getKeywords(err);
-    if (U_SUCCESS(err)) {
-        const char* pluralCount;
-        while ((pluralCount = keywords->next(NULL, err)) != NULL) {
-            if ( U_SUCCESS(err) ) {
-                for (int32_t i = 0; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; ++i) {
-                    // for each time unit, 
-                    // get all the patterns for each plural rule in this locale.
-                    Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
-                    if ( countToPatterns == NULL ) {
-                        countToPatterns = initHash(err);
-                        if (U_FAILURE(err)) {
-                            delete countToPatterns;
-                            return;
-                        }
-                        fTimeUnitToCountToPatterns[i] = countToPatterns;
-                    }
-                    MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCount);
-                    if( formatters == NULL || formatters[style] == NULL ) {
-                        // look through parents
-                        searchInLocaleChain(style, key,
-                                            (TimeUnit::UTimeUnitFields)i, 
-                                            pluralCount, pluralCount, 
-                                            countToPatterns, err);
-                    }
-                }
-            }
-        }
-    }
-    delete keywords;
-}
-
-
-
-// srcPluralCount is the original plural count on which the pattern is
-// searched for.
-// searchPluralCount is the fallback plural count.
-// For example, to search for pattern for ""one" hour",
-// "one" is the srcPluralCount,
-// if the pattern is not found even in root, fallback to 
-// using patterns of plural count "other", 
-// then, "other" is the searchPluralCount.
-void 
-TimeUnitFormat::searchInLocaleChain(EStyle style, const char* key,
-                                TimeUnit::UTimeUnitFields srcTimeUnitField,
-                                const char* srcPluralCount,
-                                const char* searchPluralCount, 
-                                Hashtable* countToPatterns,
-                                UErrorCode& err) {
-    if (U_FAILURE(err)) {
-        return;
-    }
-    UErrorCode status = U_ZERO_ERROR;
-    const char *locName = fLocale.getName();
-    char parentLocale[ULOC_FULLNAME_CAPACITY];
-    uprv_strcpy(parentLocale, locName);
-    int32_t locNameLen;
-    while ((locNameLen = uloc_getParent(parentLocale, parentLocale,
-                                        ULOC_FULLNAME_CAPACITY, &status)) >= 0){
-        // look for pattern for srcPluralCount in locale tree
-        UResourceBundle *rb, *unitsRes, *countsToPatternRB;
-        rb = ures_open(NULL, parentLocale, &status);
-        unitsRes = ures_getByKey(rb, key, NULL, &status);
-        const char* timeUnitName = getTimeUnitName(srcTimeUnitField, status);
-        countsToPatternRB = ures_getByKey(unitsRes, timeUnitName, NULL, &status);
-        const UChar* pattern;
-        int32_t      ptLength;
-        pattern = ures_getStringByKeyWithFallback(countsToPatternRB, searchPluralCount, &ptLength, &status);
-        if (U_SUCCESS(status)) {
-            //found
-            MessageFormat* messageFormat = new MessageFormat(pattern, fLocale, err);
-            if (U_SUCCESS(err)) {
-                if (fNumberFormat != NULL) {
-                    messageFormat->setFormat(0, *fNumberFormat);
-                }
-                MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
-                if (formatters == NULL) {
-                    //formatters = new MessageFormat*[kTotal];
-                    formatters = (MessageFormat**)uprv_malloc(2*sizeof(MessageFormat*));
-                    formatters[kFull] = NULL;
-                    formatters[kAbbreviate] = NULL;
-                    countToPatterns->put(srcPluralCount, formatters, err);
-                    if (U_FAILURE(err)) {
-                        delete [] formatters;
-                        delete messageFormat;
-                    }
-                } 
-                if (U_SUCCESS(err)) {
-                    //delete formatters[style];
-                    formatters[style] = messageFormat;
-                }
-            } else {
-                delete messageFormat;
-            }
-            ures_close(countsToPatternRB);
-            ures_close(unitsRes);
-            ures_close(rb);
-            return;
-        }
-        ures_close(countsToPatternRB);
-        ures_close(unitsRes);
-        ures_close(rb);
-        if ( locNameLen ==0 ) {
-            break;
-        }
-    }
-    // if not found the pattern for this plural count at all,
-    // fall-back to plural count "other"
-    if ( uprv_strcmp(searchPluralCount, gPluralCountOther) == 0 ) {
-        // set default fall back the same as the resource in root
-        MessageFormat* messageFormat = NULL;
-        if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_SECOND ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_SECOND, fLocale, err);
-        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_MINUTE ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MINUTE, fLocale, err);
-        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_HOUR ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_HOUR, fLocale, err);
-        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_WEEK ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_WEEK, fLocale, err);
-        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_DAY ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_DAY, fLocale, err);
-        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_MONTH ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MONTH, fLocale, err);
-        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_YEAR ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_YEAR, fLocale, err);
-        }
-        if (U_SUCCESS(err)) {
-            if (fNumberFormat != NULL && messageFormat != NULL) {
-                messageFormat->setFormat(0, *fNumberFormat);
-            }
-            MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
-            if (formatters == NULL) {
-                //formatters = new MessageFormat*[kTotal];
-                formatters = (MessageFormat**)uprv_malloc(2*sizeof(MessageFormat*));
-                formatters[kFull] = NULL;
-                formatters[kAbbreviate] = NULL;
-                countToPatterns->put(srcPluralCount, formatters, err);
-                if (U_FAILURE(err)) {
-                    delete [] formatters;
-                    delete messageFormat;
-                }
-            }
-            if (U_SUCCESS(err)) {
-                //delete formatters[style];
-                formatters[style] = messageFormat;
-            }
-        } else {
-            delete messageFormat;
-        }
-    } else {
-        // fall back to rule "other", and search in parents
-        searchInLocaleChain(style, key, srcTimeUnitField, srcPluralCount, 
-                            gPluralCountOther, countToPatterns, err);
-    }
-}
-
-void 
-TimeUnitFormat::setLocale(const Locale& locale, UErrorCode& status) {
-    if (U_SUCCESS(status) && fLocale != locale) {
-        fLocale = locale;
-        setup(status);
-    }
-}
-
-
-void 
-TimeUnitFormat::setNumberFormat(const NumberFormat& format, UErrorCode& status){
-    if (U_FAILURE(status) || fNumberFormat && format == *fNumberFormat) {
-        return;
-    }
-    delete fNumberFormat;
-    fNumberFormat = (NumberFormat*)format.clone();
-    // reset the number formatter in the fTimeUnitToCountToPatterns map
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        int32_t pos = -1;
-        const UHashElement* elem = NULL;
-        while ((elem = fTimeUnitToCountToPatterns[i]->nextElement(pos)) != NULL){
-            const UHashTok keyTok = elem->value;
-            MessageFormat** pattern = (MessageFormat**)keyTok.pointer;
-            pattern[kFull]->setFormat(0, format);
-            pattern[kAbbreviate]->setFormat(0, format);
-        }
-    }
-}
-
-
-void
-TimeUnitFormat::deleteHash(Hashtable* htable) {
-    int32_t pos = -1;
-    const UHashElement* element = NULL;
-    if ( htable ) {
-        while ( (element = htable->nextElement(pos)) != NULL ) {
-            const UHashTok valueTok = element->value;
-            const MessageFormat** value = (const MessageFormat**)valueTok.pointer;
-            delete value[kFull];
-            delete value[kAbbreviate];
-            //delete[] value;
-            uprv_free(value);
-        }
-    }
-    delete htable;
-}
-
-
-void
-TimeUnitFormat::copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return;
-    }
-    int32_t pos = -1;
-    const UHashElement* element = NULL;
-    if ( source ) {
-        while ( (element = source->nextElement(pos)) != NULL ) {
-            const UHashTok keyTok = element->key;
-            const UnicodeString* key = (UnicodeString*)keyTok.pointer;
-            const UHashTok valueTok = element->value;
-            const MessageFormat** value = (const MessageFormat**)valueTok.pointer;
-            //MessageFormat** newVal = new MessageFormat*[kTotal];
-            MessageFormat** newVal = (MessageFormat**)uprv_malloc(2*sizeof(MessageFormat*));
-            newVal[0] = (MessageFormat*)value[0]->clone();
-            newVal[1] = (MessageFormat*)value[1]->clone();
-            target->put(UnicodeString(*key), newVal, status);
-            if ( U_FAILURE(status) ) {
-                delete newVal[0];
-                delete newVal[1];
-                delete [] newVal;
-                return;
-            }
-        }
-    }
-}
-
-
-U_CDECL_BEGIN 
-
-/**
- * set hash table value comparator
- *
- * @param val1  one value in comparison
- * @param val2  the other value in comparison
- * @return      TRUE if 2 values are the same, FALSE otherwise
- */
-static UBool U_CALLCONV hashTableValueComparator(UHashTok val1, UHashTok val2);
-
-U_CDECL_END
-
-UBool 
-U_CALLCONV hashTableValueComparator(UHashTok val1, UHashTok val2) {
-    const MessageFormat** pattern1 = (const MessageFormat**)val1.pointer;
-    const MessageFormat** pattern2 = (const MessageFormat**)val2.pointer;
-    return *pattern1[0] == *pattern2[0] && *pattern1[1] == *pattern2[1];
-}
-
-
-Hashtable*
-TimeUnitFormat::initHash(UErrorCode& status) {
-    if ( U_FAILURE(status) ) {
-        return NULL;
-    }
-    Hashtable* hTable;
-    if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
-        status = U_MEMORY_ALLOCATION_ERROR;
-        return NULL;
-    }
-    hTable->setValueCompartor(hashTableValueComparator);
-    return hTable;
-}
-
-
-const char*
-TimeUnitFormat::getTimeUnitName(TimeUnit::UTimeUnitFields unitField, 
-                                UErrorCode& status) {
-    if (U_FAILURE(status)) {
-        return NULL;
-    }
-    switch (unitField) {
-      case TimeUnit::UTIMEUNIT_YEAR:
-        return gTimeUnitYear;
-      case TimeUnit::UTIMEUNIT_MONTH:
-        return gTimeUnitMonth;
-      case TimeUnit::UTIMEUNIT_DAY:
-        return gTimeUnitDay;
-      case TimeUnit::UTIMEUNIT_WEEK:
-        return gTimeUnitWeek;
-      case TimeUnit::UTIMEUNIT_HOUR:
-        return gTimeUnitHour;
-      case TimeUnit::UTIMEUNIT_MINUTE:
-        return gTimeUnitMinute;
-      case TimeUnit::UTIMEUNIT_SECOND:
-        return gTimeUnitSecond;
-      default:
-        status = U_ILLEGAL_ARGUMENT_ERROR;
-        return NULL;
-    }
-}
-
-U_NAMESPACE_END
-
-#endif
+/*
+ *******************************************************************************
+ * Copyright (C) 2008-2009, Google, International Business Machines Corporation
+ * and  others. All Rights Reserved.                                           
+ *******************************************************************************
+ */
+
+
+#include "unicode/tmutfmt.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cmemory.h"
+#include "cstring.h"
+#include "hash.h"
+#include "uresimp.h"
+#include "unicode/msgfmt.h"
+
+#define LEFT_CURLY_BRACKET  ((UChar)0x007B)
+#define RIGHT_CURLY_BRACKET ((UChar)0x007D)
+#define SPACE             ((UChar)0x0020)
+#define DIGIT_ZERO        ((UChar)0x0030)
+#define LOW_S             ((UChar)0x0073)
+#define LOW_M             ((UChar)0x006D)
+#define LOW_I             ((UChar)0x0069)
+#define LOW_N             ((UChar)0x006E)
+#define LOW_H             ((UChar)0x0068)
+#define LOW_W             ((UChar)0x0077)
+#define LOW_D             ((UChar)0x0064)
+#define LOW_Y             ((UChar)0x0079)
+#define LOW_Z             ((UChar)0x007A)
+#define LOW_E             ((UChar)0x0065)
+#define LOW_R             ((UChar)0x0072)
+#define LOW_O             ((UChar)0x006F)
+#define LOW_N             ((UChar)0x006E)
+#define LOW_T             ((UChar)0x0074)
+
+
+//TODO: define in compile time
+//#define TMUTFMT_DEBUG 1
+
+#ifdef TMUTFMT_DEBUG
+#include <iostream>
+#endif
+
+U_NAMESPACE_BEGIN
+
+
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeUnitFormat)
+
+static const char gUnitsTag[] = "units";
+static const char gShortUnitsTag[] = "unitsShort";
+static const char gTimeUnitYear[] = "year";
+static const char gTimeUnitMonth[] = "month";
+static const char gTimeUnitDay[] = "day";
+static const char gTimeUnitWeek[] = "week";
+static const char gTimeUnitHour[] = "hour";
+static const char gTimeUnitMinute[] = "minute";
+static const char gTimeUnitSecond[] = "second";
+static const char gPluralCountOther[] = "other";
+
+static const UChar DEFAULT_PATTERN_FOR_SECOND[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_S, 0};
+static const UChar DEFAULT_PATTERN_FOR_MINUTE[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_M, LOW_I, LOW_N, 0};
+static const UChar DEFAULT_PATTERN_FOR_HOUR[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_H, 0};
+static const UChar DEFAULT_PATTERN_FOR_WEEK[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_W, 0};
+static const UChar DEFAULT_PATTERN_FOR_DAY[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_D, 0};
+static const UChar DEFAULT_PATTERN_FOR_MONTH[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_M, 0};
+static const UChar DEFAULT_PATTERN_FOR_YEAR[] = {LEFT_CURLY_BRACKET, DIGIT_ZERO, RIGHT_CURLY_BRACKET, SPACE, LOW_Y, 0};
+
+static const UChar PLURAL_COUNT_ZERO[] = {LOW_Z, LOW_E, LOW_R, LOW_O, 0};
+static const UChar PLURAL_COUNT_ONE[] = {LOW_O, LOW_N, LOW_E, 0};
+static const UChar PLURAL_COUNT_TWO[] = {LOW_T, LOW_W, LOW_O, 0};
+
+
+TimeUnitFormat::TimeUnitFormat(UErrorCode& status)
+:   fNumberFormat(NULL),
+    fPluralRules(NULL) {
+    create(Locale::getDefault(), kFull, status);
+}
+
+
+TimeUnitFormat::TimeUnitFormat(const Locale& locale, UErrorCode& status)
+:   fNumberFormat(NULL),
+    fPluralRules(NULL) {
+    create(locale, kFull, status);
+}
+
+
+TimeUnitFormat::TimeUnitFormat(const Locale& locale, EStyle style, UErrorCode& status)
+:   fNumberFormat(NULL),
+    fPluralRules(NULL) {
+    create(locale, style, status);
+}
+
+
+TimeUnitFormat::TimeUnitFormat(const TimeUnitFormat& other)
+:   MeasureFormat(other),
+    fNumberFormat(NULL),
+    fPluralRules(NULL),
+    fStyle(kFull)
+{
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        fTimeUnitToCountToPatterns[i] = NULL;
+    }
+    *this = other;
+}
+
+
+TimeUnitFormat::~TimeUnitFormat() {
+    delete fNumberFormat;
+    fNumberFormat = NULL;
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        deleteHash(fTimeUnitToCountToPatterns[i]);
+        fTimeUnitToCountToPatterns[i] = NULL;
+    }
+    delete fPluralRules;
+    fPluralRules = NULL;
+}
+
+
+Format* 
+TimeUnitFormat::clone(void) const {
+    return new TimeUnitFormat(*this);
+}
+
+
+TimeUnitFormat& 
+TimeUnitFormat::operator=(const TimeUnitFormat& other) {
+    if (this == &other) {
+        return *this;
+    }
+    delete fNumberFormat;
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        deleteHash(fTimeUnitToCountToPatterns[i]);
+        fTimeUnitToCountToPatterns[i] = NULL;
+    }
+    delete fPluralRules;
+    if (other.fNumberFormat) {
+        fNumberFormat = (NumberFormat*)other.fNumberFormat->clone();
+    } else {
+        fNumberFormat = NULL;
+    }
+    fLocale = other.fLocale;
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        UErrorCode status = U_ZERO_ERROR;
+        fTimeUnitToCountToPatterns[i] = initHash(status);
+        if (U_SUCCESS(status)) {
+            copyHash(other.fTimeUnitToCountToPatterns[i], fTimeUnitToCountToPatterns[i], status);
+        } else {
+            delete fTimeUnitToCountToPatterns[i];
+            fTimeUnitToCountToPatterns[i] = NULL;
+        }
+    } 
+    if (other.fPluralRules) {
+        fPluralRules = (PluralRules*)other.fPluralRules->clone();
+    } else {
+        fPluralRules = NULL;
+    }
+    fStyle = other.fStyle;
+    return *this;
+}
+
+
+UBool 
+TimeUnitFormat::operator==(const Format& other) const {
+    if (other.getDynamicClassID() == TimeUnitFormat::getStaticClassID()) {
+        TimeUnitFormat* fmt = (TimeUnitFormat*)&other;
+        UBool ret =  ( (fNumberFormat && fmt->fNumberFormat && 
+                        *fNumberFormat == *fmt->fNumberFormat ||
+                        fNumberFormat == fmt->fNumberFormat ) &&
+                       fLocale == fmt->fLocale &&
+                       (fPluralRules && fmt->fPluralRules &&
+                        *fPluralRules == *fmt->fPluralRules ||
+                        fPluralRules == fmt->fPluralRules) &&
+                      fStyle == fmt->fStyle); 
+        if (ret) {
+            for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+                 i < TimeUnit::UTIMEUNIT_FIELD_COUNT && ret;
+                 i = (TimeUnit::UTimeUnitFields)(i+1)) {
+                ret = fTimeUnitToCountToPatterns[i]->equals(*(fmt->fTimeUnitToCountToPatterns[i]));
+            }
+        }
+        return ret;
+    }
+    return false;
+}
+
+
+UnicodeString& 
+TimeUnitFormat::format(const Formattable& obj, UnicodeString& toAppendTo,
+                       FieldPosition& pos, UErrorCode& status) const {
+    if (U_FAILURE(status)) {
+        return toAppendTo;
+    }
+    if (obj.getType() == Formattable::kObject) {
+        const UObject* formatObj = obj.getObject();
+        if (formatObj->getDynamicClassID() == TimeUnitAmount::getStaticClassID()){
+            TimeUnitAmount* amount = (TimeUnitAmount*)formatObj;
+            Hashtable* countToPattern = fTimeUnitToCountToPatterns[amount->getTimeUnitField()];
+            double number;
+            const Formattable& amtNumber = amount->getNumber();
+            if (amtNumber.getType() == Formattable::kDouble) {
+                number = amtNumber.getDouble();
+            } else if (amtNumber.getType() == Formattable::kLong) {
+                number = amtNumber.getLong();
+            } else {
+                status = U_ILLEGAL_ARGUMENT_ERROR;
+                return toAppendTo;
+            }
+            UnicodeString count = fPluralRules->select(number);
+#ifdef TMUTFMT_DEBUG
+            char result[1000];
+            count.extract(0, count.length(), result, "UTF-8");
+            std::cout << "number: " << number << "; format plural count: " << result << "\n";           
+#endif
+            MessageFormat* pattern = ((MessageFormat**)countToPattern->get(count))[fStyle];
+            Formattable formattable[1];
+            formattable[0].setDouble(number);
+            return pattern->format(formattable, 1, toAppendTo, pos, status);
+        }
+    }
+    status = U_ILLEGAL_ARGUMENT_ERROR;
+    return toAppendTo;
+}
+
+
+void 
+TimeUnitFormat::parseObject(const UnicodeString& source, 
+                            Formattable& result,
+                            ParsePosition& pos) const {
+    double resultNumber = -1; 
+    UBool withNumberFormat = false;
+    TimeUnit::UTimeUnitFields resultTimeUnit = TimeUnit::UTIMEUNIT_FIELD_COUNT;
+    int32_t oldPos = pos.getIndex();
+    int32_t newPos = -1;
+    int32_t longestParseDistance = 0;
+    UnicodeString* countOfLongestMatch = NULL;
+#ifdef TMUTFMT_DEBUG
+    char res[1000];
+    source.extract(0, source.length(), res, "UTF-8");
+    std::cout << "parse source: " << res << "\n";           
+#endif
+    // parse by iterating through all available patterns
+    // and looking for the longest match.
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
+        int32_t elemPos = -1;
+        const UHashElement* elem = NULL;
+        while ((elem = countToPatterns->nextElement(elemPos)) != NULL){
+            const UHashTok keyTok = elem->key;
+            UnicodeString* count = (UnicodeString*)keyTok.pointer;
+#ifdef TMUTFMT_DEBUG
+            count->extract(0, count->length(), res, "UTF-8");
+            std::cout << "parse plural count: " << res << "\n";           
+#endif
+            const UHashTok valueTok = elem->value;
+            // the value is a pair of MessageFormat*
+            MessageFormat** patterns = (MessageFormat**)valueTok.pointer;
+            for (EStyle style = kFull; style < kTotal; style = (EStyle)(style + 1)) {
+                MessageFormat* pattern = patterns[style];
+                pos.setErrorIndex(-1);
+                pos.setIndex(oldPos);
+                // see if we can parse
+                Formattable parsed;
+                pattern->parseObject(source, parsed, pos);
+                if (pos.getErrorIndex() != -1 || pos.getIndex() == oldPos) {
+                    continue;
+                }
+    #ifdef TMUTFMT_DEBUG
+                std::cout << "parsed.getType: " << parsed.getType() << "\n";
+    #endif
+                double tmpNumber = 0;
+                if (pattern->getArgTypeCount() != 0) {
+                    // pattern with Number as beginning, such as "{0} d".
+                    // check to make sure that the timeUnit is consistent
+                    Formattable& temp = parsed[0];
+                    if (temp.getType() == Formattable::kDouble) {
+                        tmpNumber = temp.getDouble();
+                    } else if (temp.getType() == Formattable::kLong) {
+                        tmpNumber = temp.getLong();
+                    } else {
+                        continue;
+                    }
+                    UnicodeString select = fPluralRules->select(tmpNumber);
+    #ifdef TMUTFMT_DEBUG
+                    select.extract(0, select.length(), res, "UTF-8");
+                    std::cout << "parse plural select count: " << res << "\n"; 
+    #endif
+                    if (*count != select) {
+                        continue;
+                    }
+                }
+                int32_t parseDistance = pos.getIndex() - oldPos;
+                if (parseDistance > longestParseDistance) {
+                    if (pattern->getArgTypeCount() != 0) {
+                        resultNumber = tmpNumber;
+                        withNumberFormat = true;
+                    } else {
+                        withNumberFormat = false;
+                    }
+                    resultTimeUnit = i;
+                    newPos = pos.getIndex();
+                    longestParseDistance = parseDistance;
+                    countOfLongestMatch = count;
+                }
+            }
+        }
+    }
+    /* After find the longest match, parse the number.
+     * Result number could be null for the pattern without number pattern.
+     * such as unit pattern in Arabic.
+     * When result number is null, use plural rule to set the number.
+     */
+    if (withNumberFormat == false && longestParseDistance != 0) {
+        // set the number using plurrual count
+        if ( *countOfLongestMatch == PLURAL_COUNT_ZERO ) {
+            resultNumber = 0;
+        } else if ( *countOfLongestMatch == PLURAL_COUNT_ONE ) {
+            resultNumber = 1;
+        } else if ( *countOfLongestMatch == PLURAL_COUNT_TWO ) {
+            resultNumber = 2;
+        } else {
+            // should not happen.
+            // TODO: how to handle?
+            resultNumber = 3;
+        }
+    }
+    if (longestParseDistance == 0) {
+        pos.setIndex(oldPos);
+        pos.setErrorIndex(0);
+    } else {
+        UErrorCode status = U_ZERO_ERROR;
+        TimeUnitAmount* tmutamt = new TimeUnitAmount(resultNumber, resultTimeUnit, status);
+        if (U_SUCCESS(status)) {
+            result.adoptObject(tmutamt);
+            pos.setIndex(newPos);
+            pos.setErrorIndex(-1);
+        } else {
+            pos.setIndex(oldPos);
+            pos.setErrorIndex(0);
+        }
+    }
+}
+
+
+void
+TimeUnitFormat::create(const Locale& locale, EStyle style, UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return;
+    }
+    if (style < kFull || style > kAbbreviate) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return;
+    }
+    fStyle = style;
+    fLocale = locale;
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        fTimeUnitToCountToPatterns[i] = NULL;
+    }
+    //TODO: format() and parseObj() are const member functions,
+    //so, can not do lazy initialization in C++.
+    //setup has to be done in constructors.
+    //and here, the behavior is not consistent with Java.
+    //In Java, create an empty instance does not setup locale as
+    //default locale. If it followed by setNumberFormat(),
+    //in format(), the locale will set up as the locale in fNumberFormat.
+    //But in C++, this sets the locale as the default locale. 
+    setup(status);
+}
+
+void 
+TimeUnitFormat::setup(UErrorCode& err) {
+    initDataMembers(err);
+    readFromCurrentLocale(kFull, gUnitsTag, err);
+    checkConsistency(kFull, gUnitsTag, err);
+    readFromCurrentLocale(kAbbreviate, gShortUnitsTag, err);
+    checkConsistency(kAbbreviate, gShortUnitsTag, err);
+}
+
+
+void
+TimeUnitFormat::initDataMembers(UErrorCode& err){
+    if (U_FAILURE(err)) {
+        return;
+    }
+    if (fNumberFormat == NULL) {
+        fNumberFormat = NumberFormat::createInstance(fLocale, err);
+    }
+    delete fPluralRules;
+    fPluralRules = PluralRules::forLocale(fLocale, err);
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        deleteHash(fTimeUnitToCountToPatterns[i]);
+        fTimeUnitToCountToPatterns[i] = NULL;
+    }
+}
+
+
+
+
+void
+TimeUnitFormat::readFromCurrentLocale(EStyle style, const char* key, UErrorCode& err) {
+    if (U_FAILURE(err)) {
+        return;
+    }
+    // fill timeUnitToCountToPatterns from resource file
+    // err is used to indicate wrong status except missing resource.
+    // status is an error code used in resource lookup.
+    // status does not affect "err".
+    UErrorCode status = U_ZERO_ERROR;
+    UResourceBundle *rb, *unitsRes;
+    rb = ures_open(NULL, fLocale.getName(), &status);
+    unitsRes = ures_getByKey(rb, key, NULL, &status);
+    if (U_FAILURE(status)) {
+        ures_close(unitsRes);
+        ures_close(rb);
+        return;
+    }
+    int32_t size = ures_getSize(unitsRes);
+    for ( int32_t index = 0; index < size; ++index) {
+        // resource of one time unit
+        UResourceBundle* oneTimeUnit = ures_getByIndex(unitsRes, index,
+                                                       NULL, &status);
+        if (U_SUCCESS(status)) {
+            const char* timeUnitName = ures_getKey(oneTimeUnit);
+            if (timeUnitName == NULL) {
+                ures_close(oneTimeUnit);
+                continue;
+            }
+            UResourceBundle* countsToPatternRB = ures_getByKey(unitsRes, 
+                                                             timeUnitName, 
+                                                             NULL, &status);
+            if (countsToPatternRB == NULL || U_FAILURE(status)) {
+                ures_close(countsToPatternRB);
+                ures_close(oneTimeUnit);
+                continue;
+            }
+            TimeUnit::UTimeUnitFields timeUnitField = TimeUnit::UTIMEUNIT_FIELD_COUNT;
+            if ( uprv_strcmp(timeUnitName, gTimeUnitYear) == 0 ) {
+                timeUnitField = TimeUnit::UTIMEUNIT_YEAR;
+            } else if ( uprv_strcmp(timeUnitName, gTimeUnitMonth) == 0 ) {
+                timeUnitField = TimeUnit::UTIMEUNIT_MONTH;
+            } else if ( uprv_strcmp(timeUnitName, gTimeUnitDay) == 0 ) {
+                timeUnitField = TimeUnit::UTIMEUNIT_DAY;
+            } else if ( uprv_strcmp(timeUnitName, gTimeUnitHour) == 0 ) {
+                timeUnitField = TimeUnit::UTIMEUNIT_HOUR;
+            } else if ( uprv_strcmp(timeUnitName, gTimeUnitMinute) == 0 ) {
+                timeUnitField = TimeUnit::UTIMEUNIT_MINUTE;
+            } else if ( uprv_strcmp(timeUnitName, gTimeUnitSecond) == 0 ) {
+                timeUnitField = TimeUnit::UTIMEUNIT_SECOND;
+            } else if ( uprv_strcmp(timeUnitName, gTimeUnitWeek) == 0 ) {
+                timeUnitField = TimeUnit::UTIMEUNIT_WEEK;
+            } else {
+                ures_close(countsToPatternRB);
+                ures_close(oneTimeUnit);
+                continue;
+            }
+            Hashtable* countToPatterns = fTimeUnitToCountToPatterns[timeUnitField];
+            if (countToPatterns == NULL) {
+                countToPatterns = initHash(err);
+                if (U_FAILURE(err)) {
+                    ures_close(countsToPatternRB);
+                    ures_close(oneTimeUnit);
+                    delete countToPatterns;
+                    break;
+                }
+            }
+            int32_t count = ures_getSize(countsToPatternRB);
+            const UChar* pattern;
+            const char*  pluralCount;
+            int32_t ptLength; 
+            for ( int32_t pluralIndex = 0; pluralIndex < count; ++pluralIndex) {
+                // resource of count to pattern
+                pattern = ures_getNextString(countsToPatternRB, &ptLength,
+                                             &pluralCount, &status);
+                if (U_FAILURE(status)) {
+                    continue;
+                }
+                MessageFormat* messageFormat = new MessageFormat(pattern, fLocale, err);
+                if ( U_SUCCESS(err) ) {
+                  if (fNumberFormat != NULL) {
+                    messageFormat->setFormat(0, *fNumberFormat);
+                  }
+                  MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCount);
+                  if (formatters == NULL) {
+                    // formatters = new MessageFormat*[kTotal];
+                    formatters = (MessageFormat**)uprv_malloc(2*sizeof(MessageFormat*));
+                    formatters[kFull] = NULL;
+                    formatters[kAbbreviate] = NULL;
+                    countToPatterns->put(pluralCount, formatters, err);
+                    if (U_FAILURE(err)) {
+                        delete [] formatters;
+                    }
+                  } 
+                  if (U_SUCCESS(err)) {
+                      //delete formatters[style];
+                      formatters[style] = messageFormat;
+                  }
+                } 
+                if (U_FAILURE(err)) {
+                    ures_close(countsToPatternRB);
+                    ures_close(oneTimeUnit);
+                    ures_close(unitsRes);
+                    ures_close(rb);
+                    delete messageFormat;
+                    delete countToPatterns;
+                    return;
+                }
+            }
+            if (fTimeUnitToCountToPatterns[timeUnitField] == NULL) {
+                fTimeUnitToCountToPatterns[timeUnitField] = countToPatterns;
+            }
+            ures_close(countsToPatternRB);
+        }
+        ures_close(oneTimeUnit);
+    }
+    ures_close(unitsRes);
+    ures_close(rb);
+}
+
+
+void 
+TimeUnitFormat::checkConsistency(EStyle style, const char* key, UErrorCode& err) {
+    if (U_FAILURE(err)) {
+        return;
+    }
+    // there should be patterns for each plural rule in each time unit.
+    // For each time unit, 
+    //     for each plural rule, following is unit pattern fall-back rule:
+    //         ( for example: "one" hour )
+    //         look for its unit pattern in its locale tree.
+    //         if pattern is not found in its own locale, such as de_DE,
+    //         look for the pattern in its parent, such as de,
+    //         keep looking till found or till root.
+    //         if the pattern is not found in root either,
+    //         fallback to plural count "other",
+    //         look for the pattern of "other" in the locale tree:
+    //         "de_DE" to "de" to "root".
+    //         If not found, fall back to value of 
+    //         static variable DEFAULT_PATTERN_FOR_xxx, such as "{0} h". 
+    //
+    // Following is consistency check to create pattern for each
+    // plural rule in each time unit using above fall-back rule.
+    //
+    StringEnumeration* keywords = fPluralRules->getKeywords(err);
+    if (U_SUCCESS(err)) {
+        const char* pluralCount;
+        while ((pluralCount = keywords->next(NULL, err)) != NULL) {
+            if ( U_SUCCESS(err) ) {
+                for (int32_t i = 0; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; ++i) {
+                    // for each time unit, 
+                    // get all the patterns for each plural rule in this locale.
+                    Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
+                    if ( countToPatterns == NULL ) {
+                        countToPatterns = initHash(err);
+                        if (U_FAILURE(err)) {
+                            delete countToPatterns;
+                            return;
+                        }
+                        fTimeUnitToCountToPatterns[i] = countToPatterns;
+                    }
+                    MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCount);
+                    if( formatters == NULL || formatters[style] == NULL ) {
+                        // look through parents
+                        searchInLocaleChain(style, key,
+                                            (TimeUnit::UTimeUnitFields)i, 
+                                            pluralCount, pluralCount, 
+                                            countToPatterns, err);
+                    }
+                }
+            }
+        }
+    }
+    delete keywords;
+}
+
+
+
+// srcPluralCount is the original plural count on which the pattern is
+// searched for.
+// searchPluralCount is the fallback plural count.
+// For example, to search for pattern for ""one" hour",
+// "one" is the srcPluralCount,
+// if the pattern is not found even in root, fallback to 
+// using patterns of plural count "other", 
+// then, "other" is the searchPluralCount.
+void 
+TimeUnitFormat::searchInLocaleChain(EStyle style, const char* key,
+                                TimeUnit::UTimeUnitFields srcTimeUnitField,
+                                const char* srcPluralCount,
+                                const char* searchPluralCount, 
+                                Hashtable* countToPatterns,
+                                UErrorCode& err) {
+    if (U_FAILURE(err)) {
+        return;
+    }
+    UErrorCode status = U_ZERO_ERROR;
+    const char *locName = fLocale.getName();
+    char parentLocale[ULOC_FULLNAME_CAPACITY];
+    uprv_strcpy(parentLocale, locName);
+    int32_t locNameLen;
+    while ((locNameLen = uloc_getParent(parentLocale, parentLocale,
+                                        ULOC_FULLNAME_CAPACITY, &status)) >= 0){
+        // look for pattern for srcPluralCount in locale tree
+        UResourceBundle *rb, *unitsRes, *countsToPatternRB;
+        rb = ures_open(NULL, parentLocale, &status);
+        unitsRes = ures_getByKey(rb, key, NULL, &status);
+        const char* timeUnitName = getTimeUnitName(srcTimeUnitField, status);
+        countsToPatternRB = ures_getByKey(unitsRes, timeUnitName, NULL, &status);
+        const UChar* pattern;
+        int32_t      ptLength;
+        pattern = ures_getStringByKeyWithFallback(countsToPatternRB, searchPluralCount, &ptLength, &status);
+        if (U_SUCCESS(status)) {
+            //found
+            MessageFormat* messageFormat = new MessageFormat(pattern, fLocale, err);
+            if (U_SUCCESS(err)) {
+                if (fNumberFormat != NULL) {
+                    messageFormat->setFormat(0, *fNumberFormat);
+                }
+                MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
+                if (formatters == NULL) {
+                    //formatters = new MessageFormat*[kTotal];
+                    formatters = (MessageFormat**)uprv_malloc(2*sizeof(MessageFormat*));
+                    formatters[kFull] = NULL;
+                    formatters[kAbbreviate] = NULL;
+                    countToPatterns->put(srcPluralCount, formatters, err);
+                    if (U_FAILURE(err)) {
+                        delete [] formatters;
+                        delete messageFormat;
+                    }
+                } 
+                if (U_SUCCESS(err)) {
+                    //delete formatters[style];
+                    formatters[style] = messageFormat;
+                }
+            } else {
+                delete messageFormat;
+            }
+            ures_close(countsToPatternRB);
+            ures_close(unitsRes);
+            ures_close(rb);
+            return;
+        }
+        ures_close(countsToPatternRB);
+        ures_close(unitsRes);
+        ures_close(rb);
+        if ( locNameLen ==0 ) {
+            break;
+        }
+    }
+    // if not found the pattern for this plural count at all,
+    // fall-back to plural count "other"
+    if ( uprv_strcmp(searchPluralCount, gPluralCountOther) == 0 ) {
+        // set default fall back the same as the resource in root
+        MessageFormat* messageFormat = NULL;
+        if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_SECOND ) {
+            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_SECOND, fLocale, err);
+        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_MINUTE ) {
+            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MINUTE, fLocale, err);
+        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_HOUR ) {
+            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_HOUR, fLocale, err);
+        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_WEEK ) {
+            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_WEEK, fLocale, err);
+        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_DAY ) {
+            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_DAY, fLocale, err);
+        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_MONTH ) {
+            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MONTH, fLocale, err);
+        } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_YEAR ) {
+            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_YEAR, fLocale, err);
+        }
+        if (U_SUCCESS(err)) {
+            if (fNumberFormat != NULL && messageFormat != NULL) {
+                messageFormat->setFormat(0, *fNumberFormat);
+            }
+            MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
+            if (formatters == NULL) {
+                //formatters = new MessageFormat*[kTotal];
+                formatters = (MessageFormat**)uprv_malloc(2*sizeof(MessageFormat*));
+                formatters[kFull] = NULL;
+                formatters[kAbbreviate] = NULL;
+                countToPatterns->put(srcPluralCount, formatters, err);
+                if (U_FAILURE(err)) {
+                    delete [] formatters;
+                    delete messageFormat;
+                }
+            }
+            if (U_SUCCESS(err)) {
+                //delete formatters[style];
+                formatters[style] = messageFormat;
+            }
+        } else {
+            delete messageFormat;
+        }
+    } else {
+        // fall back to rule "other", and search in parents
+        searchInLocaleChain(style, key, srcTimeUnitField, srcPluralCount, 
+                            gPluralCountOther, countToPatterns, err);
+    }
+}
+
+void 
+TimeUnitFormat::setLocale(const Locale& locale, UErrorCode& status) {
+    if (U_SUCCESS(status) && fLocale != locale) {
+        fLocale = locale;
+        setup(status);
+    }
+}
+
+
+void 
+TimeUnitFormat::setNumberFormat(const NumberFormat& format, UErrorCode& status){
+    if (U_FAILURE(status) || fNumberFormat && format == *fNumberFormat) {
+        return;
+    }
+    delete fNumberFormat;
+    fNumberFormat = (NumberFormat*)format.clone();
+    // reset the number formatter in the fTimeUnitToCountToPatterns map
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        int32_t pos = -1;
+        const UHashElement* elem = NULL;
+        while ((elem = fTimeUnitToCountToPatterns[i]->nextElement(pos)) != NULL){
+            const UHashTok keyTok = elem->value;
+            MessageFormat** pattern = (MessageFormat**)keyTok.pointer;
+            pattern[kFull]->setFormat(0, format);
+            pattern[kAbbreviate]->setFormat(0, format);
+        }
+    }
+}
+
+
+void
+TimeUnitFormat::deleteHash(Hashtable* htable) {
+    int32_t pos = -1;
+    const UHashElement* element = NULL;
+    if ( htable ) {
+        while ( (element = htable->nextElement(pos)) != NULL ) {
+            const UHashTok valueTok = element->value;
+            const MessageFormat** value = (const MessageFormat**)valueTok.pointer;
+            delete value[kFull];
+            delete value[kAbbreviate];
+            //delete[] value;
+            uprv_free(value);
+        }
+    }
+    delete htable;
+}
+
+
+void
+TimeUnitFormat::copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return;
+    }
+    int32_t pos = -1;
+    const UHashElement* element = NULL;
+    if ( source ) {
+        while ( (element = source->nextElement(pos)) != NULL ) {
+            const UHashTok keyTok = element->key;
+            const UnicodeString* key = (UnicodeString*)keyTok.pointer;
+            const UHashTok valueTok = element->value;
+            const MessageFormat** value = (const MessageFormat**)valueTok.pointer;
+            //MessageFormat** newVal = new MessageFormat*[kTotal];
+            MessageFormat** newVal = (MessageFormat**)uprv_malloc(2*sizeof(MessageFormat*));
+            newVal[0] = (MessageFormat*)value[0]->clone();
+            newVal[1] = (MessageFormat*)value[1]->clone();
+            target->put(UnicodeString(*key), newVal, status);
+            if ( U_FAILURE(status) ) {
+                delete newVal[0];
+                delete newVal[1];
+                delete [] newVal;
+                return;
+            }
+        }
+    }
+}
+
+
+U_CDECL_BEGIN 
+
+/**
+ * set hash table value comparator
+ *
+ * @param val1  one value in comparison
+ * @param val2  the other value in comparison
+ * @return      TRUE if 2 values are the same, FALSE otherwise
+ */
+static UBool U_CALLCONV hashTableValueComparator(UHashTok val1, UHashTok val2);
+
+U_CDECL_END
+
+UBool 
+U_CALLCONV hashTableValueComparator(UHashTok val1, UHashTok val2) {
+    const MessageFormat** pattern1 = (const MessageFormat**)val1.pointer;
+    const MessageFormat** pattern2 = (const MessageFormat**)val2.pointer;
+    return *pattern1[0] == *pattern2[0] && *pattern1[1] == *pattern2[1];
+}
+
+
+Hashtable*
+TimeUnitFormat::initHash(UErrorCode& status) {
+    if ( U_FAILURE(status) ) {
+        return NULL;
+    }
+    Hashtable* hTable;
+    if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return NULL;
+    }
+    hTable->setValueCompartor(hashTableValueComparator);
+    return hTable;
+}
+
+
+const char*
+TimeUnitFormat::getTimeUnitName(TimeUnit::UTimeUnitFields unitField, 
+                                UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    switch (unitField) {
+      case TimeUnit::UTIMEUNIT_YEAR:
+        return gTimeUnitYear;
+      case TimeUnit::UTIMEUNIT_MONTH:
+        return gTimeUnitMonth;
+      case TimeUnit::UTIMEUNIT_DAY:
+        return gTimeUnitDay;
+      case TimeUnit::UTIMEUNIT_WEEK:
+        return gTimeUnitWeek;
+      case TimeUnit::UTIMEUNIT_HOUR:
+        return gTimeUnitHour;
+      case TimeUnit::UTIMEUNIT_MINUTE:
+        return gTimeUnitMinute;
+      case TimeUnit::UTIMEUNIT_SECOND:
+        return gTimeUnitSecond;
+      default:
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return NULL;
+    }
+}
+
+U_NAMESPACE_END
+
+#endif

Modified: trunk/source/i18n/unicode/currpinf.h
===================================================================
--- trunk/source/i18n/unicode/currpinf.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/unicode/currpinf.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,259 +1,259 @@
-/*
- *******************************************************************************
- * Copyright (C) 2009, International Business Machines Corporation and         *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-#ifndef CURRPINF_H
-#define CURRPINF_H
-
-#include "unicode/utypes.h"
-
-/**
- * \file
- * \brief C++ API: Currency Plural Information used by Decimal Format
- */
-
-#if !UCONFIG_NO_FORMATTING
-
-#include "unicode/unistr.h"
-
-union UHashTok;
-
-U_NAMESPACE_BEGIN
-
-class Locale;
-class PluralRules;
-class Hashtable;
-
-/**
- * This class represents the information needed by 
- * DecimalFormat to format currency plural, 
- * such as "3.00 US dollars" or "1.00 US dollar". 
- * DecimalFormat creates for itself an instance of
- * CurrencyPluralInfo from its locale data.  
- * If you need to change any of these symbols, you can get the
- * CurrencyPluralInfo object from your 
- * DecimalFormat and modify it.
- *
- * Following are the information needed for currency plural format and parse:
- * locale information,
- * plural rule of the locale,
- * currency plural pattern of the locale.
- *
- * @draft ICU 4.2
- */
-class  U_I18N_API CurrencyPluralInfo : public UObject {
-public:
-
-    /**
-     * Create a CurrencyPluralInfo object for the default locale.
-     * @param status output param set to success/failure code on exit
-     * @draft ICU 4.2
-     */
-    CurrencyPluralInfo(UErrorCode& status);
-
-    /**
-     * Create a CurrencyPluralInfo object for the given locale.
-     * @param locale the locale
-     * @param status output param set to success/failure code on exit
-     * @draft ICU 4.2
-     */
-    CurrencyPluralInfo(const Locale& locale, UErrorCode& status); 
-
-    /**
-     * Copy constructor
-     *
-     * @draft ICU 4.2
-     */
-    CurrencyPluralInfo(const CurrencyPluralInfo& info);
-
-
-    /**
-     * Assignment operator
-     *
-     * @draft ICU 4.2
-     */
-    CurrencyPluralInfo& operator=(const CurrencyPluralInfo& info);
-
-
-    /**
-     * Destructor
-     *
-     * @draft ICU 4.2
-     */
-    virtual ~CurrencyPluralInfo();
-
-
-    /**
-     * Equal operator.
-     *
-     * @draft ICU 4.2
-     */
-    UBool operator==(const CurrencyPluralInfo& info) const;
-
-
-    /**
-     * Not equal operator
-     *
-     * @draft ICU 4.2
-     */
-    UBool operator!=(const CurrencyPluralInfo& info) const;
-
-
-    /**
-     * Clone
-     *
-     * @draft ICU 4.2
-     */
-    CurrencyPluralInfo* clone() const;
-
-
-    /**
-     * Gets plural rules of this locale, used for currency plural format
-     *
-     * @return plural rule
-     * @draft ICU 4.2
-     */
-    const PluralRules* getPluralRules() const;
-
-    /**
-     * Given a plural count, gets currency plural pattern of this locale, 
-     * used for currency plural format
-     *
-     * @param  pluralCount currency plural count
-     * @param  result      output param to receive the pattern
-     * @return a currency plural pattern based on plural count
-     * @draft ICU 4.2
-     */
-    UnicodeString& getCurrencyPluralPattern(const UnicodeString& pluralCount,
-                                            UnicodeString& result) const; 
-
-    /**
-     * Get locale 
-     *
-     * @return locale
-     * @draft ICU 4.2
-     */
-    const Locale& getLocale() const;
-
-    /**
-     * Set plural rules.
-     * The plural rule is set when CurrencyPluralInfo
-     * instance is created.
-     * You can call this method to reset plural rules only if you want
-     * to modify the default plural rule of the locale.
-     *
-     * @param ruleDescription new plural rule description
-     * @param status output param set to success/failure code on exit
-     * @draft ICU 4.2
-     */
-    void setPluralRules(const UnicodeString& ruleDescription,
-                        UErrorCode& status);
-
-    /**
-     * Set currency plural pattern.
-     * The currency plural pattern is set when CurrencyPluralInfo
-     * instance is created.
-     * You can call this method to reset currency plural pattern only if 
-     * you want to modify the default currency plural pattern of the locale.
-     *
-     * @param pluralCount the plural count for which the currency pattern will 
-     *                    be overridden.
-     * @param pattern     the new currency plural pattern
-     * @param status      output param set to success/failure code on exit
-     * @draft ICU 4.2
-     */
-    void setCurrencyPluralPattern(const UnicodeString& pluralCount, 
-                                  const UnicodeString& pattern,
-                                  UErrorCode& status);
-
-    /**
-     * Set locale
-     *
-     * @param loc     the new locale to set
-     * @param status  output param set to success/failure code on exit
-     * @draft ICU 4.2
-     */
-    void setLocale(const Locale& loc, UErrorCode& status);
-
-    /**
-     * ICU "poor man's RTTI", returns a UClassID for the actual class.
-     *
-     * @draft ICU 4.2
-     */
-    virtual UClassID getDynamicClassID() const;
-
-    /**
-     * ICU "poor man's RTTI", returns a UClassID for this class.
-     *
-     * @draft ICU 4.2
-     */
-    static UClassID U_EXPORT2 getStaticClassID();
-
-private:
-    friend class DecimalFormat;
-
-    void initialize(const Locale& loc, UErrorCode& status);
-   
-    void setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status);
-
-    /*
-     * delete hash table
-     *
-     * @param hTable  hash table to be deleted
-     */
-    void deleteHash(Hashtable* hTable);
-
-
-    /*
-     * initialize hash table
-     *
-     * @param status   output param set to success/failure code on exit
-     * @return         hash table initialized
-     */
-    Hashtable* initHash(UErrorCode& status);
-
-
-
-    /**
-     * copy hash table
-     *
-     * @param source   the source to copy from
-     * @param target   the target to copy to
-     */
-    void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
-
-    //-------------------- private data member ---------------------
-    // map from plural count to currency plural pattern, for example
-    // a plural pattern defined in "CurrencyUnitPatterns" is
-    // "one{{0} {1}}", in which "one" is a plural count
-    // and "{0} {1}" is a currency plural pattern".
-    // The currency plural pattern saved in this mapping is the pattern
-    // defined in "CurrencyUnitPattern" by replacing
-    // {0} with the number format pattern,
-    // and {1} with 3 currency sign.
-    Hashtable* fPluralCountToCurrencyUnitPattern;
-
-    /*
-     * The plural rule is used to format currency plural name,
-     * for example: "3.00 US Dollars".
-     * If there are 3 currency signs in the currency patttern,
-     * the 3 currency signs will be replaced by currency plural name.
-     */
-    PluralRules* fPluralRules;
-
-    // locale
-    Locale* fLocale;
-};
-
-
-inline UBool
-CurrencyPluralInfo::operator!=(const CurrencyPluralInfo& info) const {              return !operator==(info);                                                   }  
-
-U_NAMESPACE_END
-
-#endif /* #if !UCONFIG_NO_FORMATTING */
-
-#endif // _CURRPINFO
-//eof
+/*
+ *******************************************************************************
+ * Copyright (C) 2009, International Business Machines Corporation and         *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+#ifndef CURRPINF_H
+#define CURRPINF_H
+
+#include "unicode/utypes.h"
+
+/**
+ * \file
+ * \brief C++ API: Currency Plural Information used by Decimal Format
+ */
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/unistr.h"
+
+union UHashTok;
+
+U_NAMESPACE_BEGIN
+
+class Locale;
+class PluralRules;
+class Hashtable;
+
+/**
+ * This class represents the information needed by 
+ * DecimalFormat to format currency plural, 
+ * such as "3.00 US dollars" or "1.00 US dollar". 
+ * DecimalFormat creates for itself an instance of
+ * CurrencyPluralInfo from its locale data.  
+ * If you need to change any of these symbols, you can get the
+ * CurrencyPluralInfo object from your 
+ * DecimalFormat and modify it.
+ *
+ * Following are the information needed for currency plural format and parse:
+ * locale information,
+ * plural rule of the locale,
+ * currency plural pattern of the locale.
+ *
+ * @draft ICU 4.2
+ */
+class  U_I18N_API CurrencyPluralInfo : public UObject {
+public:
+
+    /**
+     * Create a CurrencyPluralInfo object for the default locale.
+     * @param status output param set to success/failure code on exit
+     * @draft ICU 4.2
+     */
+    CurrencyPluralInfo(UErrorCode& status);
+
+    /**
+     * Create a CurrencyPluralInfo object for the given locale.
+     * @param locale the locale
+     * @param status output param set to success/failure code on exit
+     * @draft ICU 4.2
+     */
+    CurrencyPluralInfo(const Locale& locale, UErrorCode& status); 
+
+    /**
+     * Copy constructor
+     *
+     * @draft ICU 4.2
+     */
+    CurrencyPluralInfo(const CurrencyPluralInfo& info);
+
+
+    /**
+     * Assignment operator
+     *
+     * @draft ICU 4.2
+     */
+    CurrencyPluralInfo& operator=(const CurrencyPluralInfo& info);
+
+
+    /**
+     * Destructor
+     *
+     * @draft ICU 4.2
+     */
+    virtual ~CurrencyPluralInfo();
+
+
+    /**
+     * Equal operator.
+     *
+     * @draft ICU 4.2
+     */
+    UBool operator==(const CurrencyPluralInfo& info) const;
+
+
+    /**
+     * Not equal operator
+     *
+     * @draft ICU 4.2
+     */
+    UBool operator!=(const CurrencyPluralInfo& info) const;
+
+
+    /**
+     * Clone
+     *
+     * @draft ICU 4.2
+     */
+    CurrencyPluralInfo* clone() const;
+
+
+    /**
+     * Gets plural rules of this locale, used for currency plural format
+     *
+     * @return plural rule
+     * @draft ICU 4.2
+     */
+    const PluralRules* getPluralRules() const;
+
+    /**
+     * Given a plural count, gets currency plural pattern of this locale, 
+     * used for currency plural format
+     *
+     * @param  pluralCount currency plural count
+     * @param  result      output param to receive the pattern
+     * @return a currency plural pattern based on plural count
+     * @draft ICU 4.2
+     */
+    UnicodeString& getCurrencyPluralPattern(const UnicodeString& pluralCount,
+                                            UnicodeString& result) const; 
+
+    /**
+     * Get locale 
+     *
+     * @return locale
+     * @draft ICU 4.2
+     */
+    const Locale& getLocale() const;
+
+    /**
+     * Set plural rules.
+     * The plural rule is set when CurrencyPluralInfo
+     * instance is created.
+     * You can call this method to reset plural rules only if you want
+     * to modify the default plural rule of the locale.
+     *
+     * @param ruleDescription new plural rule description
+     * @param status output param set to success/failure code on exit
+     * @draft ICU 4.2
+     */
+    void setPluralRules(const UnicodeString& ruleDescription,
+                        UErrorCode& status);
+
+    /**
+     * Set currency plural pattern.
+     * The currency plural pattern is set when CurrencyPluralInfo
+     * instance is created.
+     * You can call this method to reset currency plural pattern only if 
+     * you want to modify the default currency plural pattern of the locale.
+     *
+     * @param pluralCount the plural count for which the currency pattern will 
+     *                    be overridden.
+     * @param pattern     the new currency plural pattern
+     * @param status      output param set to success/failure code on exit
+     * @draft ICU 4.2
+     */
+    void setCurrencyPluralPattern(const UnicodeString& pluralCount, 
+                                  const UnicodeString& pattern,
+                                  UErrorCode& status);
+
+    /**
+     * Set locale
+     *
+     * @param loc     the new locale to set
+     * @param status  output param set to success/failure code on exit
+     * @draft ICU 4.2
+     */
+    void setLocale(const Locale& loc, UErrorCode& status);
+
+    /**
+     * ICU "poor man's RTTI", returns a UClassID for the actual class.
+     *
+     * @draft ICU 4.2
+     */
+    virtual UClassID getDynamicClassID() const;
+
+    /**
+     * ICU "poor man's RTTI", returns a UClassID for this class.
+     *
+     * @draft ICU 4.2
+     */
+    static UClassID U_EXPORT2 getStaticClassID();
+
+private:
+    friend class DecimalFormat;
+
+    void initialize(const Locale& loc, UErrorCode& status);
+   
+    void setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status);
+
+    /*
+     * delete hash table
+     *
+     * @param hTable  hash table to be deleted
+     */
+    void deleteHash(Hashtable* hTable);
+
+
+    /*
+     * initialize hash table
+     *
+     * @param status   output param set to success/failure code on exit
+     * @return         hash table initialized
+     */
+    Hashtable* initHash(UErrorCode& status);
+
+
+
+    /**
+     * copy hash table
+     *
+     * @param source   the source to copy from
+     * @param target   the target to copy to
+     */
+    void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
+
+    //-------------------- private data member ---------------------
+    // map from plural count to currency plural pattern, for example
+    // a plural pattern defined in "CurrencyUnitPatterns" is
+    // "one{{0} {1}}", in which "one" is a plural count
+    // and "{0} {1}" is a currency plural pattern".
+    // The currency plural pattern saved in this mapping is the pattern
+    // defined in "CurrencyUnitPattern" by replacing
+    // {0} with the number format pattern,
+    // and {1} with 3 currency sign.
+    Hashtable* fPluralCountToCurrencyUnitPattern;
+
+    /*
+     * The plural rule is used to format currency plural name,
+     * for example: "3.00 US Dollars".
+     * If there are 3 currency signs in the currency patttern,
+     * the 3 currency signs will be replaced by currency plural name.
+     */
+    PluralRules* fPluralRules;
+
+    // locale
+    Locale* fLocale;
+};
+
+
+inline UBool
+CurrencyPluralInfo::operator!=(const CurrencyPluralInfo& info) const {              return !operator==(info);                                                   }  
+
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif // _CURRPINFO
+//eof

Modified: trunk/source/i18n/unicode/dtitvfmt.h
===================================================================
--- trunk/source/i18n/unicode/dtitvfmt.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/unicode/dtitvfmt.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,972 +1,972 @@
-/********************************************************************************
-* Copyright (C) 2008-2009, International Business Machines Corporation and others. All Rights Reserved.
-*******************************************************************************
-*
-* File DTITVFMT.H
-*
-*******************************************************************************
-*/
-
-#ifndef __DTITVFMT_H__
-#define __DTITVFMT_H__
-
-
-#include "unicode/utypes.h"
-
-/**
- * \file 
- * \brief C++ API: Format and parse date interval in a language-independent manner.
- */
- 
-#if !UCONFIG_NO_FORMATTING
-
-#include "unicode/ucal.h"
-#include "unicode/smpdtfmt.h"
-#include "unicode/dtintrv.h"
-#include "unicode/dtitvinf.h"
-#include "unicode/dtptngen.h"
-
-U_NAMESPACE_BEGIN
-
-
-
-/**
- * DateIntervalFormat is a class for formatting and parsing date 
- * intervals in a language-independent manner. 
- * Date interval formatting is supported in Gregorian calendar only.
- * And only formatting is supported. Parsing is not supported.
- *
- * <P>
- * Date interval means from one date to another date,
- * for example, from "Jan 11, 2008" to "Jan 18, 2008".
- * We introduced class DateInterval to represent it.
- * DateInterval is a pair of UDate, which is 
- * the standard milliseconds since 24:00 GMT, Jan 1, 1970.
- *
- * <P>
- * DateIntervalFormat formats a DateInterval into
- * text as compactly as possible. 
- * For example, the date interval format from "Jan 11, 2008" to "Jan 18,. 2008"
- * is "Jan 11-18, 2008" for English.
- * And it parses text into DateInterval, 
- * although initially, parsing is not supported. 
- *
- * <P>
- * There is no structural information in date time patterns. 
- * For any punctuations and string literals inside a date time pattern, 
- * we do not know whether it is just a separator, or a prefix, or a suffix. 
- * Without such information, so, it is difficult to generate a sub-pattern 
- * (or super-pattern) by algorithm.
- * So, formatting a DateInterval is pattern-driven. It is very
- * similar to formatting in SimpleDateFormat.
- * We introduce class DateIntervalInfo to save date interval 
- * patterns, similar to date time pattern in SimpleDateFormat.
- *
- * <P>
- * Logically, the interval patterns are mappings
- * from (skeleton, the_largest_different_calendar_field)
- * to (date_interval_pattern).
- *
- * <P>
- * A skeleton 
- * <ol>
- * <li>
- * only keeps the field pattern letter and ignores all other parts 
- * in a pattern, such as space, punctuations, and string literals.
- * </li>
- * <li>
- * hides the order of fields. 
- * </li>
- * <li>
- * might hide a field's pattern letter length.
- * </li>
- * </ol>
- *
- * For those non-digit calendar fields, the pattern letter length is 
- * important, such as MMM, MMMM, and MMMMM; EEE and EEEE, 
- * and the field's pattern letter length is honored.
- *    
- * For the digit calendar fields,  such as M or MM, d or dd, yy or yyyy, 
- * the field pattern length is ignored and the best match, which is defined 
- * in date time patterns, will be returned without honor the field pattern
- * letter length in skeleton.
- *
- * <P>
- * The calendar fields we support for interval formatting are:
- * year, month, date, day-of-week, am-pm, hour, hour-of-day, and minute.
- * Those calendar fields can be defined in the following order:
- * year >  month > date > hour (in day) >  minute 
- *  
- * The largest different calendar fields between 2 calendars is the
- * first different calendar field in above order.
- *
- * For example: the largest different calendar fields between "Jan 10, 2007" 
- * and "Feb 20, 2008" is year.
- *
- * <P>
- * For other calendar fields, the compact interval formatting is not
- * supported. And the interval format will be fall back to fall-back
- * patterns, which is mostly "{date0} - {date1}".
- *   
- * <P>
- * There is a set of pre-defined static skeleton strings.
- * There are pre-defined interval patterns for those pre-defined skeletons
- * in locales' resource files.
- * For example, for a skeleton UDAT_YEAR_ABBR_MONTH_DAY, which is  "yMMMd",
- * in  en_US, if the largest different calendar field between date1 and date2 
- * is "year", the date interval pattern  is "MMM d, yyyy - MMM d, yyyy", 
- * such as "Jan 10, 2007 - Jan 10, 2008".
- * If the largest different calendar field between date1 and date2 is "month",
- * the date interval pattern is "MMM d - MMM d, yyyy",
- * such as "Jan 10 - Feb 10, 2007".
- * If the largest different calendar field between date1 and date2 is "day",
- * the date interval pattern is ""MMM d-d, yyyy", such as "Jan 10-20, 2007".
- *
- * For date skeleton, the interval patterns when year, or month, or date is 
- * different are defined in resource files.
- * For time skeleton, the interval patterns when am/pm, or hour, or minute is
- * different are defined in resource files.
- *
- * <P>
- * If a skeleton is not found in a locale's DateIntervalInfo, which means
- * the interval patterns for the skeleton is not defined in resource file,
- * the interval pattern will falls back to the interval "fallback" pattern 
- * defined in resource file.
- * If the interval "fallback" pattern is not defined, the default fall-back
- * is "{date0} - {data1}".
- *
- * <P>
- * For the combination of date and time, 
- * The rule to generate interval patterns are:
- * <ol>
- * <li>
- *    when the year, month, or day differs, falls back to fall-back
- *    interval pattern, which mostly is the concatenate the two original 
- *    expressions with a separator between, 
- *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
- *    to "Jan 11, 2007 10:10am" is 
- *    "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 
- * </li>
- * <li>
- *    otherwise, present the date followed by the range expression 
- *    for the time.
- *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
- *    to "Jan 10, 2007 11:10am" is "Jan 10, 2007 10:10 am - 11:10am" 
- * </li>
- * </ol>
- *
- *
- * <P>
- * If two dates are the same, the interval pattern is the single date pattern.
- * For example, interval pattern from "Jan 10, 2007" to "Jan 10, 2007" is 
- * "Jan 10, 2007".
- *
- * Or if the presenting fields between 2 dates have the exact same values,
- * the interval pattern is the  single date pattern. 
- * For example, if user only requests year and month,
- * the interval pattern from "Jan 10, 2007" to "Jan 20, 2007" is "Jan 2007".
- *
- * <P>
- * DateIntervalFormat needs the following information for correct 
- * formatting: time zone, calendar type, pattern, date format symbols, 
- * and date interval patterns.
- * It can be instantiated in 2 ways:
- * <ol>
- * <li>
- *    create an instance using default or given locale plus given skeleton.
- *    Users are encouraged to created date interval formatter this way and 
- *    to use the pre-defined skeleton macros, such as
- *    UDAT_YEAR_NUM_MONTH, which consists the calendar fields and
- *    the format style. 
- * </li>
- * <li>
- *    create an instance using default or given locale plus given skeleton
- *    plus a given DateIntervalInfo.
- *    This factory method is for powerful users who want to provide their own 
- *    interval patterns. 
- *    Locale provides the timezone, calendar, and format symbols information.
- *    Local plus skeleton provides full pattern information.
- *    DateIntervalInfo provides the date interval patterns.
- * </li>
- * </ol>
- *
- * <P>
- * For the calendar field pattern letter, such as G, y, M, d, a, h, H, m, s etc.
- * DateIntervalFormat uses the same syntax as that of
- * DateTime format.
- * 
- * <P>
- * Code Sample: general usage
- * <pre>
- * \code
- *   // the date interval object which the DateIntervalFormat formats on
- *   // and parses into
- *   DateInterval*  dtInterval = new DateInterval(1000*3600*24, 1000*3600*24*2);
- *   UErrorCode status = U_ZERO_ERROR;
- *   DateIntervalFormat* dtIntervalFmt = DateIntervalFormat::createInstance(
- *                           UDAT_YEAR_MONTH_DAY, 
- *                           Locale("en", "GB", ""), status);
- *   UnicodeUnicodeString dateIntervalString;
- *   FieldPosition pos = 0;
- *   // formatting
- *   dtIntervalFmt->format(dtInterval, dateIntervalUnicodeString, pos, status);
- *   delete dtIntervalFmt;
- * \endcode
- * </pre>
- */
-
-class U_I18N_API DateIntervalFormat : public Format {
-public:
-
-    /**
-     * Construct a DateIntervalFormat from skeleton and  the default locale.
-     *
-     * This is a convenient override of 
-     * createInstance(const UnicodeString& skeleton, const Locale& locale,
-     *                UErrorCode&)  
-     * with the value of locale as default locale.
-     *
-     * @param skeleton  the skeleton on which interval format based.
-     * @param status    output param set to success/failure code on exit
-     * @return          a date time interval formatter which the caller owns.
-     * @stable ICU 4.0
-     */
-    static DateIntervalFormat* U_EXPORT2 createInstance(
-                                               const UnicodeString& skeleton,
-                                               UErrorCode& status);
-
-    /**
-     * Construct a DateIntervalFormat from skeleton and a given locale.
-     * <P>
-     * In this factory method, 
-     * the date interval pattern information is load from resource files.
-     * Users are encouraged to created date interval formatter this way and 
-     * to use the pre-defined skeleton macros.
-     *
-     * <P>
-     * There are pre-defined skeletons (defined in udate.h) having predefined 
-     * interval patterns in resource files.
-     * Users are encouraged to use those macros.
-     * For example: 
-     * DateIntervalFormat::createInstance(UDAT_MONTH_DAY, status) 
-     *
-     * The given Locale provides the interval patterns.
-     * For example, for en_GB, if skeleton is UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY,
-     * which is "yMMMEEEd",
-     * the interval patterns defined in resource file to above skeleton are:
-     * "EEE, d MMM, yyyy - EEE, d MMM, yyyy" for year differs,
-     * "EEE, d MMM - EEE, d MMM, yyyy" for month differs,
-     * "EEE, d - EEE, d MMM, yyyy" for day differs,
-     * @param skeleton  the skeleton on which interval format based.
-     * @param locale    the given locale
-     * @param status    output param set to success/failure code on exit
-     * @return          a date time interval formatter which the caller owns.
-     * @stable ICU 4.0
-     */
-
-    static DateIntervalFormat* U_EXPORT2 createInstance(
-                                               const UnicodeString& skeleton,
-                                               const Locale& locale,
-                                               UErrorCode& status);
-
-    /**
-     * Construct a DateIntervalFormat from skeleton
-     *  DateIntervalInfo, and default locale.
-     *
-     * This is a convenient override of
-     * createInstance(const UnicodeString& skeleton, const Locale& locale, 
-     *                const DateIntervalInfo& dtitvinf, UErrorCode&)
-     * with the locale value as default locale.
-     *
-     * @param skeleton  the skeleton on which interval format based.
-     * @param dtitvinf  the DateIntervalInfo object. 
-     * @param status    output param set to success/failure code on exit
-     * @return          a date time interval formatter which the caller owns.
-     * @stable ICU 4.0
-     */
-    static DateIntervalFormat* U_EXPORT2 createInstance(
-                                              const UnicodeString& skeleton,
-                                              const DateIntervalInfo& dtitvinf,
-                                              UErrorCode& status);
-
-    /**
-     * Construct a DateIntervalFormat from skeleton
-     * a DateIntervalInfo, and the given locale.
-     *
-     * <P>
-     * In this factory method, user provides its own date interval pattern
-     * information, instead of using those pre-defined data in resource file. 
-     * This factory method is for powerful users who want to provide their own 
-     * interval patterns. 
-     * <P>
-     * There are pre-defined skeletons (defined in udate.h) having predefined 
-     * interval patterns in resource files.
-     * Users are encouraged to use those macros.
-     * For example: 
-     * DateIntervalFormat::createInstance(UDAT_MONTH_DAY, status) 
-     *
-     * The DateIntervalInfo provides the interval patterns.
-     * and the DateIntervalInfo ownership remains to the caller. 
-     *
-     * User are encouraged to set default interval pattern in DateIntervalInfo
-     * as well, if they want to set other interval patterns ( instead of
-     * reading the interval patterns from resource files).
-     * When the corresponding interval pattern for a largest calendar different
-     * field is not found ( if user not set it ), interval format fallback to
-     * the default interval pattern.
-     * If user does not provide default interval pattern, it fallback to
-     * "{date0} - {date1}" 
-     *
-     * @param skeleton  the skeleton on which interval format based.
-     * @param locale    the given locale
-     * @param dtitvinf  the DateIntervalInfo object.
-     * @param status    output param set to success/failure code on exit
-     * @return          a date time interval formatter which the caller owns.
-     * @stable ICU 4.0
-     */
-    static DateIntervalFormat* U_EXPORT2 createInstance(
-                                              const UnicodeString& skeleton,
-                                              const Locale& locale,
-                                              const DateIntervalInfo& dtitvinf,
-                                              UErrorCode& status);
-
-    /**
-     * Destructor.
-     * @stable ICU 4.0
-     */
-    virtual ~DateIntervalFormat();
-
-    /**
-     * Clone this Format object polymorphically. The caller owns the result and
-     * should delete it when done.
-     * @return    A copy of the object.
-     * @stable ICU 4.0
-     */
-    virtual Format* clone(void) const;
-
-    /**
-     * Return true if the given Format objects are semantically equal. Objects
-     * of different subclasses are considered unequal.
-     * @param other    the object to be compared with.
-     * @return         true if the given Format objects are semantically equal.
-     * @stable ICU 4.0
-     */
-    virtual UBool operator==(const Format& other) const;
-
-    /**
-     * Return true if the given Format objects are not semantically equal. 
-     * Objects of different subclasses are considered unequal.
-     * @param other the object to be compared with.
-     * @return      true if the given Format objects are not semantically equal.
-     * @stable ICU 4.0
-     */
-    UBool operator!=(const Format& other) const;
-
-    /**
-     * Format an object to produce a string. This method handles Formattable
-     * objects with a DateInterval type. 
-     * If a the Formattable object type is not a DateInterval,
-     * then it returns a failing UErrorCode.
-     *
-     * @param obj               The object to format. 
-     *                          Must be a DateInterval.
-     * @param appendTo          Output parameter to receive result.
-     *                          Result is appended to existing contents.
-     * @param fieldPosition     On input: an alignment field, if desired.
-     *                          On output: the offsets of the alignment field.
-     * @param status            Output param filled with success/failure status.
-     * @return                  Reference to 'appendTo' parameter.
-     * @stable ICU 4.0
-     */
-    virtual UnicodeString& format(const Formattable& obj,
-                                  UnicodeString& appendTo,
-                                  FieldPosition& fieldPosition,
-                                  UErrorCode& status) const ;
-                                    
-                                    
-
-    /**
-     * Format a DateInterval to produce a string. 
-     *
-     * @param dtInterval        DateInterval to be formatted.
-     * @param appendTo          Output parameter to receive result.
-     *                          Result is appended to existing contents.
-     * @param fieldPosition     On input: an alignment field, if desired.
-     *                          On output: the offsets of the alignment field.
-     * @param status            Output param filled with success/failure status.
-     * @return                  Reference to 'appendTo' parameter.
-     * @stable ICU 4.0
-     */
-    UnicodeString& format(const DateInterval* dtInterval,
-                          UnicodeString& appendTo,
-                          FieldPosition& fieldPosition,
-                          UErrorCode& status) const ;
-                                    
-                                    
-    /**
-     * Format 2 Calendars to produce a string. 
-     *
-     * Note: "fromCalendar" and "toCalendar" are not const,
-     * since calendar is not const in  SimpleDateFormat::format(Calendar&),
-     *
-     * @param fromCalendar      calendar set to the from date in date interval
-     *                          to be formatted into date interval string
-     * @param toCalendar        calendar set to the to date in date interval
-     *                          to be formatted into date interval string
-     * @param appendTo          Output parameter to receive result.
-     *                          Result is appended to existing contents.
-     * @param fieldPosition     On input: an alignment field, if desired.
-     *                          On output: the offsets of the alignment field.
-     * @param status            Output param filled with success/failure status.
-     *                          Caller needs to make sure it is SUCCESS
-     *                          at the function entrance
-     * @return                  Reference to 'appendTo' parameter.
-     * @stable ICU 4.0
-     */
-    UnicodeString& format(Calendar& fromCalendar,
-                          Calendar& toCalendar,
-                          UnicodeString& appendTo,
-                          FieldPosition& fieldPosition,
-                          UErrorCode& status) const ;
-
-    /**
-     * Date interval parsing is not supported. Please do not use.
-     * <P>
-     * This method should handle parsing of
-     * date time interval strings into Formattable objects with 
-     * DateInterval type, which is a pair of UDate.
-     * <P>
-     * Before calling, set parse_pos.index to the offset you want to start
-     * parsing at in the source. After calling, parse_pos.index is the end of
-     * the text you parsed. If error occurs, index is unchanged.
-     * <P>
-     * When parsing, leading whitespace is discarded (with a successful parse),
-     * while trailing whitespace is left as is.
-     * <P>
-     * See Format::parseObject() for more.
-     *
-     * @param source    The string to be parsed into an object.
-     * @param result    Formattable to be set to the parse result.
-     *                  If parse fails, return contents are undefined.
-     * @param parse_pos The position to start parsing at. Since no parsing
-     *                  is supported, upon return this param is unchanged.
-     * @return          A newly created Formattable* object, or NULL
-     *                  on failure.  The caller owns this and should
-     *                  delete it when done.
-     * @internal ICU 4.0
-     */
-    virtual void parseObject(const UnicodeString& source,
-                             Formattable& result,
-                             ParsePosition& parse_pos) const;
-
-
-    /**
-     * Gets the date time interval patterns.
-     * @return the date time interval patterns associated with
-     * this date interval formatter.
-     * @stable ICU 4.0
-     */
-    const DateIntervalInfo* getDateIntervalInfo(void) const;
-
-
-    /**
-     * Set the date time interval patterns. 
-     * @param newIntervalPatterns   the given interval patterns to copy.
-     * @param status          output param set to success/failure code on exit
-     * @stable ICU 4.0
-     */
-    void setDateIntervalInfo(const DateIntervalInfo& newIntervalPatterns,
-                             UErrorCode& status);
-
-
-    /**
-     * Gets the date formatter
-     * @return the date formatter associated with this date interval formatter.
-     * @stable ICU 4.0
-     */
-    const DateFormat* getDateFormat(void) const;
-
-    /**
-     * Return the class ID for this class. This is useful only for comparing to
-     * a return value from getDynamicClassID(). For example:
-     * <pre>
-     * .   Base* polymorphic_pointer = createPolymorphicObject();
-     * .   if (polymorphic_pointer->getDynamicClassID() ==
-     * .       erived::getStaticClassID()) ...
-     * </pre>
-     * @return          The class ID for all objects of this class.
-     * @stable ICU 4.0
-     */
-    static UClassID U_EXPORT2 getStaticClassID(void);
-
-    /**
-     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
-     * method is to implement a simple version of RTTI, since not all C++
-     * compilers support genuine RTTI. Polymorphic operator==() and clone()
-     * methods call this method.
-     *
-     * @return          The class ID for this object. All objects of a
-     *                  given class have the same class ID.  Objects of
-     *                  other classes have different class IDs.
-     * @stable ICU 4.0
-     */
-    virtual UClassID getDynamicClassID(void) const;
-
-protected:
-
-    /**
-     * Copy constructor.
-     * @stable ICU 4.0
-     */
-    DateIntervalFormat(const DateIntervalFormat&);
-
-    /**
-     * Assignment operator.
-     * @stable ICU 4.0
-     */
-    DateIntervalFormat& operator=(const DateIntervalFormat&);
-
-private:
-
-    /*
-     * This is for ICU internal use only. Please do not use.
-     * Save the interval pattern information.
-     * Interval pattern consists of 2 single date patterns and the separator.
-     * For example, interval pattern "MMM d - MMM d, yyyy" consists
-     * a single date pattern "MMM d", another single date pattern "MMM d, yyyy",
-     * and a separator "-".
-     * The pattern is divided into 2 parts. For above example,
-     * the first part is "MMM d - ", and the second part is "MMM d, yyyy".
-     * Also, the first date appears in an interval pattern could be 
-     * the earlier date or the later date.
-     * And such information is saved in the interval pattern as well.
-     * @internal ICU 4.0
-     */
-    struct PatternInfo {
-        UnicodeString firstPart;
-        UnicodeString secondPart;
-        /**
-         * Whether the first date in interval pattern is later date or not.
-         * Fallback format set the default ordering.
-         * And for a particular interval pattern, the order can be 
-         * overriden by prefixing the interval pattern with "latestFirst:" or 
-         * "earliestFirst:"
-         * For example, given 2 date, Jan 10, 2007 to Feb 10, 2007.
-         * if the fallback format is "{0} - {1}", 
-         * and the pattern is "d MMM - d MMM yyyy", the interval format is
-         * "10 Jan - 10 Feb, 2007".
-         * If the pattern is "latestFirst:d MMM - d MMM yyyy", 
-         * the interval format is "10 Feb - 10 Jan, 2007"
-         */
-        UBool         laterDateFirst;
-    };
-
-   
-    /**
-     * default constructor 
-     * @internal ICU 4.0
-     */
-    DateIntervalFormat();
-
-    /**
-     * Construct a DateIntervalFormat from DateFormat,
-     * a DateIntervalInfo, and skeleton.
-     * DateFormat provides the timezone, calendar,
-     * full pattern, and date format symbols information.
-     * It should be a SimpleDateFormat object which 
-     * has a pattern in it.
-     * the DateIntervalInfo provides the interval patterns.
-     *
-     * Note: the DateIntervalFormat takes ownership of both 
-     * DateFormat and DateIntervalInfo objects. 
-     * Caller should not delete them.
-     *
-     * @param locale    the locale of this date interval formatter.
-     * @param dtitvinf  the DateIntervalInfo object to be adopted.
-     * @param skeleton  the skeleton of the date formatter
-     * @param status    output param set to success/failure code on exit
-     * @internal ICU 4.0
-     */
-    DateIntervalFormat(const Locale& locale, DateIntervalInfo* dtItvInfo,
-                       const UnicodeString* skeleton, UErrorCode& status);
-
-    
-    /**
-     * Construct a DateIntervalFormat from DateFormat
-     * and a DateIntervalInfo.
-     *
-     * It is a wrapper of the constructor.
-     *
-     * @param locale    the locale of this date interval formatter.
-     * @param dtitvinf  the DateIntervalInfo object to be adopted.
-     * @param skeleton  the skeleton of this formatter.
-     * @param status    Output param set to success/failure code.
-     * @return          a date time interval formatter which the caller owns.
-     * @internal ICU 4.0
-     */
-    static DateIntervalFormat* U_EXPORT2 create(const Locale& locale,
-                                                DateIntervalInfo* dtitvinf,
-                                                const UnicodeString* skeleton,
-                                                UErrorCode& status);
-
-    /**
-     * Create a simple date/time formatter from skeleton, given locale,
-     * and date time pattern generator.
-     *
-     * @param skeleton  the skeleton on which date format based.
-     * @param locale    the given locale.
-     * @param dtpng     the date time pattern generator.
-     * @param status    Output param to be set to success/failure code.
-     *                  If it is failure, the returned date formatter will
-     *                  be NULL.
-     * @return          a simple date formatter which the caller owns.
-     * @internal ICU 4.0
-     */
-    static SimpleDateFormat* U_EXPORT2 createSDFPatternInstance(
-                                        const UnicodeString& skeleton,
-                                        const Locale& locale,
-                                        DateTimePatternGenerator* dtpng,
-                                        UErrorCode& status);
-
-
-    /**
-     *  Below are for generating interval patterns local to the formatter 
-     */
-
-
-    /**
-     * Format 2 Calendars using fall-back interval pattern
-     *
-     * The full pattern used in this fall-back format is the
-     * full pattern of the date formatter.
-     *
-     * @param fromCalendar      calendar set to the from date in date interval
-     *                          to be formatted into date interval string
-     * @param toCalendar        calendar set to the to date in date interval
-     *                          to be formatted into date interval string
-     * @param appendTo          Output parameter to receive result.
-     *                          Result is appended to existing contents.
-     * @param pos               On input: an alignment field, if desired.
-     *                          On output: the offsets of the alignment field.
-     * @param status            output param set to success/failure code on exit
-     * @return                  Reference to 'appendTo' parameter.
-     * @internal ICU 4.0
-     */
-    UnicodeString& fallbackFormat(Calendar& fromCalendar,
-                                  Calendar& toCalendar,
-                                  UnicodeString& appendTo,
-                                  FieldPosition& pos,
-                                  UErrorCode& status) const;
-
-
-
-    /** 
-     * Initialize interval patterns locale to this formatter
-     * 
-     * This code is a bit complicated since 
-     * 1. the interval patterns saved in resource bundle files are interval
-     *    patterns based on date or time only.
-     *    It does not have interval patterns based on both date and time.
-     *    Interval patterns on both date and time are algorithm generated.
-     *
-     *    For example, it has interval patterns on skeleton "dMy" and "hm",
-     *    but it does not have interval patterns on skeleton "dMyhm".
-     *    
-     *    The rule to generate interval patterns for both date and time skeleton are
-     *    1) when the year, month, or day differs, concatenate the two original 
-     *    expressions with a separator between, 
-     *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
-     *    to "Jan 11, 2007 10:10am" is 
-     *    "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 
-     *
-     *    2) otherwise, present the date followed by the range expression 
-     *    for the time.
-     *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
-     *    to "Jan 10, 2007 11:10am" is 
-     *    "Jan 10, 2007 10:10 am - 11:10am" 
-     *
-     * 2. even a pattern does not request a certain calendar field,
-     *    the interval pattern needs to include such field if such fields are
-     *    different between 2 dates.
-     *    For example, a pattern/skeleton is "hm", but the interval pattern 
-     *    includes year, month, and date when year, month, and date differs.
-     * 
-     *
-     * @param status    output param set to success/failure code on exit
-     * @internal ICU 4.0 
-     */
-    void initializePattern(UErrorCode& status); 
-                              
-
-
-    /**
-     * Set fall back interval pattern given a calendar field,
-     * a skeleton, and a date time pattern generator.
-     * @param field      the largest different calendar field
-     * @param skeleton   a skeleton
-     * @param status     output param set to success/failure code on exit
-     * @internal ICU 4.0 
-     */
-    void setFallbackPattern(UCalendarDateFields field, 
-                            const UnicodeString& skeleton,
-                            UErrorCode& status);
-                            
-
-
-    /** 
-     * get separated date and time skeleton from a combined skeleton.
-     *
-     * The difference between date skeleton and normalizedDateSkeleton are:
-     * 1. both 'y' and 'd' are appeared only once in normalizeDateSkeleton
-     * 2. 'E' and 'EE' are normalized into 'EEE'
-     * 3. 'MM' is normalized into 'M'
-     *
-     ** the difference between time skeleton and normalizedTimeSkeleton are:
-     * 1. both 'H' and 'h' are normalized as 'h' in normalized time skeleton,
-     * 2. 'a' is omitted in normalized time skeleton.
-     * 3. there is only one appearance for 'h', 'm','v', 'z' in normalized time
-     *    skeleton
-     *
-     *
-     *  @param skeleton               given combined skeleton.
-     *  @param date                   Output parameter for date only skeleton.
-     *  @param normalizedDate         Output parameter for normalized date only
-     *
-     *  @param time                   Output parameter for time only skeleton.
-     *  @param normalizedTime         Output parameter for normalized time only
-     *                                skeleton.
-     *
-     * @internal ICU 4.0 
-     */
-    static void  U_EXPORT2 getDateTimeSkeleton(const UnicodeString& skeleton,
-                                    UnicodeString& date,
-                                    UnicodeString& normalizedDate,
-                                    UnicodeString& time,
-                                    UnicodeString& normalizedTime);
-
-
-
-    /**
-     * Generate date or time interval pattern from resource,
-     * and set them into the interval pattern locale to this formatter.
-     *
-     * It needs to handle the following: 
-     * 1. need to adjust field width.
-     *    For example, the interval patterns saved in DateIntervalInfo
-     *    includes "dMMMy", but not "dMMMMy".
-     *    Need to get interval patterns for dMMMMy from dMMMy.
-     *    Another example, the interval patterns saved in DateIntervalInfo
-     *    includes "hmv", but not "hmz".
-     *    Need to get interval patterns for "hmz' from 'hmv'
-     *
-     * 2. there might be no pattern for 'y' differ for skeleton "Md",
-     *    in order to get interval patterns for 'y' differ,
-     *    need to look for it from skeleton 'yMd'
-     *
-     * @param dateSkeleton   normalized date skeleton
-     * @param timeSkeleton   normalized time skeleton
-     * @return               whether the resource is found for the skeleton.
-     *                       TRUE if interval pattern found for the skeleton,
-     *                       FALSE otherwise.
-     * @internal ICU 4.0
-     */
-    UBool setSeparateDateTimePtn(const UnicodeString& dateSkeleton, 
-                                 const UnicodeString& timeSkeleton);
-                                   
-
-
-
-    /**
-     * Generate interval pattern from existing resource
-     *
-     * It not only save the interval patterns,
-     * but also return the extended skeleton and its best match skeleton.
-     *
-     * @param field           largest different calendar field
-     * @param skeleton        skeleton
-     * @param bestSkeleton    the best match skeleton which has interval pattern
-     *                        defined in resource
-     * @param differenceInfo  the difference between skeleton and best skeleton
-     *         0 means the best matched skeleton is the same as input skeleton
-     *         1 means the fields are the same, but field width are different
-     *         2 means the only difference between fields are v/z,
-     *        -1 means there are other fields difference 
-     *
-     * @param extendedSkeleton      extended skeleton
-     * @param extendedBestSkeleton  extended best match skeleton
-     * @return                      whether the interval pattern is found 
-     *                              through extending skeleton or not.
-     *                              TRUE if interval pattern is found by
-     *                              extending skeleton, FALSE otherwise.
-     * @internal ICU 4.0
-     */
-    UBool setIntervalPattern(UCalendarDateFields field, 
-                             const UnicodeString* skeleton, 
-                             const UnicodeString* bestSkeleton, 
-                             int8_t differenceInfo, 
-                             UnicodeString* extendedSkeleton = NULL,
-                             UnicodeString* extendedBestSkeleton = NULL);
-
-    /**
-     * Adjust field width in best match interval pattern to match
-     * the field width in input skeleton.
-     *
-     * TODO (xji) make a general solution
-     * The adjusting rule can be:
-     * 1. always adjust
-     * 2. never adjust
-     * 3. default adjust, which means adjust according to the following rules
-     * 3.1 always adjust string, such as MMM and MMMM
-     * 3.2 never adjust between string and numeric, such as MM and MMM
-     * 3.3 always adjust year
-     * 3.4 do not adjust 'd', 'h', or 'm' if h presents
-     * 3.5 do not adjust 'M' if it is numeric(?)
-     *
-     * Since date interval format is well-formed format,
-     * date and time skeletons are normalized previously,
-     * till this stage, the adjust here is only "adjust strings, such as MMM
-     * and MMMM, EEE and EEEE.
-     *
-     * @param inputSkeleton            the input skeleton
-     * @param bestMatchSkeleton        the best match skeleton
-     * @param bestMatchIntervalpattern the best match interval pattern
-     * @param differenceInfo           the difference between 2 skeletons
-     *                                 1 means only field width differs
-     *                                 2 means v/z exchange
-     * @param adjustedIntervalPattern  adjusted interval pattern
-     * @internal ICU 4.0
-     */
-    static void U_EXPORT2 adjustFieldWidth(
-                            const UnicodeString& inputSkeleton,
-                            const UnicodeString& bestMatchSkeleton,
-                            const UnicodeString& bestMatchIntervalPattern,
-                            int8_t differenceInfo,
-                            UnicodeString& adjustedIntervalPattern);
-
-    /**
-     * Concat a single date pattern with a time interval pattern,
-     * set it into the intervalPatterns, while field is time field.
-     * This is used to handle time interval patterns on skeleton with
-     * both time and date. Present the date followed by 
-     * the range expression for the time.
-     * @param format         date and time format
-     * @param formatLen      format string length
-     * @param datePattern    date pattern
-     * @param field          time calendar field: AM_PM, HOUR, MINUTE
-     * @param status         output param set to success/failure code on exit
-     * @internal ICU 4.0 
-     */
-    void concatSingleDate2TimeInterval(const UChar* format,
-                                       int32_t formatLen,
-                                       const UnicodeString& datePattern,
-                                       UCalendarDateFields field,
-                                       UErrorCode& status); 
-
-    /**
-     * check whether a calendar field present in a skeleton.
-     * @param field      calendar field need to check
-     * @param skeleton   given skeleton on which to check the calendar field
-     * @return           true if field present in a skeleton.
-     * @internal ICU 4.0 
-     */
-    static UBool U_EXPORT2 fieldExistsInSkeleton(UCalendarDateFields field, 
-                                                 const UnicodeString& skeleton);
-
-
-    /**
-     * Split interval patterns into 2 part.
-     * @param intervalPattern  interval pattern
-     * @return the index in interval pattern which split the pattern into 2 part
-     * @internal ICU 4.0
-     */
-    static int32_t  U_EXPORT2 splitPatternInto2Part(const UnicodeString& intervalPattern);
-
-
-    /**
-     * Break interval patterns as 2 part and save them into pattern info.
-     * @param field            calendar field
-     * @param intervalPattern  interval pattern
-     * @internal ICU 4.0
-     */
-    void setIntervalPattern(UCalendarDateFields field,
-                            const UnicodeString& intervalPattern);
-
-
-    /**
-     * Break interval patterns as 2 part and save them into pattern info.
-     * @param field            calendar field
-     * @param intervalPattern  interval pattern
-     * @param laterDateFirst   whether later date appear first in interval pattern
-     * @internal ICU 4.0
-     */
-    void setIntervalPattern(UCalendarDateFields field,
-                            const UnicodeString& intervalPattern,
-                            UBool laterDateFirst);
-
-
-    /**
-     * Set pattern information.
-     *
-     * @param field            calendar field
-     * @param firstPart        the first part in interval pattern
-     * @param secondPart       the second part in interval pattern
-     * @param laterDateFirst   whether the first date in intervalPattern
-     *                         is earlier date or later date
-     * @internal ICU 4.0
-     */
-    void setPatternInfo(UCalendarDateFields field,
-                        const UnicodeString* firstPart,
-                        const UnicodeString* secondpart,
-                        UBool laterDateFirst);
-
-
-    // from calendar field to pattern letter
-    static const UChar fgCalendarFieldToPatternLetter[];
-
-
-    /**
-     * The interval patterns for this locale.
-     */
-    DateIntervalInfo*     fInfo;
-
-    /**
-     * The DateFormat object used to format single pattern
-     */
-    SimpleDateFormat*     fDateFormat;
-
-    /**
-     * The 2 calendars with the from and to date.
-     * could re-use the calendar in fDateFormat,
-     * but keeping 2 calendars make it clear and clean.
-     */
-    Calendar* fFromCalendar;
-    Calendar* fToCalendar;
-
-    /**
-     * Date time pattern generator
-     */
-    DateTimePatternGenerator* fDtpng;
-
-    /**
-     * Following are interval information relavent (locale) to this formatter.
-     */
-    UnicodeString fSkeleton;
-    PatternInfo fIntervalPatterns[DateIntervalInfo::kIPI_MAX_INDEX];
-};
- 
-
-
- 
-
-
-inline UBool 
-DateIntervalFormat::operator!=(const Format& other) const  {
-    return !operator==(other); 
-}
- 
-U_NAMESPACE_END
-
-#endif /* #if !UCONFIG_NO_FORMATTING */
-
-#endif // _DTITVFMT_H__
-//eof
+/********************************************************************************
+* Copyright (C) 2008-2009, International Business Machines Corporation and others. All Rights Reserved.
+*******************************************************************************
+*
+* File DTITVFMT.H
+*
+*******************************************************************************
+*/
+
+#ifndef __DTITVFMT_H__
+#define __DTITVFMT_H__
+
+
+#include "unicode/utypes.h"
+
+/**
+ * \file 
+ * \brief C++ API: Format and parse date interval in a language-independent manner.
+ */
+ 
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/ucal.h"
+#include "unicode/smpdtfmt.h"
+#include "unicode/dtintrv.h"
+#include "unicode/dtitvinf.h"
+#include "unicode/dtptngen.h"
+
+U_NAMESPACE_BEGIN
+
+
+
+/**
+ * DateIntervalFormat is a class for formatting and parsing date 
+ * intervals in a language-independent manner. 
+ * Date interval formatting is supported in Gregorian calendar only.
+ * And only formatting is supported. Parsing is not supported.
+ *
+ * <P>
+ * Date interval means from one date to another date,
+ * for example, from "Jan 11, 2008" to "Jan 18, 2008".
+ * We introduced class DateInterval to represent it.
+ * DateInterval is a pair of UDate, which is 
+ * the standard milliseconds since 24:00 GMT, Jan 1, 1970.
+ *
+ * <P>
+ * DateIntervalFormat formats a DateInterval into
+ * text as compactly as possible. 
+ * For example, the date interval format from "Jan 11, 2008" to "Jan 18,. 2008"
+ * is "Jan 11-18, 2008" for English.
+ * And it parses text into DateInterval, 
+ * although initially, parsing is not supported. 
+ *
+ * <P>
+ * There is no structural information in date time patterns. 
+ * For any punctuations and string literals inside a date time pattern, 
+ * we do not know whether it is just a separator, or a prefix, or a suffix. 
+ * Without such information, so, it is difficult to generate a sub-pattern 
+ * (or super-pattern) by algorithm.
+ * So, formatting a DateInterval is pattern-driven. It is very
+ * similar to formatting in SimpleDateFormat.
+ * We introduce class DateIntervalInfo to save date interval 
+ * patterns, similar to date time pattern in SimpleDateFormat.
+ *
+ * <P>
+ * Logically, the interval patterns are mappings
+ * from (skeleton, the_largest_different_calendar_field)
+ * to (date_interval_pattern).
+ *
+ * <P>
+ * A skeleton 
+ * <ol>
+ * <li>
+ * only keeps the field pattern letter and ignores all other parts 
+ * in a pattern, such as space, punctuations, and string literals.
+ * </li>
+ * <li>
+ * hides the order of fields. 
+ * </li>
+ * <li>
+ * might hide a field's pattern letter length.
+ * </li>
+ * </ol>
+ *
+ * For those non-digit calendar fields, the pattern letter length is 
+ * important, such as MMM, MMMM, and MMMMM; EEE and EEEE, 
+ * and the field's pattern letter length is honored.
+ *    
+ * For the digit calendar fields,  such as M or MM, d or dd, yy or yyyy, 
+ * the field pattern length is ignored and the best match, which is defined 
+ * in date time patterns, will be returned without honor the field pattern
+ * letter length in skeleton.
+ *
+ * <P>
+ * The calendar fields we support for interval formatting are:
+ * year, month, date, day-of-week, am-pm, hour, hour-of-day, and minute.
+ * Those calendar fields can be defined in the following order:
+ * year >  month > date > hour (in day) >  minute 
+ *  
+ * The largest different calendar fields between 2 calendars is the
+ * first different calendar field in above order.
+ *
+ * For example: the largest different calendar fields between "Jan 10, 2007" 
+ * and "Feb 20, 2008" is year.
+ *
+ * <P>
+ * For other calendar fields, the compact interval formatting is not
+ * supported. And the interval format will be fall back to fall-back
+ * patterns, which is mostly "{date0} - {date1}".
+ *   
+ * <P>
+ * There is a set of pre-defined static skeleton strings.
+ * There are pre-defined interval patterns for those pre-defined skeletons
+ * in locales' resource files.
+ * For example, for a skeleton UDAT_YEAR_ABBR_MONTH_DAY, which is  "yMMMd",
+ * in  en_US, if the largest different calendar field between date1 and date2 
+ * is "year", the date interval pattern  is "MMM d, yyyy - MMM d, yyyy", 
+ * such as "Jan 10, 2007 - Jan 10, 2008".
+ * If the largest different calendar field between date1 and date2 is "month",
+ * the date interval pattern is "MMM d - MMM d, yyyy",
+ * such as "Jan 10 - Feb 10, 2007".
+ * If the largest different calendar field between date1 and date2 is "day",
+ * the date interval pattern is ""MMM d-d, yyyy", such as "Jan 10-20, 2007".
+ *
+ * For date skeleton, the interval patterns when year, or month, or date is 
+ * different are defined in resource files.
+ * For time skeleton, the interval patterns when am/pm, or hour, or minute is
+ * different are defined in resource files.
+ *
+ * <P>
+ * If a skeleton is not found in a locale's DateIntervalInfo, which means
+ * the interval patterns for the skeleton is not defined in resource file,
+ * the interval pattern will falls back to the interval "fallback" pattern 
+ * defined in resource file.
+ * If the interval "fallback" pattern is not defined, the default fall-back
+ * is "{date0} - {data1}".
+ *
+ * <P>
+ * For the combination of date and time, 
+ * The rule to generate interval patterns are:
+ * <ol>
+ * <li>
+ *    when the year, month, or day differs, falls back to fall-back
+ *    interval pattern, which mostly is the concatenate the two original 
+ *    expressions with a separator between, 
+ *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
+ *    to "Jan 11, 2007 10:10am" is 
+ *    "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 
+ * </li>
+ * <li>
+ *    otherwise, present the date followed by the range expression 
+ *    for the time.
+ *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
+ *    to "Jan 10, 2007 11:10am" is "Jan 10, 2007 10:10 am - 11:10am" 
+ * </li>
+ * </ol>
+ *
+ *
+ * <P>
+ * If two dates are the same, the interval pattern is the single date pattern.
+ * For example, interval pattern from "Jan 10, 2007" to "Jan 10, 2007" is 
+ * "Jan 10, 2007".
+ *
+ * Or if the presenting fields between 2 dates have the exact same values,
+ * the interval pattern is the  single date pattern. 
+ * For example, if user only requests year and month,
+ * the interval pattern from "Jan 10, 2007" to "Jan 20, 2007" is "Jan 2007".
+ *
+ * <P>
+ * DateIntervalFormat needs the following information for correct 
+ * formatting: time zone, calendar type, pattern, date format symbols, 
+ * and date interval patterns.
+ * It can be instantiated in 2 ways:
+ * <ol>
+ * <li>
+ *    create an instance using default or given locale plus given skeleton.
+ *    Users are encouraged to created date interval formatter this way and 
+ *    to use the pre-defined skeleton macros, such as
+ *    UDAT_YEAR_NUM_MONTH, which consists the calendar fields and
+ *    the format style. 
+ * </li>
+ * <li>
+ *    create an instance using default or given locale plus given skeleton
+ *    plus a given DateIntervalInfo.
+ *    This factory method is for powerful users who want to provide their own 
+ *    interval patterns. 
+ *    Locale provides the timezone, calendar, and format symbols information.
+ *    Local plus skeleton provides full pattern information.
+ *    DateIntervalInfo provides the date interval patterns.
+ * </li>
+ * </ol>
+ *
+ * <P>
+ * For the calendar field pattern letter, such as G, y, M, d, a, h, H, m, s etc.
+ * DateIntervalFormat uses the same syntax as that of
+ * DateTime format.
+ * 
+ * <P>
+ * Code Sample: general usage
+ * <pre>
+ * \code
+ *   // the date interval object which the DateIntervalFormat formats on
+ *   // and parses into
+ *   DateInterval*  dtInterval = new DateInterval(1000*3600*24, 1000*3600*24*2);
+ *   UErrorCode status = U_ZERO_ERROR;
+ *   DateIntervalFormat* dtIntervalFmt = DateIntervalFormat::createInstance(
+ *                           UDAT_YEAR_MONTH_DAY, 
+ *                           Locale("en", "GB", ""), status);
+ *   UnicodeUnicodeString dateIntervalString;
+ *   FieldPosition pos = 0;
+ *   // formatting
+ *   dtIntervalFmt->format(dtInterval, dateIntervalUnicodeString, pos, status);
+ *   delete dtIntervalFmt;
+ * \endcode
+ * </pre>
+ */
+
+class U_I18N_API DateIntervalFormat : public Format {
+public:
+
+    /**
+     * Construct a DateIntervalFormat from skeleton and  the default locale.
+     *
+     * This is a convenient override of 
+     * createInstance(const UnicodeString& skeleton, const Locale& locale,
+     *                UErrorCode&)  
+     * with the value of locale as default locale.
+     *
+     * @param skeleton  the skeleton on which interval format based.
+     * @param status    output param set to success/failure code on exit
+     * @return          a date time interval formatter which the caller owns.
+     * @stable ICU 4.0
+     */
+    static DateIntervalFormat* U_EXPORT2 createInstance(
+                                               const UnicodeString& skeleton,
+                                               UErrorCode& status);
+
+    /**
+     * Construct a DateIntervalFormat from skeleton and a given locale.
+     * <P>
+     * In this factory method, 
+     * the date interval pattern information is load from resource files.
+     * Users are encouraged to created date interval formatter this way and 
+     * to use the pre-defined skeleton macros.
+     *
+     * <P>
+     * There are pre-defined skeletons (defined in udate.h) having predefined 
+     * interval patterns in resource files.
+     * Users are encouraged to use those macros.
+     * For example: 
+     * DateIntervalFormat::createInstance(UDAT_MONTH_DAY, status) 
+     *
+     * The given Locale provides the interval patterns.
+     * For example, for en_GB, if skeleton is UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY,
+     * which is "yMMMEEEd",
+     * the interval patterns defined in resource file to above skeleton are:
+     * "EEE, d MMM, yyyy - EEE, d MMM, yyyy" for year differs,
+     * "EEE, d MMM - EEE, d MMM, yyyy" for month differs,
+     * "EEE, d - EEE, d MMM, yyyy" for day differs,
+     * @param skeleton  the skeleton on which interval format based.
+     * @param locale    the given locale
+     * @param status    output param set to success/failure code on exit
+     * @return          a date time interval formatter which the caller owns.
+     * @stable ICU 4.0
+     */
+
+    static DateIntervalFormat* U_EXPORT2 createInstance(
+                                               const UnicodeString& skeleton,
+                                               const Locale& locale,
+                                               UErrorCode& status);
+
+    /**
+     * Construct a DateIntervalFormat from skeleton
+     *  DateIntervalInfo, and default locale.
+     *
+     * This is a convenient override of
+     * createInstance(const UnicodeString& skeleton, const Locale& locale, 
+     *                const DateIntervalInfo& dtitvinf, UErrorCode&)
+     * with the locale value as default locale.
+     *
+     * @param skeleton  the skeleton on which interval format based.
+     * @param dtitvinf  the DateIntervalInfo object. 
+     * @param status    output param set to success/failure code on exit
+     * @return          a date time interval formatter which the caller owns.
+     * @stable ICU 4.0
+     */
+    static DateIntervalFormat* U_EXPORT2 createInstance(
+                                              const UnicodeString& skeleton,
+                                              const DateIntervalInfo& dtitvinf,
+                                              UErrorCode& status);
+
+    /**
+     * Construct a DateIntervalFormat from skeleton
+     * a DateIntervalInfo, and the given locale.
+     *
+     * <P>
+     * In this factory method, user provides its own date interval pattern
+     * information, instead of using those pre-defined data in resource file. 
+     * This factory method is for powerful users who want to provide their own 
+     * interval patterns. 
+     * <P>
+     * There are pre-defined skeletons (defined in udate.h) having predefined 
+     * interval patterns in resource files.
+     * Users are encouraged to use those macros.
+     * For example: 
+     * DateIntervalFormat::createInstance(UDAT_MONTH_DAY, status) 
+     *
+     * The DateIntervalInfo provides the interval patterns.
+     * and the DateIntervalInfo ownership remains to the caller. 
+     *
+     * User are encouraged to set default interval pattern in DateIntervalInfo
+     * as well, if they want to set other interval patterns ( instead of
+     * reading the interval patterns from resource files).
+     * When the corresponding interval pattern for a largest calendar different
+     * field is not found ( if user not set it ), interval format fallback to
+     * the default interval pattern.
+     * If user does not provide default interval pattern, it fallback to
+     * "{date0} - {date1}" 
+     *
+     * @param skeleton  the skeleton on which interval format based.
+     * @param locale    the given locale
+     * @param dtitvinf  the DateIntervalInfo object.
+     * @param status    output param set to success/failure code on exit
+     * @return          a date time interval formatter which the caller owns.
+     * @stable ICU 4.0
+     */
+    static DateIntervalFormat* U_EXPORT2 createInstance(
+                                              const UnicodeString& skeleton,
+                                              const Locale& locale,
+                                              const DateIntervalInfo& dtitvinf,
+                                              UErrorCode& status);
+
+    /**
+     * Destructor.
+     * @stable ICU 4.0
+     */
+    virtual ~DateIntervalFormat();
+
+    /**
+     * Clone this Format object polymorphically. The caller owns the result and
+     * should delete it when done.
+     * @return    A copy of the object.
+     * @stable ICU 4.0
+     */
+    virtual Format* clone(void) const;
+
+    /**
+     * Return true if the given Format objects are semantically equal. Objects
+     * of different subclasses are considered unequal.
+     * @param other    the object to be compared with.
+     * @return         true if the given Format objects are semantically equal.
+     * @stable ICU 4.0
+     */
+    virtual UBool operator==(const Format& other) const;
+
+    /**
+     * Return true if the given Format objects are not semantically equal. 
+     * Objects of different subclasses are considered unequal.
+     * @param other the object to be compared with.
+     * @return      true if the given Format objects are not semantically equal.
+     * @stable ICU 4.0
+     */
+    UBool operator!=(const Format& other) const;
+
+    /**
+     * Format an object to produce a string. This method handles Formattable
+     * objects with a DateInterval type. 
+     * If a the Formattable object type is not a DateInterval,
+     * then it returns a failing UErrorCode.
+     *
+     * @param obj               The object to format. 
+     *                          Must be a DateInterval.
+     * @param appendTo          Output parameter to receive result.
+     *                          Result is appended to existing contents.
+     * @param fieldPosition     On input: an alignment field, if desired.
+     *                          On output: the offsets of the alignment field.
+     * @param status            Output param filled with success/failure status.
+     * @return                  Reference to 'appendTo' parameter.
+     * @stable ICU 4.0
+     */
+    virtual UnicodeString& format(const Formattable& obj,
+                                  UnicodeString& appendTo,
+                                  FieldPosition& fieldPosition,
+                                  UErrorCode& status) const ;
+                                    
+                                    
+
+    /**
+     * Format a DateInterval to produce a string. 
+     *
+     * @param dtInterval        DateInterval to be formatted.
+     * @param appendTo          Output parameter to receive result.
+     *                          Result is appended to existing contents.
+     * @param fieldPosition     On input: an alignment field, if desired.
+     *                          On output: the offsets of the alignment field.
+     * @param status            Output param filled with success/failure status.
+     * @return                  Reference to 'appendTo' parameter.
+     * @stable ICU 4.0
+     */
+    UnicodeString& format(const DateInterval* dtInterval,
+                          UnicodeString& appendTo,
+                          FieldPosition& fieldPosition,
+                          UErrorCode& status) const ;
+                                    
+                                    
+    /**
+     * Format 2 Calendars to produce a string. 
+     *
+     * Note: "fromCalendar" and "toCalendar" are not const,
+     * since calendar is not const in  SimpleDateFormat::format(Calendar&),
+     *
+     * @param fromCalendar      calendar set to the from date in date interval
+     *                          to be formatted into date interval string
+     * @param toCalendar        calendar set to the to date in date interval
+     *                          to be formatted into date interval string
+     * @param appendTo          Output parameter to receive result.
+     *                          Result is appended to existing contents.
+     * @param fieldPosition     On input: an alignment field, if desired.
+     *                          On output: the offsets of the alignment field.
+     * @param status            Output param filled with success/failure status.
+     *                          Caller needs to make sure it is SUCCESS
+     *                          at the function entrance
+     * @return                  Reference to 'appendTo' parameter.
+     * @stable ICU 4.0
+     */
+    UnicodeString& format(Calendar& fromCalendar,
+                          Calendar& toCalendar,
+                          UnicodeString& appendTo,
+                          FieldPosition& fieldPosition,
+                          UErrorCode& status) const ;
+
+    /**
+     * Date interval parsing is not supported. Please do not use.
+     * <P>
+     * This method should handle parsing of
+     * date time interval strings into Formattable objects with 
+     * DateInterval type, which is a pair of UDate.
+     * <P>
+     * Before calling, set parse_pos.index to the offset you want to start
+     * parsing at in the source. After calling, parse_pos.index is the end of
+     * the text you parsed. If error occurs, index is unchanged.
+     * <P>
+     * When parsing, leading whitespace is discarded (with a successful parse),
+     * while trailing whitespace is left as is.
+     * <P>
+     * See Format::parseObject() for more.
+     *
+     * @param source    The string to be parsed into an object.
+     * @param result    Formattable to be set to the parse result.
+     *                  If parse fails, return contents are undefined.
+     * @param parse_pos The position to start parsing at. Since no parsing
+     *                  is supported, upon return this param is unchanged.
+     * @return          A newly created Formattable* object, or NULL
+     *                  on failure.  The caller owns this and should
+     *                  delete it when done.
+     * @internal ICU 4.0
+     */
+    virtual void parseObject(const UnicodeString& source,
+                             Formattable& result,
+                             ParsePosition& parse_pos) const;
+
+
+    /**
+     * Gets the date time interval patterns.
+     * @return the date time interval patterns associated with
+     * this date interval formatter.
+     * @stable ICU 4.0
+     */
+    const DateIntervalInfo* getDateIntervalInfo(void) const;
+
+
+    /**
+     * Set the date time interval patterns. 
+     * @param newIntervalPatterns   the given interval patterns to copy.
+     * @param status          output param set to success/failure code on exit
+     * @stable ICU 4.0
+     */
+    void setDateIntervalInfo(const DateIntervalInfo& newIntervalPatterns,
+                             UErrorCode& status);
+
+
+    /**
+     * Gets the date formatter
+     * @return the date formatter associated with this date interval formatter.
+     * @stable ICU 4.0
+     */
+    const DateFormat* getDateFormat(void) const;
+
+    /**
+     * Return the class ID for this class. This is useful only for comparing to
+     * a return value from getDynamicClassID(). For example:
+     * <pre>
+     * .   Base* polymorphic_pointer = createPolymorphicObject();
+     * .   if (polymorphic_pointer->getDynamicClassID() ==
+     * .       erived::getStaticClassID()) ...
+     * </pre>
+     * @return          The class ID for all objects of this class.
+     * @stable ICU 4.0
+     */
+    static UClassID U_EXPORT2 getStaticClassID(void);
+
+    /**
+     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
+     * method is to implement a simple version of RTTI, since not all C++
+     * compilers support genuine RTTI. Polymorphic operator==() and clone()
+     * methods call this method.
+     *
+     * @return          The class ID for this object. All objects of a
+     *                  given class have the same class ID.  Objects of
+     *                  other classes have different class IDs.
+     * @stable ICU 4.0
+     */
+    virtual UClassID getDynamicClassID(void) const;
+
+protected:
+
+    /**
+     * Copy constructor.
+     * @stable ICU 4.0
+     */
+    DateIntervalFormat(const DateIntervalFormat&);
+
+    /**
+     * Assignment operator.
+     * @stable ICU 4.0
+     */
+    DateIntervalFormat& operator=(const DateIntervalFormat&);
+
+private:
+
+    /*
+     * This is for ICU internal use only. Please do not use.
+     * Save the interval pattern information.
+     * Interval pattern consists of 2 single date patterns and the separator.
+     * For example, interval pattern "MMM d - MMM d, yyyy" consists
+     * a single date pattern "MMM d", another single date pattern "MMM d, yyyy",
+     * and a separator "-".
+     * The pattern is divided into 2 parts. For above example,
+     * the first part is "MMM d - ", and the second part is "MMM d, yyyy".
+     * Also, the first date appears in an interval pattern could be 
+     * the earlier date or the later date.
+     * And such information is saved in the interval pattern as well.
+     * @internal ICU 4.0
+     */
+    struct PatternInfo {
+        UnicodeString firstPart;
+        UnicodeString secondPart;
+        /**
+         * Whether the first date in interval pattern is later date or not.
+         * Fallback format set the default ordering.
+         * And for a particular interval pattern, the order can be 
+         * overriden by prefixing the interval pattern with "latestFirst:" or 
+         * "earliestFirst:"
+         * For example, given 2 date, Jan 10, 2007 to Feb 10, 2007.
+         * if the fallback format is "{0} - {1}", 
+         * and the pattern is "d MMM - d MMM yyyy", the interval format is
+         * "10 Jan - 10 Feb, 2007".
+         * If the pattern is "latestFirst:d MMM - d MMM yyyy", 
+         * the interval format is "10 Feb - 10 Jan, 2007"
+         */
+        UBool         laterDateFirst;
+    };
+
+   
+    /**
+     * default constructor 
+     * @internal ICU 4.0
+     */
+    DateIntervalFormat();
+
+    /**
+     * Construct a DateIntervalFormat from DateFormat,
+     * a DateIntervalInfo, and skeleton.
+     * DateFormat provides the timezone, calendar,
+     * full pattern, and date format symbols information.
+     * It should be a SimpleDateFormat object which 
+     * has a pattern in it.
+     * the DateIntervalInfo provides the interval patterns.
+     *
+     * Note: the DateIntervalFormat takes ownership of both 
+     * DateFormat and DateIntervalInfo objects. 
+     * Caller should not delete them.
+     *
+     * @param locale    the locale of this date interval formatter.
+     * @param dtitvinf  the DateIntervalInfo object to be adopted.
+     * @param skeleton  the skeleton of the date formatter
+     * @param status    output param set to success/failure code on exit
+     * @internal ICU 4.0
+     */
+    DateIntervalFormat(const Locale& locale, DateIntervalInfo* dtItvInfo,
+                       const UnicodeString* skeleton, UErrorCode& status);
+
+    
+    /**
+     * Construct a DateIntervalFormat from DateFormat
+     * and a DateIntervalInfo.
+     *
+     * It is a wrapper of the constructor.
+     *
+     * @param locale    the locale of this date interval formatter.
+     * @param dtitvinf  the DateIntervalInfo object to be adopted.
+     * @param skeleton  the skeleton of this formatter.
+     * @param status    Output param set to success/failure code.
+     * @return          a date time interval formatter which the caller owns.
+     * @internal ICU 4.0
+     */
+    static DateIntervalFormat* U_EXPORT2 create(const Locale& locale,
+                                                DateIntervalInfo* dtitvinf,
+                                                const UnicodeString* skeleton,
+                                                UErrorCode& status);
+
+    /**
+     * Create a simple date/time formatter from skeleton, given locale,
+     * and date time pattern generator.
+     *
+     * @param skeleton  the skeleton on which date format based.
+     * @param locale    the given locale.
+     * @param dtpng     the date time pattern generator.
+     * @param status    Output param to be set to success/failure code.
+     *                  If it is failure, the returned date formatter will
+     *                  be NULL.
+     * @return          a simple date formatter which the caller owns.
+     * @internal ICU 4.0
+     */
+    static SimpleDateFormat* U_EXPORT2 createSDFPatternInstance(
+                                        const UnicodeString& skeleton,
+                                        const Locale& locale,
+                                        DateTimePatternGenerator* dtpng,
+                                        UErrorCode& status);
+
+
+    /**
+     *  Below are for generating interval patterns local to the formatter 
+     */
+
+
+    /**
+     * Format 2 Calendars using fall-back interval pattern
+     *
+     * The full pattern used in this fall-back format is the
+     * full pattern of the date formatter.
+     *
+     * @param fromCalendar      calendar set to the from date in date interval
+     *                          to be formatted into date interval string
+     * @param toCalendar        calendar set to the to date in date interval
+     *                          to be formatted into date interval string
+     * @param appendTo          Output parameter to receive result.
+     *                          Result is appended to existing contents.
+     * @param pos               On input: an alignment field, if desired.
+     *                          On output: the offsets of the alignment field.
+     * @param status            output param set to success/failure code on exit
+     * @return                  Reference to 'appendTo' parameter.
+     * @internal ICU 4.0
+     */
+    UnicodeString& fallbackFormat(Calendar& fromCalendar,
+                                  Calendar& toCalendar,
+                                  UnicodeString& appendTo,
+                                  FieldPosition& pos,
+                                  UErrorCode& status) const;
+
+
+
+    /** 
+     * Initialize interval patterns locale to this formatter
+     * 
+     * This code is a bit complicated since 
+     * 1. the interval patterns saved in resource bundle files are interval
+     *    patterns based on date or time only.
+     *    It does not have interval patterns based on both date and time.
+     *    Interval patterns on both date and time are algorithm generated.
+     *
+     *    For example, it has interval patterns on skeleton "dMy" and "hm",
+     *    but it does not have interval patterns on skeleton "dMyhm".
+     *    
+     *    The rule to generate interval patterns for both date and time skeleton are
+     *    1) when the year, month, or day differs, concatenate the two original 
+     *    expressions with a separator between, 
+     *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
+     *    to "Jan 11, 2007 10:10am" is 
+     *    "Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am" 
+     *
+     *    2) otherwise, present the date followed by the range expression 
+     *    for the time.
+     *    For example, interval pattern from "Jan 10, 2007 10:10 am" 
+     *    to "Jan 10, 2007 11:10am" is 
+     *    "Jan 10, 2007 10:10 am - 11:10am" 
+     *
+     * 2. even a pattern does not request a certain calendar field,
+     *    the interval pattern needs to include such field if such fields are
+     *    different between 2 dates.
+     *    For example, a pattern/skeleton is "hm", but the interval pattern 
+     *    includes year, month, and date when year, month, and date differs.
+     * 
+     *
+     * @param status    output param set to success/failure code on exit
+     * @internal ICU 4.0 
+     */
+    void initializePattern(UErrorCode& status); 
+                              
+
+
+    /**
+     * Set fall back interval pattern given a calendar field,
+     * a skeleton, and a date time pattern generator.
+     * @param field      the largest different calendar field
+     * @param skeleton   a skeleton
+     * @param status     output param set to success/failure code on exit
+     * @internal ICU 4.0 
+     */
+    void setFallbackPattern(UCalendarDateFields field, 
+                            const UnicodeString& skeleton,
+                            UErrorCode& status);
+                            
+
+
+    /** 
+     * get separated date and time skeleton from a combined skeleton.
+     *
+     * The difference between date skeleton and normalizedDateSkeleton are:
+     * 1. both 'y' and 'd' are appeared only once in normalizeDateSkeleton
+     * 2. 'E' and 'EE' are normalized into 'EEE'
+     * 3. 'MM' is normalized into 'M'
+     *
+     ** the difference between time skeleton and normalizedTimeSkeleton are:
+     * 1. both 'H' and 'h' are normalized as 'h' in normalized time skeleton,
+     * 2. 'a' is omitted in normalized time skeleton.
+     * 3. there is only one appearance for 'h', 'm','v', 'z' in normalized time
+     *    skeleton
+     *
+     *
+     *  @param skeleton               given combined skeleton.
+     *  @param date                   Output parameter for date only skeleton.
+     *  @param normalizedDate         Output parameter for normalized date only
+     *
+     *  @param time                   Output parameter for time only skeleton.
+     *  @param normalizedTime         Output parameter for normalized time only
+     *                                skeleton.
+     *
+     * @internal ICU 4.0 
+     */
+    static void  U_EXPORT2 getDateTimeSkeleton(const UnicodeString& skeleton,
+                                    UnicodeString& date,
+                                    UnicodeString& normalizedDate,
+                                    UnicodeString& time,
+                                    UnicodeString& normalizedTime);
+
+
+
+    /**
+     * Generate date or time interval pattern from resource,
+     * and set them into the interval pattern locale to this formatter.
+     *
+     * It needs to handle the following: 
+     * 1. need to adjust field width.
+     *    For example, the interval patterns saved in DateIntervalInfo
+     *    includes "dMMMy", but not "dMMMMy".
+     *    Need to get interval patterns for dMMMMy from dMMMy.
+     *    Another example, the interval patterns saved in DateIntervalInfo
+     *    includes "hmv", but not "hmz".
+     *    Need to get interval patterns for "hmz' from 'hmv'
+     *
+     * 2. there might be no pattern for 'y' differ for skeleton "Md",
+     *    in order to get interval patterns for 'y' differ,
+     *    need to look for it from skeleton 'yMd'
+     *
+     * @param dateSkeleton   normalized date skeleton
+     * @param timeSkeleton   normalized time skeleton
+     * @return               whether the resource is found for the skeleton.
+     *                       TRUE if interval pattern found for the skeleton,
+     *                       FALSE otherwise.
+     * @internal ICU 4.0
+     */
+    UBool setSeparateDateTimePtn(const UnicodeString& dateSkeleton, 
+                                 const UnicodeString& timeSkeleton);
+                                   
+
+
+
+    /**
+     * Generate interval pattern from existing resource
+     *
+     * It not only save the interval patterns,
+     * but also return the extended skeleton and its best match skeleton.
+     *
+     * @param field           largest different calendar field
+     * @param skeleton        skeleton
+     * @param bestSkeleton    the best match skeleton which has interval pattern
+     *                        defined in resource
+     * @param differenceInfo  the difference between skeleton and best skeleton
+     *         0 means the best matched skeleton is the same as input skeleton
+     *         1 means the fields are the same, but field width are different
+     *         2 means the only difference between fields are v/z,
+     *        -1 means there are other fields difference 
+     *
+     * @param extendedSkeleton      extended skeleton
+     * @param extendedBestSkeleton  extended best match skeleton
+     * @return                      whether the interval pattern is found 
+     *                              through extending skeleton or not.
+     *                              TRUE if interval pattern is found by
+     *                              extending skeleton, FALSE otherwise.
+     * @internal ICU 4.0
+     */
+    UBool setIntervalPattern(UCalendarDateFields field, 
+                             const UnicodeString* skeleton, 
+                             const UnicodeString* bestSkeleton, 
+                             int8_t differenceInfo, 
+                             UnicodeString* extendedSkeleton = NULL,
+                             UnicodeString* extendedBestSkeleton = NULL);
+
+    /**
+     * Adjust field width in best match interval pattern to match
+     * the field width in input skeleton.
+     *
+     * TODO (xji) make a general solution
+     * The adjusting rule can be:
+     * 1. always adjust
+     * 2. never adjust
+     * 3. default adjust, which means adjust according to the following rules
+     * 3.1 always adjust string, such as MMM and MMMM
+     * 3.2 never adjust between string and numeric, such as MM and MMM
+     * 3.3 always adjust year
+     * 3.4 do not adjust 'd', 'h', or 'm' if h presents
+     * 3.5 do not adjust 'M' if it is numeric(?)
+     *
+     * Since date interval format is well-formed format,
+     * date and time skeletons are normalized previously,
+     * till this stage, the adjust here is only "adjust strings, such as MMM
+     * and MMMM, EEE and EEEE.
+     *
+     * @param inputSkeleton            the input skeleton
+     * @param bestMatchSkeleton        the best match skeleton
+     * @param bestMatchIntervalpattern the best match interval pattern
+     * @param differenceInfo           the difference between 2 skeletons
+     *                                 1 means only field width differs
+     *                                 2 means v/z exchange
+     * @param adjustedIntervalPattern  adjusted interval pattern
+     * @internal ICU 4.0
+     */
+    static void U_EXPORT2 adjustFieldWidth(
+                            const UnicodeString& inputSkeleton,
+                            const UnicodeString& bestMatchSkeleton,
+                            const UnicodeString& bestMatchIntervalPattern,
+                            int8_t differenceInfo,
+                            UnicodeString& adjustedIntervalPattern);
+
+    /**
+     * Concat a single date pattern with a time interval pattern,
+     * set it into the intervalPatterns, while field is time field.
+     * This is used to handle time interval patterns on skeleton with
+     * both time and date. Present the date followed by 
+     * the range expression for the time.
+     * @param format         date and time format
+     * @param formatLen      format string length
+     * @param datePattern    date pattern
+     * @param field          time calendar field: AM_PM, HOUR, MINUTE
+     * @param status         output param set to success/failure code on exit
+     * @internal ICU 4.0 
+     */
+    void concatSingleDate2TimeInterval(const UChar* format,
+                                       int32_t formatLen,
+                                       const UnicodeString& datePattern,
+                                       UCalendarDateFields field,
+                                       UErrorCode& status); 
+
+    /**
+     * check whether a calendar field present in a skeleton.
+     * @param field      calendar field need to check
+     * @param skeleton   given skeleton on which to check the calendar field
+     * @return           true if field present in a skeleton.
+     * @internal ICU 4.0 
+     */
+    static UBool U_EXPORT2 fieldExistsInSkeleton(UCalendarDateFields field, 
+                                                 const UnicodeString& skeleton);
+
+
+    /**
+     * Split interval patterns into 2 part.
+     * @param intervalPattern  interval pattern
+     * @return the index in interval pattern which split the pattern into 2 part
+     * @internal ICU 4.0
+     */
+    static int32_t  U_EXPORT2 splitPatternInto2Part(const UnicodeString& intervalPattern);
+
+
+    /**
+     * Break interval patterns as 2 part and save them into pattern info.
+     * @param field            calendar field
+     * @param intervalPattern  interval pattern
+     * @internal ICU 4.0
+     */
+    void setIntervalPattern(UCalendarDateFields field,
+                            const UnicodeString& intervalPattern);
+
+
+    /**
+     * Break interval patterns as 2 part and save them into pattern info.
+     * @param field            calendar field
+     * @param intervalPattern  interval pattern
+     * @param laterDateFirst   whether later date appear first in interval pattern
+     * @internal ICU 4.0
+     */
+    void setIntervalPattern(UCalendarDateFields field,
+                            const UnicodeString& intervalPattern,
+                            UBool laterDateFirst);
+
+
+    /**
+     * Set pattern information.
+     *
+     * @param field            calendar field
+     * @param firstPart        the first part in interval pattern
+     * @param secondPart       the second part in interval pattern
+     * @param laterDateFirst   whether the first date in intervalPattern
+     *                         is earlier date or later date
+     * @internal ICU 4.0
+     */
+    void setPatternInfo(UCalendarDateFields field,
+                        const UnicodeString* firstPart,
+                        const UnicodeString* secondpart,
+                        UBool laterDateFirst);
+
+
+    // from calendar field to pattern letter
+    static const UChar fgCalendarFieldToPatternLetter[];
+
+
+    /**
+     * The interval patterns for this locale.
+     */
+    DateIntervalInfo*     fInfo;
+
+    /**
+     * The DateFormat object used to format single pattern
+     */
+    SimpleDateFormat*     fDateFormat;
+
+    /**
+     * The 2 calendars with the from and to date.
+     * could re-use the calendar in fDateFormat,
+     * but keeping 2 calendars make it clear and clean.
+     */
+    Calendar* fFromCalendar;
+    Calendar* fToCalendar;
+
+    /**
+     * Date time pattern generator
+     */
+    DateTimePatternGenerator* fDtpng;
+
+    /**
+     * Following are interval information relavent (locale) to this formatter.
+     */
+    UnicodeString fSkeleton;
+    PatternInfo fIntervalPatterns[DateIntervalInfo::kIPI_MAX_INDEX];
+};
+ 
+
+
+ 
+
+
+inline UBool 
+DateIntervalFormat::operator!=(const Format& other) const  {
+    return !operator==(other); 
+}
+ 
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif // _DTITVFMT_H__
+//eof

Modified: trunk/source/i18n/unicode/dtitvinf.h
===================================================================
--- trunk/source/i18n/unicode/dtitvinf.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/unicode/dtitvinf.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,528 +1,528 @@
-/*
- *******************************************************************************
- * Copyright (C) 2008-2009, International Business Machines Corporation and
- * others. All Rights Reserved.
- *******************************************************************************
- *
- * File DTITVINF.H
- *
- *******************************************************************************
- */
-
-#ifndef __DTITVINF_H__
-#define __DTITVINF_H__
-
-#include "unicode/utypes.h"
-
-/**
- * \file
- * \brief C++ API: Date/Time interval patterns for formatting date/time interval
- */
-
-#if !UCONFIG_NO_FORMATTING
-
-#include "unicode/udat.h"
-#include "unicode/locid.h"
-#include "unicode/ucal.h"
-#include "unicode/dtptngen.h"
-//#include "dtitv_impl.h"
-
-/**
- * @internal ICU 4.0
- */
- 
-union UHashTok;
-
-
-U_NAMESPACE_BEGIN
-
-U_CDECL_BEGIN 
-
-/**
- * @internal ICU 4.0
- */
-UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) ;
-
-U_CDECL_END 
-
-
-/**
- * DateIntervalInfo is a public class for encapsulating localizable
- * date time interval patterns. It is used by DateIntervalFormat.
- *
- * <P>
- * For most users, ordinary use of DateIntervalFormat does not need to create
- * DateIntervalInfo object directly.
- * DateIntervalFormat will take care of it when creating a date interval
- * formatter when user pass in skeleton and locale.
- *
- * <P>
- * For power users, who want to create their own date interval patterns,
- * or want to re-set date interval patterns, they could do so by
- * directly creating DateIntervalInfo and manupulating it.
- *
- * <P>
- * Logically, the interval patterns are mappings
- * from (skeleton, the_largest_different_calendar_field)
- * to (date_interval_pattern).
- *
- * <P>
- * A skeleton 
- * <ol>
- * <li>
- * only keeps the field pattern letter and ignores all other parts 
- * in a pattern, such as space, punctuations, and string literals.
- * <li>
- * hides the order of fields. 
- * <li>
- * might hide a field's pattern letter length.
- *
- * For those non-digit calendar fields, the pattern letter length is 
- * important, such as MMM, MMMM, and MMMMM; EEE and EEEE, 
- * and the field's pattern letter length is honored.
- *    
- * For the digit calendar fields,  such as M or MM, d or dd, yy or yyyy, 
- * the field pattern length is ignored and the best match, which is defined 
- * in date time patterns, will be returned without honor the field pattern
- * letter length in skeleton.
- * </ol>
- *
- * <P>
- * The calendar fields we support for interval formatting are:
- * year, month, date, day-of-week, am-pm, hour, hour-of-day, and minute.
- * Those calendar fields can be defined in the following order:
- * year >  month > date > am-pm > hour >  minute 
- *  
- * The largest different calendar fields between 2 calendars is the
- * first different calendar field in above order.
- *
- * For example: the largest different calendar fields between "Jan 10, 2007" 
- * and "Feb 20, 2008" is year.
- *   
- * <P>
- * There is a set of pre-defined static skeleton strings.
- * There are pre-defined interval patterns for those pre-defined skeletons
- * in locales' resource files.
- * For example, for a skeleton UDAT_YEAR_ABBR_MONTH_DAY, which is  "yMMMd",
- * in  en_US, if the largest different calendar field between date1 and date2 
- * is "year", the date interval pattern  is "MMM d, yyyy - MMM d, yyyy", 
- * such as "Jan 10, 2007 - Jan 10, 2008".
- * If the largest different calendar field between date1 and date2 is "month",
- * the date interval pattern is "MMM d - MMM d, yyyy",
- * such as "Jan 10 - Feb 10, 2007".
- * If the largest different calendar field between date1 and date2 is "day",
- * the date interval pattern is ""MMM d-d, yyyy", such as "Jan 10-20, 2007".
- *
- * For date skeleton, the interval patterns when year, or month, or date is 
- * different are defined in resource files.
- * For time skeleton, the interval patterns when am/pm, or hour, or minute is
- * different are defined in resource files.
- *
- *
- * <P>
- * There are 2 dates in interval pattern. For most locales, the first date
- * in an interval pattern is the earlier date. There might be a locale in which
- * the first date in an interval pattern is the later date.
- * We use fallback format for the default order for the locale.
- * For example, if the fallback format is "{0} - {1}", it means
- * the first date in the interval pattern for this locale is earlier date.
- * If the fallback format is "{1} - {0}", it means the first date is the 
- * later date.
- * For a particular interval pattern, the default order can be overriden
- * by prefixing "latestFirst:" or "earliestFirst:" to the interval pattern.
- * For example, if the fallback format is "{0}-{1}",
- * but for skeleton "yMMMd", the interval pattern when day is different is 
- * "latestFirst:d-d MMM yy", it means by default, the first date in interval
- * pattern is the earlier date. But for skeleton "yMMMd", when day is different,
- * the first date in "d-d MMM yy" is the later date.
- * 
- * <P>
- * The recommended way to create a DateIntervalFormat object is to pass in 
- * the locale. 
- * By using a Locale parameter, the DateIntervalFormat object is 
- * initialized with the pre-defined interval patterns for a given or 
- * default locale.
- * <P>
- * Users can also create DateIntervalFormat object 
- * by supplying their own interval patterns.
- * It provides flexibility for power users.
- *
- * <P>
- * After a DateIntervalInfo object is created, clients may modify
- * the interval patterns using setIntervalPattern function as so desired.
- * Currently, users can only set interval patterns when the following 
- * calendar fields are different: ERA, YEAR, MONTH, DATE,  DAY_OF_MONTH, 
- * DAY_OF_WEEK, AM_PM,  HOUR, HOUR_OF_DAY, and MINUTE.
- * Interval patterns when other calendar fields are different is not supported.
- * <P>
- * DateIntervalInfo objects are cloneable. 
- * When clients obtain a DateIntervalInfo object, 
- * they can feel free to modify it as necessary.
- * <P>
- * DateIntervalInfo are not expected to be subclassed. 
- * Data for a calendar is loaded out of resource bundles. 
- * To ICU 4.0, date interval patterns are only supported in Gregorian calendar. 
- * @stable ICU 4.0
-**/
-
-class U_I18N_API DateIntervalInfo : public UObject {
-public:
-    /**
-     * Default constructor.
-     * It does not initialize any interval patterns except
-     * that it initialize default fall-back pattern as "{0} - {1}",
-     * which can be reset by setFallbackIntervalPattern().
-     * It should be followed by setFallbackIntervalPattern() and 
-     * setIntervalPattern(), 
-     * and is recommended to be used only for power users who
-     * wants to create their own interval patterns and use them to create
-     * date interval formatter.
-     * @param status   output param set to success/failure code on exit
-     * @internal ICU 4.0
-     */
-    DateIntervalInfo(UErrorCode& status);
-
-
-    /** 
-     * Construct DateIntervalInfo for the given locale,
-     * @param locale  the interval patterns are loaded from the Gregorian 
-     *                calendar data in this locale.
-     * @param status  output param set to success/failure code on exit
-     * @stable ICU 4.0
-     */
-    DateIntervalInfo(const Locale& locale, UErrorCode& status);
-
-
-    /**
-     * Copy constructor.
-     * @stable ICU 4.0
-     */
-    DateIntervalInfo(const DateIntervalInfo&);
-
-    /**
-     * Assignment operator
-     * @stable ICU 4.0
-     */
-    DateIntervalInfo& operator=(const DateIntervalInfo&);
-
-    /**
-     * Clone this object polymorphically.
-     * The caller owns the result and should delete it when done.
-     * @return   a copy of the object
-     * @stable ICU 4.0
-     */
-    virtual DateIntervalInfo* clone(void) const;
-
-    /**
-     * Destructor.
-     * It is virtual to be safe, but it is not designed to be subclassed.
-     * @stable ICU 4.0
-     */
-    virtual ~DateIntervalInfo();
-
-
-    /**
-     * Return true if another object is semantically equal to this one.
-     *
-     * @param other    the DateIntervalInfo object to be compared with.
-     * @return         true if other is semantically equal to this.
-     * @stable ICU 4.0
-     */
-    virtual UBool operator==(const DateIntervalInfo& other) const;
-
-    /**
-     * Return true if another object is semantically unequal to this one.
-     *
-     * @param other    the DateIntervalInfo object to be compared with.
-     * @return         true if other is semantically unequal to this.
-     * @stable ICU 4.0
-     */
-    UBool operator!=(const DateIntervalInfo& other) const;
-
-
-
-    /** 
-     * Provides a way for client to build interval patterns.
-     * User could construct DateIntervalInfo by providing a list of skeletons
-     * and their patterns.
-     * <P>
-     * For example:
-     * <pre>
-     * UErrorCode status = U_ZERO_ERROR;
-     * DateIntervalInfo dIntervalInfo = new DateIntervalInfo();
-     * dIntervalInfo->setFallbackIntervalPattern("{0} ~ {1}");
-     * dIntervalInfo->setIntervalPattern("yMd", UCAL_YEAR, "'from' yyyy-M-d 'to' yyyy-M-d", status); 
-     * dIntervalInfo->setIntervalPattern("yMMMd", UCAL_MONTH, "'from' yyyy MMM d 'to' MMM d", status);
-     * dIntervalInfo->setIntervalPattern("yMMMd", UCAL_DAY, "yyyy MMM d-d", status, status);
-     * </pre>
-     *
-     * Restriction: 
-     * Currently, users can only set interval patterns when the following 
-     * calendar fields are different: ERA, YEAR, MONTH, DATE,  DAY_OF_MONTH, 
-     * DAY_OF_WEEK, AM_PM,  HOUR, HOUR_OF_DAY, and MINUTE.
-     * Interval patterns when other calendar fields are different are 
-     * not supported.
-     *
-     * @param skeleton         the skeleton on which interval pattern based
-     * @param lrgDiffCalUnit   the largest different calendar unit.
-     * @param intervalPattern  the interval pattern on the largest different
-     *                         calendar unit.
-     *                         For example, if lrgDiffCalUnit is 
-     *                         "year", the interval pattern for en_US when year
-     *                         is different could be "'from' yyyy 'to' yyyy".
-     * @param status           output param set to success/failure code on exit
-     * @stable ICU 4.0
-     */
-    void setIntervalPattern(const UnicodeString& skeleton, 
-                            UCalendarDateFields lrgDiffCalUnit, 
-                            const UnicodeString& intervalPattern,
-                            UErrorCode& status);
-
-    /**
-     * Get the interval pattern given skeleton and 
-     * the largest different calendar field.
-     * @param skeleton   the skeleton
-     * @param field      the largest different calendar field
-     * @param result     output param to receive the pattern
-     * @param status     output param set to success/failure code on exit
-     * @return a reference to 'result'
-     * @stable ICU 4.0 
-     */
-    UnicodeString& getIntervalPattern(const UnicodeString& skeleton,
-                                      UCalendarDateFields field,
-                                      UnicodeString& result,
-                                      UErrorCode& status) const; 
-
-    /**
-     * Get the fallback interval pattern.
-     * @param  result   output param to receive the pattern
-     * @return a reference to 'result'
-     * @stable ICU 4.0 
-     */
-    UnicodeString& getFallbackIntervalPattern(UnicodeString& result) const;
-
-
-    /**
-     * Re-set the fallback interval pattern.
-     *
-     * In construction, default fallback pattern is set as "{0} - {1}".
-     * And constructor taking locale as parameter will set the
-     * fallback pattern as what defined in the locale resource file.
-     *
-     * This method provides a way for user to replace the fallback pattern.
-     *
-     * @param fallbackPattern  fall-back interval pattern.
-     * @param status           output param set to success/failure code on exit
-     * @stable ICU 4.0 
-     */
-    void setFallbackIntervalPattern(const UnicodeString& fallbackPattern,
-                                    UErrorCode& status);
-
-
-    /** Get default order -- whether the first date in pattern is later date
-                             or not.
-     * return default date ordering in interval pattern. TRUE if the first date
-     *        in pattern is later date, FALSE otherwise.
-     * @stable ICU 4.0 
-     */
-    UBool getDefaultOrder() const;
-
-
-    /**
-     * ICU "poor man's RTTI", returns a UClassID for the actual class.
-     *
-     * @stable ICU 4.0
-     */
-    virtual UClassID getDynamicClassID() const;
-
-    /**
-     * ICU "poor man's RTTI", returns a UClassID for this class.
-     *
-     * @stable ICU 4.0
-     */
-    static UClassID U_EXPORT2 getStaticClassID();
-
-
-private:
-    /**
-     * DateIntervalFormat will need access to
-     * getBestSkeleton(), parseSkeleton(), enum IntervalPatternIndex,
-     * and calendarFieldToPatternIndex().
-     *
-     * Instead of making above public,
-     * make DateIntervalFormat a friend of DateIntervalInfo.
-     */
-    friend class DateIntervalFormat;
-
-    friend UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) ;
-
-    /**
-     * Following is for saving the interval patterns.
-     * We only support interval patterns on
-     * ERA, YEAR, MONTH, DAY, AM_PM, HOUR, and MINUTE
-     */
-    enum IntervalPatternIndex
-    {
-        kIPI_ERA,
-        kIPI_YEAR,
-        kIPI_MONTH,
-        kIPI_DATE,
-        kIPI_AM_PM,
-        kIPI_HOUR,
-        kIPI_MINUTE,
-        kIPI_MAX_INDEX
-    };
-
-    /** 
-     * Initialize the DateIntervalInfo from locale
-     * @param locale   the given locale.
-     * @param status   output param set to success/failure code on exit
-     * @internal ICU 4.0 
-     */
-    void initializeData(const Locale& locale, UErrorCode& status);
-
-
-    /* Set Interval pattern.
-     *
-     * It sets interval pattern into the hash map.
-     *
-     * @param skeleton         skeleton on which the interval pattern based
-     * @param lrgDiffCalUnit   the largest different calendar unit.
-     * @param intervalPattern  the interval pattern on the largest different
-     *                         calendar unit.
-     * @param status           output param set to success/failure code on exit
-     * @internal ICU 4.0
-     */
-    void setIntervalPatternInternally(const UnicodeString& skeleton,
-                                      UCalendarDateFields lrgDiffCalUnit,
-                                      const UnicodeString& intervalPattern,
-                                      UErrorCode& status); 
-
-
-    /**given an input skeleton, get the best match skeleton 
-     * which has pre-defined interval pattern in resource file.
-     * Also return the difference between the input skeleton
-     * and the best match skeleton.
-     *
-     * TODO (xji): set field weight or
-     *             isolate the funtionality in DateTimePatternGenerator
-     * @param  skeleton               input skeleton
-     * @param  bestMatchDistanceInfo  the difference between input skeleton
-     *                                and best match skeleton.
-     *         0, if there is exact match for input skeleton
-     *         1, if there is only field width difference between 
-     *            the best match and the input skeleton
-     *         2, the only field difference is 'v' and 'z'
-     *        -1, if there is calendar field difference between
-     *            the best match and the input skeleton
-     * @return                        best match skeleton
-     * @internal ICU 4.0
-     */
-    const UnicodeString* getBestSkeleton(const UnicodeString& skeleton,
-                                         int8_t& bestMatchDistanceInfo) const;
-
-
-    /**
-     * Parse skeleton, save each field's width.
-     * It is used for looking for best match skeleton,
-     * and adjust pattern field width.
-     * @param skeleton            skeleton to be parsed
-     * @param skeletonFieldWidth  parsed skeleton field width
-     * @internal ICU 4.0
-     */
-    static void U_EXPORT2 parseSkeleton(const UnicodeString& skeleton, 
-                                        int32_t* skeletonFieldWidth);
-
-
-    /**
-     * Check whether one field width is numeric while the other is string.
-     *
-     * TODO (xji): make it general
-     *
-     * @param fieldWidth          one field width
-     * @param anotherFieldWidth   another field width
-     * @param patternLetter       pattern letter char
-     * @return true if one field width is numeric and the other is string,
-     *         false otherwise.
-     * @internal ICU 4.0
-     */
-    static UBool U_EXPORT2 stringNumeric(int32_t fieldWidth,
-                                         int32_t anotherFieldWidth,
-                                         char patternLetter);
-
-
-    /** 
-     * Convert calendar field to the interval pattern index in 
-     * hash table.
-     *
-     * Since we only support the following calendar fields: 
-     * ERA, YEAR, MONTH, DATE,  DAY_OF_MONTH, DAY_OF_WEEK, 
-     * AM_PM,  HOUR, HOUR_OF_DAY, and MINUTE,
-     * We reserve only 4 interval patterns for a skeleton.
-     *
-     * @param field    calendar field
-     * @param status   output param set to success/failure code on exit
-     * @return  interval pattern index in hash table
-     * @internal ICU 4.0
-     */
-    static IntervalPatternIndex U_EXPORT2 calendarFieldToIntervalIndex(
-                                                      UCalendarDateFields field,
-                                                      UErrorCode& status);
-
-
-    /**
-     * delete hash table (of type fIntervalPatterns).
-     *
-     * @param hTable  hash table to be deleted
-     * @internal ICU 4.0
-     */
-    void deleteHash(Hashtable* hTable);
-
-
-    /**
-     * initialize hash table (of type fIntervalPatterns).
-     *
-     * @param status   output param set to success/failure code on exit
-     * @return         hash table initialized
-     * @internal ICU 4.0
-     */
-    Hashtable* initHash(UErrorCode& status);
-
-
-
-    /**
-     * copy hash table (of type fIntervalPatterns).
-     *
-     * @param source   the source to copy from
-     * @param target   the target to copy to
-     * @param status   output param set to success/failure code on exit
-     * @internal ICU 4.0
-     */
-    void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
-
-
-    // data members
-    // fallback interval pattern 
-    UnicodeString fFallbackIntervalPattern;
-    // default order
-    UBool fFirstDateInPtnIsLaterDate;
-
-    // HashMap<UnicodeString, UnicodeString[kIPI_MAX_INDEX]>
-    // HashMap( skeleton, pattern[largest_different_field] )
-    Hashtable* fIntervalPatterns;
-
-};// end class DateIntervalInfo
-
-
-inline UBool
-DateIntervalInfo::operator!=(const DateIntervalInfo& other) const {
-    return !operator==(other);
-}
-
-
-U_NAMESPACE_END
-
-#endif
-
-#endif
-
+/*
+ *******************************************************************************
+ * Copyright (C) 2008-2009, International Business Machines Corporation and
+ * others. All Rights Reserved.
+ *******************************************************************************
+ *
+ * File DTITVINF.H
+ *
+ *******************************************************************************
+ */
+
+#ifndef __DTITVINF_H__
+#define __DTITVINF_H__
+
+#include "unicode/utypes.h"
+
+/**
+ * \file
+ * \brief C++ API: Date/Time interval patterns for formatting date/time interval
+ */
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/udat.h"
+#include "unicode/locid.h"
+#include "unicode/ucal.h"
+#include "unicode/dtptngen.h"
+//#include "dtitv_impl.h"
+
+/**
+ * @internal ICU 4.0
+ */
+ 
+union UHashTok;
+
+
+U_NAMESPACE_BEGIN
+
+U_CDECL_BEGIN 
+
+/**
+ * @internal ICU 4.0
+ */
+UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) ;
+
+U_CDECL_END 
+
+
+/**
+ * DateIntervalInfo is a public class for encapsulating localizable
+ * date time interval patterns. It is used by DateIntervalFormat.
+ *
+ * <P>
+ * For most users, ordinary use of DateIntervalFormat does not need to create
+ * DateIntervalInfo object directly.
+ * DateIntervalFormat will take care of it when creating a date interval
+ * formatter when user pass in skeleton and locale.
+ *
+ * <P>
+ * For power users, who want to create their own date interval patterns,
+ * or want to re-set date interval patterns, they could do so by
+ * directly creating DateIntervalInfo and manupulating it.
+ *
+ * <P>
+ * Logically, the interval patterns are mappings
+ * from (skeleton, the_largest_different_calendar_field)
+ * to (date_interval_pattern).
+ *
+ * <P>
+ * A skeleton 
+ * <ol>
+ * <li>
+ * only keeps the field pattern letter and ignores all other parts 
+ * in a pattern, such as space, punctuations, and string literals.
+ * <li>
+ * hides the order of fields. 
+ * <li>
+ * might hide a field's pattern letter length.
+ *
+ * For those non-digit calendar fields, the pattern letter length is 
+ * important, such as MMM, MMMM, and MMMMM; EEE and EEEE, 
+ * and the field's pattern letter length is honored.
+ *    
+ * For the digit calendar fields,  such as M or MM, d or dd, yy or yyyy, 
+ * the field pattern length is ignored and the best match, which is defined 
+ * in date time patterns, will be returned without honor the field pattern
+ * letter length in skeleton.
+ * </ol>
+ *
+ * <P>
+ * The calendar fields we support for interval formatting are:
+ * year, month, date, day-of-week, am-pm, hour, hour-of-day, and minute.
+ * Those calendar fields can be defined in the following order:
+ * year >  month > date > am-pm > hour >  minute 
+ *  
+ * The largest different calendar fields between 2 calendars is the
+ * first different calendar field in above order.
+ *
+ * For example: the largest different calendar fields between "Jan 10, 2007" 
+ * and "Feb 20, 2008" is year.
+ *   
+ * <P>
+ * There is a set of pre-defined static skeleton strings.
+ * There are pre-defined interval patterns for those pre-defined skeletons
+ * in locales' resource files.
+ * For example, for a skeleton UDAT_YEAR_ABBR_MONTH_DAY, which is  "yMMMd",
+ * in  en_US, if the largest different calendar field between date1 and date2 
+ * is "year", the date interval pattern  is "MMM d, yyyy - MMM d, yyyy", 
+ * such as "Jan 10, 2007 - Jan 10, 2008".
+ * If the largest different calendar field between date1 and date2 is "month",
+ * the date interval pattern is "MMM d - MMM d, yyyy",
+ * such as "Jan 10 - Feb 10, 2007".
+ * If the largest different calendar field between date1 and date2 is "day",
+ * the date interval pattern is ""MMM d-d, yyyy", such as "Jan 10-20, 2007".
+ *
+ * For date skeleton, the interval patterns when year, or month, or date is 
+ * different are defined in resource files.
+ * For time skeleton, the interval patterns when am/pm, or hour, or minute is
+ * different are defined in resource files.
+ *
+ *
+ * <P>
+ * There are 2 dates in interval pattern. For most locales, the first date
+ * in an interval pattern is the earlier date. There might be a locale in which
+ * the first date in an interval pattern is the later date.
+ * We use fallback format for the default order for the locale.
+ * For example, if the fallback format is "{0} - {1}", it means
+ * the first date in the interval pattern for this locale is earlier date.
+ * If the fallback format is "{1} - {0}", it means the first date is the 
+ * later date.
+ * For a particular interval pattern, the default order can be overriden
+ * by prefixing "latestFirst:" or "earliestFirst:" to the interval pattern.
+ * For example, if the fallback format is "{0}-{1}",
+ * but for skeleton "yMMMd", the interval pattern when day is different is 
+ * "latestFirst:d-d MMM yy", it means by default, the first date in interval
+ * pattern is the earlier date. But for skeleton "yMMMd", when day is different,
+ * the first date in "d-d MMM yy" is the later date.
+ * 
+ * <P>
+ * The recommended way to create a DateIntervalFormat object is to pass in 
+ * the locale. 
+ * By using a Locale parameter, the DateIntervalFormat object is 
+ * initialized with the pre-defined interval patterns for a given or 
+ * default locale.
+ * <P>
+ * Users can also create DateIntervalFormat object 
+ * by supplying their own interval patterns.
+ * It provides flexibility for power users.
+ *
+ * <P>
+ * After a DateIntervalInfo object is created, clients may modify
+ * the interval patterns using setIntervalPattern function as so desired.
+ * Currently, users can only set interval patterns when the following 
+ * calendar fields are different: ERA, YEAR, MONTH, DATE,  DAY_OF_MONTH, 
+ * DAY_OF_WEEK, AM_PM,  HOUR, HOUR_OF_DAY, and MINUTE.
+ * Interval patterns when other calendar fields are different is not supported.
+ * <P>
+ * DateIntervalInfo objects are cloneable. 
+ * When clients obtain a DateIntervalInfo object, 
+ * they can feel free to modify it as necessary.
+ * <P>
+ * DateIntervalInfo are not expected to be subclassed. 
+ * Data for a calendar is loaded out of resource bundles. 
+ * To ICU 4.0, date interval patterns are only supported in Gregorian calendar. 
+ * @stable ICU 4.0
+**/
+
+class U_I18N_API DateIntervalInfo : public UObject {
+public:
+    /**
+     * Default constructor.
+     * It does not initialize any interval patterns except
+     * that it initialize default fall-back pattern as "{0} - {1}",
+     * which can be reset by setFallbackIntervalPattern().
+     * It should be followed by setFallbackIntervalPattern() and 
+     * setIntervalPattern(), 
+     * and is recommended to be used only for power users who
+     * wants to create their own interval patterns and use them to create
+     * date interval formatter.
+     * @param status   output param set to success/failure code on exit
+     * @internal ICU 4.0
+     */
+    DateIntervalInfo(UErrorCode& status);
+
+
+    /** 
+     * Construct DateIntervalInfo for the given locale,
+     * @param locale  the interval patterns are loaded from the Gregorian 
+     *                calendar data in this locale.
+     * @param status  output param set to success/failure code on exit
+     * @stable ICU 4.0
+     */
+    DateIntervalInfo(const Locale& locale, UErrorCode& status);
+
+
+    /**
+     * Copy constructor.
+     * @stable ICU 4.0
+     */
+    DateIntervalInfo(const DateIntervalInfo&);
+
+    /**
+     * Assignment operator
+     * @stable ICU 4.0
+     */
+    DateIntervalInfo& operator=(const DateIntervalInfo&);
+
+    /**
+     * Clone this object polymorphically.
+     * The caller owns the result and should delete it when done.
+     * @return   a copy of the object
+     * @stable ICU 4.0
+     */
+    virtual DateIntervalInfo* clone(void) const;
+
+    /**
+     * Destructor.
+     * It is virtual to be safe, but it is not designed to be subclassed.
+     * @stable ICU 4.0
+     */
+    virtual ~DateIntervalInfo();
+
+
+    /**
+     * Return true if another object is semantically equal to this one.
+     *
+     * @param other    the DateIntervalInfo object to be compared with.
+     * @return         true if other is semantically equal to this.
+     * @stable ICU 4.0
+     */
+    virtual UBool operator==(const DateIntervalInfo& other) const;
+
+    /**
+     * Return true if another object is semantically unequal to this one.
+     *
+     * @param other    the DateIntervalInfo object to be compared with.
+     * @return         true if other is semantically unequal to this.
+     * @stable ICU 4.0
+     */
+    UBool operator!=(const DateIntervalInfo& other) const;
+
+
+
+    /** 
+     * Provides a way for client to build interval patterns.
+     * User could construct DateIntervalInfo by providing a list of skeletons
+     * and their patterns.
+     * <P>
+     * For example:
+     * <pre>
+     * UErrorCode status = U_ZERO_ERROR;
+     * DateIntervalInfo dIntervalInfo = new DateIntervalInfo();
+     * dIntervalInfo->setFallbackIntervalPattern("{0} ~ {1}");
+     * dIntervalInfo->setIntervalPattern("yMd", UCAL_YEAR, "'from' yyyy-M-d 'to' yyyy-M-d", status); 
+     * dIntervalInfo->setIntervalPattern("yMMMd", UCAL_MONTH, "'from' yyyy MMM d 'to' MMM d", status);
+     * dIntervalInfo->setIntervalPattern("yMMMd", UCAL_DAY, "yyyy MMM d-d", status, status);
+     * </pre>
+     *
+     * Restriction: 
+     * Currently, users can only set interval patterns when the following 
+     * calendar fields are different: ERA, YEAR, MONTH, DATE,  DAY_OF_MONTH, 
+     * DAY_OF_WEEK, AM_PM,  HOUR, HOUR_OF_DAY, and MINUTE.
+     * Interval patterns when other calendar fields are different are 
+     * not supported.
+     *
+     * @param skeleton         the skeleton on which interval pattern based
+     * @param lrgDiffCalUnit   the largest different calendar unit.
+     * @param intervalPattern  the interval pattern on the largest different
+     *                         calendar unit.
+     *                         For example, if lrgDiffCalUnit is 
+     *                         "year", the interval pattern for en_US when year
+     *                         is different could be "'from' yyyy 'to' yyyy".
+     * @param status           output param set to success/failure code on exit
+     * @stable ICU 4.0
+     */
+    void setIntervalPattern(const UnicodeString& skeleton, 
+                            UCalendarDateFields lrgDiffCalUnit, 
+                            const UnicodeString& intervalPattern,
+                            UErrorCode& status);
+
+    /**
+     * Get the interval pattern given skeleton and 
+     * the largest different calendar field.
+     * @param skeleton   the skeleton
+     * @param field      the largest different calendar field
+     * @param result     output param to receive the pattern
+     * @param status     output param set to success/failure code on exit
+     * @return a reference to 'result'
+     * @stable ICU 4.0 
+     */
+    UnicodeString& getIntervalPattern(const UnicodeString& skeleton,
+                                      UCalendarDateFields field,
+                                      UnicodeString& result,
+                                      UErrorCode& status) const; 
+
+    /**
+     * Get the fallback interval pattern.
+     * @param  result   output param to receive the pattern
+     * @return a reference to 'result'
+     * @stable ICU 4.0 
+     */
+    UnicodeString& getFallbackIntervalPattern(UnicodeString& result) const;
+
+
+    /**
+     * Re-set the fallback interval pattern.
+     *
+     * In construction, default fallback pattern is set as "{0} - {1}".
+     * And constructor taking locale as parameter will set the
+     * fallback pattern as what defined in the locale resource file.
+     *
+     * This method provides a way for user to replace the fallback pattern.
+     *
+     * @param fallbackPattern  fall-back interval pattern.
+     * @param status           output param set to success/failure code on exit
+     * @stable ICU 4.0 
+     */
+    void setFallbackIntervalPattern(const UnicodeString& fallbackPattern,
+                                    UErrorCode& status);
+
+
+    /** Get default order -- whether the first date in pattern is later date
+                             or not.
+     * return default date ordering in interval pattern. TRUE if the first date
+     *        in pattern is later date, FALSE otherwise.
+     * @stable ICU 4.0 
+     */
+    UBool getDefaultOrder() const;
+
+
+    /**
+     * ICU "poor man's RTTI", returns a UClassID for the actual class.
+     *
+     * @stable ICU 4.0
+     */
+    virtual UClassID getDynamicClassID() const;
+
+    /**
+     * ICU "poor man's RTTI", returns a UClassID for this class.
+     *
+     * @stable ICU 4.0
+     */
+    static UClassID U_EXPORT2 getStaticClassID();
+
+
+private:
+    /**
+     * DateIntervalFormat will need access to
+     * getBestSkeleton(), parseSkeleton(), enum IntervalPatternIndex,
+     * and calendarFieldToPatternIndex().
+     *
+     * Instead of making above public,
+     * make DateIntervalFormat a friend of DateIntervalInfo.
+     */
+    friend class DateIntervalFormat;
+
+    friend UBool U_CALLCONV dtitvinfHashTableValueComparator(UHashTok val1, UHashTok val2) ;
+
+    /**
+     * Following is for saving the interval patterns.
+     * We only support interval patterns on
+     * ERA, YEAR, MONTH, DAY, AM_PM, HOUR, and MINUTE
+     */
+    enum IntervalPatternIndex
+    {
+        kIPI_ERA,
+        kIPI_YEAR,
+        kIPI_MONTH,
+        kIPI_DATE,
+        kIPI_AM_PM,
+        kIPI_HOUR,
+        kIPI_MINUTE,
+        kIPI_MAX_INDEX
+    };
+
+    /** 
+     * Initialize the DateIntervalInfo from locale
+     * @param locale   the given locale.
+     * @param status   output param set to success/failure code on exit
+     * @internal ICU 4.0 
+     */
+    void initializeData(const Locale& locale, UErrorCode& status);
+
+
+    /* Set Interval pattern.
+     *
+     * It sets interval pattern into the hash map.
+     *
+     * @param skeleton         skeleton on which the interval pattern based
+     * @param lrgDiffCalUnit   the largest different calendar unit.
+     * @param intervalPattern  the interval pattern on the largest different
+     *                         calendar unit.
+     * @param status           output param set to success/failure code on exit
+     * @internal ICU 4.0
+     */
+    void setIntervalPatternInternally(const UnicodeString& skeleton,
+                                      UCalendarDateFields lrgDiffCalUnit,
+                                      const UnicodeString& intervalPattern,
+                                      UErrorCode& status); 
+
+
+    /**given an input skeleton, get the best match skeleton 
+     * which has pre-defined interval pattern in resource file.
+     * Also return the difference between the input skeleton
+     * and the best match skeleton.
+     *
+     * TODO (xji): set field weight or
+     *             isolate the funtionality in DateTimePatternGenerator
+     * @param  skeleton               input skeleton
+     * @param  bestMatchDistanceInfo  the difference between input skeleton
+     *                                and best match skeleton.
+     *         0, if there is exact match for input skeleton
+     *         1, if there is only field width difference between 
+     *            the best match and the input skeleton
+     *         2, the only field difference is 'v' and 'z'
+     *        -1, if there is calendar field difference between
+     *            the best match and the input skeleton
+     * @return                        best match skeleton
+     * @internal ICU 4.0
+     */
+    const UnicodeString* getBestSkeleton(const UnicodeString& skeleton,
+                                         int8_t& bestMatchDistanceInfo) const;
+
+
+    /**
+     * Parse skeleton, save each field's width.
+     * It is used for looking for best match skeleton,
+     * and adjust pattern field width.
+     * @param skeleton            skeleton to be parsed
+     * @param skeletonFieldWidth  parsed skeleton field width
+     * @internal ICU 4.0
+     */
+    static void U_EXPORT2 parseSkeleton(const UnicodeString& skeleton, 
+                                        int32_t* skeletonFieldWidth);
+
+
+    /**
+     * Check whether one field width is numeric while the other is string.
+     *
+     * TODO (xji): make it general
+     *
+     * @param fieldWidth          one field width
+     * @param anotherFieldWidth   another field width
+     * @param patternLetter       pattern letter char
+     * @return true if one field width is numeric and the other is string,
+     *         false otherwise.
+     * @internal ICU 4.0
+     */
+    static UBool U_EXPORT2 stringNumeric(int32_t fieldWidth,
+                                         int32_t anotherFieldWidth,
+                                         char patternLetter);
+
+
+    /** 
+     * Convert calendar field to the interval pattern index in 
+     * hash table.
+     *
+     * Since we only support the following calendar fields: 
+     * ERA, YEAR, MONTH, DATE,  DAY_OF_MONTH, DAY_OF_WEEK, 
+     * AM_PM,  HOUR, HOUR_OF_DAY, and MINUTE,
+     * We reserve only 4 interval patterns for a skeleton.
+     *
+     * @param field    calendar field
+     * @param status   output param set to success/failure code on exit
+     * @return  interval pattern index in hash table
+     * @internal ICU 4.0
+     */
+    static IntervalPatternIndex U_EXPORT2 calendarFieldToIntervalIndex(
+                                                      UCalendarDateFields field,
+                                                      UErrorCode& status);
+
+
+    /**
+     * delete hash table (of type fIntervalPatterns).
+     *
+     * @param hTable  hash table to be deleted
+     * @internal ICU 4.0
+     */
+    void deleteHash(Hashtable* hTable);
+
+
+    /**
+     * initialize hash table (of type fIntervalPatterns).
+     *
+     * @param status   output param set to success/failure code on exit
+     * @return         hash table initialized
+     * @internal ICU 4.0
+     */
+    Hashtable* initHash(UErrorCode& status);
+
+
+
+    /**
+     * copy hash table (of type fIntervalPatterns).
+     *
+     * @param source   the source to copy from
+     * @param target   the target to copy to
+     * @param status   output param set to success/failure code on exit
+     * @internal ICU 4.0
+     */
+    void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
+
+
+    // data members
+    // fallback interval pattern 
+    UnicodeString fFallbackIntervalPattern;
+    // default order
+    UBool fFirstDateInPtnIsLaterDate;
+
+    // HashMap<UnicodeString, UnicodeString[kIPI_MAX_INDEX]>
+    // HashMap( skeleton, pattern[largest_different_field] )
+    Hashtable* fIntervalPatterns;
+
+};// end class DateIntervalInfo
+
+
+inline UBool
+DateIntervalInfo::operator!=(const DateIntervalInfo& other) const {
+    return !operator==(other);
+}
+
+
+U_NAMESPACE_END
+
+#endif
+
+#endif
+

Modified: trunk/source/i18n/unicode/dtptngen.h
===================================================================
--- trunk/source/i18n/unicode/dtptngen.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/unicode/dtptngen.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -399,7 +399,7 @@
     void addCanonicalItems();
     void addICUPatterns(const Locale& locale, UErrorCode& status);
     void hackTimes(const UnicodeString& hackPattern, UErrorCode& status);
-    void addCLDRData(const Locale& locale);
+    void addCLDRData(const Locale& locale, UErrorCode& status);
     UDateTimePatternConflict addPatternWithSkeleton(const UnicodeString& pattern, const UnicodeString * skeletonToUse, UBool override, UnicodeString& conflictingPattern, UErrorCode& status);
     void initHashtable(UErrorCode& status);
     void setDateTimeFromCalendar(const Locale& locale, UErrorCode& status);

Modified: trunk/source/i18n/unicode/smpdtfmt.h
===================================================================
--- trunk/source/i18n/unicode/smpdtfmt.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/unicode/smpdtfmt.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -947,6 +947,7 @@
     /**
      * Get the numbering system to be used for a particular field.
      */
+    using DateFormat::getNumberFormat;    // Do not hide visibility of base class function
     NumberFormat * getNumberFormat(UDateFormatField index) const;
 
     /**

Modified: trunk/source/i18n/unicode/tmunit.h
===================================================================
--- trunk/source/i18n/unicode/tmunit.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/unicode/tmunit.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,149 +1,149 @@
-/*
- *******************************************************************************
- * Copyright (C) 2009, Google, International Business Machines Corporation and *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-#ifndef __TMUNIT_H__
-#define __TMUNIT_H__
-
-
-/**
- * \file
- * \brief C++ API: time unit object
- */
-
-
-#include "unicode/measunit.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-U_NAMESPACE_BEGIN
-
-/**
- * Measurement unit for time units.
- * @see TimeUnitAmount
- * @see TimeUnit
- * @draft ICU 4.2
- */
-class U_I18N_API TimeUnit: public MeasureUnit {
-public:
-    /**
-     * Constants for all the time units we supported.
-     * @draft ICU 4.2
-     */
-    enum UTimeUnitFields {
-        UTIMEUNIT_YEAR,
-        UTIMEUNIT_MONTH,
-        UTIMEUNIT_DAY,
-        UTIMEUNIT_WEEK,
-        UTIMEUNIT_HOUR,
-        UTIMEUNIT_MINUTE,
-        UTIMEUNIT_SECOND,
-        UTIMEUNIT_FIELD_COUNT
-    };
-
-    /**
-     * Create Instance.
-     * @param timeUnitField  time unit field based on which the instance 
-     *                       is created.
-     * @param status         input-output error code. 
-     *                       If the timeUnitField is invalid,
-     *                       then this will be set to U_ILLEGAL_ARGUMENT_ERROR.
-     * @return               a TimeUnit instance
-     * @draft ICU 4.2 
-     */
-    static TimeUnit* U_EXPORT2 createInstance(UTimeUnitFields timeUnitField,
-                                              UErrorCode& status);
-
-
-    /**
-     * Override clone.
-     * @draft ICU 4.2 
-     */
-    virtual UObject* clone() const;
-
-    /**
-     * Copy operator.
-     * @draft ICU 4.2 
-     */
-    TimeUnit(const TimeUnit& other);
-
-    /**
-     * Assignment operator.
-     * @draft ICU 4.2 
-     */
-    TimeUnit& operator=(const TimeUnit& other);
-
-    /**
-     * Equality operator. 
-     * @return true if 2 objects are the same.
-     * @draft ICU 4.2 
-     */
-    virtual UBool operator==(const UObject& other) const;
-
-    /**
-     * Non-Equality operator. 
-     * @return true if 2 objects are not the same.
-     * @draft ICU 4.2 
-     */
-    UBool operator!=(const UObject& other) const;
-
-    /**
-     * Returns a unique class ID for this object POLYMORPHICALLY.
-     * This method implements a simple form of RTTI used by ICU.
-     * @return The class ID for this object. All objects of a given
-     * class have the same class ID.  Objects of other classes have
-     * different class IDs.
-     * @draft ICU 4.2 
-     */
-    virtual UClassID getDynamicClassID() const;
-
-    /**
-     * Returns the class ID for this class. This is used to compare to
-     * the return value of getDynamicClassID().
-     * @return The class ID for all objects of this class.
-     * @draft ICU 4.2 
-     */
-    static UClassID U_EXPORT2 getStaticClassID();
-
-
-    /**
-     * Get time unit field.
-     * @return time unit field.
-     * @draft ICU 4.2 
-     */
-    UTimeUnitFields getTimeUnitField() const;
-
-    /**
-     * Destructor.
-     * @draft ICU 4.2 
-     */
-    virtual ~TimeUnit();
-
-private:
-    UTimeUnitFields fTimeUnitField;
-
-    /**
-     * Constructor
-     * @internal ICU 4.2 
-     */
-    TimeUnit(UTimeUnitFields timeUnitField);
-
-};
-
-
-inline UBool 
-TimeUnit::operator!=(const UObject& other) const {
-    return !operator==(other);
-}
-
-
-U_NAMESPACE_END
-
-#endif /* #if !UCONFIG_NO_FORMATTING */
-
-#endif // __TMUNIT_H__
-//eof
-//
+/*
+ *******************************************************************************
+ * Copyright (C) 2009, Google, International Business Machines Corporation and *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+#ifndef __TMUNIT_H__
+#define __TMUNIT_H__
+
+
+/**
+ * \file
+ * \brief C++ API: time unit object
+ */
+
+
+#include "unicode/measunit.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+U_NAMESPACE_BEGIN
+
+/**
+ * Measurement unit for time units.
+ * @see TimeUnitAmount
+ * @see TimeUnit
+ * @draft ICU 4.2
+ */
+class U_I18N_API TimeUnit: public MeasureUnit {
+public:
+    /**
+     * Constants for all the time units we supported.
+     * @draft ICU 4.2
+     */
+    enum UTimeUnitFields {
+        UTIMEUNIT_YEAR,
+        UTIMEUNIT_MONTH,
+        UTIMEUNIT_DAY,
+        UTIMEUNIT_WEEK,
+        UTIMEUNIT_HOUR,
+        UTIMEUNIT_MINUTE,
+        UTIMEUNIT_SECOND,
+        UTIMEUNIT_FIELD_COUNT
+    };
+
+    /**
+     * Create Instance.
+     * @param timeUnitField  time unit field based on which the instance 
+     *                       is created.
+     * @param status         input-output error code. 
+     *                       If the timeUnitField is invalid,
+     *                       then this will be set to U_ILLEGAL_ARGUMENT_ERROR.
+     * @return               a TimeUnit instance
+     * @draft ICU 4.2 
+     */
+    static TimeUnit* U_EXPORT2 createInstance(UTimeUnitFields timeUnitField,
+                                              UErrorCode& status);
+
+
+    /**
+     * Override clone.
+     * @draft ICU 4.2 
+     */
+    virtual UObject* clone() const;
+
+    /**
+     * Copy operator.
+     * @draft ICU 4.2 
+     */
+    TimeUnit(const TimeUnit& other);
+
+    /**
+     * Assignment operator.
+     * @draft ICU 4.2 
+     */
+    TimeUnit& operator=(const TimeUnit& other);
+
+    /**
+     * Equality operator. 
+     * @return true if 2 objects are the same.
+     * @draft ICU 4.2 
+     */
+    virtual UBool operator==(const UObject& other) const;
+
+    /**
+     * Non-Equality operator. 
+     * @return true if 2 objects are not the same.
+     * @draft ICU 4.2 
+     */
+    UBool operator!=(const UObject& other) const;
+
+    /**
+     * Returns a unique class ID for this object POLYMORPHICALLY.
+     * This method implements a simple form of RTTI used by ICU.
+     * @return The class ID for this object. All objects of a given
+     * class have the same class ID.  Objects of other classes have
+     * different class IDs.
+     * @draft ICU 4.2 
+     */
+    virtual UClassID getDynamicClassID() const;
+
+    /**
+     * Returns the class ID for this class. This is used to compare to
+     * the return value of getDynamicClassID().
+     * @return The class ID for all objects of this class.
+     * @draft ICU 4.2 
+     */
+    static UClassID U_EXPORT2 getStaticClassID();
+
+
+    /**
+     * Get time unit field.
+     * @return time unit field.
+     * @draft ICU 4.2 
+     */
+    UTimeUnitFields getTimeUnitField() const;
+
+    /**
+     * Destructor.
+     * @draft ICU 4.2 
+     */
+    virtual ~TimeUnit();
+
+private:
+    UTimeUnitFields fTimeUnitField;
+
+    /**
+     * Constructor
+     * @internal ICU 4.2 
+     */
+    TimeUnit(UTimeUnitFields timeUnitField);
+
+};
+
+
+inline UBool 
+TimeUnit::operator!=(const UObject& other) const {
+    return !operator==(other);
+}
+
+
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif // __TMUNIT_H__
+//eof
+//

Modified: trunk/source/i18n/unicode/tmutamt.h
===================================================================
--- trunk/source/i18n/unicode/tmutamt.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/unicode/tmutamt.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,168 +1,168 @@
-/*
- *******************************************************************************
- * Copyright (C) 2009, Google, International Business Machines Corporation and *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */ 
-
-#ifndef __TMUTAMT_H__
-#define __TMUTAMT_H__
-
-
-/**
- * \file
- * \brief C++ API: time unit amount object.
- */
-
-#include "unicode/measure.h"
-#include "unicode/tmunit.h"
-
-#if !UCONFIG_NO_FORMATTING
-
-U_NAMESPACE_BEGIN
-
-
-/**
- * Express a duration as a time unit and number. Patterned after Currency.
- * @see TimeUnitAmount
- * @see TimeUnitFormat
- * @draft ICU 4.2
- */
-class U_I18N_API TimeUnitAmount: public Measure {
-public:
-    /**
-     * Construct TimeUnitAmount object with the given number and the
-     * given time unit. 
-     * @param number        a numeric object; number.isNumeric() must be TRUE
-     * @param timeUnitField the time unit field of a time unit
-     * @param status        the input-output error code. 
-     *                      If the number is not numeric or the timeUnitField
-     *                      is not valid,
-     *                      then this will be set to a failing value:
-     *                      U_ILLEGAL_ARGUMENT_ERROR.
-     * @draft ICU 4.2
-     */
-    TimeUnitAmount(const Formattable& number, 
-                   TimeUnit::UTimeUnitFields timeUnitField,
-                   UErrorCode& status);
-
-    /**
-     * Construct TimeUnitAmount object with the given numeric amount and the
-     * given time unit. 
-     * @param amount        a numeric amount.
-     * @param timeUnitField the time unit field on which a time unit amount
-     *                      object will be created.
-     * @param status        the input-output error code. 
-     *                      If the timeUnitField is not valid,
-     *                      then this will be set to a failing value:
-     *                      U_ILLEGAL_ARGUMENT_ERROR.
-     * @draft ICU 4.2
-     */
-    TimeUnitAmount(double amount, TimeUnit::UTimeUnitFields timeUnitField,
-                   UErrorCode& status);
-
-
-    /**
-     * Copy constructor 
-     * @draft ICU 4.2
-     */
-    TimeUnitAmount(const TimeUnitAmount& other);
-
-
-    /**
-     * Assignment operator
-     * @draft ICU 4.2
-     */
-    TimeUnitAmount& operator=(const TimeUnitAmount& other);
-
-
-    /**
-     * Clone. 
-     * @return a polymorphic clone of this object. The result will have the same               class as returned by getDynamicClassID().
-     * @draft ICU 4.2
-     */
-    virtual UObject* clone() const;
-
-    
-    /**
-     * Destructor
-     * @draft ICU 4.2
-     */
-    virtual ~TimeUnitAmount();
-
-    
-    /** 
-     * Equality operator.  
-     * @param other  the object to compare to.
-     * @return       true if this object is equal to the given object.
-     * @draft ICU 4.2
-     */
-    virtual UBool operator==(const UObject& other) const;
-
-
-    /** 
-     * Not-equality operator.  
-     * @param other  the object to compare to.
-     * @return       true if this object is not equal to the given object.
-     * @draft ICU 4.2
-     */
-    UBool operator!=(const UObject& other) const;
-
-
-    /**
-     * Return the class ID for this class. This is useful only for comparing to
-     * a return value from getDynamicClassID(). For example:
-     * <pre>
-     * .   Base* polymorphic_pointer = createPolymorphicObject();
-     * .   if (polymorphic_pointer->getDynamicClassID() ==
-     * .       erived::getStaticClassID()) ...
-     * </pre>
-     * @return          The class ID for all objects of this class.
-     * @draft ICU 4.2
-     */
-    static UClassID U_EXPORT2 getStaticClassID(void);
-
-
-    /**
-     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
-     * method is to implement a simple version of RTTI, since not all C++
-     * compilers support genuine RTTI. Polymorphic operator==() and clone()
-     * methods call this method.
-     *
-     * @return          The class ID for this object. All objects of a
-     *                  given class have the same class ID.  Objects of
-     *                  other classes have different class IDs.
-     * @draft ICU 4.2
-     */
-    virtual UClassID getDynamicClassID(void) const;
-
-
-    /**
-     * Get the time unit.
-     * @return time unit object.
-     * @draft ICU 4.2
-     */
-    const TimeUnit& getTimeUnit() const;
-
-    /**
-     * Get the time unit field value.
-     * @return time unit field value.
-     * @draft ICU 4.2
-     */
-    TimeUnit::UTimeUnitFields getTimeUnitField() const;
-};
-
-
-
-inline UBool 
-TimeUnitAmount::operator!=(const UObject& other) const {
-    return !operator==(other);
-}
-
-U_NAMESPACE_END
-
-#endif /* #if !UCONFIG_NO_FORMATTING */
-
-#endif // __TMUTAMT_H__
-//eof
-//
+/*
+ *******************************************************************************
+ * Copyright (C) 2009, Google, International Business Machines Corporation and *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */ 
+
+#ifndef __TMUTAMT_H__
+#define __TMUTAMT_H__
+
+
+/**
+ * \file
+ * \brief C++ API: time unit amount object.
+ */
+
+#include "unicode/measure.h"
+#include "unicode/tmunit.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+U_NAMESPACE_BEGIN
+
+
+/**
+ * Express a duration as a time unit and number. Patterned after Currency.
+ * @see TimeUnitAmount
+ * @see TimeUnitFormat
+ * @draft ICU 4.2
+ */
+class U_I18N_API TimeUnitAmount: public Measure {
+public:
+    /**
+     * Construct TimeUnitAmount object with the given number and the
+     * given time unit. 
+     * @param number        a numeric object; number.isNumeric() must be TRUE
+     * @param timeUnitField the time unit field of a time unit
+     * @param status        the input-output error code. 
+     *                      If the number is not numeric or the timeUnitField
+     *                      is not valid,
+     *                      then this will be set to a failing value:
+     *                      U_ILLEGAL_ARGUMENT_ERROR.
+     * @draft ICU 4.2
+     */
+    TimeUnitAmount(const Formattable& number, 
+                   TimeUnit::UTimeUnitFields timeUnitField,
+                   UErrorCode& status);
+
+    /**
+     * Construct TimeUnitAmount object with the given numeric amount and the
+     * given time unit. 
+     * @param amount        a numeric amount.
+     * @param timeUnitField the time unit field on which a time unit amount
+     *                      object will be created.
+     * @param status        the input-output error code. 
+     *                      If the timeUnitField is not valid,
+     *                      then this will be set to a failing value:
+     *                      U_ILLEGAL_ARGUMENT_ERROR.
+     * @draft ICU 4.2
+     */
+    TimeUnitAmount(double amount, TimeUnit::UTimeUnitFields timeUnitField,
+                   UErrorCode& status);
+
+
+    /**
+     * Copy constructor 
+     * @draft ICU 4.2
+     */
+    TimeUnitAmount(const TimeUnitAmount& other);
+
+
+    /**
+     * Assignment operator
+     * @draft ICU 4.2
+     */
+    TimeUnitAmount& operator=(const TimeUnitAmount& other);
+
+
+    /**
+     * Clone. 
+     * @return a polymorphic clone of this object. The result will have the same               class as returned by getDynamicClassID().
+     * @draft ICU 4.2
+     */
+    virtual UObject* clone() const;
+
+    
+    /**
+     * Destructor
+     * @draft ICU 4.2
+     */
+    virtual ~TimeUnitAmount();
+
+    
+    /** 
+     * Equality operator.  
+     * @param other  the object to compare to.
+     * @return       true if this object is equal to the given object.
+     * @draft ICU 4.2
+     */
+    virtual UBool operator==(const UObject& other) const;
+
+
+    /** 
+     * Not-equality operator.  
+     * @param other  the object to compare to.
+     * @return       true if this object is not equal to the given object.
+     * @draft ICU 4.2
+     */
+    UBool operator!=(const UObject& other) const;
+
+
+    /**
+     * Return the class ID for this class. This is useful only for comparing to
+     * a return value from getDynamicClassID(). For example:
+     * <pre>
+     * .   Base* polymorphic_pointer = createPolymorphicObject();
+     * .   if (polymorphic_pointer->getDynamicClassID() ==
+     * .       erived::getStaticClassID()) ...
+     * </pre>
+     * @return          The class ID for all objects of this class.
+     * @draft ICU 4.2
+     */
+    static UClassID U_EXPORT2 getStaticClassID(void);
+
+
+    /**
+     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
+     * method is to implement a simple version of RTTI, since not all C++
+     * compilers support genuine RTTI. Polymorphic operator==() and clone()
+     * methods call this method.
+     *
+     * @return          The class ID for this object. All objects of a
+     *                  given class have the same class ID.  Objects of
+     *                  other classes have different class IDs.
+     * @draft ICU 4.2
+     */
+    virtual UClassID getDynamicClassID(void) const;
+
+
+    /**
+     * Get the time unit.
+     * @return time unit object.
+     * @draft ICU 4.2
+     */
+    const TimeUnit& getTimeUnit() const;
+
+    /**
+     * Get the time unit field value.
+     * @return time unit field value.
+     * @draft ICU 4.2
+     */
+    TimeUnit::UTimeUnitFields getTimeUnitField() const;
+};
+
+
+
+inline UBool 
+TimeUnitAmount::operator!=(const UObject& other) const {
+    return !operator==(other);
+}
+
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif // __TMUTAMT_H__
+//eof
+//

Modified: trunk/source/i18n/unicode/tmutfmt.h
===================================================================
--- trunk/source/i18n/unicode/tmutfmt.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/unicode/tmutfmt.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,281 +1,281 @@
-/*
- *******************************************************************************
- * Copyright (C) 2008, Google, International Business Machines Corporation and *
- * others. All Rights Reserved.                                                *
- *******************************************************************************
- */
-
-#ifndef __TMUTFMT_H__
-#define __TMUTFMT_H__
-
-#include "unicode/utypes.h"
-
-/**
- * \file
- * \brief C++ API: Format and parse duration in single time unit
- */
-
-
-#if !UCONFIG_NO_FORMATTING
-
-#include "unicode/unistr.h"
-#include "unicode/tmunit.h"
-#include "unicode/tmutamt.h"
-#include "unicode/measfmt.h"
-#include "unicode/numfmt.h"
-#include "unicode/plurrule.h"
-
-/**
- * @internal ICU 4.2
- */
-
-union UHashTok;
-
-U_NAMESPACE_BEGIN
-
-U_CDECL_BEGIN
-
-/**
- * @internal ICU 4.2
- */
-static UBool U_CALLCONV hashTableValueComparator(UHashTok val1, UHashTok val2) ;
-
-U_CDECL_END
-
-
-class Hashtable;
-
-
-/**
- * Format or parse a TimeUnitAmount, using plural rules for the units where available.
- *
- * <P>
- * Code Sample: 
- * <pre>
- *   // create time unit amount instance - a combination of Number and time unit
- *   UErrorCode status = U_ZERO_ERROR;
- *   TimeUnitAmount* source = new TimeUnitAmount(2, TimeUnit::UTIMEUNIT_YEAR, status);
- *   // create time unit format instance
- *   TimeUnitFormat* format = new TimeUnitFormat(Locale("en"), status);
- *   // format a time unit amount
- *   UnicodeString formatted;
- *   Formattable formattable;
- *   if (U_SUCCESS(status)) {
- *       formattable.adoptObject(source);
- *       formatted = ((Format*)format)->format(formattable, formatted, status);
- *       Formattable result;
- *       ((Format*)format)->parseObject(formatted, result, status);
- *       if (U_SUCCESS(status)) {
- *           assert (result == formattable); 
- *       }
- *   }
- * </pre>
- *
- * <P>
- * @see TimeUnitAmount
- * @see TimeUnitFormat
- * @draft ICU 4.2
- */
-class U_I18N_API TimeUnitFormat: public MeasureFormat {
-public:
-
-    /**
-     * Constants for various styles.
-     * There are 2 styles: full name and abbreviated name.
-     * For example, for English, the full name for hour duration is "3 hours",
-     * and the abbreviated name is "3 hrs".
-     * @draft ICU 4.2
-     */
-    enum EStyle {
-        kFull = 0,
-        kAbbreviate = 1,
-        kTotal = kAbbreviate + 1
-    };
-    
-    /**
-     * Create TimeUnitFormat with default locale, and full name style. 
-     * Use setLocale and/or setFormat to modify.
-     * @draft ICU 4.2
-     */
-    TimeUnitFormat(UErrorCode& status);
-
-    /**
-     * Create TimeUnitFormat given locale, and full name style.
-     * @draft ICU 4.2
-     */
-    TimeUnitFormat(const Locale& locale, UErrorCode& status);
-
-    /**
-     * Create TimeUnitFormat given locale and style.
-     * @draft ICU 4.2
-     */
-    TimeUnitFormat(const Locale& locale, EStyle style, UErrorCode& status);
-
-    /**
-     * Copy constructor.
-     * @draft ICU 4.2
-     */
-    TimeUnitFormat(const TimeUnitFormat&);
-
-    /**
-     * deconstructor
-     * @draft ICU 4.2
-     */
-    virtual ~TimeUnitFormat();
-
-    /**
-     * Clone this Format object polymorphically. The caller owns the result and
-     * should delete it when done.
-     * @return    A copy of the object.
-     * @draft ICU 4.2
-     */
-    virtual Format* clone(void) const;
-
-    /**
-     * Assignment operator
-     * @draft ICU 4.2
-     */
-    TimeUnitFormat& operator=(const TimeUnitFormat& other);
-
-
-    /**
-     * Return true if the given Format objects are semantically equal. Objects
-     * of different subclasses are considered unequal.
-     * @param other    the object to be compared with.
-     * @return         true if the given Format objects are semantically equal.
-     * @draft ICU 4.2
-     */
-    virtual UBool operator==(const Format& other) const;
-
-    /**
-     * Return true if the given Format objects are not semantically equal. 
-     * Objects of different subclasses are considered unequal.
-     * @param other the object to be compared with.
-     * @return      true if the given Format objects are not semantically equal.
-     * @draft ICU 4.2
-     */
-    UBool operator!=(const Format& other) const;
-
-    /**
-     * Set the locale used for formatting or parsing.
-     * @param locale  the locale to be set
-     * @param status  output param set to success/failure code on exit
-     * @draft ICU 4.2
-     */
-    void setLocale(const Locale& locale, UErrorCode& status);
-
-
-    /**
-     * Set the number format used for formatting or parsing. 
-     * @param format  the number formatter to be set
-     * @param status  output param set to success/failure code on exit
-     * @draft ICU 4.2
-     */
-    void setNumberFormat(const NumberFormat& format, UErrorCode& status);
-
-    /**
-     * Format a TimeUnitAmount.
-     * If the formattable object is not a time unit amount object,
-     * or the number in time unit amount is not a double type or long type
-     * numeric, it returns a failing status: U_ILLEGAL_ARGUMENT_ERROR.
-     * @see Format#format(const Formattable&, UnicodeString&, FieldPosition&,  UErrorCode&) const
-     * @draft ICU 4.2
-     */
-    virtual UnicodeString& format(const Formattable& obj, 
-                                  UnicodeString& toAppendTo,
-                                  FieldPosition& pos, 
-                                  UErrorCode& status) const; 
-
-    /**
-     * Parse a TimeUnitAmount.
-     * @see Format#parseObject(const UnicodeString&, Formattable&, ParsePosition&) const;
-     * @draft ICU 4.2
-     */
-    virtual void parseObject(const UnicodeString& source, 
-                             Formattable& result,
-                             ParsePosition& pos) const;
-
-    /**
-     * Return the class ID for this class. This is useful only for comparing to
-     * a return value from getDynamicClassID(). For example:
-     * <pre>
-     * .   Base* polymorphic_pointer = createPolymorphicObject();
-     * .   if (polymorphic_pointer->getDynamicClassID() ==
-     * .       erived::getStaticClassID()) ...
-     * </pre>
-     * @return          The class ID for all objects of this class.
-     * @draft ICU 4.2
-     */
-    static UClassID U_EXPORT2 getStaticClassID(void);
-
-    /**
-     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
-     * method is to implement a simple version of RTTI, since not all C++
-     * compilers support genuine RTTI. Polymorphic operator==() and clone()
-     * methods call this method.
-     *
-     * @return          The class ID for this object. All objects of a
-     *                  given class have the same class ID.  Objects of
-     *                  other classes have different class IDs.
-     * @draft ICU 4.2
-     */
-    virtual UClassID getDynamicClassID(void) const;
-
-private:
-    NumberFormat* fNumberFormat;
-    Locale        fLocale;
-    Hashtable*    fTimeUnitToCountToPatterns[TimeUnit::UTIMEUNIT_FIELD_COUNT];
-    PluralRules*  fPluralRules;
-    EStyle           fStyle;
-
-    friend UBool U_CALLCONV hashTableValueComparator(UHashTok val1, UHashTok val2);
-    
-    void create(const Locale& locale, EStyle style, UErrorCode& status);
-
-    // it might actually be simpler to make them Decimal Formats later.
-    // initialize all private data members
-    void setup(UErrorCode& status); 
- 
-    // initialize data member without fill in data for fTimeUnitToCountToPattern
-    void initDataMembers(UErrorCode& status);
-
-    // initialize fTimeUnitToCountToPatterns from current locale's resource.
-    void readFromCurrentLocale(EStyle style, const char* key, UErrorCode& status);
-
-    // check completeness of fTimeUnitToCountToPatterns against all time units,
-    // and all plural rules, fill in fallback as necessary.
-    void checkConsistency(EStyle style, const char* key, UErrorCode& status);
-
-    // fill in fTimeUnitToCountToPatterns from locale fall-back chain
-    void searchInLocaleChain(EStyle style, const char* key, 
-                             TimeUnit::UTimeUnitFields field, const char*, 
-                             const char*, Hashtable*, UErrorCode&);
-
-    // initialize hash table
-    Hashtable* initHash(UErrorCode& status);
-
-    // delete hash table
-    void deleteHash(Hashtable* htable);
-
-    // copy hash table
-    void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
-    // get time unit name, such as "year", from time unit field enum, such as
-    // UTIMEUNIT_YEAR.
-    static const char* getTimeUnitName(TimeUnit::UTimeUnitFields field, UErrorCode& status);
-};
-
-
-
-inline UBool
-TimeUnitFormat::operator!=(const Format& other) const  {
-    return !operator==(other);
-}
-
-
-
-U_NAMESPACE_END
-
-#endif /* #if !UCONFIG_NO_FORMATTING */
-
-#endif // __TMUTFMT_H__
-//eof
+/*
+ *******************************************************************************
+ * Copyright (C) 2008, Google, International Business Machines Corporation and *
+ * others. All Rights Reserved.                                                *
+ *******************************************************************************
+ */
+
+#ifndef __TMUTFMT_H__
+#define __TMUTFMT_H__
+
+#include "unicode/utypes.h"
+
+/**
+ * \file
+ * \brief C++ API: Format and parse duration in single time unit
+ */
+
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/unistr.h"
+#include "unicode/tmunit.h"
+#include "unicode/tmutamt.h"
+#include "unicode/measfmt.h"
+#include "unicode/numfmt.h"
+#include "unicode/plurrule.h"
+
+/**
+ * @internal ICU 4.2
+ */
+
+union UHashTok;
+
+U_NAMESPACE_BEGIN
+
+U_CDECL_BEGIN
+
+/**
+ * @internal ICU 4.2
+ */
+static UBool U_CALLCONV hashTableValueComparator(UHashTok val1, UHashTok val2) ;
+
+U_CDECL_END
+
+
+class Hashtable;
+
+
+/**
+ * Format or parse a TimeUnitAmount, using plural rules for the units where available.
+ *
+ * <P>
+ * Code Sample: 
+ * <pre>
+ *   // create time unit amount instance - a combination of Number and time unit
+ *   UErrorCode status = U_ZERO_ERROR;
+ *   TimeUnitAmount* source = new TimeUnitAmount(2, TimeUnit::UTIMEUNIT_YEAR, status);
+ *   // create time unit format instance
+ *   TimeUnitFormat* format = new TimeUnitFormat(Locale("en"), status);
+ *   // format a time unit amount
+ *   UnicodeString formatted;
+ *   Formattable formattable;
+ *   if (U_SUCCESS(status)) {
+ *       formattable.adoptObject(source);
+ *       formatted = ((Format*)format)->format(formattable, formatted, status);
+ *       Formattable result;
+ *       ((Format*)format)->parseObject(formatted, result, status);
+ *       if (U_SUCCESS(status)) {
+ *           assert (result == formattable); 
+ *       }
+ *   }
+ * </pre>
+ *
+ * <P>
+ * @see TimeUnitAmount
+ * @see TimeUnitFormat
+ * @draft ICU 4.2
+ */
+class U_I18N_API TimeUnitFormat: public MeasureFormat {
+public:
+
+    /**
+     * Constants for various styles.
+     * There are 2 styles: full name and abbreviated name.
+     * For example, for English, the full name for hour duration is "3 hours",
+     * and the abbreviated name is "3 hrs".
+     * @draft ICU 4.2
+     */
+    enum EStyle {
+        kFull = 0,
+        kAbbreviate = 1,
+        kTotal = kAbbreviate + 1
+    };
+    
+    /**
+     * Create TimeUnitFormat with default locale, and full name style. 
+     * Use setLocale and/or setFormat to modify.
+     * @draft ICU 4.2
+     */
+    TimeUnitFormat(UErrorCode& status);
+
+    /**
+     * Create TimeUnitFormat given locale, and full name style.
+     * @draft ICU 4.2
+     */
+    TimeUnitFormat(const Locale& locale, UErrorCode& status);
+
+    /**
+     * Create TimeUnitFormat given locale and style.
+     * @draft ICU 4.2
+     */
+    TimeUnitFormat(const Locale& locale, EStyle style, UErrorCode& status);
+
+    /**
+     * Copy constructor.
+     * @draft ICU 4.2
+     */
+    TimeUnitFormat(const TimeUnitFormat&);
+
+    /**
+     * deconstructor
+     * @draft ICU 4.2
+     */
+    virtual ~TimeUnitFormat();
+
+    /**
+     * Clone this Format object polymorphically. The caller owns the result and
+     * should delete it when done.
+     * @return    A copy of the object.
+     * @draft ICU 4.2
+     */
+    virtual Format* clone(void) const;
+
+    /**
+     * Assignment operator
+     * @draft ICU 4.2
+     */
+    TimeUnitFormat& operator=(const TimeUnitFormat& other);
+
+
+    /**
+     * Return true if the given Format objects are semantically equal. Objects
+     * of different subclasses are considered unequal.
+     * @param other    the object to be compared with.
+     * @return         true if the given Format objects are semantically equal.
+     * @draft ICU 4.2
+     */
+    virtual UBool operator==(const Format& other) const;
+
+    /**
+     * Return true if the given Format objects are not semantically equal. 
+     * Objects of different subclasses are considered unequal.
+     * @param other the object to be compared with.
+     * @return      true if the given Format objects are not semantically equal.
+     * @draft ICU 4.2
+     */
+    UBool operator!=(const Format& other) const;
+
+    /**
+     * Set the locale used for formatting or parsing.
+     * @param locale  the locale to be set
+     * @param status  output param set to success/failure code on exit
+     * @draft ICU 4.2
+     */
+    void setLocale(const Locale& locale, UErrorCode& status);
+
+
+    /**
+     * Set the number format used for formatting or parsing. 
+     * @param format  the number formatter to be set
+     * @param status  output param set to success/failure code on exit
+     * @draft ICU 4.2
+     */
+    void setNumberFormat(const NumberFormat& format, UErrorCode& status);
+
+    /**
+     * Format a TimeUnitAmount.
+     * If the formattable object is not a time unit amount object,
+     * or the number in time unit amount is not a double type or long type
+     * numeric, it returns a failing status: U_ILLEGAL_ARGUMENT_ERROR.
+     * @see Format#format(const Formattable&, UnicodeString&, FieldPosition&,  UErrorCode&) const
+     * @draft ICU 4.2
+     */
+    virtual UnicodeString& format(const Formattable& obj, 
+                                  UnicodeString& toAppendTo,
+                                  FieldPosition& pos, 
+                                  UErrorCode& status) const; 
+
+    /**
+     * Parse a TimeUnitAmount.
+     * @see Format#parseObject(const UnicodeString&, Formattable&, ParsePosition&) const;
+     * @draft ICU 4.2
+     */
+    virtual void parseObject(const UnicodeString& source, 
+                             Formattable& result,
+                             ParsePosition& pos) const;
+
+    /**
+     * Return the class ID for this class. This is useful only for comparing to
+     * a return value from getDynamicClassID(). For example:
+     * <pre>
+     * .   Base* polymorphic_pointer = createPolymorphicObject();
+     * .   if (polymorphic_pointer->getDynamicClassID() ==
+     * .       erived::getStaticClassID()) ...
+     * </pre>
+     * @return          The class ID for all objects of this class.
+     * @draft ICU 4.2
+     */
+    static UClassID U_EXPORT2 getStaticClassID(void);
+
+    /**
+     * Returns a unique class ID POLYMORPHICALLY. Pure virtual override. This
+     * method is to implement a simple version of RTTI, since not all C++
+     * compilers support genuine RTTI. Polymorphic operator==() and clone()
+     * methods call this method.
+     *
+     * @return          The class ID for this object. All objects of a
+     *                  given class have the same class ID.  Objects of
+     *                  other classes have different class IDs.
+     * @draft ICU 4.2
+     */
+    virtual UClassID getDynamicClassID(void) const;
+
+private:
+    NumberFormat* fNumberFormat;
+    Locale        fLocale;
+    Hashtable*    fTimeUnitToCountToPatterns[TimeUnit::UTIMEUNIT_FIELD_COUNT];
+    PluralRules*  fPluralRules;
+    EStyle           fStyle;
+
+    friend UBool U_CALLCONV hashTableValueComparator(UHashTok val1, UHashTok val2);
+    
+    void create(const Locale& locale, EStyle style, UErrorCode& status);
+
+    // it might actually be simpler to make them Decimal Formats later.
+    // initialize all private data members
+    void setup(UErrorCode& status); 
+ 
+    // initialize data member without fill in data for fTimeUnitToCountToPattern
+    void initDataMembers(UErrorCode& status);
+
+    // initialize fTimeUnitToCountToPatterns from current locale's resource.
+    void readFromCurrentLocale(EStyle style, const char* key, UErrorCode& status);
+
+    // check completeness of fTimeUnitToCountToPatterns against all time units,
+    // and all plural rules, fill in fallback as necessary.
+    void checkConsistency(EStyle style, const char* key, UErrorCode& status);
+
+    // fill in fTimeUnitToCountToPatterns from locale fall-back chain
+    void searchInLocaleChain(EStyle style, const char* key, 
+                             TimeUnit::UTimeUnitFields field, const char*, 
+                             const char*, Hashtable*, UErrorCode&);
+
+    // initialize hash table
+    Hashtable* initHash(UErrorCode& status);
+
+    // delete hash table
+    void deleteHash(Hashtable* htable);
+
+    // copy hash table
+    void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
+    // get time unit name, such as "year", from time unit field enum, such as
+    // UTIMEUNIT_YEAR.
+    static const char* getTimeUnitName(TimeUnit::UTimeUnitFields field, UErrorCode& status);
+};
+
+
+
+inline UBool
+TimeUnitFormat::operator!=(const Format& other) const  {
+    return !operator==(other);
+}
+
+
+
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
+
+#endif // __TMUTFMT_H__
+//eof

Modified: trunk/source/i18n/uspoof_impl.cpp
===================================================================
--- trunk/source/i18n/uspoof_impl.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/i18n/uspoof_impl.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -27,7 +27,7 @@
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SpoofImpl)
 
 SpoofImpl::SpoofImpl(SpoofData *data, UErrorCode &status) :
-    fMagic(0), fSpoofData(NULL), fAllowedCharsSet(NULL) {
+    fMagic(0), fSpoofData(NULL), fAllowedCharsSet(NULL) , fAllowedLocales(NULL) {
     if (U_FAILURE(status)) {
         return;
     }

Deleted: trunk/source/layout/HindiFeatureTags.h
===================================================================
--- trunk/source/layout/HindiFeatureTags.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/layout/HindiFeatureTags.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,42 +0,0 @@
-/*
- *
- * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
- *
- */
-
-#ifndef __HINDIFEATURETAGS_H
-#define __HINDIFEATURETAGS_H
-
-/**
- * \file
- * \internal
- */
-
-#include "jni.h"
-#include "LETypes.h"
-#include "OpenTypeTables.h"
-
-U_NAMESPACE_BEGIN
-
-const LETag oopsFeatureTag = 0x6F6F7073; // 'oops'
-
-const LETag nuktFeatureTag = 0x6E756B74; // 'nukt'
-const LETag akhnFeatureTag = 0x616B686E; // 'akhn'
-const LETag rphfFeatureTag = 0x72706866; // 'rphf'
-const LETag blwfFeatureTag = 0x626C7766; // 'blwf'
-const LETag halfFeatureTag = 0x68616C66; // 'half'
-const LETag pstfFeatureTag = 0x70737466; // 'pstf'
-const LETag vatuFeatureTag = 0x76617475; // 'vatu'
-const LETag presFeatureTag = 0x70726573; // 'pres'
-const LETag blwsFeatureTag = 0x626C7773; // 'blws'
-const LETag abvsFeatureTag = 0x61627673; // 'abvs'
-const LETag pstsFeatureTag = 0x70737473; // 'psts'
-const LETag halnFeatureTag = 0x68616C6E; // 'haln'
-
-const LETag blwmFeatureTag = 0x626C776D; // 'blwm'
-const LETag abvmFeatureTag = 0x6162766D; // 'abvm'
-const LETag distFeatureTag = 0x64697374; // 'dist'
-
-U_NAMESPACE_END
-#endif
-

Modified: trunk/source/samples/layout/cgnomelayout.c
===================================================================
--- trunk/source/samples/layout/cgnomelayout.c	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/samples/layout/cgnomelayout.c	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,342 +1,342 @@
-
-/*
- ****************************************************************************** *
- *
- *   Copyright (C) 1999-2007, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- *
- ****************************************************************************** *
- */
-
-#include <gnome.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#include "pflow.h"
-
-#include "gnomeglue.h"
-
-#include "arraymem.h"
-
-struct Context
-{
-    long width;
-    long height;
-    pf_flow *paragraph;
-};
-
-typedef struct Context Context;
-
-static FT_Library engine;
-static gs_guiSupport *guiSupport;
-static fm_fontMap *fontMap;
-static le_font *font;
-
-static GSList *appList = NULL;
-
-GtkWidget *newSample(const gchar *fileName);
-void       closeSample(GtkWidget *sample);
-
-static void showabout(GtkWidget *widget, gpointer data)
-{
-    GtkWidget *aboutBox;
-    const gchar *documentedBy[] = {NULL};
-    const gchar *writtenBy[] = {
-        "Eric Mader",
-        NULL
-    };
-
-    aboutBox = gnome_about_new("Gnome Layout Sample",
-                               "0.1",
-                               "Copyright (C) 1998-2006 By International Business Machines Corporation and others. All Rights Reserved.",
-                               "A simple demo of the ICU LayoutEngine.",
-                               writtenBy,
-                               documentedBy,
-                               "",
-                               NULL);
-
-    gtk_widget_show(aboutBox);
-}
-
-#if 0
-static void notimpl(GtkObject *object, gpointer data)
-{
-    gnome_ok_dialog("Not implemented...");
-}
-#endif
-
-static gchar *prettyTitle(const gchar *path)
-{
-  const gchar *name  = g_basename(path);
-  gchar *title = g_strconcat("Gnome Layout Sample - ", name, NULL);
-
-  return title;
-}
-
-static void openOK(GtkObject *object, gpointer data)
-{
-  GtkFileSelection *fileselection = GTK_FILE_SELECTION(data);
-  GtkWidget *app = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(fileselection), "app"));
-  Context *context = (Context *) gtk_object_get_data(GTK_OBJECT(app), "context");
-  gchar *fileName  = g_strdup(gtk_file_selection_get_filename(fileselection));
-  pf_flow *newPara;
-
-  gtk_widget_destroy(GTK_WIDGET(fileselection));
-
-  newPara = pf_factory(fileName, font, guiSupport);
-
-  if (newPara != NULL) {
-    gchar *title = prettyTitle(fileName);
-    GtkWidget *area = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(app), "area"));
-
-    if (context->paragraph != NULL) {
-      pf_close(context->paragraph);
-    }
-
-    context->paragraph = newPara;
-    gtk_window_set_title(GTK_WINDOW(app), title);
-
-    gtk_widget_hide(area);
-    pf_breakLines(context->paragraph, context->width, context->height);
-    gtk_widget_show_all(area);
-
-    g_free(title);
-  }
-
-  g_free(fileName);
-}
-
-static void openfile(GtkObject *object, gpointer data)
-{
-  GtkWidget *app = GTK_WIDGET(data);
-  GtkWidget *fileselection;
-  GtkWidget *okButton;
-  GtkWidget *cancelButton;
-
-  fileselection =
-    gtk_file_selection_new("Open File");
-
-  gtk_object_set_data(GTK_OBJECT(fileselection), "app", app);
-
-  okButton =
-    GTK_FILE_SELECTION(fileselection)->ok_button;
-
-  cancelButton =
-    GTK_FILE_SELECTION(fileselection)->cancel_button;
-
-  gtk_signal_connect(GTK_OBJECT(fileselection), "destroy",
-             GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
-
-  gtk_signal_connect(GTK_OBJECT(okButton), "clicked",
-             GTK_SIGNAL_FUNC(openOK), fileselection);
-
-  gtk_signal_connect_object(GTK_OBJECT(cancelButton), "clicked",
-             GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(fileselection));
-
-  gtk_window_set_modal(GTK_WINDOW(fileselection), TRUE);
-  gtk_widget_show(fileselection);
-  gtk_main();
-}
-
-static void newapp(GtkObject *object, gpointer data)
-{
-  GtkWidget *app = newSample("Sample.txt");
-
-  gtk_widget_show_all(app);
-}
-
-static void closeapp(GtkWidget *widget, gpointer data)
-{
-  GtkWidget *app = GTK_WIDGET(data);
-
-  closeSample(app);
-}
-
-static void shutdown(GtkObject *object, gpointer data)
-{
-    gtk_main_quit();
-}
-
-GnomeUIInfo fileMenu[] =
-{
-  GNOMEUIINFO_MENU_NEW_ITEM((gchar *) "_New Sample",
-                (gchar *) "Create a new Gnome Layout Sample",
-                newapp, NULL),
-
-  GNOMEUIINFO_MENU_OPEN_ITEM(openfile, NULL),
-  GNOMEUIINFO_SEPARATOR,
-  GNOMEUIINFO_MENU_CLOSE_ITEM(closeapp, NULL),
-  GNOMEUIINFO_MENU_EXIT_ITEM(shutdown, NULL),
-  GNOMEUIINFO_END
-};
-
-GnomeUIInfo helpMenu[] =
-{
-    /* GNOMEUIINFO_HELP("gnomelayout"), */
-    GNOMEUIINFO_MENU_ABOUT_ITEM(showabout, NULL),
-    GNOMEUIINFO_END
-};
-
-GnomeUIInfo mainMenu[] =
-{
-    GNOMEUIINFO_SUBTREE(N_((gchar *) "File"), fileMenu),
-    GNOMEUIINFO_SUBTREE(N_((gchar *) "Help"), helpMenu),
-    GNOMEUIINFO_END
-};
-
-static gint eventDelete(GtkWidget *widget, GdkEvent *event, gpointer data)
-{
-  closeSample(widget);
-
-  /* indicate that closeapp  already destroyed the window */
-  return TRUE;
-}
-
-static gint eventConfigure(GtkWidget *widget, GdkEventConfigure *event, Context *context)
-{
-  if (context->paragraph != NULL) {
-    context->width  = event->width;
-    context->height = event->height;
-
-    if (context->width > 0 && context->height > 0) {
-        pf_breakLines(context->paragraph, context->width, context->height);
-    }
-  }
-
-  return TRUE;
-}
-
-static gint eventExpose(GtkWidget *widget, GdkEvent *event, Context *context)
-{
-  if (context->paragraph != NULL) {
-    gint maxLines = pf_getLineCount(context->paragraph) - 1;
-    gint firstLine = 0, lastLine = context->height / pf_getLineHeight(context->paragraph);
-    rs_surface *surface = rs_gnomeRenderingSurfaceOpen(widget);
-
-    pf_draw(context->paragraph, surface, firstLine, (maxLines < lastLine)? maxLines : lastLine);
-    
-    rs_gnomeRenderingSurfaceClose(surface);
-  }
-
-  return TRUE;
-}
-
-GtkWidget *newSample(const gchar *fileName)
-{
-  Context *context = NEW_ARRAY(Context, 1);
-  gchar *title;
-  GtkWidget *app;
-  GtkWidget *area;
-  GtkStyle *style;
-  int i;
-
-  context->width  = 600;
-  context->height = 400;
-  context->paragraph = pf_factory(fileName, font, guiSupport);
-
-  title = prettyTitle(fileName);
-  app = gnome_app_new("gnomeLayout", title);
-
-  gtk_object_set_data(GTK_OBJECT(app), "context", context);
-
-  gtk_window_set_default_size(GTK_WINDOW(app), 600 - 24, 400);
-
-  gnome_app_create_menus_with_data(GNOME_APP(app), mainMenu, app);
-
-  gtk_signal_connect(GTK_OBJECT(app), "delete_event",
-             GTK_SIGNAL_FUNC(eventDelete), NULL);
-
-  area = gtk_drawing_area_new();
-  gtk_object_set_data(GTK_OBJECT(app), "area", area);
-
-  style = gtk_style_copy(gtk_widget_get_style(area));
-
-  for (i = 0; i < 5; i += 1) {
-    style->fg[i] = style->white;
-  }
-    
-  gtk_widget_set_style(area, style);
-
-  gnome_app_set_contents(GNOME_APP(app), area);
-
-  gtk_signal_connect(GTK_OBJECT(area),
-             "expose_event",
-             GTK_SIGNAL_FUNC(eventExpose),
-             context);
-
-  gtk_signal_connect(GTK_OBJECT(area),
-             "configure_event",
-             GTK_SIGNAL_FUNC(eventConfigure),
-             context);
-
-  appList = g_slist_prepend(appList, app);
-
-  g_free(title);
-
-  return app;
-}
-
-void closeSample(GtkWidget *app)
-{
-  Context *context = (Context *) gtk_object_get_data(GTK_OBJECT(app), "context");
-
-  if (context->paragraph != NULL) {
-    pf_close(context->paragraph);
-  }
-
-  DELETE_ARRAY(context);
-
-  appList = g_slist_remove(appList, app);
-
-  gtk_widget_destroy(app);
-
-  if (appList == NULL) {
-    gtk_main_quit();
-  }
-}
-
-int main (int argc, char *argv[])
-{
-    LEErrorCode   fontStatus = LE_NO_ERROR;
-    poptContext   ptctx;
-    GtkWidget    *app;
-    const char   *defaultArgs[] = {"Sample.txt", NULL};
-    const char  **args;
-    int i;
-
-    FT_Init_FreeType(&engine);
-
-    gnome_init_with_popt_table("gnomelayout", "0.1", argc, argv, NULL, 0, &ptctx);
-
-    guiSupport = gs_gnomeGuiSupportOpen();
-    fontMap    = fm_gnomeFontMapOpen(engine, "FontMap.Gnome", 24, guiSupport, &fontStatus);
-    font       = le_scriptCompositeFontOpen(fontMap);
-
-    if (LE_FAILURE(fontStatus)) {
-        FT_Done_FreeType(engine);
-        return 1;
-    }
-
-    args = poptGetArgs(ptctx);
-    
-    if (args == NULL) {
-        args = defaultArgs;
-    }
-
-    for (i = 0; args[i] != NULL; i += 1) {
-       app = newSample(args[i]);
-           
-       gtk_widget_show_all(app);
-    }
-    
-    poptFreeContext(ptctx);
-    
-    gtk_main();
-
-    le_fontClose(font);
-    gs_gnomeGuiSupportClose(guiSupport);
-
-    FT_Done_FreeType(engine);
-
-    exit(0);
-}
+
+/*
+ ****************************************************************************** *
+ *
+ *   Copyright (C) 1999-2007, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *
+ ****************************************************************************** *
+ */
+
+#include <gnome.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "pflow.h"
+
+#include "gnomeglue.h"
+
+#include "arraymem.h"
+
+struct Context
+{
+    long width;
+    long height;
+    pf_flow *paragraph;
+};
+
+typedef struct Context Context;
+
+static FT_Library engine;
+static gs_guiSupport *guiSupport;
+static fm_fontMap *fontMap;
+static le_font *font;
+
+static GSList *appList = NULL;
+
+GtkWidget *newSample(const gchar *fileName);
+void       closeSample(GtkWidget *sample);
+
+static void showabout(GtkWidget *widget, gpointer data)
+{
+    GtkWidget *aboutBox;
+    const gchar *documentedBy[] = {NULL};
+    const gchar *writtenBy[] = {
+        "Eric Mader",
+        NULL
+    };
+
+    aboutBox = gnome_about_new("Gnome Layout Sample",
+                               "0.1",
+                               "Copyright (C) 1998-2006 By International Business Machines Corporation and others. All Rights Reserved.",
+                               "A simple demo of the ICU LayoutEngine.",
+                               writtenBy,
+                               documentedBy,
+                               "",
+                               NULL);
+
+    gtk_widget_show(aboutBox);
+}
+
+#if 0
+static void notimpl(GtkObject *object, gpointer data)
+{
+    gnome_ok_dialog("Not implemented...");
+}
+#endif
+
+static gchar *prettyTitle(const gchar *path)
+{
+  const gchar *name  = g_basename(path);
+  gchar *title = g_strconcat("Gnome Layout Sample - ", name, NULL);
+
+  return title;
+}
+
+static void openOK(GtkObject *object, gpointer data)
+{
+  GtkFileSelection *fileselection = GTK_FILE_SELECTION(data);
+  GtkWidget *app = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(fileselection), "app"));
+  Context *context = (Context *) gtk_object_get_data(GTK_OBJECT(app), "context");
+  gchar *fileName  = g_strdup(gtk_file_selection_get_filename(fileselection));
+  pf_flow *newPara;
+
+  gtk_widget_destroy(GTK_WIDGET(fileselection));
+
+  newPara = pf_factory(fileName, font, guiSupport);
+
+  if (newPara != NULL) {
+    gchar *title = prettyTitle(fileName);
+    GtkWidget *area = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(app), "area"));
+
+    if (context->paragraph != NULL) {
+      pf_close(context->paragraph);
+    }
+
+    context->paragraph = newPara;
+    gtk_window_set_title(GTK_WINDOW(app), title);
+
+    gtk_widget_hide(area);
+    pf_breakLines(context->paragraph, context->width, context->height);
+    gtk_widget_show_all(area);
+
+    g_free(title);
+  }
+
+  g_free(fileName);
+}
+
+static void openfile(GtkObject *object, gpointer data)
+{
+  GtkWidget *app = GTK_WIDGET(data);
+  GtkWidget *fileselection;
+  GtkWidget *okButton;
+  GtkWidget *cancelButton;
+
+  fileselection =
+    gtk_file_selection_new("Open File");
+
+  gtk_object_set_data(GTK_OBJECT(fileselection), "app", app);
+
+  okButton =
+    GTK_FILE_SELECTION(fileselection)->ok_button;
+
+  cancelButton =
+    GTK_FILE_SELECTION(fileselection)->cancel_button;
+
+  gtk_signal_connect(GTK_OBJECT(fileselection), "destroy",
+             GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+
+  gtk_signal_connect(GTK_OBJECT(okButton), "clicked",
+             GTK_SIGNAL_FUNC(openOK), fileselection);
+
+  gtk_signal_connect_object(GTK_OBJECT(cancelButton), "clicked",
+             GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(fileselection));
+
+  gtk_window_set_modal(GTK_WINDOW(fileselection), TRUE);
+  gtk_widget_show(fileselection);
+  gtk_main();
+}
+
+static void newapp(GtkObject *object, gpointer data)
+{
+  GtkWidget *app = newSample("Sample.txt");
+
+  gtk_widget_show_all(app);
+}
+
+static void closeapp(GtkWidget *widget, gpointer data)
+{
+  GtkWidget *app = GTK_WIDGET(data);
+
+  closeSample(app);
+}
+
+static void shutdown(GtkObject *object, gpointer data)
+{
+    gtk_main_quit();
+}
+
+GnomeUIInfo fileMenu[] =
+{
+  GNOMEUIINFO_MENU_NEW_ITEM((gchar *) "_New Sample",
+                (gchar *) "Create a new Gnome Layout Sample",
+                newapp, NULL),
+
+  GNOMEUIINFO_MENU_OPEN_ITEM(openfile, NULL),
+  GNOMEUIINFO_SEPARATOR,
+  GNOMEUIINFO_MENU_CLOSE_ITEM(closeapp, NULL),
+  GNOMEUIINFO_MENU_EXIT_ITEM(shutdown, NULL),
+  GNOMEUIINFO_END
+};
+
+GnomeUIInfo helpMenu[] =
+{
+    /* GNOMEUIINFO_HELP("gnomelayout"), */
+    GNOMEUIINFO_MENU_ABOUT_ITEM(showabout, NULL),
+    GNOMEUIINFO_END
+};
+
+GnomeUIInfo mainMenu[] =
+{
+    GNOMEUIINFO_SUBTREE(N_((gchar *) "File"), fileMenu),
+    GNOMEUIINFO_SUBTREE(N_((gchar *) "Help"), helpMenu),
+    GNOMEUIINFO_END
+};
+
+static gint eventDelete(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+  closeSample(widget);
+
+  /* indicate that closeapp  already destroyed the window */
+  return TRUE;
+}
+
+static gint eventConfigure(GtkWidget *widget, GdkEventConfigure *event, Context *context)
+{
+  if (context->paragraph != NULL) {
+    context->width  = event->width;
+    context->height = event->height;
+
+    if (context->width > 0 && context->height > 0) {
+        pf_breakLines(context->paragraph, context->width, context->height);
+    }
+  }
+
+  return TRUE;
+}
+
+static gint eventExpose(GtkWidget *widget, GdkEvent *event, Context *context)
+{
+  if (context->paragraph != NULL) {
+    gint maxLines = pf_getLineCount(context->paragraph) - 1;
+    gint firstLine = 0, lastLine = context->height / pf_getLineHeight(context->paragraph);
+    rs_surface *surface = rs_gnomeRenderingSurfaceOpen(widget);
+
+    pf_draw(context->paragraph, surface, firstLine, (maxLines < lastLine)? maxLines : lastLine);
+    
+    rs_gnomeRenderingSurfaceClose(surface);
+  }
+
+  return TRUE;
+}
+
+GtkWidget *newSample(const gchar *fileName)
+{
+  Context *context = NEW_ARRAY(Context, 1);
+  gchar *title;
+  GtkWidget *app;
+  GtkWidget *area;
+  GtkStyle *style;
+  int i;
+
+  context->width  = 600;
+  context->height = 400;
+  context->paragraph = pf_factory(fileName, font, guiSupport);
+
+  title = prettyTitle(fileName);
+  app = gnome_app_new("gnomeLayout", title);
+
+  gtk_object_set_data(GTK_OBJECT(app), "context", context);
+
+  gtk_window_set_default_size(GTK_WINDOW(app), 600 - 24, 400);
+
+  gnome_app_create_menus_with_data(GNOME_APP(app), mainMenu, app);
+
+  gtk_signal_connect(GTK_OBJECT(app), "delete_event",
+             GTK_SIGNAL_FUNC(eventDelete), NULL);
+
+  area = gtk_drawing_area_new();
+  gtk_object_set_data(GTK_OBJECT(app), "area", area);
+
+  style = gtk_style_copy(gtk_widget_get_style(area));
+
+  for (i = 0; i < 5; i += 1) {
+    style->fg[i] = style->white;
+  }
+    
+  gtk_widget_set_style(area, style);
+
+  gnome_app_set_contents(GNOME_APP(app), area);
+
+  gtk_signal_connect(GTK_OBJECT(area),
+             "expose_event",
+             GTK_SIGNAL_FUNC(eventExpose),
+             context);
+
+  gtk_signal_connect(GTK_OBJECT(area),
+             "configure_event",
+             GTK_SIGNAL_FUNC(eventConfigure),
+             context);
+
+  appList = g_slist_prepend(appList, app);
+
+  g_free(title);
+
+  return app;
+}
+
+void closeSample(GtkWidget *app)
+{
+  Context *context = (Context *) gtk_object_get_data(GTK_OBJECT(app), "context");
+
+  if (context->paragraph != NULL) {
+    pf_close(context->paragraph);
+  }
+
+  DELETE_ARRAY(context);
+
+  appList = g_slist_remove(appList, app);
+
+  gtk_widget_destroy(app);
+
+  if (appList == NULL) {
+    gtk_main_quit();
+  }
+}
+
+int main (int argc, char *argv[])
+{
+    LEErrorCode   fontStatus = LE_NO_ERROR;
+    poptContext   ptctx;
+    GtkWidget    *app;
+    const char   *defaultArgs[] = {"Sample.txt", NULL};
+    const char  **args;
+    int i;
+
+    FT_Init_FreeType(&engine);
+
+    gnome_init_with_popt_table("gnomelayout", "0.1", argc, argv, NULL, 0, &ptctx);
+
+    guiSupport = gs_gnomeGuiSupportOpen();
+    fontMap    = fm_gnomeFontMapOpen(engine, "FontMap.Gnome", 24, guiSupport, &fontStatus);
+    font       = le_scriptCompositeFontOpen(fontMap);
+
+    if (LE_FAILURE(fontStatus)) {
+        FT_Done_FreeType(engine);
+        return 1;
+    }
+
+    args = poptGetArgs(ptctx);
+    
+    if (args == NULL) {
+        args = defaultArgs;
+    }
+
+    for (i = 0; args[i] != NULL; i += 1) {
+       app = newSample(args[i]);
+           
+       gtk_widget_show_all(app);
+    }
+    
+    poptFreeContext(ptctx);
+    
+    gtk_main();
+
+    le_fontClose(font);
+    gs_gnomeGuiSupportClose(guiSupport);
+
+    FT_Done_FreeType(engine);
+
+    exit(0);
+}

Modified: trunk/source/tools/ctestfw/ctest.c
===================================================================
--- trunk/source/tools/ctestfw/ctest.c	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/ctestfw/ctest.c	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,7 +1,7 @@
 /*
 ********************************************************************************
 *
-*   Copyright (C) 1996-2008, International Business Machines
+*   Copyright (C) 1996-2009, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ********************************************************************************
@@ -482,6 +482,33 @@
 }
 
 void T_CTEST_EXPORT2
+log_err_status(UErrorCode status, const char* pattern, ...)
+{
+    va_list ap;
+    va_start(ap, pattern);
+    
+    if ((status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR)) {
+        ++DATA_ERROR_COUNT; /* for informational message at the end */
+        
+        if (WARN_ON_MISSING_DATA == 0) {
+            /* Fatal error. */
+            if (strchr(pattern, '\n') != NULL) {
+                ++ERROR_COUNT;
+            }
+            vlog_err(NULL, pattern, ap); /* no need for prefix in default case */
+        } else {
+            vlog_info("[DATA] ", pattern, ap); 
+        }
+    } else {
+        /* Fatal error. */
+        if(strchr(pattern, '\n') != NULL) {
+            ++ERROR_COUNT;
+        }
+        vlog_err(NULL, pattern, ap); /* no need for prefix in default case */
+    }
+}
+
+void T_CTEST_EXPORT2
 log_info(const char* pattern, ...)
 {
     va_list ap;
@@ -515,7 +542,7 @@
         }
         vlog_err(NULL, pattern, ap); /* no need for prefix in default case */
     } else {
-        vlog_info("[Data] ", pattern, ap); 
+        vlog_info("[DATA] ", pattern, ap); 
     }
 }
 

Modified: trunk/source/tools/ctestfw/tstdtmod.cpp
===================================================================
--- trunk/source/tools/ctestfw/tstdtmod.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/ctestfw/tstdtmod.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 2002-2008, International Business Machines Corporation and
+ * Copyright (c) 2002-2009, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 
@@ -158,7 +158,7 @@
     if (testBundle == NULL) {
         testBundle = ures_openDirect(icu_data, bundleName, &status);
         if (status != U_ZERO_ERROR) {
-            fLog.dataerrln(UNICODE_STRING_SIMPLE("[DATA] Could not load test data from resourcebundle: ") + UnicodeString(bundleName, -1, US_INV));
+            fLog.dataerrln(UNICODE_STRING_SIMPLE("Could not load test data from resourcebundle: ") + UnicodeString(bundleName, -1, US_INV) + "\n");
             fDataTestValid = FALSE;
         }
     }

Modified: trunk/source/tools/ctestfw/unicode/ctest.h
===================================================================
--- trunk/source/tools/ctestfw/unicode/ctest.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/ctestfw/unicode/ctest.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,7 +1,7 @@
 /*
  ********************************************************************************
  *
- *   Copyright (C) 1996-2008, International Business Machines
+ *   Copyright (C) 1996-2009, International Business Machines
  *   Corporation and others.  All Rights Reserved.
  *
  ********************************************************************************
@@ -151,6 +151,8 @@
 T_CTEST_API void T_CTEST_EXPORT2
 log_err(const char* pattern, ...);
 
+T_CTEST_API void T_CTEST_EXPORT2
+log_err_status(UErrorCode status, const char* pattern, ...);
 /**
  * Log an informational message. (printf style)
  * @param pattern printf-style format string

Modified: trunk/source/tools/pkgdata/pkgdata.cpp
===================================================================
--- trunk/source/tools/pkgdata/pkgdata.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/pkgdata/pkgdata.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,1486 +1,1486 @@
-/******************************************************************************
- *   Copyright (C) 2000-2009, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- *******************************************************************************
- *   file name:  pkgdata.c
- *   encoding:   ANSI X3.4 (1968)
- *   tab size:   8 (not used)
- *   indentation:4
- *
- *   created on: 2000may15
- *   created by: Steven \u24C7 Loomis
- *
- *   This program packages the ICU data into different forms
- *   (DLL, common data, etc.)
- */
-
-/*
- * We define _XOPEN_SOURCE so that we can get popen and pclose.
- */
-#if !defined(_XOPEN_SOURCE)
-#if __STDC_VERSION__ >= 199901L
-/* It is invalid to compile an XPG3, XPG4, XPG4v2 or XPG5 application using c99 on Solaris */
-#define _XOPEN_SOURCE 600
-#else
-#define _XOPEN_SOURCE 4
-#endif
-#endif
-
-
-#include "unicode/utypes.h"
-
-#if U_HAVE_POPEN
-#if defined(U_CYGWIN) && defined(__STRICT_ANSI__)
-/* popen/pclose aren't defined in strict ANSI on Cygwin */
-#undef __STRICT_ANSI__
-#endif
-#endif
-
-#include "unicode/putil.h"
-#include "cmemory.h"
-#include "cstring.h"
-#include "filestrm.h"
-#include "toolutil.h"
-#include "unicode/uclean.h"
-#include "unewdata.h"
-#include "uoptions.h"
-#include "putilimp.h"
-#include "package.h"
-#include "pkg_icu.h"
-#include "pkg_genc.h"
-#include "pkg_gencmn.h"
-#include "flagparser.h"
-#include "filetools.h"
-
-
-#if U_HAVE_POPEN
-# include <unistd.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-
-U_CDECL_BEGIN
-#include "pkgtypes.h"
-U_CDECL_END
-
-#ifdef U_WINDOWS
-#ifdef __GNUC__
-#define WINDOWS_WITH_GNUC
-#else
-#define WINDOWS_WITH_MSVC
-#endif
-#endif
-#if !defined(WINDOWS_WITH_MSVC) && !defined(U_LINUX)
-#define BUILD_DATA_WITHOUT_ASSEMBLY
-#endif
-#if defined(WINDOWS_WITH_MSVC) || defined(U_LINUX)
-#define CAN_WRITE_OBJ_CODE
-#endif
-
-/*
- * When building the data library without assembly,
- * some platforms use a single c code file for all of
- * the data to generate the final data library. This can
- * increase the performance of the pkdata tool.
- */
-#if defined(OS400)
-#define USE_SINGLE_CCODE_FILE
-#endif
-
-/* Need to fix the file seperator character when using MinGW. */
-#ifdef WINDOWS_WITH_GNUC
-#define PKGDATA_FILE_SEP_STRING "/"
-#else
-#define PKGDATA_FILE_SEP_STRING U_FILE_SEP_STRING
-#endif
-
-#define LARGE_BUFFER_MAX_SIZE 2048
-#define SMALL_BUFFER_MAX_SIZE 512
-
-static void loadLists(UPKGOptions *o, UErrorCode *status);
-
-static int32_t pkg_executeOptions(UPKGOptions *o);
-
-#ifdef WINDOWS_WITH_MSVC
-static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o);
-#endif
-static int32_t pkg_createSymLinks(const char *targetDir);
-static int32_t pkg_installLibrary(const char *installDir, const char *dir);
-static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName);
-
-#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
-static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
-#endif
-
-static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath);
-static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL);
-static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt);
-static void createFileNames(const char *version_major, const char *version, const char *libName, const UBool reverseExt);
-
-static int32_t pkg_getOptionsFromICUConfig(UOption *option);
-
-enum {
-    NAME,
-    BLDOPT,
-    MODE,
-    HELP,
-    HELP_QUESTION_MARK,
-    VERBOSE,
-    COPYRIGHT,
-    COMMENT,
-    DESTDIR,
-    REBUILD,
-    TEMPDIR,
-    INSTALL,
-    SOURCEDIR,
-    ENTRYPOINT,
-    REVISION,
-    FORCE_PREFIX,
-    LIBNAME,
-    QUIET
-};
-
-/* This sets the modes that are available */
-static struct {
-    const char *name, *alt_name;
-    const char *desc;
-} modes[] = {
-        { "files", 0,           "Uses raw data files (no effect). Installation copies all files to the target location." },
-#ifdef U_WINDOWS
-        { "dll",    "library",  "Generates one common data file and one shared library, <package>.dll"},
-        { "common", "archive",  "Generates just the common file, <package>.dat"},
-        { "static", "static",   "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
-#else
-#ifdef UDATA_SO_SUFFIX
-        { "dll",    "library",  "Generates one shared library, <package>" UDATA_SO_SUFFIX },
-#endif
-        { "common", "archive",  "Generates one common data file, <package>.dat" },
-        { "static", "static",   "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
-#endif
-};
-
-static UOption options[]={
-    /*00*/    UOPTION_DEF( "name",    'p', UOPT_REQUIRES_ARG),
-    /*01*/    UOPTION_DEF( "bldopt",  'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
-    /*02*/    UOPTION_DEF( "mode",    'm', UOPT_REQUIRES_ARG),
-    /*03*/    UOPTION_HELP_H,                                   /* -h */
-    /*04*/    UOPTION_HELP_QUESTION_MARK,                       /* -? */
-    /*05*/    UOPTION_VERBOSE,                                  /* -v */
-    /*06*/    UOPTION_COPYRIGHT,                                /* -c */
-    /*07*/    UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
-    /*08*/    UOPTION_DESTDIR,                                  /* -d */
-    /*11*/    UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
-    /*12*/    UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
-    /*13*/    UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
-    /*14*/    UOPTION_SOURCEDIR ,
-    /*15*/    UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
-    /*16*/    UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
-    /*17*/    UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
-    /*18*/    UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
-    /*19*/    UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG)
-};
-
-enum {
-    GENCCODE_ASSEMBLY_TYPE,
-    SO_EXT,
-    SOBJ_EXT,
-    A_EXT,
-    LIBPREFIX,
-    LIB_EXT_ORDER,
-    COMPILER,
-    LIBFLAGS,
-    GENLIB,
-    LDICUDTFLAGS,
-    LD_SONAME,
-    RPATH_FLAGS,
-    BIR_FLAGS,
-    AR,
-    ARFLAGS,
-    RANLIB,
-    INSTALL_CMD,
-    PKGDATA_FLAGS_SIZE
-};
-static char **pkgDataFlags = NULL;
-
-enum {
-    LIB_FILE,
-    LIB_FILE_VERSION_MAJOR,
-    LIB_FILE_VERSION,
-    LIB_FILE_VERSION_TMP,
-#ifdef U_CYGWIN
-    LIB_FILE_CYGWIN,
-#endif
-    LIB_FILENAMES_SIZE
-};
-static char libFileNames[LIB_FILENAMES_SIZE][256];
-
-static void pkg_checkFlag(UPKGOptions *o);
-
-const char options_help[][320]={
-    "Set the data name",
-#ifdef U_MAKE_IS_NMAKE
-    "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
-#else
-    "Specify options for the builder.",
-#endif
-    "Specify the mode of building (see below; default: common)",
-    "This usage text",
-    "This usage text",
-    "Make the output verbose",
-    "Use the standard ICU copyright",
-    "Use a custom comment (instead of the copyright)",
-    "Specify the destination directory for files",
-    "Force rebuilding of all data",
-    "Specify temporary dir (default: output dir)",
-    "Install the data (specify target)",
-    "Specify a custom source directory",
-    "Specify a custom entrypoint name (default: short name)",
-    "Specify a version when packaging in DLL or static mode",
-    "Add package to all file names if not present",
-    "Library name to build (if different than package name)",
-    "Quite mode. (e.g. Do not output a readme file for static libraries)"
-};
-
-const char  *progname = "PKGDATA";
-
-int
-main(int argc, char* argv[]) {
-    int result = 0;
-    /* FileStream  *out; */
-    UPKGOptions  o;
-    CharList    *tail;
-    UBool        needsHelp = FALSE;
-    UErrorCode   status = U_ZERO_ERROR;
-    /* char         tmp[1024]; */
-    uint32_t i;
-    int32_t n;
-
-    U_MAIN_INIT_ARGS(argc, argv);
-
-    progname = argv[0];
-
-    options[MODE].value = "common";
-
-    /* read command line options */
-    argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
-
-    /* error handling, printing usage message */
-    /* I've decided to simply print an error and quit. This tool has too
-    many options to just display them all of the time. */
-
-    if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) {
-        needsHelp = TRUE;
-    }
-    else {
-        if(!needsHelp && argc<0) {
-            fprintf(stderr,
-                "%s: error in command line argument \"%s\"\n",
-                progname,
-                argv[-argc]);
-            fprintf(stderr, "Run '%s --help' for help.\n", progname);
-            return 1;
-        }
-
-
-#ifndef WINDOWS_WITH_MSVC
-        if(!options[BLDOPT].doesOccur) {
-            if (pkg_getOptionsFromICUConfig(&options[BLDOPT]) != 0) {
-                fprintf(stderr, " required parameter is missing: -O is required \n");
-                fprintf(stderr, "Run '%s --help' for help.\n", progname);
-                return 1;
-            }
-        }
-#else
-        if(options[BLDOPT].doesOccur) {
-            fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
-        }
-#endif
-
-        if(!options[NAME].doesOccur) /* -O we already have - don't report it. */
-        {
-            fprintf(stderr, " required parameter -p is missing \n");
-            fprintf(stderr, "Run '%s --help' for help.\n", progname);
-            return 1;
-        }
-
-        if(argc == 1) {
-            fprintf(stderr,
-                "No input files specified.\n"
-                "Run '%s --help' for help.\n", progname);
-            return 1;
-        }
-    }   /* end !needsHelp */
-
-    if(argc<0 || needsHelp  ) {
-        fprintf(stderr,
-            "usage: %s [-options] [-] [packageFile] \n"
-            "\tProduce packaged ICU data from the given list(s) of files.\n"
-            "\t'-' by itself means to read from stdin.\n"
-            "\tpackageFile is a text file containing the list of files to package.\n",
-            progname);
-
-        fprintf(stderr, "\n options:\n");
-        for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
-            fprintf(stderr, "%-5s -%c %s%-10s  %s\n",
-                (i<1?"[REQ]":""),
-                options[i].shortName,
-                options[i].longName ? "or --" : "     ",
-                options[i].longName ? options[i].longName : "",
-                options_help[i]);
-        }
-
-        fprintf(stderr, "modes: (-m option)\n");
-        for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) {
-            fprintf(stderr, "   %-9s ", modes[i].name);
-            if (modes[i].alt_name) {
-                fprintf(stderr, "/ %-9s", modes[i].alt_name);
-            } else {
-                fprintf(stderr, "           ");
-            }
-            fprintf(stderr, "  %s\n", modes[i].desc);
-        }
-        return 1;
-    }
-
-    /* OK, fill in the options struct */
-    uprv_memset(&o, 0, sizeof(o));
-
-    o.mode      = options[MODE].value;
-    o.version   = options[REVISION].doesOccur ? options[REVISION].value : 0;
-
-    o.shortName = options[NAME].value;
-    {
-        int32_t len = (int32_t)uprv_strlen(o.shortName);
-        char *csname, *cp;
-        const char *sp;
-
-        cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName));
-        if (*(sp = o.shortName)) {
-            *cp++ = isalpha(*sp) ? * sp : '_';
-            for (++sp; *sp; ++sp) {
-                *cp++ = isalnum(*sp) ? *sp : '_';
-            }
-        }
-        *cp = 0;
-
-        o.cShortName = csname;
-    }
-
-    if(options[LIBNAME].doesOccur) { /* get libname from shortname, or explicit -L parameter */
-      o.libName = options[LIBNAME].value;
-    } else {
-      o.libName = o.shortName;
-    }
-
-    if(options[QUIET].doesOccur) {
-      o.quiet = TRUE;
-    } else {
-      o.quiet = FALSE;
-    }
-
-    o.verbose   = options[VERBOSE].doesOccur;
-
-#ifndef WINDOWS_WITH_MSVC /* on UNIX, we'll just include the file... */
-    o.options   = options[BLDOPT].value;
-#endif
-    if(options[COPYRIGHT].doesOccur) {
-        o.comment = U_COPYRIGHT_STRING;
-    } else if (options[COMMENT].doesOccur) {
-        o.comment = options[COMMENT].value;
-    }
-
-    if( options[DESTDIR].doesOccur ) {
-        o.targetDir = options[DESTDIR].value;
-    } else {
-        o.targetDir = ".";  /* cwd */
-    }
-
-    o.rebuild   = options[REBUILD].doesOccur;
-
-    if( options[TEMPDIR].doesOccur ) {
-        o.tmpDir    = options[TEMPDIR].value;
-    } else {
-        o.tmpDir    = o.targetDir;
-    }
-
-    if( options[INSTALL].doesOccur ) {
-        o.install  = options[INSTALL].value;
-    } else {
-        o.install = NULL;
-    }
-
-    if( options[SOURCEDIR].doesOccur ) {
-        o.srcDir   = options[SOURCEDIR].value;
-    } else {
-        o.srcDir   = ".";
-    }
-
-    if( options[ENTRYPOINT].doesOccur ) {
-        o.entryName = options[ENTRYPOINT].value;
-    } else {
-        o.entryName = o.cShortName;
-    }
-
-    /* OK options are set up. Now the file lists. */
-    tail = NULL;
-    for( n=1; n<argc; n++) {
-        o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n]));
-    }
-
-    /* load the files */
-    loadLists(&o, &status);
-    if( U_FAILURE(status) ) {
-        fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
-        return 2;
-    }
-
-    result = pkg_executeOptions(&o);
-
-    if (pkgDataFlags != NULL) {
-        for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) {
-            if (pkgDataFlags[n] != NULL) {
-                uprv_free(pkgDataFlags[n]);
-            }
-        }
-        uprv_free(pkgDataFlags);
-    }
-
-    if (o.cShortName != NULL) {
-        uprv_free((char *)o.cShortName);
-    }
-    if (o.fileListFiles != NULL) {
-        pkg_deleteList(o.fileListFiles);
-    }
-    if (o.filePaths != NULL) {
-        pkg_deleteList(o.filePaths);
-    }
-    if (o.files != NULL) {
-        pkg_deleteList(o.files);
-    }
-
-    return result;
-}
-
-#define LN_CMD "ln -s"
-#define RM_CMD "rm -f"
-
-#define MODE_COMMON 'c'
-#define MODE_STATIC 's'
-#define MODE_DLL    'd'
-#define MODE_FILES  'f'
-
-static int32_t pkg_executeOptions(UPKGOptions *o) {
-    UErrorCode status = U_ZERO_ERROR;
-    int32_t result = 0;
-//    char cmd[SMALL_BUFFER_MAX_SIZE] = "";
-    const char mode = o->mode[0];
-    char targetDir[SMALL_BUFFER_MAX_SIZE] = "";
-    char tmpDir[SMALL_BUFFER_MAX_SIZE] = "";
-    char datFileName[SMALL_BUFFER_MAX_SIZE] = "";
-    char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
-    char checkLibFile[LARGE_BUFFER_MAX_SIZE] = "";
-
-    /* Initialize pkgdataFlags */
-    pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE);
-    if (pkgDataFlags != NULL) {
-        for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
-            pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * SMALL_BUFFER_MAX_SIZE);
-            if (pkgDataFlags[i] != NULL) {
-                pkgDataFlags[i][0] = 0;
-            } else {
-                fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
-                return -1;
-            }
-        }
-    } else {
-        fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
-        return -1;
-    }
-#ifndef WINDOWS_WITH_MSVC
-    /* Read in options file. */
-    parseFlagsFile(o->options, pkgDataFlags, SMALL_BUFFER_MAX_SIZE, (int32_t)PKGDATA_FLAGS_SIZE, &status);
-    if (U_FAILURE(status)) {
-        fprintf(stderr,"Unable to open or read \"%s\" option file.\n", o->options);
-        return -1;
-    }
-#endif
-    if (mode == MODE_FILES) {
-        /* Copy the raw data to the installation directory. */
-        if (o->install != NULL) {
-            uprv_strcpy(targetDir, o->install);
-            if (o->shortName != NULL) {
-                uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
-                uprv_strcat(targetDir, o->shortName);
-            }
-            result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str);
-        }
-        return result;
-    } else /* if (mode == MODE_COMMON || mode == MODE_STATIC || mode == MODE_DLL) */ {
-        uprv_strcpy(targetDir, o->targetDir);
-        uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
-
-        uprv_strcpy(tmpDir, o->tmpDir);
-        uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING);
-
-        uprv_strcpy(datFileNamePath, tmpDir);
-
-        uprv_strcpy(datFileName, o->shortName);
-        uprv_strcat(datFileName, UDATA_CMN_SUFFIX);
-
-        uprv_strcat(datFileNamePath, datFileName);
-
-        result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, NULL, U_IS_BIG_ENDIAN ? 'b' : 'l');
-        if (result != 0) {
-            fprintf(stderr,"Error writing package dat file.\n");
-            return result;
-        }
-
-        if (mode == MODE_COMMON) {
-            char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
-
-            uprv_strcpy(targetFileNamePath, targetDir);
-            uprv_strcat(targetFileNamePath, datFileName);
-
-            if (T_FileStream_file_exists(targetFileNamePath)) {
-                if ((result = remove(targetFileNamePath)) != 0) {
-                    fprintf(stderr, "Unable to remove old dat file: %s\n", targetFileNamePath);
-                    return result;
-                }
-            }
-
-            /* Move the dat file created to the target directory. */
-            result = rename(datFileNamePath, targetFileNamePath);
-            if (result != 0) {
-                fprintf(stderr, "Unable to move dat file (%s) to target location (%s).\n", datFileNamePath, targetFileNamePath);
-            }
-
-            return result;
-        } else /* if (mode[0] == MODE_STATIC || mode[0] == MODE_DLL) */ {
-            char gencFilePath[SMALL_BUFFER_MAX_SIZE] = "";
-            char version_major[10] = "";
-            UBool reverseExt = FALSE;
-
-#ifndef WINDOWS_WITH_MSVC
-            /* Get the version major number. */
-            if (o->version != NULL) {
-                for (uint32_t i = 0;i < sizeof(version_major);i++) {
-                    if (o->version[i] == '.') {
-                        version_major[i] = 0;
-                        break;
-                    }
-                    version_major[i] = o->version[i];
-                }
-            }
-
-#ifndef OS400
-            /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
-             * reverseExt is FALSE if the suffix should be the version number.
-             */
-            if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) {
-                reverseExt = TRUE;
-            }
-#endif
-            /* Using the base libName and version number, generate the library file names. */
-            createFileNames(version_major, o->version, o->libName, reverseExt);
-
-            if (o->version != 0 && o->rebuild == FALSE) {
-                /* Check to see if a previous built data library file exists and check if it is the latest. */
-                sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION_TMP]);
-                if (T_FileStream_file_exists(checkLibFile)) {
-                    if (isFileModTimeLater(checkLibFile, o->srcDir, TRUE) && isFileModTimeLater(checkLibFile, o->options)) {
-                        if (o->install != NULL) {
-                            uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
-                            result = pkg_installLibrary(o->install, targetDir);
-                        }
-                        return result;
-                    }
-                }
-            }
-
-            pkg_checkFlag(o);
-#endif
-
-            if (pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) {
-                const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE];
-
-                /* Offset genccodeAssembly by 3 because "-a " */
-                if (checkAssemblyHeaderName(genccodeAssembly+3)) {
-                    writeAssemblyCode(datFileNamePath, o->tmpDir, o->entryName, NULL, gencFilePath);
-
-                    result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath);
-                    if (result != 0) {
-                        fprintf(stderr, "Error generating assembly code for data.\n");
-                        return result;
-                    } else if (mode == MODE_STATIC) {
-                        return result;
-                    }
-                } else {
-                    fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly);
-                    return -1;
-                }
-            } else {
-#ifdef CAN_WRITE_OBJ_CODE
-                writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath);
-#ifdef U_LINUX
-                result = pkg_generateLibraryFile(targetDir, mode, gencFilePath);
-#elif defined(WINDOWS_WITH_MSVC)
-                return pkg_createWindowsDLL(mode, gencFilePath, o);
-#endif
-#elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
-                result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
-#endif
-                if (result != 0) {
-                    fprintf(stderr, "Error generating package data.\n");
-                    return result;
-                }
-            }
-#ifndef U_WINDOWS
-            /* Certain platforms uses archive library. (e.g. AIX) */
-            result = pkg_archiveLibrary(targetDir, o->version, reverseExt);
-            if (result != 0) {
-                fprintf(stderr, "Error creating data archive library file.\n");
-               return result;
-            }
-#ifndef OS400
-            /* Create symbolic links for the final library file. */
-            result = pkg_createSymLinks(targetDir);
-            if (result != 0) {
-                fprintf(stderr, "Error creating symbolic links of the data library file.\n");
-                return result;
-            }
-#endif
-            /* Install the libraries if option was set. */
-            if (o->install != NULL) {
-                result = pkg_installLibrary(o->install, targetDir);
-                if (result != 0) {
-                    fprintf(stderr, "Error installing the data library.\n");
-                    return result;
-                }
-            }
-#endif
-        }
-    }
-    return result;
-}
-/*
- * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
- * Depending on the configuration, the library name may either end with version number or shared object suffix.
- */
-static void createFileNames(const char *version_major, const char *version, const char *libName, UBool reverseExt) {
-        sprintf(libFileNames[LIB_FILE], "%s%s",
-                pkgDataFlags[LIBPREFIX],
-                libName);
-        if (version != NULL) {
-#ifdef U_CYGWIN
-            sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s%s.%s",
-                    libName,
-                    version_major,
-                    pkgDataFlags[SO_EXT]);
-
-            sprintf(pkgDataFlags[SO_EXT], "%s.%s",
-                    pkgDataFlags[SO_EXT],
-                    pkgDataFlags[A_EXT]);
-#elif defined(OS400)
-            sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s",
-                    libFileNames[LIB_FILE],
-                    pkgDataFlags[SOBJ_EXT]);
-#else
-            sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s",
-                    libFileNames[LIB_FILE],
-                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
-                    reverseExt ? version : pkgDataFlags[SOBJ_EXT],
-                    reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
-#endif
-            sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s",
-                    libFileNames[LIB_FILE],
-                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
-                    reverseExt ? version_major : pkgDataFlags[SO_EXT],
-                    reverseExt ? pkgDataFlags[SO_EXT] : version_major);
-
-            libFileNames[LIB_FILE_VERSION][0] = 0;
-
-#ifdef U_CYGWIN
-            /* Cygwin only deals with the version major number. */
-            uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]);
-#endif
-        }
-}
-
-/* Create the symbolic links for the final library file. */
-static int32_t pkg_createSymLinks(const char *targetDir) {
-    int32_t result = 0;
-    char cmd[LARGE_BUFFER_MAX_SIZE];
-
-#ifndef U_CYGWIN
-    /* No symbolic link to make. */
-    if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) {
-        return result;
-    }
-    
-    sprintf(cmd, "cd %s && %s %s && %s %s %s",
-            targetDir,
-            RM_CMD,
-            libFileNames[LIB_FILE_VERSION_MAJOR],
-            LN_CMD,
-            libFileNames[LIB_FILE_VERSION],
-            libFileNames[LIB_FILE_VERSION_MAJOR]);
-    result = system(cmd);
-    if (result != 0) {
-        return result;
-    }
-#endif
-    sprintf(cmd, "cd %s && %s %s.%s && %s %s %s.%s",
-            targetDir,
-            RM_CMD,
-            libFileNames[LIB_FILE], pkgDataFlags[SO_EXT],
-            LN_CMD,
-            libFileNames[LIB_FILE_VERSION],
-            libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]);
-
-     result = system(cmd);
-
-    return result;
-}
-
-static int32_t pkg_installLibrary(const char *installDir, const char *targetDir) {
-    int32_t result = 0;
-    char cmd[SMALL_BUFFER_MAX_SIZE];
-
-    sprintf(cmd, "cd %s && %s %s %s%s%s",
-            targetDir,
-            pkgDataFlags[INSTALL_CMD],
-            libFileNames[LIB_FILE_VERSION],
-            installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]
-            );
-
-    result = system(cmd);
-
-    if (result != 0) {
-        return result;
-    }
-
-    return pkg_createSymLinks(installDir);
-}
-
-#ifdef U_WINDOWS_MSVC
-/* Copy commands for installing the raw data files on Windows. */
-#define WIN_INSTALL_CMD "xcopy"
-#define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
-#endif
-static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) {
-    int32_t result = 0;
-    char cmd[SMALL_BUFFER_MAX_SIZE] = "";
-
-    if (!T_FileStream_file_exists(installDir)) {
-        UErrorCode status = U_ZERO_ERROR;
-
-        uprv_mkdir(installDir, &status);
-        if (U_FAILURE(status)) {
-            fprintf(stderr, "Error creating installation directory: %s\n", installDir);
-            return -1;
-        }
-    }
-#ifndef U_WINDOWS_WITH_MSVC
-    char buffer[SMALL_BUFFER_MAX_SIZE] = "";
-
-    FileStream *f = T_FileStream_open(fileListName, "r");
-    if (f != NULL) {
-        for(;;) {
-            if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) {
-                /* Remove new line character. */
-                buffer[uprv_strlen(buffer)-1] = 0;
-
-                sprintf(cmd, "%s %s%s%s %s%s%s",
-                        pkgDataFlags[INSTALL_CMD],
-                        srcDir, PKGDATA_FILE_SEP_STRING, buffer,
-                        installDir, PKGDATA_FILE_SEP_STRING, buffer);
-
-                result = system(cmd);
-                if (result != 0) {
-                    fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
-                    break;
-                }
-            } else {
-                if (!T_FileStream_eof(f)) {
-                    fprintf(stderr, "Failed to read line from file: %s\n", fileListName);
-                    result = -1;
-                }
-                break;
-            }
-        }
-        T_FileStream_close(f);
-    } else {
-        result = -1;
-        fprintf(stderr, "Unable to open list file: %s\n", fileListName);
-    }
-#else
-    sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS);
-    result = system(cmd);
-    if (result != 0) {
-        fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
-    }
-#endif
-
-    return result;
-}
-
-/* Archiving of the library file may be needed depending on the platform and options given.
- * If archiving is not needed, copy over the library file name.
- */
-static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) {
-    int32_t result = 0;
-    char cmd[LARGE_BUFFER_MAX_SIZE];
-
-    /* If the shard object suffix and the final object suffix is different and the final object suffix and the
-     * archive file suffix is the same, then the final library needs to be archived.
-     */
-    if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) {
-        sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
-                libFileNames[LIB_FILE],
-                pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
-                reverseExt ? version : pkgDataFlags[SO_EXT],
-                reverseExt ? pkgDataFlags[SO_EXT] : version);
-
-        sprintf(cmd, "%s %s %s%s %s%s",
-                pkgDataFlags[AR],
-                pkgDataFlags[ARFLAGS],
-                targetDir,
-                libFileNames[LIB_FILE_VERSION],
-                targetDir,
-                libFileNames[LIB_FILE_VERSION_TMP]);
-
-        result = system(cmd);
-        if (result != 0) {
-            return result;
-        }
-
-        /* Remove unneeded library file. */
-        sprintf(cmd, "%s %s%s",
-                RM_CMD,
-                targetDir,
-                libFileNames[LIB_FILE_VERSION_TMP]);
-
-        result = system(cmd);
-        if (result != 0) {
-            return result;
-        }
-
-    } else {
-        uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
-    }
-
-    return result;
-}
-
-/*
- * Using the compiler information from the configuration file set by -O option, generate the library file.
- * command may be given to allow for a larger buffer for cmd.
- */
-static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command) {
-    int32_t result = 0;
-    char *cmd = NULL;
-    UBool freeCmd = FALSE;
-
-    /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
-     * containing many object files and so the calling function should supply a command buffer that is large
-     * enough to handle this. Otherwise, use the default size.
-     */
-    if (command != NULL) {
-        cmd = command;
-    } else {
-        if ((cmd = (char *)uprv_malloc(sizeof(char) * LARGE_BUFFER_MAX_SIZE)) == NULL) {
-            fprintf(stderr, "Unable to allocate memory for command.\n");
-            return -1;
-        }
-        freeCmd = TRUE;
-    }
-
-    if (mode == MODE_STATIC) {
-#ifdef OS400
-        sprintf(cmd, "QSH CMD('%s %s %s%s.%s %s')",
-#else
-        sprintf(cmd, "%s %s %s%s.%s %s",
-#endif
-                pkgDataFlags[AR],
-                pkgDataFlags[ARFLAGS],
-                targetDir,
-                libFileNames[LIB_FILE],
-                pkgDataFlags[A_EXT],
-                objectFile);
-
-        result = system(cmd);
-    } else /* if (mode == MODE_DLL) */ {
-#ifdef U_CYGWIN
-        sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
-                pkgDataFlags[GENLIB],
-                targetDir,
-                libFileNames[LIB_FILE_VERSION_TMP],
-                pkgDataFlags[LDICUDTFLAGS],
-                targetDir, libFileNames[LIB_FILE_CYGWIN],
-#else
-#ifdef OS400
-        sprintf(cmd, "QSH CMD('%s %s -o %s%s %s %s%s %s %s')",
-#else
-        sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s",
-#endif
-                pkgDataFlags[GENLIB],
-                pkgDataFlags[LDICUDTFLAGS],
-                targetDir,
-                libFileNames[LIB_FILE_VERSION_TMP],
-#endif
-                objectFile,
-                pkgDataFlags[LD_SONAME],
-                pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
-                pkgDataFlags[RPATH_FLAGS],
-                pkgDataFlags[BIR_FLAGS]);
-
-        /* Generate the library file. */
-        result = system(cmd);
-    }
-
-    if (freeCmd) {
-        uprv_free(cmd);
-    }
-
-    return result;
-}
-
-static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
-    char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
-    char cmd[LARGE_BUFFER_MAX_SIZE] = "";
-    int32_t result = 0;
-
-    /* Remove the ending .s and replace it with .o for the new object file. */
-    uprv_strcpy(tempObjectFile, gencFilePath);
-    tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
-
-    /* Generate the object file. */
-    sprintf(cmd, "%s %s -o %s %s",
-            pkgDataFlags[COMPILER],
-            pkgDataFlags[LIBFLAGS],
-            tempObjectFile,
-            gencFilePath);
-
-    result = system(cmd);
-    if (result != 0) {
-        return result;
-    }
-
-    return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
-}
-
-#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
-/*
- * Generation of the data library without assembly code needs to compile each data file
- * individually and then link it all together.
- */
-enum {
-    DATA_PREFIX_BRKITR,
-    DATA_PREFIX_COLL,
-    DATA_PREFIX_RBNF,
-    DATA_PREFIX_TRANSLIT,
-    DATA_PREFIX_LENGTH
-};
-const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
-        "brkitr",
-        "coll",
-        "rbnf",
-        "translit"
-};
-static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
-    int32_t result = 0;
-    CharList *list = o->filePaths;
-    CharList *listNames = o->files;
-    int32_t listSize = pkg_countCharList(list);
-    char *buffer;
-    char *cmd;
-    char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
-    char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
-#ifdef USE_SINGLE_CCODE_FILE
-    char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
-    
-    sprintf(icudtAll, "%s%s%sall.c",
-            o->tmpDir,
-            PKGDATA_FILE_SEP_STRING, 
-            libFileNames[LIB_FILE]);
-#endif
-
-    if (list == NULL || listNames == NULL) {
-        /* list and listNames should never be NULL since we are looping through the CharList with
-         * the given size.
-         */
-        return -1;
-    }
-
-    if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
-        fprintf(stderr, "Unable to allocate memory for cmd.\n");
-        return -1;
-    } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
-        fprintf(stderr, "Unable to allocate memory for buffer.\n");
-        uprv_free(cmd);
-        return -1;
-    }
-
-    for (int32_t i = 0; i < (listSize + 1); i++) {
-        const char *file ;
-        const char *name;
-
-        if (i == 0) {
-            /* The first iteration calls the gencmn function and initailizes the buffer. */
-            createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
-            buffer[0] = 0;
-#ifdef USE_SINGLE_CCODE_FILE
-            uprv_strcpy(tempObjectFile, gencmnFile);
-            tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
-            
-#ifdef OS400
-            sprintf(cmd, "QSH CMD('%s %s -o %s %s')",
-#else
-            sprintf(cmd, "%s %s -o %s %s"
-#endif
-                        pkgDataFlags[COMPILER],
-                        pkgDataFlags[LIBFLAGS],
-                        tempObjectFile,
-                        gencmnFile);
-            
-            result = system(cmd);
-            if (result != 0) {
-                break;
-            }
-            
-            sprintf(buffer, "%s",tempObjectFile);
-#endif
-        } else {
-            char newName[SMALL_BUFFER_MAX_SIZE];
-            char dataName[SMALL_BUFFER_MAX_SIZE];
-            const char *pSubstring;
-            file = list->str;
-            name = listNames->str;
-
-            newName[0] = dataName[0] = 0;
-            for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
-                /* If the name contains a prefix, alter the new name accordingly. */
-                pSubstring = uprv_strstr(name, DATA_PREFIX[n]);
-                if (pSubstring != NULL) {
-                    char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
-                    const char *p = name + uprv_strlen(DATA_PREFIX[n]) + 1;
-                    for (int32_t i = 0;;i++) {
-                        if (p[i] == '.') {
-                            newNameTmp[i] = '_';
-                            continue;
-                        }
-                        newNameTmp[i] = p[i];
-                        if (p[i] == 0) {
-                            break;
-                        }
-                    }
-                    sprintf(newName, "%s_%s",
-                            DATA_PREFIX[n],
-                            newNameTmp);
-                    sprintf(dataName, "%s_%s",
-                            o->shortName,
-                            DATA_PREFIX[n]);
-                }
-                if (newName[0] != 0) {
-                    break;
-                }
-            }
-
-            writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile);
-#ifdef USE_SINGLE_CCODE_FILE
-#ifdef OS400
-            sprintf(cmd, "QSH CMD('cat %s >> %s')", gencmnFile, icudtAll);
-#else
-            sprintf(cmd, "cat %s >> %s", gencmnFile, icudtAll);
-#endif
-            
-            result = system(cmd);
-            if (result != 0) {
-                break;
-            }
-#endif
-        }
-
-#ifndef USE_SINGLE_CCODE_FILE
-        uprv_strcpy(tempObjectFile, gencmnFile);
-        tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
-        
-        sprintf(cmd, "%s %s -o %s %s",
-                    pkgDataFlags[COMPILER],
-                    pkgDataFlags[LIBFLAGS],
-                    tempObjectFile,
-                    gencmnFile);
-        result = system(cmd);
-        if (result != 0) {
-            break;
-        }
-
-        sprintf(buffer, "%s %s",
-                buffer,
-                tempObjectFile);
-#endif
-        
-        if (i > 0) {
-            list = list->next;
-            listNames = listNames->next;
-        }
-    }
-
-#ifdef USE_SINGLE_CCODE_FILE
-    uprv_strcpy(tempObjectFile, icudtAll);
-    tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
-#ifdef OS400
-    sprintf(cmd, "QSH CMD('%s %s -o %s %s')",
-#else
-    sprintf(cmd, "%s %s -o %s %s",
-#endif
-        pkgDataFlags[COMPILER],
-        pkgDataFlags[LIBFLAGS],
-        tempObjectFile,
-        icudtAll);
-    
-    result = system(cmd);
-    if (result == 0) {
-        sprintf(buffer, "%s %s",
-            buffer,
-            tempObjectFile);
-    }
-#endif
-
-    if (result == 0) {
-        /* Generate the library file. */
-        result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd);
-    }
-    uprv_free(buffer);
-    uprv_free(cmd);
-
-    return result;
-}
-#endif
-
-#ifdef WINDOWS_WITH_MSVC
-#define LINK_CMD "link.exe /nologo /release /out:"
-#define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO  /base:0x4ad00000 /implib:"
-#define LIB_CMD "LIB.exe /nologo /out:"
-#define LIB_FILE "icudt.lib"
-#define LIB_EXT UDATA_LIB_SUFFIX
-#define DLL_EXT UDATA_SO_SUFFIX
-
-static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
-    char cmd[LARGE_BUFFER_MAX_SIZE];
-    if (mode == MODE_STATIC) {
-        char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
-
-        uprv_strcpy(staticLibFilePath, o->tmpDir);
-        uprv_strcat(staticLibFilePath, PKGDATA_FILE_SEP_STRING);
-
-        uprv_strcat(staticLibFilePath, o->entryName);
-        uprv_strcat(staticLibFilePath, LIB_EXT);
-
-        sprintf(cmd, "%s\"%s\" \"%s\"",
-                LIB_CMD,
-                staticLibFilePath,
-                gencFilePath);
-    } else if (mode == MODE_DLL) {
-        char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
-        char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
-        char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
-
-#ifdef CYGWINMSVC
-        uprv_strcpy(dllFilePath, o->targetDir);
-#else
-        uprv_strcpy(dllFilePath, o->srcDir);
-#endif
-        uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
-        uprv_strcpy(libFilePath, dllFilePath);
-
-        uprv_strcpy(resFilePath, o->tmpDir);
-        uprv_strcat(resFilePath, PKGDATA_FILE_SEP_STRING);
-
-        uprv_strcat(dllFilePath, o->entryName);
-        uprv_strcat(dllFilePath, DLL_EXT);
-        uprv_strcat(libFilePath, LIB_FILE);
-        uprv_strcat(resFilePath, ICUDATA_RES_FILE);
-
-        if (!T_FileStream_file_exists(resFilePath)) {
-            uprv_memset(resFilePath, 0, sizeof(resFilePath));
-        }
-
-        /* Check if dll file and lib file exists and that it is not newer than genc file. */
-        if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
-            (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
-            return 0;
-        }
-
-        sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" \"%s\"",
-                LINK_CMD,
-                dllFilePath,
-                LINK_FLAGS,
-                libFilePath,
-                gencFilePath,
-                resFilePath
-                );
-    }
-
-    return system(cmd);
-}
-#endif
-
-static void pkg_checkFlag(UPKGOptions *o) {
-#ifdef U_AIX
-    /* AIX needs a map file. */
-    char *flag = NULL;
-    int32_t length = 0;
-    char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
-    const char MAP_FILE_EXT[] = ".map";
-    FileStream *f = NULL;
-    char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
-    int32_t start = -1;
-    int32_t count = 0;
-
-    flag = pkgDataFlags[BIR_FLAGS];
-    length = uprv_strlen(pkgDataFlags[BIR_FLAGS]);
-
-    for (int32_t i = 0; i < length; i++) {
-        if (flag[i] == MAP_FILE_EXT[count]) {
-            if (count == 0) {
-                start = i;
-            }
-            count++;
-        } else {
-            count = 0;
-        }
-
-        if (count == uprv_strlen(MAP_FILE_EXT)) {
-            break;
-        }
-    }
-
-    if (start >= 0) {
-        int32_t index = 0;
-        for (int32_t i = 0;;i++) {
-            if (i == start) {
-                for (int32_t n = 0;;n++) {
-                    if (o->shortName[n] == 0) {
-                        break;
-                    }
-                    tmpbuffer[index++] = o->shortName[n];
-                }
-            }
-
-            tmpbuffer[index++] = flag[i];
-
-            if (flag[i] == 0) {
-                break;
-            }
-        }
-
-        uprv_memset(flag, 0, length);
-        uprv_strcpy(flag, tmpbuffer);
-
-        uprv_strcpy(mapFile, o->shortName);
-        uprv_strcat(mapFile, MAP_FILE_EXT);
-
-        f = T_FileStream_open(mapFile, "w");
-        if (f == NULL) {
-            fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
-            return;
-        }
-
-        sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
-
-        T_FileStream_writeLine(f, tmpbuffer);
-
-        T_FileStream_close(f);
-    }
-#elif defined(U_CYGWIN)
-    /* Cygwin needs to change flag options. */
-    char *flag = NULL;
-    int32_t length = 0;
-
-    flag = pkgDataFlags[GENLIB];
-    length = uprv_strlen(pkgDataFlags[GENLIB]);
-
-    int32_t position = length - 1;
-
-    for(;position >= 0;position--) {
-        if (flag[position] == '=') {
-            position++;
-            break;
-        }
-    }
-
-    uprv_memset(flag + position, 0, length - position);
-#elif defined(OS400)
-    /* OS400 needs to fix the ld options (swap single quote with double quote) */
-    char *flag = NULL;
-    int32_t length = 0;
-
-    flag = pkgDataFlags[GENLIB];
-    length = uprv_strlen(pkgDataFlags[GENLIB]);
-
-    int32_t position = length - 1;
-
-    for(int32_t i = 0; i < length; i++) {
-        if (flag[i] == '\'') {
-            flag[i] = '\"';
-        }
-    }
-#endif
-}
-
-static void loadLists(UPKGOptions *o, UErrorCode *status)
-{
-    CharList   *l, *tail = NULL, *tail2 = NULL;
-    FileStream *in;
-    char        line[16384];
-    char       *linePtr, *lineNext;
-    const uint32_t   lineMax = 16300;
-    char        tmp[1024];
-    char       *s;
-    int32_t     ln=0; /* line number */
-
-    for(l = o->fileListFiles; l; l = l->next) {
-        if(o->verbose) {
-            fprintf(stdout, "# Reading %s..\n", l->str);
-        }
-        /* TODO: stdin */
-        in = T_FileStream_open(l->str, "r"); /* open files list */
-
-        if(!in) {
-            fprintf(stderr, "Error opening <%s>.\n", l->str);
-            *status = U_FILE_ACCESS_ERROR;
-            return;
-        }
-
-        while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */
-            ln++;
-            if(uprv_strlen(line)>lineMax) {
-                fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
-                exit(1);
-            }
-            /* remove spaces at the beginning */
-            linePtr = line;
-            while(isspace(*linePtr)) {
-                linePtr++;
-            }
-            s=linePtr;
-            /* remove trailing newline characters */
-            while(*s!=0) {
-                if(*s=='\r' || *s=='\n') {
-                    *s=0;
-                    break;
-                }
-                ++s;
-            }
-            if((*linePtr == 0) || (*linePtr == '#')) {
-                continue; /* comment or empty line */
-            }
-
-            /* Now, process the line */
-            lineNext = NULL;
-
-            while(linePtr && *linePtr) { /* process space-separated items */
-                while(*linePtr == ' ') {
-                    linePtr++;
-                }
-                /* Find the next quote */
-                if(linePtr[0] == '"')
-                {
-                    lineNext = uprv_strchr(linePtr+1, '"');
-                    if(lineNext == NULL) {
-                        fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
-                            l->str, (int)ln);
-                        exit(1);
-                    } else {
-                        lineNext++;
-                        if(*lineNext) {
-                            if(*lineNext != ' ') {
-                                fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
-                                    l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
-                                exit(1);
-                            }
-                            *lineNext = 0;
-                            lineNext++;
-                        }
-                    }
-                } else {
-                    lineNext = uprv_strchr(linePtr, ' ');
-                    if(lineNext) {
-                        *lineNext = 0; /* terminate at space */
-                        lineNext++;
-                    }
-                }
-
-                /* add the file */
-                s = (char*)getLongPathname(linePtr);
-
-                /* normal mode.. o->files is just the bare list without package names */
-                o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
-                if(uprv_pathIsAbsolute(s)) {
-                    fprintf(stderr, "pkgdata: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, s);
-                    exit(U_ILLEGAL_ARGUMENT_ERROR);
-                }
-                uprv_strcpy(tmp, o->srcDir);
-                uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" :PKGDATA_FILE_SEP_STRING);
-                uprv_strcat(tmp, s);
-                o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
-                linePtr = lineNext;
-            } /* for each entry on line */
-        } /* for each line */
-        T_FileStream_close(in);
-    } /* for each file list file */
-}
-
-/* Try calling icu-config directly to get the option file. */
-static int32_t pkg_getOptionsFromICUConfig(UOption *option) {
-#if U_HAVE_POPEN
-    FILE *p;
-    size_t n;
-    static char buf[512] = "";
-    const char cmd[] = "icu-config --incpkgdatafile";
-
-    p = popen(cmd, "r");
-
-    if(p == NULL)
-    {
-        fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
-        return -1;
-    }
-
-    n = fread(buf, 1, 511, p);
-
-    pclose(p);
-
-    if(n<=0)
-    {
-        fprintf(stderr,"%s: icu-config: Could not read from icu-config. (fix PATH or use -O option)\n", progname);
-        return -1;
-    }
-
-    for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
-        if (buf[length] == '\n' || buf[length] == ' ') {
-            buf[length] = 0;
-        } else {
-            break;
-        }
-    }
-
-    if(buf[strlen(buf)-1]=='\n')
-    {
-        buf[strlen(buf)-1]=0;
-    }
-
-    if(buf[0] == 0)
-    {
-        fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname);
-        return -1;
-    }
-
-    option->value = buf;
-    option->doesOccur = TRUE;
-
-    return 0;
-#endif
-    return -1;
-}
+/******************************************************************************
+ *   Copyright (C) 2000-2009, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *******************************************************************************
+ *   file name:  pkgdata.c
+ *   encoding:   ANSI X3.4 (1968)
+ *   tab size:   8 (not used)
+ *   indentation:4
+ *
+ *   created on: 2000may15
+ *   created by: Steven \u24C7 Loomis
+ *
+ *   This program packages the ICU data into different forms
+ *   (DLL, common data, etc.)
+ */
+
+/*
+ * We define _XOPEN_SOURCE so that we can get popen and pclose.
+ */
+#if !defined(_XOPEN_SOURCE)
+#if __STDC_VERSION__ >= 199901L
+/* It is invalid to compile an XPG3, XPG4, XPG4v2 or XPG5 application using c99 on Solaris */
+#define _XOPEN_SOURCE 600
+#else
+#define _XOPEN_SOURCE 4
+#endif
+#endif
+
+
+#include "unicode/utypes.h"
+
+#if U_HAVE_POPEN
+#if defined(U_CYGWIN) && defined(__STRICT_ANSI__)
+/* popen/pclose aren't defined in strict ANSI on Cygwin */
+#undef __STRICT_ANSI__
+#endif
+#endif
+
+#include "unicode/putil.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "filestrm.h"
+#include "toolutil.h"
+#include "unicode/uclean.h"
+#include "unewdata.h"
+#include "uoptions.h"
+#include "putilimp.h"
+#include "package.h"
+#include "pkg_icu.h"
+#include "pkg_genc.h"
+#include "pkg_gencmn.h"
+#include "flagparser.h"
+#include "filetools.h"
+
+
+#if U_HAVE_POPEN
+# include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+U_CDECL_BEGIN
+#include "pkgtypes.h"
+U_CDECL_END
+
+#ifdef U_WINDOWS
+#ifdef __GNUC__
+#define WINDOWS_WITH_GNUC
+#else
+#define WINDOWS_WITH_MSVC
+#endif
+#endif
+#if !defined(WINDOWS_WITH_MSVC) && !defined(U_LINUX)
+#define BUILD_DATA_WITHOUT_ASSEMBLY
+#endif
+#if defined(WINDOWS_WITH_MSVC) || defined(U_LINUX)
+#define CAN_WRITE_OBJ_CODE
+#endif
+
+/*
+ * When building the data library without assembly,
+ * some platforms use a single c code file for all of
+ * the data to generate the final data library. This can
+ * increase the performance of the pkdata tool.
+ */
+#if defined(OS400)
+#define USE_SINGLE_CCODE_FILE
+#endif
+
+/* Need to fix the file seperator character when using MinGW. */
+#ifdef WINDOWS_WITH_GNUC
+#define PKGDATA_FILE_SEP_STRING "/"
+#else
+#define PKGDATA_FILE_SEP_STRING U_FILE_SEP_STRING
+#endif
+
+#define LARGE_BUFFER_MAX_SIZE 2048
+#define SMALL_BUFFER_MAX_SIZE 512
+
+static void loadLists(UPKGOptions *o, UErrorCode *status);
+
+static int32_t pkg_executeOptions(UPKGOptions *o);
+
+#ifdef WINDOWS_WITH_MSVC
+static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o);
+#endif
+static int32_t pkg_createSymLinks(const char *targetDir);
+static int32_t pkg_installLibrary(const char *installDir, const char *dir);
+static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName);
+
+#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
+static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode);
+#endif
+
+static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath);
+static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command = NULL);
+static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt);
+static void createFileNames(const char *version_major, const char *version, const char *libName, const UBool reverseExt);
+
+static int32_t pkg_getOptionsFromICUConfig(UOption *option);
+
+enum {
+    NAME,
+    BLDOPT,
+    MODE,
+    HELP,
+    HELP_QUESTION_MARK,
+    VERBOSE,
+    COPYRIGHT,
+    COMMENT,
+    DESTDIR,
+    REBUILD,
+    TEMPDIR,
+    INSTALL,
+    SOURCEDIR,
+    ENTRYPOINT,
+    REVISION,
+    FORCE_PREFIX,
+    LIBNAME,
+    QUIET
+};
+
+/* This sets the modes that are available */
+static struct {
+    const char *name, *alt_name;
+    const char *desc;
+} modes[] = {
+        { "files", 0,           "Uses raw data files (no effect). Installation copies all files to the target location." },
+#ifdef U_WINDOWS
+        { "dll",    "library",  "Generates one common data file and one shared library, <package>.dll"},
+        { "common", "archive",  "Generates just the common file, <package>.dat"},
+        { "static", "static",   "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
+#else
+#ifdef UDATA_SO_SUFFIX
+        { "dll",    "library",  "Generates one shared library, <package>" UDATA_SO_SUFFIX },
+#endif
+        { "common", "archive",  "Generates one common data file, <package>.dat" },
+        { "static", "static",   "Generates one statically linked library, " LIB_PREFIX "<package>" UDATA_LIB_SUFFIX }
+#endif
+};
+
+static UOption options[]={
+    /*00*/    UOPTION_DEF( "name",    'p', UOPT_REQUIRES_ARG),
+    /*01*/    UOPTION_DEF( "bldopt",  'O', UOPT_REQUIRES_ARG), /* on Win32 it is release or debug */
+    /*02*/    UOPTION_DEF( "mode",    'm', UOPT_REQUIRES_ARG),
+    /*03*/    UOPTION_HELP_H,                                   /* -h */
+    /*04*/    UOPTION_HELP_QUESTION_MARK,                       /* -? */
+    /*05*/    UOPTION_VERBOSE,                                  /* -v */
+    /*06*/    UOPTION_COPYRIGHT,                                /* -c */
+    /*07*/    UOPTION_DEF( "comment", 'C', UOPT_REQUIRES_ARG),
+    /*08*/    UOPTION_DESTDIR,                                  /* -d */
+    /*11*/    UOPTION_DEF( "rebuild", 'F', UOPT_NO_ARG),
+    /*12*/    UOPTION_DEF( "tempdir", 'T', UOPT_REQUIRES_ARG),
+    /*13*/    UOPTION_DEF( "install", 'I', UOPT_REQUIRES_ARG),
+    /*14*/    UOPTION_SOURCEDIR ,
+    /*15*/    UOPTION_DEF( "entrypoint", 'e', UOPT_REQUIRES_ARG),
+    /*16*/    UOPTION_DEF( "revision", 'r', UOPT_REQUIRES_ARG),
+    /*17*/    UOPTION_DEF( "force-prefix", 'f', UOPT_NO_ARG),
+    /*18*/    UOPTION_DEF( "libname", 'L', UOPT_REQUIRES_ARG),
+    /*19*/    UOPTION_DEF( "quiet", 'q', UOPT_NO_ARG)
+};
+
+enum {
+    GENCCODE_ASSEMBLY_TYPE,
+    SO_EXT,
+    SOBJ_EXT,
+    A_EXT,
+    LIBPREFIX,
+    LIB_EXT_ORDER,
+    COMPILER,
+    LIBFLAGS,
+    GENLIB,
+    LDICUDTFLAGS,
+    LD_SONAME,
+    RPATH_FLAGS,
+    BIR_FLAGS,
+    AR,
+    ARFLAGS,
+    RANLIB,
+    INSTALL_CMD,
+    PKGDATA_FLAGS_SIZE
+};
+static char **pkgDataFlags = NULL;
+
+enum {
+    LIB_FILE,
+    LIB_FILE_VERSION_MAJOR,
+    LIB_FILE_VERSION,
+    LIB_FILE_VERSION_TMP,
+#ifdef U_CYGWIN
+    LIB_FILE_CYGWIN,
+#endif
+    LIB_FILENAMES_SIZE
+};
+static char libFileNames[LIB_FILENAMES_SIZE][256];
+
+static void pkg_checkFlag(UPKGOptions *o);
+
+const char options_help[][320]={
+    "Set the data name",
+#ifdef U_MAKE_IS_NMAKE
+    "The directory where the ICU is located (e.g. <ICUROOT> which contains the bin directory)",
+#else
+    "Specify options for the builder.",
+#endif
+    "Specify the mode of building (see below; default: common)",
+    "This usage text",
+    "This usage text",
+    "Make the output verbose",
+    "Use the standard ICU copyright",
+    "Use a custom comment (instead of the copyright)",
+    "Specify the destination directory for files",
+    "Force rebuilding of all data",
+    "Specify temporary dir (default: output dir)",
+    "Install the data (specify target)",
+    "Specify a custom source directory",
+    "Specify a custom entrypoint name (default: short name)",
+    "Specify a version when packaging in DLL or static mode",
+    "Add package to all file names if not present",
+    "Library name to build (if different than package name)",
+    "Quite mode. (e.g. Do not output a readme file for static libraries)"
+};
+
+const char  *progname = "PKGDATA";
+
+int
+main(int argc, char* argv[]) {
+    int result = 0;
+    /* FileStream  *out; */
+    UPKGOptions  o;
+    CharList    *tail;
+    UBool        needsHelp = FALSE;
+    UErrorCode   status = U_ZERO_ERROR;
+    /* char         tmp[1024]; */
+    uint32_t i;
+    int32_t n;
+
+    U_MAIN_INIT_ARGS(argc, argv);
+
+    progname = argv[0];
+
+    options[MODE].value = "common";
+
+    /* read command line options */
+    argc=u_parseArgs(argc, argv, sizeof(options)/sizeof(options[0]), options);
+
+    /* error handling, printing usage message */
+    /* I've decided to simply print an error and quit. This tool has too
+    many options to just display them all of the time. */
+
+    if(options[HELP].doesOccur || options[HELP_QUESTION_MARK].doesOccur) {
+        needsHelp = TRUE;
+    }
+    else {
+        if(!needsHelp && argc<0) {
+            fprintf(stderr,
+                "%s: error in command line argument \"%s\"\n",
+                progname,
+                argv[-argc]);
+            fprintf(stderr, "Run '%s --help' for help.\n", progname);
+            return 1;
+        }
+
+
+#ifndef WINDOWS_WITH_MSVC
+        if(!options[BLDOPT].doesOccur) {
+            if (pkg_getOptionsFromICUConfig(&options[BLDOPT]) != 0) {
+                fprintf(stderr, " required parameter is missing: -O is required \n");
+                fprintf(stderr, "Run '%s --help' for help.\n", progname);
+                return 1;
+            }
+        }
+#else
+        if(options[BLDOPT].doesOccur) {
+            fprintf(stdout, "Warning: You are using the -O option which is not needed for MSVC build on Windows.\n");
+        }
+#endif
+
+        if(!options[NAME].doesOccur) /* -O we already have - don't report it. */
+        {
+            fprintf(stderr, " required parameter -p is missing \n");
+            fprintf(stderr, "Run '%s --help' for help.\n", progname);
+            return 1;
+        }
+
+        if(argc == 1) {
+            fprintf(stderr,
+                "No input files specified.\n"
+                "Run '%s --help' for help.\n", progname);
+            return 1;
+        }
+    }   /* end !needsHelp */
+
+    if(argc<0 || needsHelp  ) {
+        fprintf(stderr,
+            "usage: %s [-options] [-] [packageFile] \n"
+            "\tProduce packaged ICU data from the given list(s) of files.\n"
+            "\t'-' by itself means to read from stdin.\n"
+            "\tpackageFile is a text file containing the list of files to package.\n",
+            progname);
+
+        fprintf(stderr, "\n options:\n");
+        for(i=0;i<(sizeof(options)/sizeof(options[0]));i++) {
+            fprintf(stderr, "%-5s -%c %s%-10s  %s\n",
+                (i<1?"[REQ]":""),
+                options[i].shortName,
+                options[i].longName ? "or --" : "     ",
+                options[i].longName ? options[i].longName : "",
+                options_help[i]);
+        }
+
+        fprintf(stderr, "modes: (-m option)\n");
+        for(i=0;i<(sizeof(modes)/sizeof(modes[0]));i++) {
+            fprintf(stderr, "   %-9s ", modes[i].name);
+            if (modes[i].alt_name) {
+                fprintf(stderr, "/ %-9s", modes[i].alt_name);
+            } else {
+                fprintf(stderr, "           ");
+            }
+            fprintf(stderr, "  %s\n", modes[i].desc);
+        }
+        return 1;
+    }
+
+    /* OK, fill in the options struct */
+    uprv_memset(&o, 0, sizeof(o));
+
+    o.mode      = options[MODE].value;
+    o.version   = options[REVISION].doesOccur ? options[REVISION].value : 0;
+
+    o.shortName = options[NAME].value;
+    {
+        int32_t len = (int32_t)uprv_strlen(o.shortName);
+        char *csname, *cp;
+        const char *sp;
+
+        cp = csname = (char *) uprv_malloc((len + 1 + 1) * sizeof(*o.cShortName));
+        if (*(sp = o.shortName)) {
+            *cp++ = isalpha(*sp) ? * sp : '_';
+            for (++sp; *sp; ++sp) {
+                *cp++ = isalnum(*sp) ? *sp : '_';
+            }
+        }
+        *cp = 0;
+
+        o.cShortName = csname;
+    }
+
+    if(options[LIBNAME].doesOccur) { /* get libname from shortname, or explicit -L parameter */
+      o.libName = options[LIBNAME].value;
+    } else {
+      o.libName = o.shortName;
+    }
+
+    if(options[QUIET].doesOccur) {
+      o.quiet = TRUE;
+    } else {
+      o.quiet = FALSE;
+    }
+
+    o.verbose   = options[VERBOSE].doesOccur;
+
+#ifndef WINDOWS_WITH_MSVC /* on UNIX, we'll just include the file... */
+    o.options   = options[BLDOPT].value;
+#endif
+    if(options[COPYRIGHT].doesOccur) {
+        o.comment = U_COPYRIGHT_STRING;
+    } else if (options[COMMENT].doesOccur) {
+        o.comment = options[COMMENT].value;
+    }
+
+    if( options[DESTDIR].doesOccur ) {
+        o.targetDir = options[DESTDIR].value;
+    } else {
+        o.targetDir = ".";  /* cwd */
+    }
+
+    o.rebuild   = options[REBUILD].doesOccur;
+
+    if( options[TEMPDIR].doesOccur ) {
+        o.tmpDir    = options[TEMPDIR].value;
+    } else {
+        o.tmpDir    = o.targetDir;
+    }
+
+    if( options[INSTALL].doesOccur ) {
+        o.install  = options[INSTALL].value;
+    } else {
+        o.install = NULL;
+    }
+
+    if( options[SOURCEDIR].doesOccur ) {
+        o.srcDir   = options[SOURCEDIR].value;
+    } else {
+        o.srcDir   = ".";
+    }
+
+    if( options[ENTRYPOINT].doesOccur ) {
+        o.entryName = options[ENTRYPOINT].value;
+    } else {
+        o.entryName = o.cShortName;
+    }
+
+    /* OK options are set up. Now the file lists. */
+    tail = NULL;
+    for( n=1; n<argc; n++) {
+        o.fileListFiles = pkg_appendToList(o.fileListFiles, &tail, uprv_strdup(argv[n]));
+    }
+
+    /* load the files */
+    loadLists(&o, &status);
+    if( U_FAILURE(status) ) {
+        fprintf(stderr, "error loading input file lists: %s\n", u_errorName(status));
+        return 2;
+    }
+
+    result = pkg_executeOptions(&o);
+
+    if (pkgDataFlags != NULL) {
+        for (n = 0; n < PKGDATA_FLAGS_SIZE; n++) {
+            if (pkgDataFlags[n] != NULL) {
+                uprv_free(pkgDataFlags[n]);
+            }
+        }
+        uprv_free(pkgDataFlags);
+    }
+
+    if (o.cShortName != NULL) {
+        uprv_free((char *)o.cShortName);
+    }
+    if (o.fileListFiles != NULL) {
+        pkg_deleteList(o.fileListFiles);
+    }
+    if (o.filePaths != NULL) {
+        pkg_deleteList(o.filePaths);
+    }
+    if (o.files != NULL) {
+        pkg_deleteList(o.files);
+    }
+
+    return result;
+}
+
+#define LN_CMD "ln -s"
+#define RM_CMD "rm -f"
+
+#define MODE_COMMON 'c'
+#define MODE_STATIC 's'
+#define MODE_DLL    'd'
+#define MODE_FILES  'f'
+
+static int32_t pkg_executeOptions(UPKGOptions *o) {
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t result = 0;
+//    char cmd[SMALL_BUFFER_MAX_SIZE] = "";
+    const char mode = o->mode[0];
+    char targetDir[SMALL_BUFFER_MAX_SIZE] = "";
+    char tmpDir[SMALL_BUFFER_MAX_SIZE] = "";
+    char datFileName[SMALL_BUFFER_MAX_SIZE] = "";
+    char datFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
+    char checkLibFile[LARGE_BUFFER_MAX_SIZE] = "";
+
+    /* Initialize pkgdataFlags */
+    pkgDataFlags = (char**)uprv_malloc(sizeof(char*) * PKGDATA_FLAGS_SIZE);
+    if (pkgDataFlags != NULL) {
+        for (int32_t i = 0; i < PKGDATA_FLAGS_SIZE; i++) {
+            pkgDataFlags[i] = (char*)uprv_malloc(sizeof(char) * SMALL_BUFFER_MAX_SIZE);
+            if (pkgDataFlags[i] != NULL) {
+                pkgDataFlags[i][0] = 0;
+            } else {
+                fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
+                return -1;
+            }
+        }
+    } else {
+        fprintf(stderr,"Error allocating memory for pkgDataFlags.\n");
+        return -1;
+    }
+#ifndef WINDOWS_WITH_MSVC
+    /* Read in options file. */
+    parseFlagsFile(o->options, pkgDataFlags, SMALL_BUFFER_MAX_SIZE, (int32_t)PKGDATA_FLAGS_SIZE, &status);
+    if (U_FAILURE(status)) {
+        fprintf(stderr,"Unable to open or read \"%s\" option file.\n", o->options);
+        return -1;
+    }
+#endif
+    if (mode == MODE_FILES) {
+        /* Copy the raw data to the installation directory. */
+        if (o->install != NULL) {
+            uprv_strcpy(targetDir, o->install);
+            if (o->shortName != NULL) {
+                uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
+                uprv_strcat(targetDir, o->shortName);
+            }
+            result = pkg_installFileMode(targetDir, o->srcDir, o->fileListFiles->str);
+        }
+        return result;
+    } else /* if (mode == MODE_COMMON || mode == MODE_STATIC || mode == MODE_DLL) */ {
+        uprv_strcpy(targetDir, o->targetDir);
+        uprv_strcat(targetDir, PKGDATA_FILE_SEP_STRING);
+
+        uprv_strcpy(tmpDir, o->tmpDir);
+        uprv_strcat(tmpDir, PKGDATA_FILE_SEP_STRING);
+
+        uprv_strcpy(datFileNamePath, tmpDir);
+
+        uprv_strcpy(datFileName, o->shortName);
+        uprv_strcat(datFileName, UDATA_CMN_SUFFIX);
+
+        uprv_strcat(datFileNamePath, datFileName);
+
+        result = writePackageDatFile(datFileNamePath, o->comment, o->srcDir, o->fileListFiles->str, NULL, U_IS_BIG_ENDIAN ? 'b' : 'l');
+        if (result != 0) {
+            fprintf(stderr,"Error writing package dat file.\n");
+            return result;
+        }
+
+        if (mode == MODE_COMMON) {
+            char targetFileNamePath[LARGE_BUFFER_MAX_SIZE] = "";
+
+            uprv_strcpy(targetFileNamePath, targetDir);
+            uprv_strcat(targetFileNamePath, datFileName);
+
+            if (T_FileStream_file_exists(targetFileNamePath)) {
+                if ((result = remove(targetFileNamePath)) != 0) {
+                    fprintf(stderr, "Unable to remove old dat file: %s\n", targetFileNamePath);
+                    return result;
+                }
+            }
+
+            /* Move the dat file created to the target directory. */
+            result = rename(datFileNamePath, targetFileNamePath);
+            if (result != 0) {
+                fprintf(stderr, "Unable to move dat file (%s) to target location (%s).\n", datFileNamePath, targetFileNamePath);
+            }
+
+            return result;
+        } else /* if (mode[0] == MODE_STATIC || mode[0] == MODE_DLL) */ {
+            char gencFilePath[SMALL_BUFFER_MAX_SIZE] = "";
+            char version_major[10] = "";
+            UBool reverseExt = FALSE;
+
+#ifndef WINDOWS_WITH_MSVC
+            /* Get the version major number. */
+            if (o->version != NULL) {
+                for (uint32_t i = 0;i < sizeof(version_major);i++) {
+                    if (o->version[i] == '.') {
+                        version_major[i] = 0;
+                        break;
+                    }
+                    version_major[i] = o->version[i];
+                }
+            }
+
+#ifndef OS400
+            /* Certain platforms have different library extension ordering. (e.g. libicudata.##.so vs libicudata.so.##)
+             * reverseExt is FALSE if the suffix should be the version number.
+             */
+            if (pkgDataFlags[LIB_EXT_ORDER][uprv_strlen(pkgDataFlags[LIB_EXT_ORDER])-1] == pkgDataFlags[SO_EXT][uprv_strlen(pkgDataFlags[SO_EXT])-1]) {
+                reverseExt = TRUE;
+            }
+#endif
+            /* Using the base libName and version number, generate the library file names. */
+            createFileNames(version_major, o->version, o->libName, reverseExt);
+
+            if (o->version != 0 && o->rebuild == FALSE) {
+                /* Check to see if a previous built data library file exists and check if it is the latest. */
+                sprintf(checkLibFile, "%s%s", targetDir, libFileNames[LIB_FILE_VERSION_TMP]);
+                if (T_FileStream_file_exists(checkLibFile)) {
+                    if (isFileModTimeLater(checkLibFile, o->srcDir, TRUE) && isFileModTimeLater(checkLibFile, o->options)) {
+                        if (o->install != NULL) {
+                            uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
+                            result = pkg_installLibrary(o->install, targetDir);
+                        }
+                        return result;
+                    }
+                }
+            }
+
+            pkg_checkFlag(o);
+#endif
+
+            if (pkgDataFlags[GENCCODE_ASSEMBLY_TYPE][0] != 0) {
+                const char* genccodeAssembly = pkgDataFlags[GENCCODE_ASSEMBLY_TYPE];
+
+                /* Offset genccodeAssembly by 3 because "-a " */
+                if (checkAssemblyHeaderName(genccodeAssembly+3)) {
+                    writeAssemblyCode(datFileNamePath, o->tmpDir, o->entryName, NULL, gencFilePath);
+
+                    result = pkg_createWithAssemblyCode(targetDir, mode, gencFilePath);
+                    if (result != 0) {
+                        fprintf(stderr, "Error generating assembly code for data.\n");
+                        return result;
+                    } else if (mode == MODE_STATIC) {
+                        return result;
+                    }
+                } else {
+                    fprintf(stderr,"Assembly type \"%s\" is unknown.\n", genccodeAssembly);
+                    return -1;
+                }
+            } else {
+#ifdef CAN_WRITE_OBJ_CODE
+                writeObjectCode(datFileNamePath, o->tmpDir, o->entryName, NULL, NULL, gencFilePath);
+#ifdef U_LINUX
+                result = pkg_generateLibraryFile(targetDir, mode, gencFilePath);
+#elif defined(WINDOWS_WITH_MSVC)
+                return pkg_createWindowsDLL(mode, gencFilePath, o);
+#endif
+#elif defined(BUILD_DATA_WITHOUT_ASSEMBLY)
+                result = pkg_createWithoutAssemblyCode(o, targetDir, mode);
+#endif
+                if (result != 0) {
+                    fprintf(stderr, "Error generating package data.\n");
+                    return result;
+                }
+            }
+#ifndef U_WINDOWS
+            /* Certain platforms uses archive library. (e.g. AIX) */
+            result = pkg_archiveLibrary(targetDir, o->version, reverseExt);
+            if (result != 0) {
+                fprintf(stderr, "Error creating data archive library file.\n");
+               return result;
+            }
+#ifndef OS400
+            /* Create symbolic links for the final library file. */
+            result = pkg_createSymLinks(targetDir);
+            if (result != 0) {
+                fprintf(stderr, "Error creating symbolic links of the data library file.\n");
+                return result;
+            }
+#endif
+            /* Install the libraries if option was set. */
+            if (o->install != NULL) {
+                result = pkg_installLibrary(o->install, targetDir);
+                if (result != 0) {
+                    fprintf(stderr, "Error installing the data library.\n");
+                    return result;
+                }
+            }
+#endif
+        }
+    }
+    return result;
+}
+/*
+ * Given the base libName and version numbers, generate the libary file names and store it in libFileNames.
+ * Depending on the configuration, the library name may either end with version number or shared object suffix.
+ */
+static void createFileNames(const char *version_major, const char *version, const char *libName, UBool reverseExt) {
+        sprintf(libFileNames[LIB_FILE], "%s%s",
+                pkgDataFlags[LIBPREFIX],
+                libName);
+        if (version != NULL) {
+#ifdef U_CYGWIN
+            sprintf(libFileNames[LIB_FILE_CYGWIN], "cyg%s%s.%s",
+                    libName,
+                    version_major,
+                    pkgDataFlags[SO_EXT]);
+
+            sprintf(pkgDataFlags[SO_EXT], "%s.%s",
+                    pkgDataFlags[SO_EXT],
+                    pkgDataFlags[A_EXT]);
+#elif defined(OS400)
+            sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s.%s",
+                    libFileNames[LIB_FILE],
+                    pkgDataFlags[SOBJ_EXT]);
+#else
+            sprintf(libFileNames[LIB_FILE_VERSION_TMP], "%s%s%s.%s",
+                    libFileNames[LIB_FILE],
+                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    reverseExt ? version : pkgDataFlags[SOBJ_EXT],
+                    reverseExt ? pkgDataFlags[SOBJ_EXT] : version);
+#endif
+            sprintf(libFileNames[LIB_FILE_VERSION_MAJOR], "%s%s%s.%s",
+                    libFileNames[LIB_FILE],
+                    pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                    reverseExt ? version_major : pkgDataFlags[SO_EXT],
+                    reverseExt ? pkgDataFlags[SO_EXT] : version_major);
+
+            libFileNames[LIB_FILE_VERSION][0] = 0;
+
+#ifdef U_CYGWIN
+            /* Cygwin only deals with the version major number. */
+            uprv_strcpy(libFileNames[LIB_FILE_VERSION_TMP], libFileNames[LIB_FILE_VERSION_MAJOR]);
+#endif
+        }
+}
+
+/* Create the symbolic links for the final library file. */
+static int32_t pkg_createSymLinks(const char *targetDir) {
+    int32_t result = 0;
+    char cmd[LARGE_BUFFER_MAX_SIZE];
+
+#ifndef U_CYGWIN
+    /* No symbolic link to make. */
+    if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) {
+        return result;
+    }
+    
+    sprintf(cmd, "cd %s && %s %s && %s %s %s",
+            targetDir,
+            RM_CMD,
+            libFileNames[LIB_FILE_VERSION_MAJOR],
+            LN_CMD,
+            libFileNames[LIB_FILE_VERSION],
+            libFileNames[LIB_FILE_VERSION_MAJOR]);
+    result = system(cmd);
+    if (result != 0) {
+        return result;
+    }
+#endif
+    sprintf(cmd, "cd %s && %s %s.%s && %s %s %s.%s",
+            targetDir,
+            RM_CMD,
+            libFileNames[LIB_FILE], pkgDataFlags[SO_EXT],
+            LN_CMD,
+            libFileNames[LIB_FILE_VERSION],
+            libFileNames[LIB_FILE], pkgDataFlags[SO_EXT]);
+
+     result = system(cmd);
+
+    return result;
+}
+
+static int32_t pkg_installLibrary(const char *installDir, const char *targetDir) {
+    int32_t result = 0;
+    char cmd[SMALL_BUFFER_MAX_SIZE];
+
+    sprintf(cmd, "cd %s && %s %s %s%s%s",
+            targetDir,
+            pkgDataFlags[INSTALL_CMD],
+            libFileNames[LIB_FILE_VERSION],
+            installDir, PKGDATA_FILE_SEP_STRING, libFileNames[LIB_FILE_VERSION]
+            );
+
+    result = system(cmd);
+
+    if (result != 0) {
+        return result;
+    }
+
+    return pkg_createSymLinks(installDir);
+}
+
+#ifdef U_WINDOWS_MSVC
+/* Copy commands for installing the raw data files on Windows. */
+#define WIN_INSTALL_CMD "xcopy"
+#define WIN_INSTALL_CMD_FLAGS "/E /Y /K"
+#endif
+static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, const char *fileListName) {
+    int32_t result = 0;
+    char cmd[SMALL_BUFFER_MAX_SIZE] = "";
+
+    if (!T_FileStream_file_exists(installDir)) {
+        UErrorCode status = U_ZERO_ERROR;
+
+        uprv_mkdir(installDir, &status);
+        if (U_FAILURE(status)) {
+            fprintf(stderr, "Error creating installation directory: %s\n", installDir);
+            return -1;
+        }
+    }
+#ifndef U_WINDOWS_WITH_MSVC
+    char buffer[SMALL_BUFFER_MAX_SIZE] = "";
+
+    FileStream *f = T_FileStream_open(fileListName, "r");
+    if (f != NULL) {
+        for(;;) {
+            if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) {
+                /* Remove new line character. */
+                buffer[uprv_strlen(buffer)-1] = 0;
+
+                sprintf(cmd, "%s %s%s%s %s%s%s",
+                        pkgDataFlags[INSTALL_CMD],
+                        srcDir, PKGDATA_FILE_SEP_STRING, buffer,
+                        installDir, PKGDATA_FILE_SEP_STRING, buffer);
+
+                result = system(cmd);
+                if (result != 0) {
+                    fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
+                    break;
+                }
+            } else {
+                if (!T_FileStream_eof(f)) {
+                    fprintf(stderr, "Failed to read line from file: %s\n", fileListName);
+                    result = -1;
+                }
+                break;
+            }
+        }
+        T_FileStream_close(f);
+    } else {
+        result = -1;
+        fprintf(stderr, "Unable to open list file: %s\n", fileListName);
+    }
+#else
+    sprintf(cmd, "%s %s %s %s", WIN_INSTALL_CMD, srcDir, installDir, WIN_INSTALL_CMD_FLAGS);
+    result = system(cmd);
+    if (result != 0) {
+        fprintf(stderr, "Failed to install data file with command: %s\n", cmd);
+    }
+#endif
+
+    return result;
+}
+
+/* Archiving of the library file may be needed depending on the platform and options given.
+ * If archiving is not needed, copy over the library file name.
+ */
+static int32_t pkg_archiveLibrary(const char *targetDir, const char *version, UBool reverseExt) {
+    int32_t result = 0;
+    char cmd[LARGE_BUFFER_MAX_SIZE];
+
+    /* If the shard object suffix and the final object suffix is different and the final object suffix and the
+     * archive file suffix is the same, then the final library needs to be archived.
+     */
+    if (uprv_strcmp(pkgDataFlags[SOBJ_EXT], pkgDataFlags[SO_EXT]) != 0 && uprv_strcmp(pkgDataFlags[A_EXT], pkgDataFlags[SO_EXT]) == 0) {
+        sprintf(libFileNames[LIB_FILE_VERSION], "%s%s%s.%s",
+                libFileNames[LIB_FILE],
+                pkgDataFlags[LIB_EXT_ORDER][0] == '.' ? "." : "",
+                reverseExt ? version : pkgDataFlags[SO_EXT],
+                reverseExt ? pkgDataFlags[SO_EXT] : version);
+
+        sprintf(cmd, "%s %s %s%s %s%s",
+                pkgDataFlags[AR],
+                pkgDataFlags[ARFLAGS],
+                targetDir,
+                libFileNames[LIB_FILE_VERSION],
+                targetDir,
+                libFileNames[LIB_FILE_VERSION_TMP]);
+
+        result = system(cmd);
+        if (result != 0) {
+            return result;
+        }
+
+        /* Remove unneeded library file. */
+        sprintf(cmd, "%s %s%s",
+                RM_CMD,
+                targetDir,
+                libFileNames[LIB_FILE_VERSION_TMP]);
+
+        result = system(cmd);
+        if (result != 0) {
+            return result;
+        }
+
+    } else {
+        uprv_strcpy(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_TMP]);
+    }
+
+    return result;
+}
+
+/*
+ * Using the compiler information from the configuration file set by -O option, generate the library file.
+ * command may be given to allow for a larger buffer for cmd.
+ */
+static int32_t pkg_generateLibraryFile(const char *targetDir, const char mode, const char *objectFile, char *command) {
+    int32_t result = 0;
+    char *cmd = NULL;
+    UBool freeCmd = FALSE;
+
+    /* This is necessary because if packaging is done without assembly code, objectFile might be extremely large
+     * containing many object files and so the calling function should supply a command buffer that is large
+     * enough to handle this. Otherwise, use the default size.
+     */
+    if (command != NULL) {
+        cmd = command;
+    } else {
+        if ((cmd = (char *)uprv_malloc(sizeof(char) * LARGE_BUFFER_MAX_SIZE)) == NULL) {
+            fprintf(stderr, "Unable to allocate memory for command.\n");
+            return -1;
+        }
+        freeCmd = TRUE;
+    }
+
+    if (mode == MODE_STATIC) {
+#ifdef OS400
+        sprintf(cmd, "QSH CMD('%s %s %s%s.%s %s')",
+#else
+        sprintf(cmd, "%s %s %s%s.%s %s",
+#endif
+                pkgDataFlags[AR],
+                pkgDataFlags[ARFLAGS],
+                targetDir,
+                libFileNames[LIB_FILE],
+                pkgDataFlags[A_EXT],
+                objectFile);
+
+        result = system(cmd);
+    } else /* if (mode == MODE_DLL) */ {
+#ifdef U_CYGWIN
+        sprintf(cmd, "%s%s%s %s -o %s%s %s %s%s %s %s",
+                pkgDataFlags[GENLIB],
+                targetDir,
+                libFileNames[LIB_FILE_VERSION_TMP],
+                pkgDataFlags[LDICUDTFLAGS],
+                targetDir, libFileNames[LIB_FILE_CYGWIN],
+#else
+#ifdef OS400
+        sprintf(cmd, "QSH CMD('%s %s -o %s%s %s %s%s %s %s')",
+#else
+        sprintf(cmd, "%s %s -o %s%s %s %s%s %s %s",
+#endif
+                pkgDataFlags[GENLIB],
+                pkgDataFlags[LDICUDTFLAGS],
+                targetDir,
+                libFileNames[LIB_FILE_VERSION_TMP],
+#endif
+                objectFile,
+                pkgDataFlags[LD_SONAME],
+                pkgDataFlags[LD_SONAME][0] == 0 ? "" : libFileNames[LIB_FILE_VERSION_MAJOR],
+                pkgDataFlags[RPATH_FLAGS],
+                pkgDataFlags[BIR_FLAGS]);
+
+        /* Generate the library file. */
+        result = system(cmd);
+    }
+
+    if (freeCmd) {
+        uprv_free(cmd);
+    }
+
+    return result;
+}
+
+static int32_t pkg_createWithAssemblyCode(const char *targetDir, const char mode, const char *gencFilePath) {
+    char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
+    char cmd[LARGE_BUFFER_MAX_SIZE] = "";
+    int32_t result = 0;
+
+    /* Remove the ending .s and replace it with .o for the new object file. */
+    uprv_strcpy(tempObjectFile, gencFilePath);
+    tempObjectFile[uprv_strlen(tempObjectFile)-1] = 'o';
+
+    /* Generate the object file. */
+    sprintf(cmd, "%s %s -o %s %s",
+            pkgDataFlags[COMPILER],
+            pkgDataFlags[LIBFLAGS],
+            tempObjectFile,
+            gencFilePath);
+
+    result = system(cmd);
+    if (result != 0) {
+        return result;
+    }
+
+    return pkg_generateLibraryFile(targetDir, mode, tempObjectFile);
+}
+
+#ifdef BUILD_DATA_WITHOUT_ASSEMBLY
+/*
+ * Generation of the data library without assembly code needs to compile each data file
+ * individually and then link it all together.
+ */
+enum {
+    DATA_PREFIX_BRKITR,
+    DATA_PREFIX_COLL,
+    DATA_PREFIX_RBNF,
+    DATA_PREFIX_TRANSLIT,
+    DATA_PREFIX_LENGTH
+};
+const static char DATA_PREFIX[DATA_PREFIX_LENGTH][10] = {
+        "brkitr",
+        "coll",
+        "rbnf",
+        "translit"
+};
+static int32_t pkg_createWithoutAssemblyCode(UPKGOptions *o, const char *targetDir, const char mode) {
+    int32_t result = 0;
+    CharList *list = o->filePaths;
+    CharList *listNames = o->files;
+    int32_t listSize = pkg_countCharList(list);
+    char *buffer;
+    char *cmd;
+    char gencmnFile[SMALL_BUFFER_MAX_SIZE] = "";
+    char tempObjectFile[SMALL_BUFFER_MAX_SIZE] = "";
+#ifdef USE_SINGLE_CCODE_FILE
+    char icudtAll[SMALL_BUFFER_MAX_SIZE] = "";
+    
+    sprintf(icudtAll, "%s%s%sall.c",
+            o->tmpDir,
+            PKGDATA_FILE_SEP_STRING, 
+            libFileNames[LIB_FILE]);
+#endif
+
+    if (list == NULL || listNames == NULL) {
+        /* list and listNames should never be NULL since we are looping through the CharList with
+         * the given size.
+         */
+        return -1;
+    }
+
+    if ((cmd = (char *)uprv_malloc((listSize + 2) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
+        fprintf(stderr, "Unable to allocate memory for cmd.\n");
+        return -1;
+    } else if ((buffer = (char *)uprv_malloc((listSize + 1) * SMALL_BUFFER_MAX_SIZE)) == NULL) {
+        fprintf(stderr, "Unable to allocate memory for buffer.\n");
+        uprv_free(cmd);
+        return -1;
+    }
+
+    for (int32_t i = 0; i < (listSize + 1); i++) {
+        const char *file ;
+        const char *name;
+
+        if (i == 0) {
+            /* The first iteration calls the gencmn function and initailizes the buffer. */
+            createCommonDataFile(o->tmpDir, o->shortName, o->entryName, NULL, o->srcDir, o->comment, o->fileListFiles->str, 0, TRUE, o->verbose, gencmnFile);
+            buffer[0] = 0;
+#ifdef USE_SINGLE_CCODE_FILE
+            uprv_strcpy(tempObjectFile, gencmnFile);
+            tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
+            
+#ifdef OS400
+            sprintf(cmd, "QSH CMD('%s %s -o %s %s')",
+#else
+            sprintf(cmd, "%s %s -o %s %s"
+#endif
+                        pkgDataFlags[COMPILER],
+                        pkgDataFlags[LIBFLAGS],
+                        tempObjectFile,
+                        gencmnFile);
+            
+            result = system(cmd);
+            if (result != 0) {
+                break;
+            }
+            
+            sprintf(buffer, "%s",tempObjectFile);
+#endif
+        } else {
+            char newName[SMALL_BUFFER_MAX_SIZE];
+            char dataName[SMALL_BUFFER_MAX_SIZE];
+            const char *pSubstring;
+            file = list->str;
+            name = listNames->str;
+
+            newName[0] = dataName[0] = 0;
+            for (int32_t n = 0; n < DATA_PREFIX_LENGTH; n++) {
+                /* If the name contains a prefix, alter the new name accordingly. */
+                pSubstring = uprv_strstr(name, DATA_PREFIX[n]);
+                if (pSubstring != NULL) {
+                    char newNameTmp[SMALL_BUFFER_MAX_SIZE] = "";
+                    const char *p = name + uprv_strlen(DATA_PREFIX[n]) + 1;
+                    for (int32_t i = 0;;i++) {
+                        if (p[i] == '.') {
+                            newNameTmp[i] = '_';
+                            continue;
+                        }
+                        newNameTmp[i] = p[i];
+                        if (p[i] == 0) {
+                            break;
+                        }
+                    }
+                    sprintf(newName, "%s_%s",
+                            DATA_PREFIX[n],
+                            newNameTmp);
+                    sprintf(dataName, "%s_%s",
+                            o->shortName,
+                            DATA_PREFIX[n]);
+                }
+                if (newName[0] != 0) {
+                    break;
+                }
+            }
+
+            writeCCode(file, o->tmpDir, dataName[0] != 0 ? dataName : o->shortName, newName[0] != 0 ? newName : NULL, gencmnFile);
+#ifdef USE_SINGLE_CCODE_FILE
+#ifdef OS400
+            sprintf(cmd, "QSH CMD('cat %s >> %s')", gencmnFile, icudtAll);
+#else
+            sprintf(cmd, "cat %s >> %s", gencmnFile, icudtAll);
+#endif
+            
+            result = system(cmd);
+            if (result != 0) {
+                break;
+            }
+#endif
+        }
+
+#ifndef USE_SINGLE_CCODE_FILE
+        uprv_strcpy(tempObjectFile, gencmnFile);
+        tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
+        
+        sprintf(cmd, "%s %s -o %s %s",
+                    pkgDataFlags[COMPILER],
+                    pkgDataFlags[LIBFLAGS],
+                    tempObjectFile,
+                    gencmnFile);
+        result = system(cmd);
+        if (result != 0) {
+            break;
+        }
+
+        sprintf(buffer, "%s %s",
+                buffer,
+                tempObjectFile);
+#endif
+        
+        if (i > 0) {
+            list = list->next;
+            listNames = listNames->next;
+        }
+    }
+
+#ifdef USE_SINGLE_CCODE_FILE
+    uprv_strcpy(tempObjectFile, icudtAll);
+    tempObjectFile[uprv_strlen(tempObjectFile) - 1] = 'o';
+#ifdef OS400
+    sprintf(cmd, "QSH CMD('%s %s -o %s %s')",
+#else
+    sprintf(cmd, "%s %s -o %s %s",
+#endif
+        pkgDataFlags[COMPILER],
+        pkgDataFlags[LIBFLAGS],
+        tempObjectFile,
+        icudtAll);
+    
+    result = system(cmd);
+    if (result == 0) {
+        sprintf(buffer, "%s %s",
+            buffer,
+            tempObjectFile);
+    }
+#endif
+
+    if (result == 0) {
+        /* Generate the library file. */
+        result = pkg_generateLibraryFile(targetDir, mode, buffer, cmd);
+    }
+    uprv_free(buffer);
+    uprv_free(cmd);
+
+    return result;
+}
+#endif
+
+#ifdef WINDOWS_WITH_MSVC
+#define LINK_CMD "link.exe /nologo /release /out:"
+#define LINK_FLAGS "/DLL /NOENTRY /MANIFEST:NO  /base:0x4ad00000 /implib:"
+#define LIB_CMD "LIB.exe /nologo /out:"
+#define LIB_FILE "icudt.lib"
+#define LIB_EXT UDATA_LIB_SUFFIX
+#define DLL_EXT UDATA_SO_SUFFIX
+
+static int32_t pkg_createWindowsDLL(const char mode, const char *gencFilePath, UPKGOptions *o) {
+    char cmd[LARGE_BUFFER_MAX_SIZE];
+    if (mode == MODE_STATIC) {
+        char staticLibFilePath[SMALL_BUFFER_MAX_SIZE] = "";
+
+        uprv_strcpy(staticLibFilePath, o->tmpDir);
+        uprv_strcat(staticLibFilePath, PKGDATA_FILE_SEP_STRING);
+
+        uprv_strcat(staticLibFilePath, o->entryName);
+        uprv_strcat(staticLibFilePath, LIB_EXT);
+
+        sprintf(cmd, "%s\"%s\" \"%s\"",
+                LIB_CMD,
+                staticLibFilePath,
+                gencFilePath);
+    } else if (mode == MODE_DLL) {
+        char dllFilePath[SMALL_BUFFER_MAX_SIZE] = "";
+        char libFilePath[SMALL_BUFFER_MAX_SIZE] = "";
+        char resFilePath[SMALL_BUFFER_MAX_SIZE] = "";
+
+#ifdef CYGWINMSVC
+        uprv_strcpy(dllFilePath, o->targetDir);
+#else
+        uprv_strcpy(dllFilePath, o->srcDir);
+#endif
+        uprv_strcat(dllFilePath, PKGDATA_FILE_SEP_STRING);
+        uprv_strcpy(libFilePath, dllFilePath);
+
+        uprv_strcpy(resFilePath, o->tmpDir);
+        uprv_strcat(resFilePath, PKGDATA_FILE_SEP_STRING);
+
+        uprv_strcat(dllFilePath, o->entryName);
+        uprv_strcat(dllFilePath, DLL_EXT);
+        uprv_strcat(libFilePath, LIB_FILE);
+        uprv_strcat(resFilePath, ICUDATA_RES_FILE);
+
+        if (!T_FileStream_file_exists(resFilePath)) {
+            uprv_memset(resFilePath, 0, sizeof(resFilePath));
+        }
+
+        /* Check if dll file and lib file exists and that it is not newer than genc file. */
+        if (!o->rebuild && (T_FileStream_file_exists(dllFilePath) && isFileModTimeLater(dllFilePath, gencFilePath)) &&
+            (T_FileStream_file_exists(libFilePath) && isFileModTimeLater(libFilePath, gencFilePath))) {
+            return 0;
+        }
+
+        sprintf(cmd, "%s\"%s\" %s\"%s\" \"%s\" \"%s\"",
+                LINK_CMD,
+                dllFilePath,
+                LINK_FLAGS,
+                libFilePath,
+                gencFilePath,
+                resFilePath
+                );
+    }
+
+    return system(cmd);
+}
+#endif
+
+static void pkg_checkFlag(UPKGOptions *o) {
+#ifdef U_AIX
+    /* AIX needs a map file. */
+    char *flag = NULL;
+    int32_t length = 0;
+    char tmpbuffer[SMALL_BUFFER_MAX_SIZE];
+    const char MAP_FILE_EXT[] = ".map";
+    FileStream *f = NULL;
+    char mapFile[SMALL_BUFFER_MAX_SIZE] = "";
+    int32_t start = -1;
+    int32_t count = 0;
+
+    flag = pkgDataFlags[BIR_FLAGS];
+    length = uprv_strlen(pkgDataFlags[BIR_FLAGS]);
+
+    for (int32_t i = 0; i < length; i++) {
+        if (flag[i] == MAP_FILE_EXT[count]) {
+            if (count == 0) {
+                start = i;
+            }
+            count++;
+        } else {
+            count = 0;
+        }
+
+        if (count == uprv_strlen(MAP_FILE_EXT)) {
+            break;
+        }
+    }
+
+    if (start >= 0) {
+        int32_t index = 0;
+        for (int32_t i = 0;;i++) {
+            if (i == start) {
+                for (int32_t n = 0;;n++) {
+                    if (o->shortName[n] == 0) {
+                        break;
+                    }
+                    tmpbuffer[index++] = o->shortName[n];
+                }
+            }
+
+            tmpbuffer[index++] = flag[i];
+
+            if (flag[i] == 0) {
+                break;
+            }
+        }
+
+        uprv_memset(flag, 0, length);
+        uprv_strcpy(flag, tmpbuffer);
+
+        uprv_strcpy(mapFile, o->shortName);
+        uprv_strcat(mapFile, MAP_FILE_EXT);
+
+        f = T_FileStream_open(mapFile, "w");
+        if (f == NULL) {
+            fprintf(stderr,"Unable to create map file: %s.\n", mapFile);
+            return;
+        }
+
+        sprintf(tmpbuffer, "%s%s ", o->entryName, UDATA_CMN_INTERMEDIATE_SUFFIX);
+
+        T_FileStream_writeLine(f, tmpbuffer);
+
+        T_FileStream_close(f);
+    }
+#elif defined(U_CYGWIN)
+    /* Cygwin needs to change flag options. */
+    char *flag = NULL;
+    int32_t length = 0;
+
+    flag = pkgDataFlags[GENLIB];
+    length = uprv_strlen(pkgDataFlags[GENLIB]);
+
+    int32_t position = length - 1;
+
+    for(;position >= 0;position--) {
+        if (flag[position] == '=') {
+            position++;
+            break;
+        }
+    }
+
+    uprv_memset(flag + position, 0, length - position);
+#elif defined(OS400)
+    /* OS400 needs to fix the ld options (swap single quote with double quote) */
+    char *flag = NULL;
+    int32_t length = 0;
+
+    flag = pkgDataFlags[GENLIB];
+    length = uprv_strlen(pkgDataFlags[GENLIB]);
+
+    int32_t position = length - 1;
+
+    for(int32_t i = 0; i < length; i++) {
+        if (flag[i] == '\'') {
+            flag[i] = '\"';
+        }
+    }
+#endif
+}
+
+static void loadLists(UPKGOptions *o, UErrorCode *status)
+{
+    CharList   *l, *tail = NULL, *tail2 = NULL;
+    FileStream *in;
+    char        line[16384];
+    char       *linePtr, *lineNext;
+    const uint32_t   lineMax = 16300;
+    char        tmp[1024];
+    char       *s;
+    int32_t     ln=0; /* line number */
+
+    for(l = o->fileListFiles; l; l = l->next) {
+        if(o->verbose) {
+            fprintf(stdout, "# Reading %s..\n", l->str);
+        }
+        /* TODO: stdin */
+        in = T_FileStream_open(l->str, "r"); /* open files list */
+
+        if(!in) {
+            fprintf(stderr, "Error opening <%s>.\n", l->str);
+            *status = U_FILE_ACCESS_ERROR;
+            return;
+        }
+
+        while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) { /* for each line */
+            ln++;
+            if(uprv_strlen(line)>lineMax) {
+                fprintf(stderr, "%s:%d - line too long (over %d chars)\n", l->str, (int)ln, (int)lineMax);
+                exit(1);
+            }
+            /* remove spaces at the beginning */
+            linePtr = line;
+            while(isspace(*linePtr)) {
+                linePtr++;
+            }
+            s=linePtr;
+            /* remove trailing newline characters */
+            while(*s!=0) {
+                if(*s=='\r' || *s=='\n') {
+                    *s=0;
+                    break;
+                }
+                ++s;
+            }
+            if((*linePtr == 0) || (*linePtr == '#')) {
+                continue; /* comment or empty line */
+            }
+
+            /* Now, process the line */
+            lineNext = NULL;
+
+            while(linePtr && *linePtr) { /* process space-separated items */
+                while(*linePtr == ' ') {
+                    linePtr++;
+                }
+                /* Find the next quote */
+                if(linePtr[0] == '"')
+                {
+                    lineNext = uprv_strchr(linePtr+1, '"');
+                    if(lineNext == NULL) {
+                        fprintf(stderr, "%s:%d - missing trailing double quote (\")\n",
+                            l->str, (int)ln);
+                        exit(1);
+                    } else {
+                        lineNext++;
+                        if(*lineNext) {
+                            if(*lineNext != ' ') {
+                                fprintf(stderr, "%s:%d - malformed quoted line at position %d, expected ' ' got '%c'\n",
+                                    l->str, (int)ln, (int)(lineNext-line), (*lineNext)?*lineNext:'0');
+                                exit(1);
+                            }
+                            *lineNext = 0;
+                            lineNext++;
+                        }
+                    }
+                } else {
+                    lineNext = uprv_strchr(linePtr, ' ');
+                    if(lineNext) {
+                        *lineNext = 0; /* terminate at space */
+                        lineNext++;
+                    }
+                }
+
+                /* add the file */
+                s = (char*)getLongPathname(linePtr);
+
+                /* normal mode.. o->files is just the bare list without package names */
+                o->files = pkg_appendToList(o->files, &tail, uprv_strdup(linePtr));
+                if(uprv_pathIsAbsolute(s)) {
+                    fprintf(stderr, "pkgdata: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, s);
+                    exit(U_ILLEGAL_ARGUMENT_ERROR);
+                }
+                uprv_strcpy(tmp, o->srcDir);
+                uprv_strcat(tmp, o->srcDir[uprv_strlen(o->srcDir)-1] == U_FILE_SEP_CHAR ? "" :PKGDATA_FILE_SEP_STRING);
+                uprv_strcat(tmp, s);
+                o->filePaths = pkg_appendToList(o->filePaths, &tail2, uprv_strdup(tmp));
+                linePtr = lineNext;
+            } /* for each entry on line */
+        } /* for each line */
+        T_FileStream_close(in);
+    } /* for each file list file */
+}
+
+/* Try calling icu-config directly to get the option file. */
+static int32_t pkg_getOptionsFromICUConfig(UOption *option) {
+#if U_HAVE_POPEN
+    FILE *p;
+    size_t n;
+    static char buf[512] = "";
+    const char cmd[] = "icu-config --incpkgdatafile";
+
+    p = popen(cmd, "r");
+
+    if(p == NULL)
+    {
+        fprintf(stderr, "%s: icu-config: No icu-config found. (fix PATH or use -O option)\n", progname);
+        return -1;
+    }
+
+    n = fread(buf, 1, 511, p);
+
+    pclose(p);
+
+    if(n<=0)
+    {
+        fprintf(stderr,"%s: icu-config: Could not read from icu-config. (fix PATH or use -O option)\n", progname);
+        return -1;
+    }
+
+    for (int32_t length = strlen(buf) - 1; length >= 0; length--) {
+        if (buf[length] == '\n' || buf[length] == ' ') {
+            buf[length] = 0;
+        } else {
+            break;
+        }
+    }
+
+    if(buf[strlen(buf)-1]=='\n')
+    {
+        buf[strlen(buf)-1]=0;
+    }
+
+    if(buf[0] == 0)
+    {
+        fprintf(stderr, "%s: icu-config: invalid response from icu-config (fix PATH or use -O option)\n", progname);
+        return -1;
+    }
+
+    option->value = buf;
+    option->doesOccur = TRUE;
+
+    return 0;
+#endif
+    return -1;
+}

Modified: trunk/source/tools/toolutil/pkg_genc.c
===================================================================
--- trunk/source/tools/toolutil/pkg_genc.c	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/toolutil/pkg_genc.c	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,1162 +1,1162 @@
-/******************************************************************************
- *   Copyright (C) 2009, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- *******************************************************************************
- */
-#include "unicode/utypes.h"
-
-#ifdef U_WINDOWS
-#   define VC_EXTRALEAN
-#   define WIN32_LEAN_AND_MEAN
-#   define NOUSER
-#   define NOSERVICE
-#   define NOIME
-#   define NOMCX
-#include <windows.h>
-#include <time.h>
-#   ifdef __GNUC__
-#       define WINDOWS_WITH_GNUC
-#   endif
-#endif
-
-#ifdef U_LINUX
-#   define U_ELF
-#endif
-
-#ifdef U_ELF
-#   include <elf.h>
-#   if defined(ELFCLASS64)
-#       define U_ELF64
-#   endif
-    /* Old elf.h headers may not have EM_X86_64, or have EM_X8664 instead. */
-#   ifndef EM_X86_64
-#       define EM_X86_64 62
-#   endif
-#   define ICU_ENTRY_OFFSET 0
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "unicode/putil.h"
-#include "cmemory.h"
-#include "cstring.h"
-#include "filestrm.h"
-#include "toolutil.h"
-#include "unicode/uclean.h"
-#include "uoptions.h"
-#include "pkg_genc.h"
-
-#define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU))
-
-#define HEX_0X 0 /*  0x1234 */
-#define HEX_0H 1 /*  01234h */
-
-#if defined(U_WINDOWS) || defined(U_ELF)
-#define CAN_GENERATE_OBJECTS
-#endif
-
-/* prototypes --------------------------------------------------------------- */
-static void
-getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename);
-
-static uint32_t
-write8(FileStream *out, uint8_t byte, uint32_t column);
-
-static uint32_t
-write32(FileStream *out, uint32_t byte, uint32_t column);
-
-#ifdef OS400
-static uint32_t
-write8str(FileStream *out, uint8_t byte, uint32_t column);
-#endif
-/* -------------------------------------------------------------------------- */
-
-/*
-Creating Template Files for New Platforms
-
-Let the cc compiler help you get started.
-Compile this program
-    const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16};
-with the -S option to produce assembly output.
-
-For example, this will generate array.s:
-gcc -S array.c
-
-This will produce a .s file that may look like this:
-
-    .file   "array.c"
-    .version        "01.01"
-gcc2_compiled.:
-    .globl x
-    .section        .rodata
-    .align 4
-    .type    x, at object
-    .size    x,20
-x:
-    .long   1
-    .long   2
-    .long   -559038737
-    .long   -1
-    .long   16
-    .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)"
-
-which gives a starting point that will compile, and can be transformed
-to become the template, generally with some consulting of as docs and
-some experimentation.
-
-If you want ICU to automatically use this assembly, you should
-specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file,
-where the name is the compiler or platform that you used in this
-assemblyHeader data structure.
-*/
-static const struct AssemblyType {
-    const char *name;
-    const char *header;
-    const char *beginLine;
-    const char *footer;
-    int8_t      hexType; /* HEX_0X or HEX_0h */
-} assemblyHeader[] = {
-    {"gcc",
-        ".globl %s\n"
-        "\t.section .note.GNU-stack,\"\", at progbits\n"
-        "\t.section .rodata\n"
-        "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
-        "\t.type %s, at object\n"
-        "%s:\n\n",
-
-        ".long ","",HEX_0X
-    },
-    {"gcc-darwin",
-        /*"\t.section __TEXT,__text,regular,pure_instructions\n"
-        "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/
-        ".globl _%s\n"
-        "\t.data\n"
-        "\t.const\n"
-        "\t.align 4\n"  /* 1<<4 = 16 */
-        "_%s:\n\n",
-
-        ".long ","",HEX_0X
-    },
-    {"gcc-cygwin",
-        ".globl _%s\n"
-        "\t.section .rodata\n"
-        "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
-        "_%s:\n\n",
-
-        ".long ","",HEX_0X
-    },
-    {"sun",
-        "\t.section \".rodata\"\n"
-        "\t.align   8\n"
-        ".globl     %s\n"
-        "%s:\n",
-
-        ".word ","",HEX_0X
-    },
-    {"sun-x86",
-        "Drodata.rodata:\n"
-        "\t.type   Drodata.rodata, at object\n"
-        "\t.size   Drodata.rodata,0\n"
-        "\t.globl  %s\n"
-        "\t.align  8\n"
-        "%s:\n",
-
-        ".4byte ","",HEX_0X
-    },
-    {"xlc",
-        ".globl %s{RO}\n"
-        "\t.toc\n"
-        "%s:\n"
-        "\t.csect %s{RO}, 4\n",
-
-        ".long ","",HEX_0X
-    },
-    {"aCC-ia64",
-        "\t.file   \"%s.s\"\n"
-        "\t.type   %s, at object\n"
-        "\t.global %s\n"
-        "\t.secalias .abe$0.rodata, \".rodata\"\n"
-        "\t.section .abe$0.rodata = \"a\", \"progbits\"\n"
-        "\t.align  16\n"
-        "%s::\t",
-
-        "data4 ","",HEX_0X
-    },
-    {"aCC-parisc",
-        "\t.SPACE  $TEXT$\n"
-        "\t.SUBSPA $LIT$\n"
-        "%s\n"
-        "\t.EXPORT %s\n"
-        "\t.ALIGN  16\n",
-
-        ".WORD ","",HEX_0X
-    },
-    { "masm",
-      "\tTITLE %s\n"
-      "; generated by genccode\n"
-      ".386\n"
-      ".model flat\n"
-      "\tPUBLIC _%s\n"
-      "ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n"
-      "\tALIGN 16\n"
-      "_%s\tLABEL DWORD\n",
-      "\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H
-    }
-};
-
-static int32_t assemblyHeaderIndex = -1;
-static int32_t hexType = HEX_0X;
-
-U_CAPI UBool U_EXPORT2
-checkAssemblyHeaderName(const char* optAssembly) {
-    int32_t idx;
-    assemblyHeaderIndex = -1;
-    for (idx = 0; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) {
-        if (uprv_strcmp(optAssembly, assemblyHeader[idx].name) == 0) {
-            assemblyHeaderIndex = idx;
-            hexType = assemblyHeader[idx].hexType; /* set the hex type */
-            return TRUE;
-        }
-    }
-
-    return FALSE;
-}
-
-
-U_CAPI void U_EXPORT2
-printAssemblyHeadersToStdErr(void) {
-    int32_t idx;
-    fprintf(stderr, "%s", assemblyHeader[0].name);
-    for (idx = 1; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) {
-        fprintf(stderr, ", %s", assemblyHeader[idx].name);
-    }
-    fprintf(stderr,
-        ")\n");
-}
-
-U_CAPI void U_EXPORT2
-writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) {
-    uint32_t column = MAX_COLUMN;
-    char entry[64];
-    uint32_t buffer[1024];
-    char *bufferStr = (char *)buffer;
-    FileStream *in, *out;
-    size_t i, length;
-
-    in=T_FileStream_open(filename, "rb");
-    if(in==NULL) {
-        fprintf(stderr, "genccode: unable to open input file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    getOutFilename(filename, destdir, bufferStr, entry, ".s", optFilename);
-    out=T_FileStream_open(bufferStr, "w");
-    if(out==NULL) {
-        fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    if (outFilePath != NULL) {
-        uprv_strcpy(outFilePath, bufferStr);
-    }
-
-#ifdef WINDOWS_WITH_GNUC
-    /* Need to fix the file seperator character when using MinGW. */
-    swapFileSepChar(outFilePath, U_FILE_SEP_CHAR, '/');
-#endif
-
-    if(optEntryPoint != NULL) {
-        uprv_strcpy(entry, optEntryPoint);
-        uprv_strcat(entry, "_dat");
-    }
-
-    /* turn dashes or dots in the entry name into underscores */
-    length=uprv_strlen(entry);
-    for(i=0; i<length; ++i) {
-        if(entry[i]=='-' || entry[i]=='.') {
-            entry[i]='_';
-        }
-    }
-
-    sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header,
-        entry, entry, entry, entry,
-        entry, entry, entry, entry);
-    T_FileStream_writeLine(out, bufferStr);
-    T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine);
-
-    for(;;) {
-        length=T_FileStream_read(in, buffer, sizeof(buffer));
-        if(length==0) {
-            break;
-        }
-        if (length != sizeof(buffer)) {
-            /* pad with extra 0's when at the end of the file */
-            for(i=0; i < (length % sizeof(uint32_t)); ++i) {
-                buffer[length+i] = 0;
-            }
-        }
-        for(i=0; i<(length/sizeof(buffer[0])); i++) {
-            column = write32(out, buffer[i], column);
-        }
-    }
-
-    T_FileStream_writeLine(out, "\n");
-
-    sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer,
-        entry, entry, entry, entry,
-        entry, entry, entry, entry);
-    T_FileStream_writeLine(out, bufferStr);
-
-    if(T_FileStream_error(in)) {
-        fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    if(T_FileStream_error(out)) {
-        fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    T_FileStream_close(out);
-    T_FileStream_close(in);
-}
-
-U_CAPI void U_EXPORT2
-writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) {
-    uint32_t column = MAX_COLUMN;
-    char buffer[4096], entry[64];
-    FileStream *in, *out;
-    size_t i, length;
-
-    in=T_FileStream_open(filename, "rb");
-    if(in==NULL) {
-        fprintf(stderr, "genccode: unable to open input file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    if(optName != NULL) { /* prepend  'icudt28_' */
-      strcpy(entry, optName);
-      strcat(entry, "_");
-    } else {
-      entry[0] = 0;
-    }
-
-    getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename);
-    if (outFilePath != NULL) {
-        uprv_strcpy(outFilePath, buffer);
-    }
-    out=T_FileStream_open(buffer, "w");
-    if(out==NULL) {
-        fprintf(stderr, "genccode: unable to open output file %s\n", buffer);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    /* turn dashes or dots in the entry name into underscores */
-    length=uprv_strlen(entry);
-    for(i=0; i<length; ++i) {
-        if(entry[i]=='-' || entry[i]=='.') {
-            entry[i]='_';
-        }
-    }
-
-#ifdef OS400
-    /*
-    TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c
-
-    This is here because this platform can't currently put
-    const data into the read-only pages of an object or
-    shared library (service program). Only strings are allowed in read-only
-    pages, so we use char * strings to store the data.
-
-    In order to prevent the beginning of the data from ever matching the
-    magic numbers we must still use the initial double.
-    [grhoten 4/24/2003]
-    */
-    sprintf(buffer,
-        "#define U_DISABLE_RENAMING 1\n"
-        "#include \"unicode/umachine.h\"\n"
-        "U_CDECL_BEGIN\n"
-        "const struct {\n"
-        "    double bogus;\n"
-        "    const char *bytes; \n"
-        "} %s={ 0.0, \n",
-        entry);
-    T_FileStream_writeLine(out, buffer);
-
-    for(;;) {
-        length=T_FileStream_read(in, buffer, sizeof(buffer));
-        if(length==0) {
-            break;
-        }
-        for(i=0; i<length; ++i) {
-            column = write8str(out, (uint8_t)buffer[i], column);
-        }
-    }
-
-    T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n");
-#else
-    /* Function renaming shouldn't be done in data */
-    sprintf(buffer,
-        "#define U_DISABLE_RENAMING 1\n"
-        "#include \"unicode/umachine.h\"\n"
-        "U_CDECL_BEGIN\n"
-        "const struct {\n"
-        "    double bogus;\n"
-        "    uint8_t bytes[%ld]; \n"
-        "} %s={ 0.0, {\n",
-        (long)T_FileStream_size(in), entry);
-    T_FileStream_writeLine(out, buffer);
-
-    for(;;) {
-        length=T_FileStream_read(in, buffer, sizeof(buffer));
-        if(length==0) {
-            break;
-        }
-        for(i=0; i<length; ++i) {
-            column = write8(out, (uint8_t)buffer[i], column);
-        }
-    }
-
-    T_FileStream_writeLine(out, "\n}\n};\nU_CDECL_END\n");
-#endif
-
-    if(T_FileStream_error(in)) {
-        fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    if(T_FileStream_error(out)) {
-        fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    T_FileStream_close(out);
-    T_FileStream_close(in);
-}
-
-static uint32_t
-write32(FileStream *out, uint32_t bitField, uint32_t column) {
-    int32_t i;
-    char bitFieldStr[64]; /* This is more bits than needed for a 32-bit number */
-    char *s = bitFieldStr;
-    uint8_t *ptrIdx = (uint8_t *)&bitField;
-    static const char hexToStr[16] = {
-        '0','1','2','3',
-        '4','5','6','7',
-        '8','9','A','B',
-        'C','D','E','F'
-    };
-
-    /* write the value, possibly with comma and newline */
-    if(column==MAX_COLUMN) {
-        /* first byte */
-        column=1;
-    } else if(column<32) {
-        *(s++)=',';
-        ++column;
-    } else {
-        *(s++)='\n';
-        uprv_strcpy(s, assemblyHeader[assemblyHeaderIndex].beginLine);
-        s+=uprv_strlen(s);
-        column=1;
-    }
-
-    if (bitField < 10) {
-        /* It's a small number. Don't waste the space for 0x */
-        *(s++)=hexToStr[bitField];
-    }
-    else {
-        int seenNonZero = 0; /* This is used to remove leading zeros */
-
-        if(hexType==HEX_0X) {
-         *(s++)='0';
-         *(s++)='x';
-        } else if(hexType==HEX_0H) {
-         *(s++)='0';
-        }
-
-        /* This creates a 32-bit field */
-#if U_IS_BIG_ENDIAN
-        for (i = 0; i < sizeof(uint32_t); i++)
-#else
-        for (i = sizeof(uint32_t)-1; i >= 0 ; i--)
-#endif
-        {
-            uint8_t value = ptrIdx[i];
-            if (value || seenNonZero) {
-                *(s++)=hexToStr[value>>4];
-                *(s++)=hexToStr[value&0xF];
-                seenNonZero = 1;
-            }
-        }
-        if(hexType==HEX_0H) {
-         *(s++)='h';
-        }
-    }
-
-    *(s++)=0;
-    T_FileStream_writeLine(out, bitFieldStr);
-    return column;
-}
-
-static uint32_t
-write8(FileStream *out, uint8_t byte, uint32_t column) {
-    char s[4];
-    int i=0;
-
-    /* convert the byte value to a string */
-    if(byte>=100) {
-        s[i++]=(char)('0'+byte/100);
-        byte%=100;
-    }
-    if(i>0 || byte>=10) {
-        s[i++]=(char)('0'+byte/10);
-        byte%=10;
-    }
-    s[i++]=(char)('0'+byte);
-    s[i]=0;
-
-    /* write the value, possibly with comma and newline */
-    if(column==MAX_COLUMN) {
-        /* first byte */
-        column=1;
-    } else if(column<16) {
-        T_FileStream_writeLine(out, ",");
-        ++column;
-    } else {
-        T_FileStream_writeLine(out, ",\n");
-        column=1;
-    }
-    T_FileStream_writeLine(out, s);
-    return column;
-}
-
-#ifdef OS400
-static uint32_t
-write8str(FileStream *out, uint8_t byte, uint32_t column) {
-    char s[8];
-
-    if (byte > 7)
-        sprintf(s, "\\x%X", byte);
-    else
-        sprintf(s, "\\%X", byte);
-
-    /* write the value, possibly with comma and newline */
-    if(column==MAX_COLUMN) {
-        /* first byte */
-        column=1;
-        T_FileStream_writeLine(out, "\"");
-    } else if(column<24) {
-        ++column;
-    } else {
-        T_FileStream_writeLine(out, "\"\n\"");
-        column=1;
-    }
-    T_FileStream_writeLine(out, s);
-    return column;
-}
-#endif
-
-static void
-getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename) {
-    const char *basename=findBasename(inFilename), *suffix=uprv_strrchr(basename, '.');
-
-    /* copy path */
-    if(destdir!=NULL && *destdir!=0) {
-        do {
-            *outFilename++=*destdir++;
-        } while(*destdir!=0);
-        if(*(outFilename-1)!=U_FILE_SEP_CHAR) {
-            *outFilename++=U_FILE_SEP_CHAR;
-        }
-        inFilename=basename;
-    } else {
-        while(inFilename<basename) {
-            *outFilename++=*inFilename++;
-        }
-    }
-
-    if(suffix==NULL) {
-        /* the filename does not have a suffix */
-        uprv_strcpy(entryName, inFilename);
-        if(optFilename != NULL) {
-          uprv_strcpy(outFilename, optFilename);
-        } else {
-          uprv_strcpy(outFilename, inFilename);
-        }
-        uprv_strcat(outFilename, newSuffix);
-    } else {
-        char *saveOutFilename = outFilename;
-        /* copy basename */
-        while(inFilename<suffix) {
-            if(*inFilename=='-') {
-                /* iSeries cannot have '-' in the .o objects. */
-                *outFilename++=*entryName++='_';
-                inFilename++;
-            }
-            else {
-                *outFilename++=*entryName++=*inFilename++;
-            }
-        }
-
-        /* replace '.' by '_' */
-        *outFilename++=*entryName++='_';
-        ++inFilename;
-
-        /* copy suffix */
-        while(*inFilename!=0) {
-            *outFilename++=*entryName++=*inFilename++;
-        }
-
-        *entryName=0;
-
-        if(optFilename != NULL) {
-            uprv_strcpy(saveOutFilename, optFilename);
-            uprv_strcat(saveOutFilename, newSuffix);
-        } else {
-            /* add ".c" */
-            uprv_strcpy(outFilename, newSuffix);
-        }
-    }
-}
-
-#ifdef CAN_GENERATE_OBJECTS
-static void
-getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char *optMatchArch) {
-    int64_t buffer[256];
-    const char *filename;
-    FileStream *in;
-    int32_t length;
-
-#ifdef U_ELF
-    /* Pointer to ELF header. Elf32_Ehdr and ELF64_Ehdr are identical for the necessary fields. */
-    const Elf32_Ehdr *pHeader32;
-#elif defined(U_WINDOWS)
-    const IMAGE_FILE_HEADER *pHeader;
-#else
-#   error "Unknown platform for CAN_GENERATE_OBJECTS."
-#endif
-
-    if(optMatchArch != NULL) {
-        filename=optMatchArch;
-    } else {
-        /* set defaults */
-#ifdef U_ELF
-        /* set EM_386 because elf.h does not provide better defaults */
-        *pCPU=EM_386;
-        *pBits=32;
-        *pIsBigEndian=(UBool)(U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB);
-#elif defined(U_WINDOWS)
-/* _M_IA64 should be defined in windows.h */
-#   if defined(_M_IA64)
-        *pCPU=IMAGE_FILE_MACHINE_IA64;
-#   elif defined(_M_AMD64)
-        *pCPU=IMAGE_FILE_MACHINE_AMD64;
-#   else
-        *pCPU=IMAGE_FILE_MACHINE_I386;
-#   endif
-        *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64;
-        *pIsBigEndian=FALSE;
-#else
-#   error "Unknown platform for CAN_GENERATE_OBJECTS."
-#endif
-        return;
-    }
-
-    in=T_FileStream_open(filename, "rb");
-    if(in==NULL) {
-        fprintf(stderr, "genccode: unable to open match-arch file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-    length=T_FileStream_read(in, buffer, sizeof(buffer));
-
-#ifdef U_ELF
-    if(length<sizeof(Elf32_Ehdr)) {
-        fprintf(stderr, "genccode: match-arch file %s is too short\n", filename);
-        exit(U_UNSUPPORTED_ERROR);
-    }
-    pHeader32=(const Elf32_Ehdr *)buffer;
-    if(
-        pHeader32->e_ident[0]!=ELFMAG0 ||
-        pHeader32->e_ident[1]!=ELFMAG1 ||
-        pHeader32->e_ident[2]!=ELFMAG2 ||
-        pHeader32->e_ident[3]!=ELFMAG3 ||
-        pHeader32->e_ident[EI_CLASS]<ELFCLASS32 || pHeader32->e_ident[EI_CLASS]>ELFCLASS64
-    ) {
-        fprintf(stderr, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename);
-        exit(U_UNSUPPORTED_ERROR);
-    }
-
-    *pBits= pHeader32->e_ident[EI_CLASS]==ELFCLASS32 ? 32 : 64; /* only 32 or 64: see check above */
-#ifdef U_ELF64
-    if(*pBits!=32 && *pBits!=64) {
-        fprintf(stderr, "genccode: currently only supports 32-bit and 64-bit ELF format\n");
-        exit(U_UNSUPPORTED_ERROR);
-    }
-#else
-    if(*pBits!=32) {
-        fprintf(stderr, "genccode: built with elf.h missing 64-bit definitions\n");
-        exit(U_UNSUPPORTED_ERROR);
-    }
-#endif
-
-    *pIsBigEndian=(UBool)(pHeader32->e_ident[EI_DATA]==ELFDATA2MSB);
-    if(*pIsBigEndian!=U_IS_BIG_ENDIAN) {
-        fprintf(stderr, "genccode: currently only same-endianness ELF formats are supported\n");
-        exit(U_UNSUPPORTED_ERROR);
-    }
-    /* TODO: Support byte swapping */
-
-    *pCPU=pHeader32->e_machine;
-#elif defined(U_WINDOWS)
-    if(length<sizeof(IMAGE_FILE_HEADER)) {
-        fprintf(stderr, "genccode: match-arch file %s is too short\n", filename);
-        exit(U_UNSUPPORTED_ERROR);
-    }
-    pHeader=(const IMAGE_FILE_HEADER *)buffer;
-    *pCPU=pHeader->Machine;
-    /*
-     * The number of bits is implicit with the Machine value.
-     * *pBits is ignored in the calling code, so this need not be precise.
-     */
-    *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64;
-    /* Windows always runs on little-endian CPUs. */
-    *pIsBigEndian=FALSE;
-#else
-#   error "Unknown platform for CAN_GENERATE_OBJECTS."
-#endif
-
-    T_FileStream_close(in);
-}
-
-U_CAPI void U_EXPORT2
-writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath) {
-    /* common variables */
-    char buffer[4096], entry[40]={ 0 };
-    FileStream *in, *out;
-    const char *newSuffix;
-    int32_t i, entryLength, length, size, entryOffset=0, entryLengthOffset=0;
-
-    uint16_t cpu, bits;
-    UBool makeBigEndian;
-
-    /* platform-specific variables and initialization code */
-#ifdef U_ELF
-    /* 32-bit Elf file header */
-    static Elf32_Ehdr header32={
-        {
-            /* e_ident[] */
-            ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
-            ELFCLASS32,
-            U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB,
-            EV_CURRENT /* EI_VERSION */
-        },
-        ET_REL,
-        EM_386,
-        EV_CURRENT, /* e_version */
-        0, /* e_entry */
-        0, /* e_phoff */
-        (Elf32_Off)sizeof(Elf32_Ehdr), /* e_shoff */
-        0, /* e_flags */
-        (Elf32_Half)sizeof(Elf32_Ehdr), /* eh_size */
-        0, /* e_phentsize */
-        0, /* e_phnum */
-        (Elf32_Half)sizeof(Elf32_Shdr), /* e_shentsize */
-        5, /* e_shnum */
-        2 /* e_shstrndx */
-    };
-
-    /* 32-bit Elf section header table */
-    static Elf32_Shdr sectionHeaders32[5]={
-        { /* SHN_UNDEF */
-            0
-        },
-        { /* .symtab */
-            1, /* sh_name */
-            SHT_SYMTAB,
-            0, /* sh_flags */
-            0, /* sh_addr */
-            (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)), /* sh_offset */
-            (Elf32_Word)(2*sizeof(Elf32_Sym)), /* sh_size */
-            3, /* sh_link=sect hdr index of .strtab */
-            1, /* sh_info=One greater than the symbol table index of the last
-                * local symbol (with STB_LOCAL). */
-            4, /* sh_addralign */
-            (Elf32_Word)(sizeof(Elf32_Sym)) /* sh_entsize */
-        },
-        { /* .shstrtab */
-            9, /* sh_name */
-            SHT_STRTAB,
-            0, /* sh_flags */
-            0, /* sh_addr */
-            (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)), /* sh_offset */
-            40, /* sh_size */
-            0, /* sh_link */
-            0, /* sh_info */
-            1, /* sh_addralign */
-            0 /* sh_entsize */
-        },
-        { /* .strtab */
-            19, /* sh_name */
-            SHT_STRTAB,
-            0, /* sh_flags */
-            0, /* sh_addr */
-            (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40), /* sh_offset */
-            (Elf32_Word)sizeof(entry), /* sh_size */
-            0, /* sh_link */
-            0, /* sh_info */
-            1, /* sh_addralign */
-            0 /* sh_entsize */
-        },
-        { /* .rodata */
-            27, /* sh_name */
-            SHT_PROGBITS,
-            SHF_ALLOC, /* sh_flags */
-            0, /* sh_addr */
-            (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40+sizeof(entry)), /* sh_offset */
-            0, /* sh_size */
-            0, /* sh_link */
-            0, /* sh_info */
-            16, /* sh_addralign */
-            0 /* sh_entsize */
-        }
-    };
-
-    /* symbol table */
-    static Elf32_Sym symbols32[2]={
-        { /* STN_UNDEF */
-            0
-        },
-        { /* data entry point */
-            1, /* st_name */
-            0, /* st_value */
-            0, /* st_size */
-            ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
-            0, /* st_other */
-            4 /* st_shndx=index of related section table entry */
-        }
-    };
-
-    /* section header string table, with decimal string offsets */
-    static const char sectionStrings[40]=
-        /*  0 */ "\0"
-        /*  1 */ ".symtab\0"
-        /*  9 */ ".shstrtab\0"
-        /* 19 */ ".strtab\0"
-        /* 27 */ ".rodata\0"
-        /* 35 */ "\0\0\0\0"; /* contains terminating NUL */
-        /* 40: padded to multiple of 8 bytes */
-
-    /*
-     * Use entry[] for the string table which will contain only the
-     * entry point name.
-     * entry[0] must be 0 (NUL)
-     * The entry point name can be up to 38 characters long (sizeof(entry)-2).
-     */
-
-    /* 16-align .rodata in the .o file, just in case */
-    static const char padding[16]={ 0 };
-    int32_t paddingSize;
-
-#ifdef U_ELF64
-    /* 64-bit Elf file header */
-    static Elf64_Ehdr header64={
-        {
-            /* e_ident[] */
-            ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
-            ELFCLASS64,
-            U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB,
-            EV_CURRENT /* EI_VERSION */
-        },
-        ET_REL,
-        EM_X86_64,
-        EV_CURRENT, /* e_version */
-        0, /* e_entry */
-        0, /* e_phoff */
-        (Elf64_Off)sizeof(Elf64_Ehdr), /* e_shoff */
-        0, /* e_flags */
-        (Elf64_Half)sizeof(Elf64_Ehdr), /* eh_size */
-        0, /* e_phentsize */
-        0, /* e_phnum */
-        (Elf64_Half)sizeof(Elf64_Shdr), /* e_shentsize */
-        5, /* e_shnum */
-        2 /* e_shstrndx */
-    };
-
-    /* 64-bit Elf section header table */
-    static Elf64_Shdr sectionHeaders64[5]={
-        { /* SHN_UNDEF */
-            0
-        },
-        { /* .symtab */
-            1, /* sh_name */
-            SHT_SYMTAB,
-            0, /* sh_flags */
-            0, /* sh_addr */
-            (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)), /* sh_offset */
-            (Elf64_Xword)(2*sizeof(Elf64_Sym)), /* sh_size */
-            3, /* sh_link=sect hdr index of .strtab */
-            1, /* sh_info=One greater than the symbol table index of the last
-                * local symbol (with STB_LOCAL). */
-            4, /* sh_addralign */
-            (Elf64_Xword)(sizeof(Elf64_Sym)) /* sh_entsize */
-        },
-        { /* .shstrtab */
-            9, /* sh_name */
-            SHT_STRTAB,
-            0, /* sh_flags */
-            0, /* sh_addr */
-            (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)), /* sh_offset */
-            40, /* sh_size */
-            0, /* sh_link */
-            0, /* sh_info */
-            1, /* sh_addralign */
-            0 /* sh_entsize */
-        },
-        { /* .strtab */
-            19, /* sh_name */
-            SHT_STRTAB,
-            0, /* sh_flags */
-            0, /* sh_addr */
-            (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40), /* sh_offset */
-            (Elf64_Xword)sizeof(entry), /* sh_size */
-            0, /* sh_link */
-            0, /* sh_info */
-            1, /* sh_addralign */
-            0 /* sh_entsize */
-        },
-        { /* .rodata */
-            27, /* sh_name */
-            SHT_PROGBITS,
-            SHF_ALLOC, /* sh_flags */
-            0, /* sh_addr */
-            (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40+sizeof(entry)), /* sh_offset */
-            0, /* sh_size */
-            0, /* sh_link */
-            0, /* sh_info */
-            16, /* sh_addralign */
-            0 /* sh_entsize */
-        }
-    };
-
-    /*
-     * 64-bit symbol table
-     * careful: different order of items compared with Elf32_sym!
-     */
-    static Elf64_Sym symbols64[2]={
-        { /* STN_UNDEF */
-            0
-        },
-        { /* data entry point */
-            1, /* st_name */
-            ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
-            0, /* st_other */
-            4, /* st_shndx=index of related section table entry */
-            0, /* st_value */
-            0 /* st_size */
-        }
-    };
-
-#endif /* U_ELF64 */
-
-    /* entry[] have a leading NUL */
-    entryOffset=1;
-
-    /* in the common code, count entryLength from after the NUL */
-    entryLengthOffset=1;
-
-    newSuffix=".o";
-
-#elif defined(U_WINDOWS)
-    struct {
-        IMAGE_FILE_HEADER fileHeader;
-        IMAGE_SECTION_HEADER sections[2];
-        char linkerOptions[100];
-    } objHeader;
-    IMAGE_SYMBOL symbols[1];
-    struct {
-        DWORD sizeofLongNames;
-        char longNames[100];
-    } symbolNames;
-
-    /*
-     * entry sometimes have a leading '_'
-     * overwritten if entryOffset==0 depending on the target platform
-     * see check for cpu below
-     */
-    entry[0]='_';
-
-    newSuffix=".obj";
-#else
-#   error "Unknown platform for CAN_GENERATE_OBJECTS."
-#endif
-
-    /* deal with options, files and the entry point name */
-    getArchitecture(&cpu, &bits, &makeBigEndian, optMatchArch);
-    printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%hu\n", cpu, bits, makeBigEndian);
-#ifdef U_WINDOWS
-    if(cpu==IMAGE_FILE_MACHINE_I386) {
-        entryOffset=1;
-    }
-#endif
-
-    in=T_FileStream_open(filename, "rb");
-    if(in==NULL) {
-        fprintf(stderr, "genccode: unable to open input file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-    size=T_FileStream_size(in);
-
-    getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix, optFilename);
-    if (outFilePath != NULL) {
-        uprv_strcpy(outFilePath, buffer);
-    }
-
-    if(optEntryPoint != NULL) {
-        uprv_strcpy(entry+entryOffset, optEntryPoint);
-        uprv_strcat(entry+entryOffset, "_dat");
-    }
-    /* turn dashes in the entry name into underscores */
-    entryLength=(int32_t)uprv_strlen(entry+entryLengthOffset);
-    for(i=0; i<entryLength; ++i) {
-        if(entry[entryLengthOffset+i]=='-') {
-            entry[entryLengthOffset+i]='_';
-        }
-    }
-
-    /* open the output file */
-    out=T_FileStream_open(buffer, "wb");
-    if(out==NULL) {
-        fprintf(stderr, "genccode: unable to open output file %s\n", buffer);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-#ifdef U_ELF
-    if(bits==32) {
-        header32.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB;
-        header32.e_machine=cpu;
-
-        /* 16-align .rodata in the .o file, just in case */
-        paddingSize=sectionHeaders32[4].sh_offset & 0xf;
-        if(paddingSize!=0) {
-                paddingSize=0x10-paddingSize;
-                sectionHeaders32[4].sh_offset+=paddingSize;
-        }
-
-        sectionHeaders32[4].sh_size=(Elf32_Word)size;
-
-        symbols32[1].st_size=(Elf32_Word)size;
-
-        /* write .o headers */
-        T_FileStream_write(out, &header32, (int32_t)sizeof(header32));
-        T_FileStream_write(out, sectionHeaders32, (int32_t)sizeof(sectionHeaders32));
-        T_FileStream_write(out, symbols32, (int32_t)sizeof(symbols32));
-    } else /* bits==64 */ {
-#ifdef U_ELF64
-        header64.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB;
-        header64.e_machine=cpu;
-
-        /* 16-align .rodata in the .o file, just in case */
-        paddingSize=sectionHeaders64[4].sh_offset & 0xf;
-        if(paddingSize!=0) {
-                paddingSize=0x10-paddingSize;
-                sectionHeaders64[4].sh_offset+=paddingSize;
-        }
-
-        sectionHeaders64[4].sh_size=(Elf64_Xword)size;
-
-        symbols64[1].st_size=(Elf64_Xword)size;
-
-        /* write .o headers */
-        T_FileStream_write(out, &header64, (int32_t)sizeof(header64));
-        T_FileStream_write(out, sectionHeaders64, (int32_t)sizeof(sectionHeaders64));
-        T_FileStream_write(out, symbols64, (int32_t)sizeof(symbols64));
-#endif
-    }
-
-    T_FileStream_write(out, sectionStrings, (int32_t)sizeof(sectionStrings));
-    T_FileStream_write(out, entry, (int32_t)sizeof(entry));
-    if(paddingSize!=0) {
-        T_FileStream_write(out, padding, paddingSize);
-    }
-#elif defined(U_WINDOWS)
-    /* populate the .obj headers */
-    uprv_memset(&objHeader, 0, sizeof(objHeader));
-    uprv_memset(&symbols, 0, sizeof(symbols));
-    uprv_memset(&symbolNames, 0, sizeof(symbolNames));
-
-    /* write the linker export directive */
-    uprv_strcpy(objHeader.linkerOptions, "-export:");
-    length=8;
-    uprv_strcpy(objHeader.linkerOptions+length, entry);
-    length+=entryLength;
-    uprv_strcpy(objHeader.linkerOptions+length, ",data ");
-    length+=6;
-
-    /* set the file header */
-    objHeader.fileHeader.Machine=cpu;
-    objHeader.fileHeader.NumberOfSections=2;
-    objHeader.fileHeader.TimeDateStamp=(DWORD)time(NULL);
-    objHeader.fileHeader.PointerToSymbolTable=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length+size; /* start of symbol table */
-    objHeader.fileHeader.NumberOfSymbols=1;
-
-    /* set the section for the linker options */
-    uprv_strncpy((char *)objHeader.sections[0].Name, ".drectve", 8);
-    objHeader.sections[0].SizeOfRawData=length;
-    objHeader.sections[0].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER;
-    objHeader.sections[0].Characteristics=IMAGE_SCN_LNK_INFO|IMAGE_SCN_LNK_REMOVE|IMAGE_SCN_ALIGN_1BYTES;
-
-    /* set the data section */
-    uprv_strncpy((char *)objHeader.sections[1].Name, ".rdata", 6);
-    objHeader.sections[1].SizeOfRawData=size;
-    objHeader.sections[1].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length;
-    objHeader.sections[1].Characteristics=IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_ALIGN_16BYTES|IMAGE_SCN_MEM_READ;
-
-    /* set the symbol table */
-    if(entryLength<=8) {
-        uprv_strncpy((char *)symbols[0].N.ShortName, entry, entryLength);
-        symbolNames.sizeofLongNames=4;
-    } else {
-        symbols[0].N.Name.Short=0;
-        symbols[0].N.Name.Long=4;
-        symbolNames.sizeofLongNames=4+entryLength+1;
-        uprv_strcpy(symbolNames.longNames, entry);
-    }
-    symbols[0].SectionNumber=2;
-    symbols[0].StorageClass=IMAGE_SYM_CLASS_EXTERNAL;
-
-    /* write the file header and the linker options section */
-    T_FileStream_write(out, &objHeader, objHeader.sections[1].PointerToRawData);
-#else
-#   error "Unknown platform for CAN_GENERATE_OBJECTS."
-#endif
-
-    /* copy the data file into section 2 */
-    for(;;) {
-        length=T_FileStream_read(in, buffer, sizeof(buffer));
-        if(length==0) {
-            break;
-        }
-        T_FileStream_write(out, buffer, (int32_t)length);
-    }
-
-#ifdef U_WINDOWS
-    /* write the symbol table */
-    T_FileStream_write(out, symbols, IMAGE_SIZEOF_SYMBOL);
-    T_FileStream_write(out, &symbolNames, symbolNames.sizeofLongNames);
-#endif
-
-    if(T_FileStream_error(in)) {
-        fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    if(T_FileStream_error(out)) {
-        fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
-        exit(U_FILE_ACCESS_ERROR);
-    }
-
-    T_FileStream_close(out);
-    T_FileStream_close(in);
-}
-#endif
+/******************************************************************************
+ *   Copyright (C) 2009, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *******************************************************************************
+ */
+#include "unicode/utypes.h"
+
+#ifdef U_WINDOWS
+#   define VC_EXTRALEAN
+#   define WIN32_LEAN_AND_MEAN
+#   define NOUSER
+#   define NOSERVICE
+#   define NOIME
+#   define NOMCX
+#include <windows.h>
+#include <time.h>
+#   ifdef __GNUC__
+#       define WINDOWS_WITH_GNUC
+#   endif
+#endif
+
+#ifdef U_LINUX
+#   define U_ELF
+#endif
+
+#ifdef U_ELF
+#   include <elf.h>
+#   if defined(ELFCLASS64)
+#       define U_ELF64
+#   endif
+    /* Old elf.h headers may not have EM_X86_64, or have EM_X8664 instead. */
+#   ifndef EM_X86_64
+#       define EM_X86_64 62
+#   endif
+#   define ICU_ENTRY_OFFSET 0
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "unicode/putil.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "filestrm.h"
+#include "toolutil.h"
+#include "unicode/uclean.h"
+#include "uoptions.h"
+#include "pkg_genc.h"
+
+#define MAX_COLUMN ((uint32_t)(0xFFFFFFFFU))
+
+#define HEX_0X 0 /*  0x1234 */
+#define HEX_0H 1 /*  01234h */
+
+#if defined(U_WINDOWS) || defined(U_ELF)
+#define CAN_GENERATE_OBJECTS
+#endif
+
+/* prototypes --------------------------------------------------------------- */
+static void
+getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename);
+
+static uint32_t
+write8(FileStream *out, uint8_t byte, uint32_t column);
+
+static uint32_t
+write32(FileStream *out, uint32_t byte, uint32_t column);
+
+#ifdef OS400
+static uint32_t
+write8str(FileStream *out, uint8_t byte, uint32_t column);
+#endif
+/* -------------------------------------------------------------------------- */
+
+/*
+Creating Template Files for New Platforms
+
+Let the cc compiler help you get started.
+Compile this program
+    const unsigned int x[5] = {1, 2, 0xdeadbeef, 0xffffffff, 16};
+with the -S option to produce assembly output.
+
+For example, this will generate array.s:
+gcc -S array.c
+
+This will produce a .s file that may look like this:
+
+    .file   "array.c"
+    .version        "01.01"
+gcc2_compiled.:
+    .globl x
+    .section        .rodata
+    .align 4
+    .type    x, at object
+    .size    x,20
+x:
+    .long   1
+    .long   2
+    .long   -559038737
+    .long   -1
+    .long   16
+    .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)"
+
+which gives a starting point that will compile, and can be transformed
+to become the template, generally with some consulting of as docs and
+some experimentation.
+
+If you want ICU to automatically use this assembly, you should
+specify "GENCCODE_ASSEMBLY=-a name" in the specific config/mh-* file,
+where the name is the compiler or platform that you used in this
+assemblyHeader data structure.
+*/
+static const struct AssemblyType {
+    const char *name;
+    const char *header;
+    const char *beginLine;
+    const char *footer;
+    int8_t      hexType; /* HEX_0X or HEX_0h */
+} assemblyHeader[] = {
+    {"gcc",
+        ".globl %s\n"
+        "\t.section .note.GNU-stack,\"\", at progbits\n"
+        "\t.section .rodata\n"
+        "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
+        "\t.type %s, at object\n"
+        "%s:\n\n",
+
+        ".long ","",HEX_0X
+    },
+    {"gcc-darwin",
+        /*"\t.section __TEXT,__text,regular,pure_instructions\n"
+        "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n"*/
+        ".globl _%s\n"
+        "\t.data\n"
+        "\t.const\n"
+        "\t.align 4\n"  /* 1<<4 = 16 */
+        "_%s:\n\n",
+
+        ".long ","",HEX_0X
+    },
+    {"gcc-cygwin",
+        ".globl _%s\n"
+        "\t.section .rodata\n"
+        "\t.align 8\n" /* Either align 8 bytes or 2^8 (256) bytes. 8 bytes is needed. */
+        "_%s:\n\n",
+
+        ".long ","",HEX_0X
+    },
+    {"sun",
+        "\t.section \".rodata\"\n"
+        "\t.align   8\n"
+        ".globl     %s\n"
+        "%s:\n",
+
+        ".word ","",HEX_0X
+    },
+    {"sun-x86",
+        "Drodata.rodata:\n"
+        "\t.type   Drodata.rodata, at object\n"
+        "\t.size   Drodata.rodata,0\n"
+        "\t.globl  %s\n"
+        "\t.align  8\n"
+        "%s:\n",
+
+        ".4byte ","",HEX_0X
+    },
+    {"xlc",
+        ".globl %s{RO}\n"
+        "\t.toc\n"
+        "%s:\n"
+        "\t.csect %s{RO}, 4\n",
+
+        ".long ","",HEX_0X
+    },
+    {"aCC-ia64",
+        "\t.file   \"%s.s\"\n"
+        "\t.type   %s, at object\n"
+        "\t.global %s\n"
+        "\t.secalias .abe$0.rodata, \".rodata\"\n"
+        "\t.section .abe$0.rodata = \"a\", \"progbits\"\n"
+        "\t.align  16\n"
+        "%s::\t",
+
+        "data4 ","",HEX_0X
+    },
+    {"aCC-parisc",
+        "\t.SPACE  $TEXT$\n"
+        "\t.SUBSPA $LIT$\n"
+        "%s\n"
+        "\t.EXPORT %s\n"
+        "\t.ALIGN  16\n",
+
+        ".WORD ","",HEX_0X
+    },
+    { "masm",
+      "\tTITLE %s\n"
+      "; generated by genccode\n"
+      ".386\n"
+      ".model flat\n"
+      "\tPUBLIC _%s\n"
+      "ICUDATA_%s\tSEGMENT READONLY PARA PUBLIC FLAT 'DATA'\n"
+      "\tALIGN 16\n"
+      "_%s\tLABEL DWORD\n",
+      "\tDWORD ","\nICUDATA_%s\tENDS\n\tEND\n",HEX_0H
+    }
+};
+
+static int32_t assemblyHeaderIndex = -1;
+static int32_t hexType = HEX_0X;
+
+U_CAPI UBool U_EXPORT2
+checkAssemblyHeaderName(const char* optAssembly) {
+    int32_t idx;
+    assemblyHeaderIndex = -1;
+    for (idx = 0; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) {
+        if (uprv_strcmp(optAssembly, assemblyHeader[idx].name) == 0) {
+            assemblyHeaderIndex = idx;
+            hexType = assemblyHeader[idx].hexType; /* set the hex type */
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+
+U_CAPI void U_EXPORT2
+printAssemblyHeadersToStdErr(void) {
+    int32_t idx;
+    fprintf(stderr, "%s", assemblyHeader[0].name);
+    for (idx = 1; idx < (int32_t)(sizeof(assemblyHeader)/sizeof(assemblyHeader[0])); idx++) {
+        fprintf(stderr, ", %s", assemblyHeader[idx].name);
+    }
+    fprintf(stderr,
+        ")\n");
+}
+
+U_CAPI void U_EXPORT2
+writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath) {
+    uint32_t column = MAX_COLUMN;
+    char entry[64];
+    uint32_t buffer[1024];
+    char *bufferStr = (char *)buffer;
+    FileStream *in, *out;
+    size_t i, length;
+
+    in=T_FileStream_open(filename, "rb");
+    if(in==NULL) {
+        fprintf(stderr, "genccode: unable to open input file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    getOutFilename(filename, destdir, bufferStr, entry, ".s", optFilename);
+    out=T_FileStream_open(bufferStr, "w");
+    if(out==NULL) {
+        fprintf(stderr, "genccode: unable to open output file %s\n", bufferStr);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    if (outFilePath != NULL) {
+        uprv_strcpy(outFilePath, bufferStr);
+    }
+
+#ifdef WINDOWS_WITH_GNUC
+    /* Need to fix the file seperator character when using MinGW. */
+    swapFileSepChar(outFilePath, U_FILE_SEP_CHAR, '/');
+#endif
+
+    if(optEntryPoint != NULL) {
+        uprv_strcpy(entry, optEntryPoint);
+        uprv_strcat(entry, "_dat");
+    }
+
+    /* turn dashes or dots in the entry name into underscores */
+    length=uprv_strlen(entry);
+    for(i=0; i<length; ++i) {
+        if(entry[i]=='-' || entry[i]=='.') {
+            entry[i]='_';
+        }
+    }
+
+    sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].header,
+        entry, entry, entry, entry,
+        entry, entry, entry, entry);
+    T_FileStream_writeLine(out, bufferStr);
+    T_FileStream_writeLine(out, assemblyHeader[assemblyHeaderIndex].beginLine);
+
+    for(;;) {
+        length=T_FileStream_read(in, buffer, sizeof(buffer));
+        if(length==0) {
+            break;
+        }
+        if (length != sizeof(buffer)) {
+            /* pad with extra 0's when at the end of the file */
+            for(i=0; i < (length % sizeof(uint32_t)); ++i) {
+                buffer[length+i] = 0;
+            }
+        }
+        for(i=0; i<(length/sizeof(buffer[0])); i++) {
+            column = write32(out, buffer[i], column);
+        }
+    }
+
+    T_FileStream_writeLine(out, "\n");
+
+    sprintf(bufferStr, assemblyHeader[assemblyHeaderIndex].footer,
+        entry, entry, entry, entry,
+        entry, entry, entry, entry);
+    T_FileStream_writeLine(out, bufferStr);
+
+    if(T_FileStream_error(in)) {
+        fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    if(T_FileStream_error(out)) {
+        fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    T_FileStream_close(out);
+    T_FileStream_close(in);
+}
+
+U_CAPI void U_EXPORT2
+writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath) {
+    uint32_t column = MAX_COLUMN;
+    char buffer[4096], entry[64];
+    FileStream *in, *out;
+    size_t i, length;
+
+    in=T_FileStream_open(filename, "rb");
+    if(in==NULL) {
+        fprintf(stderr, "genccode: unable to open input file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    if(optName != NULL) { /* prepend  'icudt28_' */
+      strcpy(entry, optName);
+      strcat(entry, "_");
+    } else {
+      entry[0] = 0;
+    }
+
+    getOutFilename(filename, destdir, buffer, entry+uprv_strlen(entry), ".c", optFilename);
+    if (outFilePath != NULL) {
+        uprv_strcpy(outFilePath, buffer);
+    }
+    out=T_FileStream_open(buffer, "w");
+    if(out==NULL) {
+        fprintf(stderr, "genccode: unable to open output file %s\n", buffer);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    /* turn dashes or dots in the entry name into underscores */
+    length=uprv_strlen(entry);
+    for(i=0; i<length; ++i) {
+        if(entry[i]=='-' || entry[i]=='.') {
+            entry[i]='_';
+        }
+    }
+
+#ifdef OS400
+    /*
+    TODO: Fix this once the compiler implements this feature. Keep in sync with udatamem.c
+
+    This is here because this platform can't currently put
+    const data into the read-only pages of an object or
+    shared library (service program). Only strings are allowed in read-only
+    pages, so we use char * strings to store the data.
+
+    In order to prevent the beginning of the data from ever matching the
+    magic numbers we must still use the initial double.
+    [grhoten 4/24/2003]
+    */
+    sprintf(buffer,
+        "#define U_DISABLE_RENAMING 1\n"
+        "#include \"unicode/umachine.h\"\n"
+        "U_CDECL_BEGIN\n"
+        "const struct {\n"
+        "    double bogus;\n"
+        "    const char *bytes; \n"
+        "} %s={ 0.0, \n",
+        entry);
+    T_FileStream_writeLine(out, buffer);
+
+    for(;;) {
+        length=T_FileStream_read(in, buffer, sizeof(buffer));
+        if(length==0) {
+            break;
+        }
+        for(i=0; i<length; ++i) {
+            column = write8str(out, (uint8_t)buffer[i], column);
+        }
+    }
+
+    T_FileStream_writeLine(out, "\"\n};\nU_CDECL_END\n");
+#else
+    /* Function renaming shouldn't be done in data */
+    sprintf(buffer,
+        "#define U_DISABLE_RENAMING 1\n"
+        "#include \"unicode/umachine.h\"\n"
+        "U_CDECL_BEGIN\n"
+        "const struct {\n"
+        "    double bogus;\n"
+        "    uint8_t bytes[%ld]; \n"
+        "} %s={ 0.0, {\n",
+        (long)T_FileStream_size(in), entry);
+    T_FileStream_writeLine(out, buffer);
+
+    for(;;) {
+        length=T_FileStream_read(in, buffer, sizeof(buffer));
+        if(length==0) {
+            break;
+        }
+        for(i=0; i<length; ++i) {
+            column = write8(out, (uint8_t)buffer[i], column);
+        }
+    }
+
+    T_FileStream_writeLine(out, "\n}\n};\nU_CDECL_END\n");
+#endif
+
+    if(T_FileStream_error(in)) {
+        fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    if(T_FileStream_error(out)) {
+        fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    T_FileStream_close(out);
+    T_FileStream_close(in);
+}
+
+static uint32_t
+write32(FileStream *out, uint32_t bitField, uint32_t column) {
+    int32_t i;
+    char bitFieldStr[64]; /* This is more bits than needed for a 32-bit number */
+    char *s = bitFieldStr;
+    uint8_t *ptrIdx = (uint8_t *)&bitField;
+    static const char hexToStr[16] = {
+        '0','1','2','3',
+        '4','5','6','7',
+        '8','9','A','B',
+        'C','D','E','F'
+    };
+
+    /* write the value, possibly with comma and newline */
+    if(column==MAX_COLUMN) {
+        /* first byte */
+        column=1;
+    } else if(column<32) {
+        *(s++)=',';
+        ++column;
+    } else {
+        *(s++)='\n';
+        uprv_strcpy(s, assemblyHeader[assemblyHeaderIndex].beginLine);
+        s+=uprv_strlen(s);
+        column=1;
+    }
+
+    if (bitField < 10) {
+        /* It's a small number. Don't waste the space for 0x */
+        *(s++)=hexToStr[bitField];
+    }
+    else {
+        int seenNonZero = 0; /* This is used to remove leading zeros */
+
+        if(hexType==HEX_0X) {
+         *(s++)='0';
+         *(s++)='x';
+        } else if(hexType==HEX_0H) {
+         *(s++)='0';
+        }
+
+        /* This creates a 32-bit field */
+#if U_IS_BIG_ENDIAN
+        for (i = 0; i < sizeof(uint32_t); i++)
+#else
+        for (i = sizeof(uint32_t)-1; i >= 0 ; i--)
+#endif
+        {
+            uint8_t value = ptrIdx[i];
+            if (value || seenNonZero) {
+                *(s++)=hexToStr[value>>4];
+                *(s++)=hexToStr[value&0xF];
+                seenNonZero = 1;
+            }
+        }
+        if(hexType==HEX_0H) {
+         *(s++)='h';
+        }
+    }
+
+    *(s++)=0;
+    T_FileStream_writeLine(out, bitFieldStr);
+    return column;
+}
+
+static uint32_t
+write8(FileStream *out, uint8_t byte, uint32_t column) {
+    char s[4];
+    int i=0;
+
+    /* convert the byte value to a string */
+    if(byte>=100) {
+        s[i++]=(char)('0'+byte/100);
+        byte%=100;
+    }
+    if(i>0 || byte>=10) {
+        s[i++]=(char)('0'+byte/10);
+        byte%=10;
+    }
+    s[i++]=(char)('0'+byte);
+    s[i]=0;
+
+    /* write the value, possibly with comma and newline */
+    if(column==MAX_COLUMN) {
+        /* first byte */
+        column=1;
+    } else if(column<16) {
+        T_FileStream_writeLine(out, ",");
+        ++column;
+    } else {
+        T_FileStream_writeLine(out, ",\n");
+        column=1;
+    }
+    T_FileStream_writeLine(out, s);
+    return column;
+}
+
+#ifdef OS400
+static uint32_t
+write8str(FileStream *out, uint8_t byte, uint32_t column) {
+    char s[8];
+
+    if (byte > 7)
+        sprintf(s, "\\x%X", byte);
+    else
+        sprintf(s, "\\%X", byte);
+
+    /* write the value, possibly with comma and newline */
+    if(column==MAX_COLUMN) {
+        /* first byte */
+        column=1;
+        T_FileStream_writeLine(out, "\"");
+    } else if(column<24) {
+        ++column;
+    } else {
+        T_FileStream_writeLine(out, "\"\n\"");
+        column=1;
+    }
+    T_FileStream_writeLine(out, s);
+    return column;
+}
+#endif
+
+static void
+getOutFilename(const char *inFilename, const char *destdir, char *outFilename, char *entryName, const char *newSuffix, const char *optFilename) {
+    const char *basename=findBasename(inFilename), *suffix=uprv_strrchr(basename, '.');
+
+    /* copy path */
+    if(destdir!=NULL && *destdir!=0) {
+        do {
+            *outFilename++=*destdir++;
+        } while(*destdir!=0);
+        if(*(outFilename-1)!=U_FILE_SEP_CHAR) {
+            *outFilename++=U_FILE_SEP_CHAR;
+        }
+        inFilename=basename;
+    } else {
+        while(inFilename<basename) {
+            *outFilename++=*inFilename++;
+        }
+    }
+
+    if(suffix==NULL) {
+        /* the filename does not have a suffix */
+        uprv_strcpy(entryName, inFilename);
+        if(optFilename != NULL) {
+          uprv_strcpy(outFilename, optFilename);
+        } else {
+          uprv_strcpy(outFilename, inFilename);
+        }
+        uprv_strcat(outFilename, newSuffix);
+    } else {
+        char *saveOutFilename = outFilename;
+        /* copy basename */
+        while(inFilename<suffix) {
+            if(*inFilename=='-') {
+                /* iSeries cannot have '-' in the .o objects. */
+                *outFilename++=*entryName++='_';
+                inFilename++;
+            }
+            else {
+                *outFilename++=*entryName++=*inFilename++;
+            }
+        }
+
+        /* replace '.' by '_' */
+        *outFilename++=*entryName++='_';
+        ++inFilename;
+
+        /* copy suffix */
+        while(*inFilename!=0) {
+            *outFilename++=*entryName++=*inFilename++;
+        }
+
+        *entryName=0;
+
+        if(optFilename != NULL) {
+            uprv_strcpy(saveOutFilename, optFilename);
+            uprv_strcat(saveOutFilename, newSuffix);
+        } else {
+            /* add ".c" */
+            uprv_strcpy(outFilename, newSuffix);
+        }
+    }
+}
+
+#ifdef CAN_GENERATE_OBJECTS
+static void
+getArchitecture(uint16_t *pCPU, uint16_t *pBits, UBool *pIsBigEndian, const char *optMatchArch) {
+    int64_t buffer[256];
+    const char *filename;
+    FileStream *in;
+    int32_t length;
+
+#ifdef U_ELF
+    /* Pointer to ELF header. Elf32_Ehdr and ELF64_Ehdr are identical for the necessary fields. */
+    const Elf32_Ehdr *pHeader32;
+#elif defined(U_WINDOWS)
+    const IMAGE_FILE_HEADER *pHeader;
+#else
+#   error "Unknown platform for CAN_GENERATE_OBJECTS."
+#endif
+
+    if(optMatchArch != NULL) {
+        filename=optMatchArch;
+    } else {
+        /* set defaults */
+#ifdef U_ELF
+        /* set EM_386 because elf.h does not provide better defaults */
+        *pCPU=EM_386;
+        *pBits=32;
+        *pIsBigEndian=(UBool)(U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB);
+#elif defined(U_WINDOWS)
+/* _M_IA64 should be defined in windows.h */
+#   if defined(_M_IA64)
+        *pCPU=IMAGE_FILE_MACHINE_IA64;
+#   elif defined(_M_AMD64)
+        *pCPU=IMAGE_FILE_MACHINE_AMD64;
+#   else
+        *pCPU=IMAGE_FILE_MACHINE_I386;
+#   endif
+        *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64;
+        *pIsBigEndian=FALSE;
+#else
+#   error "Unknown platform for CAN_GENERATE_OBJECTS."
+#endif
+        return;
+    }
+
+    in=T_FileStream_open(filename, "rb");
+    if(in==NULL) {
+        fprintf(stderr, "genccode: unable to open match-arch file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+    length=T_FileStream_read(in, buffer, sizeof(buffer));
+
+#ifdef U_ELF
+    if(length<sizeof(Elf32_Ehdr)) {
+        fprintf(stderr, "genccode: match-arch file %s is too short\n", filename);
+        exit(U_UNSUPPORTED_ERROR);
+    }
+    pHeader32=(const Elf32_Ehdr *)buffer;
+    if(
+        pHeader32->e_ident[0]!=ELFMAG0 ||
+        pHeader32->e_ident[1]!=ELFMAG1 ||
+        pHeader32->e_ident[2]!=ELFMAG2 ||
+        pHeader32->e_ident[3]!=ELFMAG3 ||
+        pHeader32->e_ident[EI_CLASS]<ELFCLASS32 || pHeader32->e_ident[EI_CLASS]>ELFCLASS64
+    ) {
+        fprintf(stderr, "genccode: match-arch file %s is not an ELF object file, or not supported\n", filename);
+        exit(U_UNSUPPORTED_ERROR);
+    }
+
+    *pBits= pHeader32->e_ident[EI_CLASS]==ELFCLASS32 ? 32 : 64; /* only 32 or 64: see check above */
+#ifdef U_ELF64
+    if(*pBits!=32 && *pBits!=64) {
+        fprintf(stderr, "genccode: currently only supports 32-bit and 64-bit ELF format\n");
+        exit(U_UNSUPPORTED_ERROR);
+    }
+#else
+    if(*pBits!=32) {
+        fprintf(stderr, "genccode: built with elf.h missing 64-bit definitions\n");
+        exit(U_UNSUPPORTED_ERROR);
+    }
+#endif
+
+    *pIsBigEndian=(UBool)(pHeader32->e_ident[EI_DATA]==ELFDATA2MSB);
+    if(*pIsBigEndian!=U_IS_BIG_ENDIAN) {
+        fprintf(stderr, "genccode: currently only same-endianness ELF formats are supported\n");
+        exit(U_UNSUPPORTED_ERROR);
+    }
+    /* TODO: Support byte swapping */
+
+    *pCPU=pHeader32->e_machine;
+#elif defined(U_WINDOWS)
+    if(length<sizeof(IMAGE_FILE_HEADER)) {
+        fprintf(stderr, "genccode: match-arch file %s is too short\n", filename);
+        exit(U_UNSUPPORTED_ERROR);
+    }
+    pHeader=(const IMAGE_FILE_HEADER *)buffer;
+    *pCPU=pHeader->Machine;
+    /*
+     * The number of bits is implicit with the Machine value.
+     * *pBits is ignored in the calling code, so this need not be precise.
+     */
+    *pBits= *pCPU==IMAGE_FILE_MACHINE_I386 ? 32 : 64;
+    /* Windows always runs on little-endian CPUs. */
+    *pIsBigEndian=FALSE;
+#else
+#   error "Unknown platform for CAN_GENERATE_OBJECTS."
+#endif
+
+    T_FileStream_close(in);
+}
+
+U_CAPI void U_EXPORT2
+writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath) {
+    /* common variables */
+    char buffer[4096], entry[40]={ 0 };
+    FileStream *in, *out;
+    const char *newSuffix;
+    int32_t i, entryLength, length, size, entryOffset=0, entryLengthOffset=0;
+
+    uint16_t cpu, bits;
+    UBool makeBigEndian;
+
+    /* platform-specific variables and initialization code */
+#ifdef U_ELF
+    /* 32-bit Elf file header */
+    static Elf32_Ehdr header32={
+        {
+            /* e_ident[] */
+            ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
+            ELFCLASS32,
+            U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB,
+            EV_CURRENT /* EI_VERSION */
+        },
+        ET_REL,
+        EM_386,
+        EV_CURRENT, /* e_version */
+        0, /* e_entry */
+        0, /* e_phoff */
+        (Elf32_Off)sizeof(Elf32_Ehdr), /* e_shoff */
+        0, /* e_flags */
+        (Elf32_Half)sizeof(Elf32_Ehdr), /* eh_size */
+        0, /* e_phentsize */
+        0, /* e_phnum */
+        (Elf32_Half)sizeof(Elf32_Shdr), /* e_shentsize */
+        5, /* e_shnum */
+        2 /* e_shstrndx */
+    };
+
+    /* 32-bit Elf section header table */
+    static Elf32_Shdr sectionHeaders32[5]={
+        { /* SHN_UNDEF */
+            0
+        },
+        { /* .symtab */
+            1, /* sh_name */
+            SHT_SYMTAB,
+            0, /* sh_flags */
+            0, /* sh_addr */
+            (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)), /* sh_offset */
+            (Elf32_Word)(2*sizeof(Elf32_Sym)), /* sh_size */
+            3, /* sh_link=sect hdr index of .strtab */
+            1, /* sh_info=One greater than the symbol table index of the last
+                * local symbol (with STB_LOCAL). */
+            4, /* sh_addralign */
+            (Elf32_Word)(sizeof(Elf32_Sym)) /* sh_entsize */
+        },
+        { /* .shstrtab */
+            9, /* sh_name */
+            SHT_STRTAB,
+            0, /* sh_flags */
+            0, /* sh_addr */
+            (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)), /* sh_offset */
+            40, /* sh_size */
+            0, /* sh_link */
+            0, /* sh_info */
+            1, /* sh_addralign */
+            0 /* sh_entsize */
+        },
+        { /* .strtab */
+            19, /* sh_name */
+            SHT_STRTAB,
+            0, /* sh_flags */
+            0, /* sh_addr */
+            (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40), /* sh_offset */
+            (Elf32_Word)sizeof(entry), /* sh_size */
+            0, /* sh_link */
+            0, /* sh_info */
+            1, /* sh_addralign */
+            0 /* sh_entsize */
+        },
+        { /* .rodata */
+            27, /* sh_name */
+            SHT_PROGBITS,
+            SHF_ALLOC, /* sh_flags */
+            0, /* sh_addr */
+            (Elf32_Off)(sizeof(header32)+sizeof(sectionHeaders32)+2*sizeof(Elf32_Sym)+40+sizeof(entry)), /* sh_offset */
+            0, /* sh_size */
+            0, /* sh_link */
+            0, /* sh_info */
+            16, /* sh_addralign */
+            0 /* sh_entsize */
+        }
+    };
+
+    /* symbol table */
+    static Elf32_Sym symbols32[2]={
+        { /* STN_UNDEF */
+            0
+        },
+        { /* data entry point */
+            1, /* st_name */
+            0, /* st_value */
+            0, /* st_size */
+            ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
+            0, /* st_other */
+            4 /* st_shndx=index of related section table entry */
+        }
+    };
+
+    /* section header string table, with decimal string offsets */
+    static const char sectionStrings[40]=
+        /*  0 */ "\0"
+        /*  1 */ ".symtab\0"
+        /*  9 */ ".shstrtab\0"
+        /* 19 */ ".strtab\0"
+        /* 27 */ ".rodata\0"
+        /* 35 */ "\0\0\0\0"; /* contains terminating NUL */
+        /* 40: padded to multiple of 8 bytes */
+
+    /*
+     * Use entry[] for the string table which will contain only the
+     * entry point name.
+     * entry[0] must be 0 (NUL)
+     * The entry point name can be up to 38 characters long (sizeof(entry)-2).
+     */
+
+    /* 16-align .rodata in the .o file, just in case */
+    static const char padding[16]={ 0 };
+    int32_t paddingSize;
+
+#ifdef U_ELF64
+    /* 64-bit Elf file header */
+    static Elf64_Ehdr header64={
+        {
+            /* e_ident[] */
+            ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
+            ELFCLASS64,
+            U_IS_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB,
+            EV_CURRENT /* EI_VERSION */
+        },
+        ET_REL,
+        EM_X86_64,
+        EV_CURRENT, /* e_version */
+        0, /* e_entry */
+        0, /* e_phoff */
+        (Elf64_Off)sizeof(Elf64_Ehdr), /* e_shoff */
+        0, /* e_flags */
+        (Elf64_Half)sizeof(Elf64_Ehdr), /* eh_size */
+        0, /* e_phentsize */
+        0, /* e_phnum */
+        (Elf64_Half)sizeof(Elf64_Shdr), /* e_shentsize */
+        5, /* e_shnum */
+        2 /* e_shstrndx */
+    };
+
+    /* 64-bit Elf section header table */
+    static Elf64_Shdr sectionHeaders64[5]={
+        { /* SHN_UNDEF */
+            0
+        },
+        { /* .symtab */
+            1, /* sh_name */
+            SHT_SYMTAB,
+            0, /* sh_flags */
+            0, /* sh_addr */
+            (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)), /* sh_offset */
+            (Elf64_Xword)(2*sizeof(Elf64_Sym)), /* sh_size */
+            3, /* sh_link=sect hdr index of .strtab */
+            1, /* sh_info=One greater than the symbol table index of the last
+                * local symbol (with STB_LOCAL). */
+            4, /* sh_addralign */
+            (Elf64_Xword)(sizeof(Elf64_Sym)) /* sh_entsize */
+        },
+        { /* .shstrtab */
+            9, /* sh_name */
+            SHT_STRTAB,
+            0, /* sh_flags */
+            0, /* sh_addr */
+            (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)), /* sh_offset */
+            40, /* sh_size */
+            0, /* sh_link */
+            0, /* sh_info */
+            1, /* sh_addralign */
+            0 /* sh_entsize */
+        },
+        { /* .strtab */
+            19, /* sh_name */
+            SHT_STRTAB,
+            0, /* sh_flags */
+            0, /* sh_addr */
+            (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40), /* sh_offset */
+            (Elf64_Xword)sizeof(entry), /* sh_size */
+            0, /* sh_link */
+            0, /* sh_info */
+            1, /* sh_addralign */
+            0 /* sh_entsize */
+        },
+        { /* .rodata */
+            27, /* sh_name */
+            SHT_PROGBITS,
+            SHF_ALLOC, /* sh_flags */
+            0, /* sh_addr */
+            (Elf64_Off)(sizeof(header64)+sizeof(sectionHeaders64)+2*sizeof(Elf64_Sym)+40+sizeof(entry)), /* sh_offset */
+            0, /* sh_size */
+            0, /* sh_link */
+            0, /* sh_info */
+            16, /* sh_addralign */
+            0 /* sh_entsize */
+        }
+    };
+
+    /*
+     * 64-bit symbol table
+     * careful: different order of items compared with Elf32_sym!
+     */
+    static Elf64_Sym symbols64[2]={
+        { /* STN_UNDEF */
+            0
+        },
+        { /* data entry point */
+            1, /* st_name */
+            ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT),
+            0, /* st_other */
+            4, /* st_shndx=index of related section table entry */
+            0, /* st_value */
+            0 /* st_size */
+        }
+    };
+
+#endif /* U_ELF64 */
+
+    /* entry[] have a leading NUL */
+    entryOffset=1;
+
+    /* in the common code, count entryLength from after the NUL */
+    entryLengthOffset=1;
+
+    newSuffix=".o";
+
+#elif defined(U_WINDOWS)
+    struct {
+        IMAGE_FILE_HEADER fileHeader;
+        IMAGE_SECTION_HEADER sections[2];
+        char linkerOptions[100];
+    } objHeader;
+    IMAGE_SYMBOL symbols[1];
+    struct {
+        DWORD sizeofLongNames;
+        char longNames[100];
+    } symbolNames;
+
+    /*
+     * entry sometimes have a leading '_'
+     * overwritten if entryOffset==0 depending on the target platform
+     * see check for cpu below
+     */
+    entry[0]='_';
+
+    newSuffix=".obj";
+#else
+#   error "Unknown platform for CAN_GENERATE_OBJECTS."
+#endif
+
+    /* deal with options, files and the entry point name */
+    getArchitecture(&cpu, &bits, &makeBigEndian, optMatchArch);
+    printf("genccode: --match-arch cpu=%hu bits=%hu big-endian=%hu\n", cpu, bits, makeBigEndian);
+#ifdef U_WINDOWS
+    if(cpu==IMAGE_FILE_MACHINE_I386) {
+        entryOffset=1;
+    }
+#endif
+
+    in=T_FileStream_open(filename, "rb");
+    if(in==NULL) {
+        fprintf(stderr, "genccode: unable to open input file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+    size=T_FileStream_size(in);
+
+    getOutFilename(filename, destdir, buffer, entry+entryOffset, newSuffix, optFilename);
+    if (outFilePath != NULL) {
+        uprv_strcpy(outFilePath, buffer);
+    }
+
+    if(optEntryPoint != NULL) {
+        uprv_strcpy(entry+entryOffset, optEntryPoint);
+        uprv_strcat(entry+entryOffset, "_dat");
+    }
+    /* turn dashes in the entry name into underscores */
+    entryLength=(int32_t)uprv_strlen(entry+entryLengthOffset);
+    for(i=0; i<entryLength; ++i) {
+        if(entry[entryLengthOffset+i]=='-') {
+            entry[entryLengthOffset+i]='_';
+        }
+    }
+
+    /* open the output file */
+    out=T_FileStream_open(buffer, "wb");
+    if(out==NULL) {
+        fprintf(stderr, "genccode: unable to open output file %s\n", buffer);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+#ifdef U_ELF
+    if(bits==32) {
+        header32.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB;
+        header32.e_machine=cpu;
+
+        /* 16-align .rodata in the .o file, just in case */
+        paddingSize=sectionHeaders32[4].sh_offset & 0xf;
+        if(paddingSize!=0) {
+                paddingSize=0x10-paddingSize;
+                sectionHeaders32[4].sh_offset+=paddingSize;
+        }
+
+        sectionHeaders32[4].sh_size=(Elf32_Word)size;
+
+        symbols32[1].st_size=(Elf32_Word)size;
+
+        /* write .o headers */
+        T_FileStream_write(out, &header32, (int32_t)sizeof(header32));
+        T_FileStream_write(out, sectionHeaders32, (int32_t)sizeof(sectionHeaders32));
+        T_FileStream_write(out, symbols32, (int32_t)sizeof(symbols32));
+    } else /* bits==64 */ {
+#ifdef U_ELF64
+        header64.e_ident[EI_DATA]= makeBigEndian ? ELFDATA2MSB : ELFDATA2LSB;
+        header64.e_machine=cpu;
+
+        /* 16-align .rodata in the .o file, just in case */
+        paddingSize=sectionHeaders64[4].sh_offset & 0xf;
+        if(paddingSize!=0) {
+                paddingSize=0x10-paddingSize;
+                sectionHeaders64[4].sh_offset+=paddingSize;
+        }
+
+        sectionHeaders64[4].sh_size=(Elf64_Xword)size;
+
+        symbols64[1].st_size=(Elf64_Xword)size;
+
+        /* write .o headers */
+        T_FileStream_write(out, &header64, (int32_t)sizeof(header64));
+        T_FileStream_write(out, sectionHeaders64, (int32_t)sizeof(sectionHeaders64));
+        T_FileStream_write(out, symbols64, (int32_t)sizeof(symbols64));
+#endif
+    }
+
+    T_FileStream_write(out, sectionStrings, (int32_t)sizeof(sectionStrings));
+    T_FileStream_write(out, entry, (int32_t)sizeof(entry));
+    if(paddingSize!=0) {
+        T_FileStream_write(out, padding, paddingSize);
+    }
+#elif defined(U_WINDOWS)
+    /* populate the .obj headers */
+    uprv_memset(&objHeader, 0, sizeof(objHeader));
+    uprv_memset(&symbols, 0, sizeof(symbols));
+    uprv_memset(&symbolNames, 0, sizeof(symbolNames));
+
+    /* write the linker export directive */
+    uprv_strcpy(objHeader.linkerOptions, "-export:");
+    length=8;
+    uprv_strcpy(objHeader.linkerOptions+length, entry);
+    length+=entryLength;
+    uprv_strcpy(objHeader.linkerOptions+length, ",data ");
+    length+=6;
+
+    /* set the file header */
+    objHeader.fileHeader.Machine=cpu;
+    objHeader.fileHeader.NumberOfSections=2;
+    objHeader.fileHeader.TimeDateStamp=(DWORD)time(NULL);
+    objHeader.fileHeader.PointerToSymbolTable=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length+size; /* start of symbol table */
+    objHeader.fileHeader.NumberOfSymbols=1;
+
+    /* set the section for the linker options */
+    uprv_strncpy((char *)objHeader.sections[0].Name, ".drectve", 8);
+    objHeader.sections[0].SizeOfRawData=length;
+    objHeader.sections[0].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER;
+    objHeader.sections[0].Characteristics=IMAGE_SCN_LNK_INFO|IMAGE_SCN_LNK_REMOVE|IMAGE_SCN_ALIGN_1BYTES;
+
+    /* set the data section */
+    uprv_strncpy((char *)objHeader.sections[1].Name, ".rdata", 6);
+    objHeader.sections[1].SizeOfRawData=size;
+    objHeader.sections[1].PointerToRawData=IMAGE_SIZEOF_FILE_HEADER+2*IMAGE_SIZEOF_SECTION_HEADER+length;
+    objHeader.sections[1].Characteristics=IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_ALIGN_16BYTES|IMAGE_SCN_MEM_READ;
+
+    /* set the symbol table */
+    if(entryLength<=8) {
+        uprv_strncpy((char *)symbols[0].N.ShortName, entry, entryLength);
+        symbolNames.sizeofLongNames=4;
+    } else {
+        symbols[0].N.Name.Short=0;
+        symbols[0].N.Name.Long=4;
+        symbolNames.sizeofLongNames=4+entryLength+1;
+        uprv_strcpy(symbolNames.longNames, entry);
+    }
+    symbols[0].SectionNumber=2;
+    symbols[0].StorageClass=IMAGE_SYM_CLASS_EXTERNAL;
+
+    /* write the file header and the linker options section */
+    T_FileStream_write(out, &objHeader, objHeader.sections[1].PointerToRawData);
+#else
+#   error "Unknown platform for CAN_GENERATE_OBJECTS."
+#endif
+
+    /* copy the data file into section 2 */
+    for(;;) {
+        length=T_FileStream_read(in, buffer, sizeof(buffer));
+        if(length==0) {
+            break;
+        }
+        T_FileStream_write(out, buffer, (int32_t)length);
+    }
+
+#ifdef U_WINDOWS
+    /* write the symbol table */
+    T_FileStream_write(out, symbols, IMAGE_SIZEOF_SYMBOL);
+    T_FileStream_write(out, &symbolNames, symbolNames.sizeofLongNames);
+#endif
+
+    if(T_FileStream_error(in)) {
+        fprintf(stderr, "genccode: file read error while generating from file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    if(T_FileStream_error(out)) {
+        fprintf(stderr, "genccode: file write error while generating from file %s\n", filename);
+        exit(U_FILE_ACCESS_ERROR);
+    }
+
+    T_FileStream_close(out);
+    T_FileStream_close(in);
+}
+#endif

Modified: trunk/source/tools/toolutil/pkg_genc.h
===================================================================
--- trunk/source/tools/toolutil/pkg_genc.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/toolutil/pkg_genc.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,27 +1,27 @@
-/******************************************************************************
- *   Copyright (C) 2008-2009, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- *******************************************************************************
- */
-
-#ifndef __PKG_GENC_H__
-#define __PKG_GENC_H__
-
-#include "unicode/utypes.h"
-
-U_INTERNAL void U_EXPORT2
-printAssemblyHeadersToStdErr();
-
-U_INTERNAL UBool U_EXPORT2
-checkAssemblyHeaderName(const char* optAssembly);
-
-U_INTERNAL void U_EXPORT2
-writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath);
-
-U_INTERNAL void U_EXPORT2
-writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath);
-
-U_INTERNAL void U_EXPORT2
-writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath);
-
-#endif
+/******************************************************************************
+ *   Copyright (C) 2008-2009, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *******************************************************************************
+ */
+
+#ifndef __PKG_GENC_H__
+#define __PKG_GENC_H__
+
+#include "unicode/utypes.h"
+
+U_INTERNAL void U_EXPORT2
+printAssemblyHeadersToStdErr();
+
+U_INTERNAL UBool U_EXPORT2
+checkAssemblyHeaderName(const char* optAssembly);
+
+U_INTERNAL void U_EXPORT2
+writeCCode(const char *filename, const char *destdir, const char *optName, const char *optFilename, char *outFilePath);
+
+U_INTERNAL void U_EXPORT2
+writeAssemblyCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optFilename, char *outFilePath);
+
+U_INTERNAL void U_EXPORT2
+writeObjectCode(const char *filename, const char *destdir, const char *optEntryPoint, const char *optMatchArch, const char *optFilename, char *outFilePath);
+
+#endif

Modified: trunk/source/tools/toolutil/pkg_gencmn.c
===================================================================
--- trunk/source/tools/toolutil/pkg_gencmn.c	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/toolutil/pkg_gencmn.c	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,546 +1,546 @@
-/******************************************************************************
- *   Copyright (C) 2008, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- *******************************************************************************
- */
-#include "unicode/utypes.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "unicode/utypes.h"
-#include "unicode/putil.h"
-#include "cmemory.h"
-#include "cstring.h"
-#include "filestrm.h"
-#include "toolutil.h"
-#include "unicode/uclean.h"
-#include "unewdata.h"
-#include "putilimp.h"
-#include "pkg_gencmn.h"
-
-#define STRING_STORE_SIZE 100000
-#define MAX_FILE_COUNT 2000
-
-#define COMMON_DATA_NAME U_ICUDATA_NAME
-#define DATA_TYPE "dat"
-
-/* ICU package data file format (.dat files) ------------------------------- ***
-
-Description of the data format after the usual ICU data file header
-(UDataInfo etc.).
-
-Format version 1
-
-A .dat package file contains a simple Table of Contents of item names,
-followed by the items themselves:
-
-1. ToC table
-
-uint32_t count; - number of items
-UDataOffsetTOCEntry entry[count]; - pair of uint32_t values per item:
-    uint32_t nameOffset; - offset of the item name
-    uint32_t dataOffset; - offset of the item data
-both are byte offsets from the beginning of the data
-
-2. item name strings
-
-All item names are stored as char * strings in one block between the ToC table
-and the data items.
-
-3. data items
-
-The data items are stored following the item names block.
-Each data item is 16-aligned.
-The data items are stored in the sorted order of their names.
-
-Therefore, the top of the name strings block is the offset of the first item,
-the length of the last item is the difference between its offset and
-the .dat file length, and the length of all previous items is the difference
-between its offset and the next one.
-
------------------------------------------------------------------------------ */
-
-/* UDataInfo cf. udata.h */
-static const UDataInfo dataInfo={
-    sizeof(UDataInfo),
-    0,
-
-    U_IS_BIG_ENDIAN,
-    U_CHARSET_FAMILY,
-    sizeof(UChar),
-    0,
-
-    {0x43, 0x6d, 0x6e, 0x44},     /* dataFormat="CmnD" */
-    {1, 0, 0, 0},                 /* formatVersion */
-    {3, 0, 0, 0}                  /* dataVersion */
-};
-
-static uint32_t maxSize;
-
-static char stringStore[STRING_STORE_SIZE];
-static uint32_t stringTop=0, basenameTotal=0;
-
-typedef struct {
-    char *pathname, *basename;
-    uint32_t basenameLength, basenameOffset, fileSize, fileOffset;
-} File;
-
-static File files[MAX_FILE_COUNT];
-static uint32_t fileCount=0;
-
-static char *symPrefix = NULL;
-
-/* prototypes --------------------------------------------------------------- */
-
-static void
-addFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose);
-
-static char *
-allocString(uint32_t length);
-
-static int
-compareFiles(const void *file1, const void *file2);
-
-static char *
-pathToFullPath(const char *path, const char *source);
-
-/* map non-tree separator (such as '\') to tree separator ('/') inplace. */
-static void
-fixDirToTreePath(char *s);
-/* -------------------------------------------------------------------------- */
-
-U_CAPI void U_EXPORT2
-createCommonDataFile(const char *destDir, const char *name, const char *entrypointName, const char *type, const char *source, const char *copyRight,
-                     const char *dataFile, uint32_t max_size, UBool sourceTOC, UBool verbose, char *gencmnFileName) {
-    static char buffer[4096];
-    char line[512];
-    char *s;
-    UErrorCode errorCode=U_ZERO_ERROR;
-    uint32_t i, fileOffset, basenameOffset, length, nread;
-    FileStream *in, *file;
-
-    maxSize = max_size;
-
-    if (destDir == NULL) {
-        destDir = u_getDataDirectory();
-    }
-    if (name == NULL) {
-        name = COMMON_DATA_NAME;
-    }
-    if (type == NULL) {
-        type = DATA_TYPE;
-    }
-    if (source == NULL) {
-        source = ".";
-    }
-
-    if (dataFile == NULL) {
-        in = T_FileStream_stdin();
-    } else {
-        in = T_FileStream_open(dataFile, "r");
-        if(in == NULL) {
-            fprintf(stderr, "gencmn: unable to open input file %s\n", dataFile);
-            exit(U_FILE_ACCESS_ERROR);
-        }
-    }
-
-    if (verbose) {
-        if(sourceTOC) {
-            printf("generating %s_%s.c (table of contents source file)\n", name, type);
-        } else {
-            printf("generating %s.%s (common data file with table of contents)\n", name, type);
-        }
-    }
-
-    /* read the list of files and get their lengths */
-    while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) {
-        /* remove trailing newline characters */
-        s=line;
-        while(*s!=0) {
-            if(*s=='\r' || *s=='\n') {
-                *s=0;
-                break;
-            }
-            ++s;
-        }
-
-        /* check for comment */
-
-        if (*line == '#') {
-            continue;
-        }
-
-        /* add the file */
-#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
-        {
-          char *t;
-          while((t = uprv_strchr(line,U_FILE_ALT_SEP_CHAR))) {
-            *t = U_FILE_SEP_CHAR;
-          }
-        }
-#endif
-        addFile(getLongPathname(line), name, source, sourceTOC, verbose);
-    }
-
-    if(in!=T_FileStream_stdin()) {
-        T_FileStream_close(in);
-    }
-
-    if(fileCount==0) {
-        fprintf(stderr, "gencmn: no files listed in %s\n", dataFile == NULL ? "<stdin>" : dataFile);
-        return;
-    }
-
-    /* sort the files by basename */
-    qsort(files, fileCount, sizeof(File), compareFiles);
-
-    if(!sourceTOC) {
-        UNewDataMemory *out;
-
-        /* determine the offsets of all basenames and files in this common one */
-        basenameOffset=4+8*fileCount;
-        fileOffset=(basenameOffset+(basenameTotal+15))&~0xf;
-        for(i=0; i<fileCount; ++i) {
-            files[i].fileOffset=fileOffset;
-            fileOffset+=(files[i].fileSize+15)&~0xf;
-            files[i].basenameOffset=basenameOffset;
-            basenameOffset+=files[i].basenameLength;
-        }
-
-        /* create the output file */
-        out=udata_create(destDir, type, name,
-                         &dataInfo,
-                         copyRight == NULL ? U_COPYRIGHT_STRING : copyRight,
-                         &errorCode);
-        if(U_FAILURE(errorCode)) {
-            fprintf(stderr, "gencmn: udata_create(-d %s -n %s -t %s) failed - %s\n",
-                destDir, name, type,
-                u_errorName(errorCode));
-            exit(errorCode);
-        }
-
-        /* write the table of contents */
-        udata_write32(out, fileCount);
-        for(i=0; i<fileCount; ++i) {
-            udata_write32(out, files[i].basenameOffset);
-            udata_write32(out, files[i].fileOffset);
-        }
-
-        /* write the basenames */
-        for(i=0; i<fileCount; ++i) {
-            udata_writeString(out, files[i].basename, files[i].basenameLength);
-        }
-        length=4+8*fileCount+basenameTotal;
-
-        /* copy the files */
-        for(i=0; i<fileCount; ++i) {
-            /* pad to 16-align the next file */
-            length&=0xf;
-            if(length!=0) {
-                udata_writePadding(out, 16-length);
-            }
-
-            if (verbose) {
-                printf("adding %s (%ld byte%s)\n", files[i].pathname, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s");
-            }
-
-            /* copy the next file */
-            file=T_FileStream_open(files[i].pathname, "rb");
-            if(file==NULL) {
-                fprintf(stderr, "gencmn: unable to open listed file %s\n", files[i].pathname);
-                exit(U_FILE_ACCESS_ERROR);
-            }
-            for(nread = 0;;) {
-                length=T_FileStream_read(file, buffer, sizeof(buffer));
-                if(length <= 0) {
-                    break;
-                }
-                nread += length;
-                udata_writeBlock(out, buffer, length);
-            }
-            T_FileStream_close(file);
-            length=files[i].fileSize;
-
-            if (nread != files[i].fileSize) {
-              fprintf(stderr, "gencmn: unable to read %s properly (got %ld/%ld byte%s)\n", files[i].pathname,  (long)nread, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s");
-                exit(U_FILE_ACCESS_ERROR);
-            }
-        }
-
-        /* pad to 16-align the last file (cleaner, avoids growing .dat files in icuswap) */
-        length&=0xf;
-        if(length!=0) {
-            udata_writePadding(out, 16-length);
-        }
-
-        /* finish */
-        udata_finish(out, &errorCode);
-        if(U_FAILURE(errorCode)) {
-            fprintf(stderr, "gencmn: udata_finish() failed - %s\n", u_errorName(errorCode));
-            exit(errorCode);
-        }
-    } else {
-        /* write a .c source file with the table of contents */
-        char *filename;
-        FileStream *out;
-
-        /* create the output filename */
-        filename=s=buffer;
-        uprv_strcpy(filename, destDir);
-        s=filename+uprv_strlen(filename);
-        if(s>filename && *(s-1)!=U_FILE_SEP_CHAR) {
-            *s++=U_FILE_SEP_CHAR;
-        }
-        uprv_strcpy(s, name);
-        if(*(type)!=0) {
-            s+=uprv_strlen(s);
-            *s++='_';
-            uprv_strcpy(s, type);
-        }
-        s+=uprv_strlen(s);
-        uprv_strcpy(s, ".c");
-
-        /* open the output file */
-        out=T_FileStream_open(filename, "w");
-        if (gencmnFileName != NULL) {
-            uprv_strcpy(gencmnFileName, filename);
-        }
-        if(out==NULL) {
-            fprintf(stderr, "gencmn: unable to open .c output file %s\n", filename);
-            exit(U_FILE_ACCESS_ERROR);
-        }
-
-        /* write the source file */
-        sprintf(buffer,
-            "/*\n"
-            " * ICU common data table of contents for %s.%s ,\n"
-            " * Automatically generated by icu/source/tools/gencmn/gencmn .\n"
-            " */\n\n"
-            "#include \"unicode/utypes.h\"\n"
-            "#include \"unicode/udata.h\"\n"
-            "\n"
-            "/* external symbol declarations for data */\n",
-            name, type);
-        T_FileStream_writeLine(out, buffer);
-
-        sprintf(buffer, "extern const char\n    %s%s[]", symPrefix?symPrefix:"", files[0].pathname);
-        T_FileStream_writeLine(out, buffer);
-        for(i=1; i<fileCount; ++i) {
-            sprintf(buffer, ",\n    %s%s[]", symPrefix?symPrefix:"", files[i].pathname);
-            T_FileStream_writeLine(out, buffer);
-        }
-        T_FileStream_writeLine(out, ";\n\n");
-
-        sprintf(
-            buffer,
-            "U_EXPORT struct {\n"
-            "    uint16_t headerSize;\n"
-            "    uint8_t magic1, magic2;\n"
-            "    UDataInfo info;\n"
-            "    char padding[%lu];\n"
-            "    uint32_t count, reserved;\n"
-            "    struct {\n"
-            "        const char *name;\n"
-            "        const void *data;\n"
-            "    } toc[%lu];\n"
-            "} U_EXPORT2 %s_dat = {\n"
-            "    32, 0xda, 0x27, {\n"
-            "        %lu, 0,\n"
-            "        %u, %u, %u, 0,\n"
-            "        {0x54, 0x6f, 0x43, 0x50},\n"
-            "        {1, 0, 0, 0},\n"
-            "        {0, 0, 0, 0}\n"
-            "    },\n"
-            "    \"\", %lu, 0, {\n",
-            (unsigned long)32-4-sizeof(UDataInfo),
-            (unsigned long)fileCount,
-            entrypointName,
-            (unsigned long)sizeof(UDataInfo),
-            U_IS_BIG_ENDIAN,
-            U_CHARSET_FAMILY,
-            U_SIZEOF_UCHAR,
-            (unsigned long)fileCount
-        );
-        T_FileStream_writeLine(out, buffer);
-
-        sprintf(buffer, "        { \"%s\", %s%s }", files[0].basename, symPrefix?symPrefix:"", files[0].pathname);
-        T_FileStream_writeLine(out, buffer);
-        for(i=1; i<fileCount; ++i) {
-            sprintf(buffer, ",\n        { \"%s\", %s%s }", files[i].basename, symPrefix?symPrefix:"", files[i].pathname);
-            T_FileStream_writeLine(out, buffer);
-        }
-
-        T_FileStream_writeLine(out, "\n    }\n};\n");
-        T_FileStream_close(out);
-
-        uprv_free(symPrefix);
-    }
-}
-
-static void
-addFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose) {
-    char *s;
-    uint32_t length;
-    char *fullPath = NULL;
-
-    if(fileCount==MAX_FILE_COUNT) {
-        fprintf(stderr, "gencmn: too many files, maximum is %d\n", MAX_FILE_COUNT);
-        exit(U_BUFFER_OVERFLOW_ERROR);
-    }
-
-    if(!sourceTOC) {
-        FileStream *file;
-
-        if(uprv_pathIsAbsolute(filename)) {
-            fprintf(stderr, "gencmn: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, filename);
-            exit(U_ILLEGAL_ARGUMENT_ERROR);
-        }
-        fullPath = pathToFullPath(filename, source);
-
-        /* store the pathname */
-        length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
-        s=allocString(length);
-        uprv_strcpy(s, name);
-        uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
-        uprv_strcat(s, filename);
-
-        /* get the basename */
-        fixDirToTreePath(s);
-        files[fileCount].basename=s;
-        files[fileCount].basenameLength=length;
-
-        files[fileCount].pathname=fullPath;
-
-        basenameTotal+=length;
-
-        /* try to open the file */
-        file=T_FileStream_open(fullPath, "rb");
-        if(file==NULL) {
-            fprintf(stderr, "gencmn: unable to open listed file %s\n", fullPath);
-            exit(U_FILE_ACCESS_ERROR);
-        }
-
-        /* get the file length */
-        length=T_FileStream_size(file);
-        if(T_FileStream_error(file) || length<=20) {
-            fprintf(stderr, "gencmn: unable to get length of listed file %s\n", fullPath);
-            exit(U_FILE_ACCESS_ERROR);
-        }
-
-        T_FileStream_close(file);
-
-        /* do not add files that are longer than maxSize */
-        if(maxSize && length>maxSize) {
-            if (verbose) {
-                printf("%s ignored (size %ld > %ld)\n", fullPath, (long)length, (long)maxSize);
-            }
-            return;
-        }
-        files[fileCount].fileSize=length;
-    } else {
-        char *t;
-
-        /* get and store the basename */
-        /* need to include the package name */
-        length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
-        s=allocString(length);
-        uprv_strcpy(s, name);
-        uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
-        uprv_strcat(s, filename);
-        fixDirToTreePath(s);
-        files[fileCount].basename=s;
-
-
-        /* turn the basename into an entry point name and store in the pathname field */
-        t=files[fileCount].pathname=allocString(length);
-        while(--length>0) {
-            if(*s=='.' || *s=='-' || *s=='/') {
-                *t='_';
-            } else {
-                *t=*s;
-            }
-            ++s;
-            ++t;
-        }
-        *t=0;
-    }
-    ++fileCount;
-}
-
-static char *
-allocString(uint32_t length) {
-    uint32_t top=stringTop+length;
-    char *p;
-
-    if(top>STRING_STORE_SIZE) {
-        fprintf(stderr, "gencmn: out of memory\n");
-        exit(U_MEMORY_ALLOCATION_ERROR);
-    }
-    p=stringStore+stringTop;
-    stringTop=top;
-    return p;
-}
-
-static char *
-pathToFullPath(const char *path, const char *source) {
-    int32_t length;
-    int32_t newLength;
-    char *fullPath;
-    int32_t n;
-
-    length = (uint32_t)(uprv_strlen(path) + 1);
-    newLength = (length + 1 + (int32_t)uprv_strlen(source));
-    fullPath = uprv_malloc(newLength);
-    if(source != NULL) {
-        uprv_strcpy(fullPath, source);
-        uprv_strcat(fullPath, U_FILE_SEP_STRING);
-    } else {
-        fullPath[0] = 0;
-    }
-    n = (int32_t)uprv_strlen(fullPath);
-    uprv_strcat(fullPath, path);
-
-#if (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
-#if (U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR)
-    /* replace tree separator (such as '/') with file sep char (such as ':' or '\\') */
-    for(;fullPath[n];n++) {
-        if(fullPath[n] == U_FILE_ALT_SEP_CHAR) {
-            fullPath[n] = U_FILE_SEP_CHAR;
-        }
-    }
-#endif
-#endif
-#if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
-    /* replace tree separator (such as '/') with file sep char (such as ':' or '\\') */
-    for(;fullPath[n];n++) {
-        if(fullPath[n] == U_TREE_ENTRY_SEP_CHAR) {
-            fullPath[n] = U_FILE_SEP_CHAR;
-        }
-    }
-#endif
-    return fullPath;
-}
-
-static int
-compareFiles(const void *file1, const void *file2) {
-    /* sort by basename */
-    return uprv_strcmp(((File *)file1)->basename, ((File *)file2)->basename);
-}
-
-static void
-fixDirToTreePath(char *s)
-{
-#if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR) || ((U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR) && (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR))
-    char *t;
-#endif
-#if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
-    for(t=s;t=uprv_strchr(t,U_FILE_SEP_CHAR);) {
-        *t = U_TREE_ENTRY_SEP_CHAR;
-    }
-#endif
-#if (U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR) && (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
-    for(t=s;t=uprv_strchr(t,U_FILE_ALT_SEP_CHAR);) {
-        *t = U_TREE_ENTRY_SEP_CHAR;
-    }
-#endif
-}
+/******************************************************************************
+ *   Copyright (C) 2008, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *******************************************************************************
+ */
+#include "unicode/utypes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "unicode/utypes.h"
+#include "unicode/putil.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "filestrm.h"
+#include "toolutil.h"
+#include "unicode/uclean.h"
+#include "unewdata.h"
+#include "putilimp.h"
+#include "pkg_gencmn.h"
+
+#define STRING_STORE_SIZE 100000
+#define MAX_FILE_COUNT 2000
+
+#define COMMON_DATA_NAME U_ICUDATA_NAME
+#define DATA_TYPE "dat"
+
+/* ICU package data file format (.dat files) ------------------------------- ***
+
+Description of the data format after the usual ICU data file header
+(UDataInfo etc.).
+
+Format version 1
+
+A .dat package file contains a simple Table of Contents of item names,
+followed by the items themselves:
+
+1. ToC table
+
+uint32_t count; - number of items
+UDataOffsetTOCEntry entry[count]; - pair of uint32_t values per item:
+    uint32_t nameOffset; - offset of the item name
+    uint32_t dataOffset; - offset of the item data
+both are byte offsets from the beginning of the data
+
+2. item name strings
+
+All item names are stored as char * strings in one block between the ToC table
+and the data items.
+
+3. data items
+
+The data items are stored following the item names block.
+Each data item is 16-aligned.
+The data items are stored in the sorted order of their names.
+
+Therefore, the top of the name strings block is the offset of the first item,
+the length of the last item is the difference between its offset and
+the .dat file length, and the length of all previous items is the difference
+between its offset and the next one.
+
+----------------------------------------------------------------------------- */
+
+/* UDataInfo cf. udata.h */
+static const UDataInfo dataInfo={
+    sizeof(UDataInfo),
+    0,
+
+    U_IS_BIG_ENDIAN,
+    U_CHARSET_FAMILY,
+    sizeof(UChar),
+    0,
+
+    {0x43, 0x6d, 0x6e, 0x44},     /* dataFormat="CmnD" */
+    {1, 0, 0, 0},                 /* formatVersion */
+    {3, 0, 0, 0}                  /* dataVersion */
+};
+
+static uint32_t maxSize;
+
+static char stringStore[STRING_STORE_SIZE];
+static uint32_t stringTop=0, basenameTotal=0;
+
+typedef struct {
+    char *pathname, *basename;
+    uint32_t basenameLength, basenameOffset, fileSize, fileOffset;
+} File;
+
+static File files[MAX_FILE_COUNT];
+static uint32_t fileCount=0;
+
+static char *symPrefix = NULL;
+
+/* prototypes --------------------------------------------------------------- */
+
+static void
+addFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose);
+
+static char *
+allocString(uint32_t length);
+
+static int
+compareFiles(const void *file1, const void *file2);
+
+static char *
+pathToFullPath(const char *path, const char *source);
+
+/* map non-tree separator (such as '\') to tree separator ('/') inplace. */
+static void
+fixDirToTreePath(char *s);
+/* -------------------------------------------------------------------------- */
+
+U_CAPI void U_EXPORT2
+createCommonDataFile(const char *destDir, const char *name, const char *entrypointName, const char *type, const char *source, const char *copyRight,
+                     const char *dataFile, uint32_t max_size, UBool sourceTOC, UBool verbose, char *gencmnFileName) {
+    static char buffer[4096];
+    char line[512];
+    char *s;
+    UErrorCode errorCode=U_ZERO_ERROR;
+    uint32_t i, fileOffset, basenameOffset, length, nread;
+    FileStream *in, *file;
+
+    maxSize = max_size;
+
+    if (destDir == NULL) {
+        destDir = u_getDataDirectory();
+    }
+    if (name == NULL) {
+        name = COMMON_DATA_NAME;
+    }
+    if (type == NULL) {
+        type = DATA_TYPE;
+    }
+    if (source == NULL) {
+        source = ".";
+    }
+
+    if (dataFile == NULL) {
+        in = T_FileStream_stdin();
+    } else {
+        in = T_FileStream_open(dataFile, "r");
+        if(in == NULL) {
+            fprintf(stderr, "gencmn: unable to open input file %s\n", dataFile);
+            exit(U_FILE_ACCESS_ERROR);
+        }
+    }
+
+    if (verbose) {
+        if(sourceTOC) {
+            printf("generating %s_%s.c (table of contents source file)\n", name, type);
+        } else {
+            printf("generating %s.%s (common data file with table of contents)\n", name, type);
+        }
+    }
+
+    /* read the list of files and get their lengths */
+    while(T_FileStream_readLine(in, line, sizeof(line))!=NULL) {
+        /* remove trailing newline characters */
+        s=line;
+        while(*s!=0) {
+            if(*s=='\r' || *s=='\n') {
+                *s=0;
+                break;
+            }
+            ++s;
+        }
+
+        /* check for comment */
+
+        if (*line == '#') {
+            continue;
+        }
+
+        /* add the file */
+#if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
+        {
+          char *t;
+          while((t = uprv_strchr(line,U_FILE_ALT_SEP_CHAR))) {
+            *t = U_FILE_SEP_CHAR;
+          }
+        }
+#endif
+        addFile(getLongPathname(line), name, source, sourceTOC, verbose);
+    }
+
+    if(in!=T_FileStream_stdin()) {
+        T_FileStream_close(in);
+    }
+
+    if(fileCount==0) {
+        fprintf(stderr, "gencmn: no files listed in %s\n", dataFile == NULL ? "<stdin>" : dataFile);
+        return;
+    }
+
+    /* sort the files by basename */
+    qsort(files, fileCount, sizeof(File), compareFiles);
+
+    if(!sourceTOC) {
+        UNewDataMemory *out;
+
+        /* determine the offsets of all basenames and files in this common one */
+        basenameOffset=4+8*fileCount;
+        fileOffset=(basenameOffset+(basenameTotal+15))&~0xf;
+        for(i=0; i<fileCount; ++i) {
+            files[i].fileOffset=fileOffset;
+            fileOffset+=(files[i].fileSize+15)&~0xf;
+            files[i].basenameOffset=basenameOffset;
+            basenameOffset+=files[i].basenameLength;
+        }
+
+        /* create the output file */
+        out=udata_create(destDir, type, name,
+                         &dataInfo,
+                         copyRight == NULL ? U_COPYRIGHT_STRING : copyRight,
+                         &errorCode);
+        if(U_FAILURE(errorCode)) {
+            fprintf(stderr, "gencmn: udata_create(-d %s -n %s -t %s) failed - %s\n",
+                destDir, name, type,
+                u_errorName(errorCode));
+            exit(errorCode);
+        }
+
+        /* write the table of contents */
+        udata_write32(out, fileCount);
+        for(i=0; i<fileCount; ++i) {
+            udata_write32(out, files[i].basenameOffset);
+            udata_write32(out, files[i].fileOffset);
+        }
+
+        /* write the basenames */
+        for(i=0; i<fileCount; ++i) {
+            udata_writeString(out, files[i].basename, files[i].basenameLength);
+        }
+        length=4+8*fileCount+basenameTotal;
+
+        /* copy the files */
+        for(i=0; i<fileCount; ++i) {
+            /* pad to 16-align the next file */
+            length&=0xf;
+            if(length!=0) {
+                udata_writePadding(out, 16-length);
+            }
+
+            if (verbose) {
+                printf("adding %s (%ld byte%s)\n", files[i].pathname, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s");
+            }
+
+            /* copy the next file */
+            file=T_FileStream_open(files[i].pathname, "rb");
+            if(file==NULL) {
+                fprintf(stderr, "gencmn: unable to open listed file %s\n", files[i].pathname);
+                exit(U_FILE_ACCESS_ERROR);
+            }
+            for(nread = 0;;) {
+                length=T_FileStream_read(file, buffer, sizeof(buffer));
+                if(length <= 0) {
+                    break;
+                }
+                nread += length;
+                udata_writeBlock(out, buffer, length);
+            }
+            T_FileStream_close(file);
+            length=files[i].fileSize;
+
+            if (nread != files[i].fileSize) {
+              fprintf(stderr, "gencmn: unable to read %s properly (got %ld/%ld byte%s)\n", files[i].pathname,  (long)nread, (long)files[i].fileSize, files[i].fileSize == 1 ? "" : "s");
+                exit(U_FILE_ACCESS_ERROR);
+            }
+        }
+
+        /* pad to 16-align the last file (cleaner, avoids growing .dat files in icuswap) */
+        length&=0xf;
+        if(length!=0) {
+            udata_writePadding(out, 16-length);
+        }
+
+        /* finish */
+        udata_finish(out, &errorCode);
+        if(U_FAILURE(errorCode)) {
+            fprintf(stderr, "gencmn: udata_finish() failed - %s\n", u_errorName(errorCode));
+            exit(errorCode);
+        }
+    } else {
+        /* write a .c source file with the table of contents */
+        char *filename;
+        FileStream *out;
+
+        /* create the output filename */
+        filename=s=buffer;
+        uprv_strcpy(filename, destDir);
+        s=filename+uprv_strlen(filename);
+        if(s>filename && *(s-1)!=U_FILE_SEP_CHAR) {
+            *s++=U_FILE_SEP_CHAR;
+        }
+        uprv_strcpy(s, name);
+        if(*(type)!=0) {
+            s+=uprv_strlen(s);
+            *s++='_';
+            uprv_strcpy(s, type);
+        }
+        s+=uprv_strlen(s);
+        uprv_strcpy(s, ".c");
+
+        /* open the output file */
+        out=T_FileStream_open(filename, "w");
+        if (gencmnFileName != NULL) {
+            uprv_strcpy(gencmnFileName, filename);
+        }
+        if(out==NULL) {
+            fprintf(stderr, "gencmn: unable to open .c output file %s\n", filename);
+            exit(U_FILE_ACCESS_ERROR);
+        }
+
+        /* write the source file */
+        sprintf(buffer,
+            "/*\n"
+            " * ICU common data table of contents for %s.%s ,\n"
+            " * Automatically generated by icu/source/tools/gencmn/gencmn .\n"
+            " */\n\n"
+            "#include \"unicode/utypes.h\"\n"
+            "#include \"unicode/udata.h\"\n"
+            "\n"
+            "/* external symbol declarations for data */\n",
+            name, type);
+        T_FileStream_writeLine(out, buffer);
+
+        sprintf(buffer, "extern const char\n    %s%s[]", symPrefix?symPrefix:"", files[0].pathname);
+        T_FileStream_writeLine(out, buffer);
+        for(i=1; i<fileCount; ++i) {
+            sprintf(buffer, ",\n    %s%s[]", symPrefix?symPrefix:"", files[i].pathname);
+            T_FileStream_writeLine(out, buffer);
+        }
+        T_FileStream_writeLine(out, ";\n\n");
+
+        sprintf(
+            buffer,
+            "U_EXPORT struct {\n"
+            "    uint16_t headerSize;\n"
+            "    uint8_t magic1, magic2;\n"
+            "    UDataInfo info;\n"
+            "    char padding[%lu];\n"
+            "    uint32_t count, reserved;\n"
+            "    struct {\n"
+            "        const char *name;\n"
+            "        const void *data;\n"
+            "    } toc[%lu];\n"
+            "} U_EXPORT2 %s_dat = {\n"
+            "    32, 0xda, 0x27, {\n"
+            "        %lu, 0,\n"
+            "        %u, %u, %u, 0,\n"
+            "        {0x54, 0x6f, 0x43, 0x50},\n"
+            "        {1, 0, 0, 0},\n"
+            "        {0, 0, 0, 0}\n"
+            "    },\n"
+            "    \"\", %lu, 0, {\n",
+            (unsigned long)32-4-sizeof(UDataInfo),
+            (unsigned long)fileCount,
+            entrypointName,
+            (unsigned long)sizeof(UDataInfo),
+            U_IS_BIG_ENDIAN,
+            U_CHARSET_FAMILY,
+            U_SIZEOF_UCHAR,
+            (unsigned long)fileCount
+        );
+        T_FileStream_writeLine(out, buffer);
+
+        sprintf(buffer, "        { \"%s\", %s%s }", files[0].basename, symPrefix?symPrefix:"", files[0].pathname);
+        T_FileStream_writeLine(out, buffer);
+        for(i=1; i<fileCount; ++i) {
+            sprintf(buffer, ",\n        { \"%s\", %s%s }", files[i].basename, symPrefix?symPrefix:"", files[i].pathname);
+            T_FileStream_writeLine(out, buffer);
+        }
+
+        T_FileStream_writeLine(out, "\n    }\n};\n");
+        T_FileStream_close(out);
+
+        uprv_free(symPrefix);
+    }
+}
+
+static void
+addFile(const char *filename, const char *name, const char *source, UBool sourceTOC, UBool verbose) {
+    char *s;
+    uint32_t length;
+    char *fullPath = NULL;
+
+    if(fileCount==MAX_FILE_COUNT) {
+        fprintf(stderr, "gencmn: too many files, maximum is %d\n", MAX_FILE_COUNT);
+        exit(U_BUFFER_OVERFLOW_ERROR);
+    }
+
+    if(!sourceTOC) {
+        FileStream *file;
+
+        if(uprv_pathIsAbsolute(filename)) {
+            fprintf(stderr, "gencmn: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, filename);
+            exit(U_ILLEGAL_ARGUMENT_ERROR);
+        }
+        fullPath = pathToFullPath(filename, source);
+
+        /* store the pathname */
+        length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
+        s=allocString(length);
+        uprv_strcpy(s, name);
+        uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
+        uprv_strcat(s, filename);
+
+        /* get the basename */
+        fixDirToTreePath(s);
+        files[fileCount].basename=s;
+        files[fileCount].basenameLength=length;
+
+        files[fileCount].pathname=fullPath;
+
+        basenameTotal+=length;
+
+        /* try to open the file */
+        file=T_FileStream_open(fullPath, "rb");
+        if(file==NULL) {
+            fprintf(stderr, "gencmn: unable to open listed file %s\n", fullPath);
+            exit(U_FILE_ACCESS_ERROR);
+        }
+
+        /* get the file length */
+        length=T_FileStream_size(file);
+        if(T_FileStream_error(file) || length<=20) {
+            fprintf(stderr, "gencmn: unable to get length of listed file %s\n", fullPath);
+            exit(U_FILE_ACCESS_ERROR);
+        }
+
+        T_FileStream_close(file);
+
+        /* do not add files that are longer than maxSize */
+        if(maxSize && length>maxSize) {
+            if (verbose) {
+                printf("%s ignored (size %ld > %ld)\n", fullPath, (long)length, (long)maxSize);
+            }
+            return;
+        }
+        files[fileCount].fileSize=length;
+    } else {
+        char *t;
+
+        /* get and store the basename */
+        /* need to include the package name */
+        length = (uint32_t)(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
+        s=allocString(length);
+        uprv_strcpy(s, name);
+        uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
+        uprv_strcat(s, filename);
+        fixDirToTreePath(s);
+        files[fileCount].basename=s;
+
+
+        /* turn the basename into an entry point name and store in the pathname field */
+        t=files[fileCount].pathname=allocString(length);
+        while(--length>0) {
+            if(*s=='.' || *s=='-' || *s=='/') {
+                *t='_';
+            } else {
+                *t=*s;
+            }
+            ++s;
+            ++t;
+        }
+        *t=0;
+    }
+    ++fileCount;
+}
+
+static char *
+allocString(uint32_t length) {
+    uint32_t top=stringTop+length;
+    char *p;
+
+    if(top>STRING_STORE_SIZE) {
+        fprintf(stderr, "gencmn: out of memory\n");
+        exit(U_MEMORY_ALLOCATION_ERROR);
+    }
+    p=stringStore+stringTop;
+    stringTop=top;
+    return p;
+}
+
+static char *
+pathToFullPath(const char *path, const char *source) {
+    int32_t length;
+    int32_t newLength;
+    char *fullPath;
+    int32_t n;
+
+    length = (uint32_t)(uprv_strlen(path) + 1);
+    newLength = (length + 1 + (int32_t)uprv_strlen(source));
+    fullPath = uprv_malloc(newLength);
+    if(source != NULL) {
+        uprv_strcpy(fullPath, source);
+        uprv_strcat(fullPath, U_FILE_SEP_STRING);
+    } else {
+        fullPath[0] = 0;
+    }
+    n = (int32_t)uprv_strlen(fullPath);
+    uprv_strcat(fullPath, path);
+
+#if (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
+#if (U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR)
+    /* replace tree separator (such as '/') with file sep char (such as ':' or '\\') */
+    for(;fullPath[n];n++) {
+        if(fullPath[n] == U_FILE_ALT_SEP_CHAR) {
+            fullPath[n] = U_FILE_SEP_CHAR;
+        }
+    }
+#endif
+#endif
+#if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
+    /* replace tree separator (such as '/') with file sep char (such as ':' or '\\') */
+    for(;fullPath[n];n++) {
+        if(fullPath[n] == U_TREE_ENTRY_SEP_CHAR) {
+            fullPath[n] = U_FILE_SEP_CHAR;
+        }
+    }
+#endif
+    return fullPath;
+}
+
+static int
+compareFiles(const void *file1, const void *file2) {
+    /* sort by basename */
+    return uprv_strcmp(((File *)file1)->basename, ((File *)file2)->basename);
+}
+
+static void
+fixDirToTreePath(char *s)
+{
+#if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR) || ((U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR) && (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR))
+    char *t;
+#endif
+#if (U_FILE_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
+    for(t=s;t=uprv_strchr(t,U_FILE_SEP_CHAR);) {
+        *t = U_TREE_ENTRY_SEP_CHAR;
+    }
+#endif
+#if (U_FILE_ALT_SEP_CHAR != U_FILE_SEP_CHAR) && (U_FILE_ALT_SEP_CHAR != U_TREE_ENTRY_SEP_CHAR)
+    for(t=s;t=uprv_strchr(t,U_FILE_ALT_SEP_CHAR);) {
+        *t = U_TREE_ENTRY_SEP_CHAR;
+    }
+#endif
+}

Modified: trunk/source/tools/toolutil/pkg_gencmn.h
===================================================================
--- trunk/source/tools/toolutil/pkg_gencmn.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/toolutil/pkg_gencmn.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,16 +1,16 @@
-/******************************************************************************
- *   Copyright (C) 2008, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- *******************************************************************************
- */
-
-#ifndef __PKG_GENCMN_H__
-#define __PKG_GENCMN_H__
-
-#include "unicode/utypes.h"
-
-U_CAPI void U_EXPORT2
-createCommonDataFile(const char *destDir, const char *name, const char *entrypointName, const char *type, const char *source, const char *copyRight,
-                     const char *dataFile, uint32_t max_size, UBool sourceTOC, UBool verbose, char *gencmnFileName);
-
-#endif
+/******************************************************************************
+ *   Copyright (C) 2008, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *******************************************************************************
+ */
+
+#ifndef __PKG_GENCMN_H__
+#define __PKG_GENCMN_H__
+
+#include "unicode/utypes.h"
+
+U_CAPI void U_EXPORT2
+createCommonDataFile(const char *destDir, const char *name, const char *entrypointName, const char *type, const char *source, const char *copyRight,
+                     const char *dataFile, uint32_t max_size, UBool sourceTOC, UBool verbose, char *gencmnFileName);
+
+#endif

Modified: trunk/source/tools/toolutil/pkg_icu.cpp
===================================================================
--- trunk/source/tools/toolutil/pkg_icu.cpp	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/toolutil/pkg_icu.cpp	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,178 +1,178 @@
-/******************************************************************************
- *   Copyright (C) 2008-2009, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- *******************************************************************************
- */
-#include "unicode/utypes.h"
-#include "unicode/putil.h"
-#include "cstring.h"
-#include "toolutil.h"
-#include "uoptions.h"
-#include "uparse.h"
-#include "package.h"
-#include "pkg_icu.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
-
-// read a file list -------------------------------------------------------- ***
-
-static const struct {
-    const char *suffix;
-    int32_t length;
-} listFileSuffixes[]={
-    { ".txt", 4 },
-    { ".lst", 4 },
-    { ".tmp", 4 }
-};
-
-/* check for multiple text file suffixes to see if this list name is a text file name */
-static UBool
-isListTextFile(const char *listname) {
-    const char *listNameEnd=strchr(listname, 0);
-    const char *suffix;
-    int32_t i, length;
-    for(i=0; i<LENGTHOF(listFileSuffixes); ++i) {
-        suffix=listFileSuffixes[i].suffix;
-        length=listFileSuffixes[i].length;
-        if((listNameEnd-listname)>length && 0==memcmp(listNameEnd-length, suffix, length)) {
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-/*
- * Read a file list.
- * If the listname ends with ".txt", then read the list file
- * (in the system/ invariant charset).
- * If the listname ends with ".dat", then read the ICU .dat package file.
- * Otherwise, read the file itself as a single-item list.
- */
-U_CAPI Package * U_EXPORT2
-readList(const char *filesPath, const char *listname, UBool readContents) {
-    Package *listPkg;
-    FILE *file;
-    const char *listNameEnd;
-
-    if(listname==NULL || listname[0]==0) {
-        fprintf(stderr, "missing list file\n");
-        return NULL;
-    }
-
-    listPkg=new Package();
-    if(listPkg==NULL) {
-        fprintf(stderr, "icupkg: not enough memory\n");
-        exit(U_MEMORY_ALLOCATION_ERROR);
-    }
-
-    listNameEnd=strchr(listname, 0);
-    if(isListTextFile(listname)) {
-        // read the list file
-        char line[1024];
-        char *end;
-        const char *start;
-
-        file=fopen(listname, "r");
-        if(file==NULL) {
-            fprintf(stderr, "icupkg: unable to open list file \"%s\"\n", listname);
-            delete listPkg;
-            exit(U_FILE_ACCESS_ERROR);
-        }
-
-        while(fgets(line, sizeof(line), file)) {
-            // remove comments
-            end=strchr(line, '#');
-            if(end!=NULL) {
-                *end=0;
-            } else {
-                // remove trailing CR LF
-                end=strchr(line, 0);
-                while(line<end && (*(end-1)=='\r' || *(end-1)=='\n')) {
-                    *--end=0;
-                }
-            }
-
-            // check first non-whitespace character and
-            // skip empty lines and
-            // skip lines starting with reserved characters
-            start=u_skipWhitespace(line);
-            if(*start==0 || NULL!=strchr(U_PKG_RESERVED_CHARS, *start)) {
-                continue;
-            }
-
-            // take whitespace-separated items from the line
-            for(;;) {
-                // find whitespace after the item or the end of the line
-                for(end=(char *)start; *end!=0 && *end!=' ' && *end!='\t'; ++end) {}
-                if(*end==0) {
-                    // this item is the last one on the line
-                    end=NULL;
-                } else {
-                    // the item is terminated by whitespace, terminate it with NUL
-                    *end=0;
-                }
-                if(readContents) {
-                    listPkg->addFile(filesPath, start);
-                } else {
-                    listPkg->addItem(start);
-                }
-
-                // find the start of the next item or exit the loop
-                if(end==NULL || *(start=u_skipWhitespace(end+1))==0) {
-                    break;
-                }
-            }
-        }
-        fclose(file);
-    } else if((listNameEnd-listname)>4 && 0==memcmp(listNameEnd-4, ".dat", 4)) {
-        // read the ICU .dat package
-        listPkg->readPackage(listname);
-    } else {
-        // list the single file itself
-        if(readContents) {
-            listPkg->addFile(filesPath, listname);
-        } else {
-            listPkg->addItem(listname);
-        }
-    }
-
-    return listPkg;
-}
-
-U_CAPI int U_EXPORT2
-writePackageDatFile(const char *outFilename, const char *outComment, const char *sourcePath, const char *addList, Package *pkg, char outType) {
-    Package *addListPkg = NULL;
-    UBool pkgDelete = FALSE;
-
-    if (pkg == NULL) {
-        pkg = new Package;
-        if(pkg == NULL) {
-            fprintf(stderr, "icupkg: not enough memory\n");
-            return U_MEMORY_ALLOCATION_ERROR;
-        }
-
-        addListPkg = readList(sourcePath, addList, TRUE);
-        if(addListPkg != NULL) {
-            pkg->addItems(*addListPkg);
-        } else {
-            return U_ILLEGAL_ARGUMENT_ERROR;
-        }
-
-        pkgDelete = TRUE;
-    }
-
-    pkg->writePackage(outFilename, outType, outComment);
-
-    if (pkgDelete) {
-        delete pkg;
-        delete addListPkg;
-    }
-
-    return 0;
-}
-
+/******************************************************************************
+ *   Copyright (C) 2008-2009, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *******************************************************************************
+ */
+#include "unicode/utypes.h"
+#include "unicode/putil.h"
+#include "cstring.h"
+#include "toolutil.h"
+#include "uoptions.h"
+#include "uparse.h"
+#include "package.h"
+#include "pkg_icu.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
+
+// read a file list -------------------------------------------------------- ***
+
+static const struct {
+    const char *suffix;
+    int32_t length;
+} listFileSuffixes[]={
+    { ".txt", 4 },
+    { ".lst", 4 },
+    { ".tmp", 4 }
+};
+
+/* check for multiple text file suffixes to see if this list name is a text file name */
+static UBool
+isListTextFile(const char *listname) {
+    const char *listNameEnd=strchr(listname, 0);
+    const char *suffix;
+    int32_t i, length;
+    for(i=0; i<LENGTHOF(listFileSuffixes); ++i) {
+        suffix=listFileSuffixes[i].suffix;
+        length=listFileSuffixes[i].length;
+        if((listNameEnd-listname)>length && 0==memcmp(listNameEnd-length, suffix, length)) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+/*
+ * Read a file list.
+ * If the listname ends with ".txt", then read the list file
+ * (in the system/ invariant charset).
+ * If the listname ends with ".dat", then read the ICU .dat package file.
+ * Otherwise, read the file itself as a single-item list.
+ */
+U_CAPI Package * U_EXPORT2
+readList(const char *filesPath, const char *listname, UBool readContents) {
+    Package *listPkg;
+    FILE *file;
+    const char *listNameEnd;
+
+    if(listname==NULL || listname[0]==0) {
+        fprintf(stderr, "missing list file\n");
+        return NULL;
+    }
+
+    listPkg=new Package();
+    if(listPkg==NULL) {
+        fprintf(stderr, "icupkg: not enough memory\n");
+        exit(U_MEMORY_ALLOCATION_ERROR);
+    }
+
+    listNameEnd=strchr(listname, 0);
+    if(isListTextFile(listname)) {
+        // read the list file
+        char line[1024];
+        char *end;
+        const char *start;
+
+        file=fopen(listname, "r");
+        if(file==NULL) {
+            fprintf(stderr, "icupkg: unable to open list file \"%s\"\n", listname);
+            delete listPkg;
+            exit(U_FILE_ACCESS_ERROR);
+        }
+
+        while(fgets(line, sizeof(line), file)) {
+            // remove comments
+            end=strchr(line, '#');
+            if(end!=NULL) {
+                *end=0;
+            } else {
+                // remove trailing CR LF
+                end=strchr(line, 0);
+                while(line<end && (*(end-1)=='\r' || *(end-1)=='\n')) {
+                    *--end=0;
+                }
+            }
+
+            // check first non-whitespace character and
+            // skip empty lines and
+            // skip lines starting with reserved characters
+            start=u_skipWhitespace(line);
+            if(*start==0 || NULL!=strchr(U_PKG_RESERVED_CHARS, *start)) {
+                continue;
+            }
+
+            // take whitespace-separated items from the line
+            for(;;) {
+                // find whitespace after the item or the end of the line
+                for(end=(char *)start; *end!=0 && *end!=' ' && *end!='\t'; ++end) {}
+                if(*end==0) {
+                    // this item is the last one on the line
+                    end=NULL;
+                } else {
+                    // the item is terminated by whitespace, terminate it with NUL
+                    *end=0;
+                }
+                if(readContents) {
+                    listPkg->addFile(filesPath, start);
+                } else {
+                    listPkg->addItem(start);
+                }
+
+                // find the start of the next item or exit the loop
+                if(end==NULL || *(start=u_skipWhitespace(end+1))==0) {
+                    break;
+                }
+            }
+        }
+        fclose(file);
+    } else if((listNameEnd-listname)>4 && 0==memcmp(listNameEnd-4, ".dat", 4)) {
+        // read the ICU .dat package
+        listPkg->readPackage(listname);
+    } else {
+        // list the single file itself
+        if(readContents) {
+            listPkg->addFile(filesPath, listname);
+        } else {
+            listPkg->addItem(listname);
+        }
+    }
+
+    return listPkg;
+}
+
+U_CAPI int U_EXPORT2
+writePackageDatFile(const char *outFilename, const char *outComment, const char *sourcePath, const char *addList, Package *pkg, char outType) {
+    Package *addListPkg = NULL;
+    UBool pkgDelete = FALSE;
+
+    if (pkg == NULL) {
+        pkg = new Package;
+        if(pkg == NULL) {
+            fprintf(stderr, "icupkg: not enough memory\n");
+            return U_MEMORY_ALLOCATION_ERROR;
+        }
+
+        addListPkg = readList(sourcePath, addList, TRUE);
+        if(addListPkg != NULL) {
+            pkg->addItems(*addListPkg);
+        } else {
+            return U_ILLEGAL_ARGUMENT_ERROR;
+        }
+
+        pkgDelete = TRUE;
+    }
+
+    pkg->writePackage(outFilename, outType, outComment);
+
+    if (pkgDelete) {
+        delete pkg;
+        delete addListPkg;
+    }
+
+    return 0;
+}
+

Modified: trunk/source/tools/toolutil/pkg_icu.h
===================================================================
--- trunk/source/tools/toolutil/pkg_icu.h	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/toolutil/pkg_icu.h	2009-07-02 19:32:00 UTC (rev 214)
@@ -1,22 +1,22 @@
-/******************************************************************************
- *   Copyright (C) 2008-2009, International Business Machines
- *   Corporation and others.  All Rights Reserved.
- *******************************************************************************
- */
-
-#ifndef __PKG_ICU_H__
-#define __PKG_ICU_H__
-
-#include "unicode/utypes.h"
-
-#define U_PKG_RESERVED_CHARS "\"%&'()*+,-./:;<=>?_"
-
-U_CAPI int U_EXPORT2
-writePackageDatFile(const char *outFilename, const char *outComment,
-                    const char *sourcePath, const char *addList, Package *pkg,
-                    char outType);
-
-U_CAPI Package * U_EXPORT2
-readList(const char *filesPath, const char *listname, UBool readContents);
-
-#endif
+/******************************************************************************
+ *   Copyright (C) 2008-2009, International Business Machines
+ *   Corporation and others.  All Rights Reserved.
+ *******************************************************************************
+ */
+
+#ifndef __PKG_ICU_H__
+#define __PKG_ICU_H__
+
+#include "unicode/utypes.h"
+
+#define U_PKG_RESERVED_CHARS "\"%&'()*+,-./:;<=>?_"
+
+U_CAPI int U_EXPORT2
+writePackageDatFile(const char *outFilename, const char *outComment,
+                    const char *sourcePath, const char *addList, Package *pkg,
+                    char outType);
+
+U_CAPI Package * U_EXPORT2
+readList(const char *filesPath, const char *listname, UBool readContents);
+
+#endif

Modified: trunk/source/tools/toolutil/toolutil.c
===================================================================
--- trunk/source/tools/toolutil/toolutil.c	2009-07-02 19:31:11 UTC (rev 213)
+++ trunk/source/tools/toolutil/toolutil.c	2009-07-02 19:32:00 UTC (rev 214)
@@ -66,7 +66,7 @@
 getLongPathname(const char *pathname) {
 #ifdef U_WINDOWS
     /* anticipate problems with "short" pathnames */
-    static WIN32_FIND_DATA info;
+    static WIN32_FIND_DATAA info;
     HANDLE file=FindFirstFileA(pathname, &info);
     if(file!=INVALID_HANDLE_VALUE) {
         if(info.cAlternateFileName[0]!=0) {




More information about the sword-cvs mailing list