Imported Upstream version 58.1
[platform/upstream/icu.git] / source / common / putil.cpp
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 *
6 *   Copyright (C) 1997-2016, International Business Machines
7 *   Corporation and others.  All Rights Reserved.
8 *
9 ******************************************************************************
10 *
11 *  FILE NAME : putil.c (previously putil.cpp and ptypes.cpp)
12 *
13 *   Date        Name        Description
14 *   04/14/97    aliu        Creation.
15 *   04/24/97    aliu        Added getDefaultDataDirectory() and
16 *                            getDefaultLocaleID().
17 *   04/28/97    aliu        Rewritten to assume Unix and apply general methods
18 *                            for assumed case.  Non-UNIX platforms must be
19 *                            special-cased.  Rewrote numeric methods dealing
20 *                            with NaN and Infinity to be platform independent
21 *                             over all IEEE 754 platforms.
22 *   05/13/97    aliu        Restored sign of timezone
23 *                            (semantics are hours West of GMT)
24 *   06/16/98    erm         Added IEEE_754 stuff, cleaned up isInfinite, isNan,
25 *                             nextDouble..
26 *   07/22/98    stephen     Added remainder, max, min, trunc
27 *   08/13/98    stephen     Added isNegativeInfinity, isPositiveInfinity
28 *   08/24/98    stephen     Added longBitsFromDouble
29 *   09/08/98    stephen     Minor changes for Mac Port
30 *   03/02/99    stephen     Removed openFile().  Added AS400 support.
31 *                            Fixed EBCDIC tables
32 *   04/15/99    stephen     Converted to C.
33 *   06/28/99    stephen     Removed mutex locking in u_isBigEndian().
34 *   08/04/99    jeffrey R.  Added OS/2 changes
35 *   11/15/99    helena      Integrated S/390 IEEE support.
36 *   04/26/01    Barry N.    OS/400 support for uprv_getDefaultLocaleID
37 *   08/15/01    Steven H.   OS/400 support for uprv_getDefaultCodepage
38 *   01/03/08    Steven L.   Fake Time Support
39 ******************************************************************************
40 */
41
42 // Defines _XOPEN_SOURCE for access to POSIX functions.
43 // Must be before any other #includes.
44 #include "uposixdefs.h"
45
46 /* include ICU headers */
47 #include "unicode/utypes.h"
48 #include "unicode/putil.h"
49 #include "unicode/ustring.h"
50 #include "putilimp.h"
51 #include "uassert.h"
52 #include "umutex.h"
53 #include "cmemory.h"
54 #include "cstring.h"
55 #include "locmap.h"
56 #include "ucln_cmn.h"
57 #include "charstr.h"
58
59 /* Include standard headers. */
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <math.h>
64 #include <locale.h>
65 #include <float.h>
66
67 #ifndef U_COMMON_IMPLEMENTATION
68 #error U_COMMON_IMPLEMENTATION not set - must be set for all ICU source files in common/ - see http://userguide.icu-project.org/howtouseicu
69 #endif
70
71
72 /* include system headers */
73 #if U_PLATFORM_USES_ONLY_WIN32_API
74     /*
75      * TODO: U_PLATFORM_USES_ONLY_WIN32_API includes MinGW.
76      * Should Cygwin be included as well (U_PLATFORM_HAS_WIN32_API)
77      * to use native APIs as much as possible?
78      */
79 #   define WIN32_LEAN_AND_MEAN
80 #   define VC_EXTRALEAN
81 #   define NOUSER
82 #   define NOSERVICE
83 #   define NOIME
84 #   define NOMCX
85 #   include <windows.h>
86 #   include "wintz.h"
87 #elif U_PLATFORM == U_PF_OS400
88 #   include <float.h>
89 #   include <qusec.h>       /* error code structure */
90 #   include <qusrjobi.h>
91 #   include <qliept.h>      /* EPT_CALL macro  - this include must be after all other "QSYSINCs" */
92 #   include <mih/testptr.h> /* For uprv_maximumPtr */
93 #elif U_PLATFORM == U_PF_OS390
94 #   include "unicode/ucnv.h"   /* Needed for UCNV_SWAP_LFNL_OPTION_STRING */
95 #elif U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD || U_PLATFORM == U_PF_SOLARIS
96 #   include <limits.h>
97 #   include <unistd.h>
98 #   if U_PLATFORM == U_PF_SOLARIS
99 #       ifndef _XPG4_2
100 #           define _XPG4_2
101 #       endif
102 #   endif
103 #elif U_PLATFORM == U_PF_QNX
104 #   include <sys/neutrino.h>
105 #endif
106
107 #if (U_PF_MINGW <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN) && defined(__STRICT_ANSI__)
108 /* tzset isn't defined in strict ANSI on Cygwin and MinGW. */
109 #undef __STRICT_ANSI__
110 #endif
111
112 /*
113  * Cygwin with GCC requires inclusion of time.h after the above disabling strict asci mode statement.
114  */
115 #include <time.h>
116
117 #if !U_PLATFORM_USES_ONLY_WIN32_API
118 #include <sys/time.h>
119 #endif
120
121 /*
122  * Only include langinfo.h if we have a way to get the codeset. If we later
123  * depend on more feature, we can test on U_HAVE_NL_LANGINFO.
124  *
125  */
126
127 #if U_HAVE_NL_LANGINFO_CODESET
128 #include <langinfo.h>
129 #endif
130
131 /**
132  * Simple things (presence of functions, etc) should just go in configure.in and be added to
133  * icucfg.h via autoheader.
134  */
135 #if U_PLATFORM_IMPLEMENTS_POSIX
136 #   if U_PLATFORM == U_PF_OS400
137 #    define HAVE_DLFCN_H 0
138 #    define HAVE_DLOPEN 0
139 #   else
140 #   ifndef HAVE_DLFCN_H
141 #    define HAVE_DLFCN_H 1
142 #   endif
143 #   ifndef HAVE_DLOPEN
144 #    define HAVE_DLOPEN 1
145 #   endif
146 #   endif
147 #   ifndef HAVE_GETTIMEOFDAY
148 #    define HAVE_GETTIMEOFDAY 1
149 #   endif
150 #else
151 #   define HAVE_DLFCN_H 0
152 #   define HAVE_DLOPEN 0
153 #   define HAVE_GETTIMEOFDAY 0
154 #endif
155
156 U_NAMESPACE_USE
157
158 /* Define the extension for data files, again... */
159 #define DATA_TYPE "dat"
160
161 /* Leave this copyright notice here! */
162 static const char copyright[] = U_COPYRIGHT_STRING;
163
164 /* floating point implementations ------------------------------------------- */
165
166 /* We return QNAN rather than SNAN*/
167 #define SIGN 0x80000000U
168
169 /* Make it easy to define certain types of constants */
170 typedef union {
171     int64_t i64; /* This must be defined first in order to allow the initialization to work. This is a C89 feature. */
172     double d64;
173 } BitPatternConversion;
174 static const BitPatternConversion gNan = { (int64_t) INT64_C(0x7FF8000000000000) };
175 static const BitPatternConversion gInf = { (int64_t) INT64_C(0x7FF0000000000000) };
176
177 /*---------------------------------------------------------------------------
178   Platform utilities
179   Our general strategy is to assume we're on a POSIX platform.  Platforms which
180   are non-POSIX must declare themselves so.  The default POSIX implementation
181   will sometimes work for non-POSIX platforms as well (e.g., the NaN-related
182   functions).
183   ---------------------------------------------------------------------------*/
184
185 #if U_PLATFORM_USES_ONLY_WIN32_API || U_PLATFORM == U_PF_OS400
186 #   undef U_POSIX_LOCALE
187 #else
188 #   define U_POSIX_LOCALE    1
189 #endif
190
191 /*
192     WARNING! u_topNBytesOfDouble and u_bottomNBytesOfDouble
193     can't be properly optimized by the gcc compiler sometimes (i.e. gcc 3.2).
194 */
195 #if !IEEE_754
196 static char*
197 u_topNBytesOfDouble(double* d, int n)
198 {
199 #if U_IS_BIG_ENDIAN
200     return (char*)d;
201 #else
202     return (char*)(d + 1) - n;
203 #endif
204 }
205
206 static char*
207 u_bottomNBytesOfDouble(double* d, int n)
208 {
209 #if U_IS_BIG_ENDIAN
210     return (char*)(d + 1) - n;
211 #else
212     return (char*)d;
213 #endif
214 }
215 #endif   /* !IEEE_754 */
216
217 #if IEEE_754
218 static UBool
219 u_signBit(double d) {
220     uint8_t hiByte;
221 #if U_IS_BIG_ENDIAN
222     hiByte = *(uint8_t *)&d;
223 #else
224     hiByte = *(((uint8_t *)&d) + sizeof(double) - 1);
225 #endif
226     return (hiByte & 0x80) != 0;
227 }
228 #endif
229
230
231
232 #if defined (U_DEBUG_FAKETIME)
233 /* Override the clock to test things without having to move the system clock.
234  * Assumes POSIX gettimeofday() will function
235  */
236 UDate fakeClock_t0 = 0; /** Time to start the clock from **/
237 UDate fakeClock_dt = 0; /** Offset (fake time - real time) **/
238 UBool fakeClock_set = FALSE; /** True if fake clock has spun up **/
239 static UMutex fakeClockMutex = U_MUTEX_INTIALIZER;
240
241 static UDate getUTCtime_real() {
242     struct timeval posixTime;
243     gettimeofday(&posixTime, NULL);
244     return (UDate)(((int64_t)posixTime.tv_sec * U_MILLIS_PER_SECOND) + (posixTime.tv_usec/1000));
245 }
246
247 static UDate getUTCtime_fake() {
248     umtx_lock(&fakeClockMutex);
249     if(!fakeClock_set) {
250         UDate real = getUTCtime_real();
251         const char *fake_start = getenv("U_FAKETIME_START");
252         if((fake_start!=NULL) && (fake_start[0]!=0)) {
253             sscanf(fake_start,"%lf",&fakeClock_t0);
254             fakeClock_dt = fakeClock_t0 - real;
255             fprintf(stderr,"U_DEBUG_FAKETIME was set at compile time, so the ICU clock will start at a preset value\n"
256                     "env variable U_FAKETIME_START=%.0f (%s) for an offset of %.0f ms from the current time %.0f\n",
257                     fakeClock_t0, fake_start, fakeClock_dt, real);
258         } else {
259           fakeClock_dt = 0;
260             fprintf(stderr,"U_DEBUG_FAKETIME was set at compile time, but U_FAKETIME_START was not set.\n"
261                     "Set U_FAKETIME_START to the number of milliseconds since 1/1/1970 to set the ICU clock.\n");
262         }
263         fakeClock_set = TRUE;
264     }
265     umtx_unlock(&fakeClockMutex);
266
267     return getUTCtime_real() + fakeClock_dt;
268 }
269 #endif
270
271 #if U_PLATFORM_USES_ONLY_WIN32_API
272 typedef union {
273     int64_t int64;
274     FILETIME fileTime;
275 } FileTimeConversion;   /* This is like a ULARGE_INTEGER */
276
277 /* Number of 100 nanoseconds from 1/1/1601 to 1/1/1970 */
278 #define EPOCH_BIAS  INT64_C(116444736000000000)
279 #define HECTONANOSECOND_PER_MILLISECOND   10000
280
281 #endif
282
283 /*---------------------------------------------------------------------------
284   Universal Implementations
285   These are designed to work on all platforms.  Try these, and if they
286   don't work on your platform, then special case your platform with new
287   implementations.
288 ---------------------------------------------------------------------------*/
289
290 U_CAPI UDate U_EXPORT2
291 uprv_getUTCtime()
292 {
293 #if defined(U_DEBUG_FAKETIME)
294     return getUTCtime_fake(); /* Hook for overriding the clock */
295 #else
296     return uprv_getRawUTCtime();
297 #endif
298 }
299
300 /* Return UTC (GMT) time measured in milliseconds since 0:00 on 1/1/70.*/
301 U_CAPI UDate U_EXPORT2
302 uprv_getRawUTCtime()
303 {
304 #if U_PLATFORM_USES_ONLY_WIN32_API
305
306     FileTimeConversion winTime;
307     GetSystemTimeAsFileTime(&winTime.fileTime);
308     return (UDate)((winTime.int64 - EPOCH_BIAS) / HECTONANOSECOND_PER_MILLISECOND);
309 #else
310
311 #if HAVE_GETTIMEOFDAY
312     struct timeval posixTime;
313     gettimeofday(&posixTime, NULL);
314     return (UDate)(((int64_t)posixTime.tv_sec * U_MILLIS_PER_SECOND) + (posixTime.tv_usec/1000));
315 #else
316     time_t epochtime;
317     time(&epochtime);
318     return (UDate)epochtime * U_MILLIS_PER_SECOND;
319 #endif
320
321 #endif
322 }
323
324 /*-----------------------------------------------------------------------------
325   IEEE 754
326   These methods detect and return NaN and infinity values for doubles
327   conforming to IEEE 754.  Platforms which support this standard include X86,
328   Mac 680x0, Mac PowerPC, AIX RS/6000, and most others.
329   If this doesn't work on your platform, you have non-IEEE floating-point, and
330   will need to code your own versions.  A naive implementation is to return 0.0
331   for getNaN and getInfinity, and false for isNaN and isInfinite.
332   ---------------------------------------------------------------------------*/
333
334 U_CAPI UBool U_EXPORT2
335 uprv_isNaN(double number)
336 {
337 #if IEEE_754
338     BitPatternConversion convertedNumber;
339     convertedNumber.d64 = number;
340     /* Infinity is 0x7FF0000000000000U. Anything greater than that is a NaN */
341     return (UBool)((convertedNumber.i64 & U_INT64_MAX) > gInf.i64);
342
343 #elif U_PLATFORM == U_PF_OS390
344     uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number,
345                         sizeof(uint32_t));
346     uint32_t lowBits  = *(uint32_t*)u_bottomNBytesOfDouble(&number,
347                         sizeof(uint32_t));
348
349     return ((highBits & 0x7F080000L) == 0x7F080000L) &&
350       (lowBits == 0x00000000L);
351
352 #else
353     /* If your platform doesn't support IEEE 754 but *does* have an NaN value,*/
354     /* you'll need to replace this default implementation with what's correct*/
355     /* for your platform.*/
356     return number != number;
357 #endif
358 }
359
360 U_CAPI UBool U_EXPORT2
361 uprv_isInfinite(double number)
362 {
363 #if IEEE_754
364     BitPatternConversion convertedNumber;
365     convertedNumber.d64 = number;
366     /* Infinity is exactly 0x7FF0000000000000U. */
367     return (UBool)((convertedNumber.i64 & U_INT64_MAX) == gInf.i64);
368 #elif U_PLATFORM == U_PF_OS390
369     uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number,
370                         sizeof(uint32_t));
371     uint32_t lowBits  = *(uint32_t*)u_bottomNBytesOfDouble(&number,
372                         sizeof(uint32_t));
373
374     return ((highBits  & ~SIGN) == 0x70FF0000L) && (lowBits == 0x00000000L);
375
376 #else
377     /* If your platform doesn't support IEEE 754 but *does* have an infinity*/
378     /* value, you'll need to replace this default implementation with what's*/
379     /* correct for your platform.*/
380     return number == (2.0 * number);
381 #endif
382 }
383
384 U_CAPI UBool U_EXPORT2
385 uprv_isPositiveInfinity(double number)
386 {
387 #if IEEE_754 || U_PLATFORM == U_PF_OS390
388     return (UBool)(number > 0 && uprv_isInfinite(number));
389 #else
390     return uprv_isInfinite(number);
391 #endif
392 }
393
394 U_CAPI UBool U_EXPORT2
395 uprv_isNegativeInfinity(double number)
396 {
397 #if IEEE_754 || U_PLATFORM == U_PF_OS390
398     return (UBool)(number < 0 && uprv_isInfinite(number));
399
400 #else
401     uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number,
402                         sizeof(uint32_t));
403     return((highBits & SIGN) && uprv_isInfinite(number));
404
405 #endif
406 }
407
408 U_CAPI double U_EXPORT2
409 uprv_getNaN()
410 {
411 #if IEEE_754 || U_PLATFORM == U_PF_OS390
412     return gNan.d64;
413 #else
414     /* If your platform doesn't support IEEE 754 but *does* have an NaN value,*/
415     /* you'll need to replace this default implementation with what's correct*/
416     /* for your platform.*/
417     return 0.0;
418 #endif
419 }
420
421 U_CAPI double U_EXPORT2
422 uprv_getInfinity()
423 {
424 #if IEEE_754 || U_PLATFORM == U_PF_OS390
425     return gInf.d64;
426 #else
427     /* If your platform doesn't support IEEE 754 but *does* have an infinity*/
428     /* value, you'll need to replace this default implementation with what's*/
429     /* correct for your platform.*/
430     return 0.0;
431 #endif
432 }
433
434 U_CAPI double U_EXPORT2
435 uprv_floor(double x)
436 {
437     return floor(x);
438 }
439
440 U_CAPI double U_EXPORT2
441 uprv_ceil(double x)
442 {
443     return ceil(x);
444 }
445
446 U_CAPI double U_EXPORT2
447 uprv_round(double x)
448 {
449     return uprv_floor(x + 0.5);
450 }
451
452 U_CAPI double U_EXPORT2
453 uprv_fabs(double x)
454 {
455     return fabs(x);
456 }
457
458 U_CAPI double U_EXPORT2
459 uprv_modf(double x, double* y)
460 {
461     return modf(x, y);
462 }
463
464 U_CAPI double U_EXPORT2
465 uprv_fmod(double x, double y)
466 {
467     return fmod(x, y);
468 }
469
470 U_CAPI double U_EXPORT2
471 uprv_pow(double x, double y)
472 {
473     /* This is declared as "double pow(double x, double y)" */
474     return pow(x, y);
475 }
476
477 U_CAPI double U_EXPORT2
478 uprv_pow10(int32_t x)
479 {
480     return pow(10.0, (double)x);
481 }
482
483 U_CAPI double U_EXPORT2
484 uprv_fmax(double x, double y)
485 {
486 #if IEEE_754
487     /* first handle NaN*/
488     if(uprv_isNaN(x) || uprv_isNaN(y))
489         return uprv_getNaN();
490
491     /* check for -0 and 0*/
492     if(x == 0.0 && y == 0.0 && u_signBit(x))
493         return y;
494
495 #endif
496
497     /* this should work for all flt point w/o NaN and Inf special cases */
498     return (x > y ? x : y);
499 }
500
501 U_CAPI double U_EXPORT2
502 uprv_fmin(double x, double y)
503 {
504 #if IEEE_754
505     /* first handle NaN*/
506     if(uprv_isNaN(x) || uprv_isNaN(y))
507         return uprv_getNaN();
508
509     /* check for -0 and 0*/
510     if(x == 0.0 && y == 0.0 && u_signBit(y))
511         return y;
512
513 #endif
514
515     /* this should work for all flt point w/o NaN and Inf special cases */
516     return (x > y ? y : x);
517 }
518
519 /**
520  * Truncates the given double.
521  * trunc(3.3) = 3.0, trunc (-3.3) = -3.0
522  * This is different than calling floor() or ceil():
523  * floor(3.3) = 3, floor(-3.3) = -4
524  * ceil(3.3) = 4, ceil(-3.3) = -3
525  */
526 U_CAPI double U_EXPORT2
527 uprv_trunc(double d)
528 {
529 #if IEEE_754
530     /* handle error cases*/
531     if(uprv_isNaN(d))
532         return uprv_getNaN();
533     if(uprv_isInfinite(d))
534         return uprv_getInfinity();
535
536     if(u_signBit(d))    /* Signbit() picks up -0.0;  d<0 does not. */
537         return ceil(d);
538     else
539         return floor(d);
540
541 #else
542     return d >= 0 ? floor(d) : ceil(d);
543
544 #endif
545 }
546
547 /**
548  * Return the largest positive number that can be represented by an integer
549  * type of arbitrary bit length.
550  */
551 U_CAPI double U_EXPORT2
552 uprv_maxMantissa(void)
553 {
554     return pow(2.0, DBL_MANT_DIG + 1.0) - 1.0;
555 }
556
557 U_CAPI double U_EXPORT2
558 uprv_log(double d)
559 {
560     return log(d);
561 }
562
563 U_CAPI void * U_EXPORT2
564 uprv_maximumPtr(void * base)
565 {
566 #if U_PLATFORM == U_PF_OS400
567     /*
568      * With the provided function we should never be out of range of a given segment
569      * (a traditional/typical segment that is).  Our segments have 5 bytes for the
570      * id and 3 bytes for the offset.  The key is that the casting takes care of
571      * only retrieving the offset portion minus x1000.  Hence, the smallest offset
572      * seen in a program is x001000 and when casted to an int would be 0.
573      * That's why we can only add 0xffefff.  Otherwise, we would exceed the segment.
574      *
575      * Currently, 16MB is the current addressing limitation on i5/OS if the activation is
576      * non-TERASPACE.  If it is TERASPACE it is 2GB - 4k(header information).
577      * This function determines the activation based on the pointer that is passed in and
578      * calculates the appropriate maximum available size for
579      * each pointer type (TERASPACE and non-TERASPACE)
580      *
581      * Unlike other operating systems, the pointer model isn't determined at
582      * compile time on i5/OS.
583      */
584     if ((base != NULL) && (_TESTPTR(base, _C_TERASPACE_CHECK))) {
585         /* if it is a TERASPACE pointer the max is 2GB - 4k */
586         return ((void *)(((char *)base)-((uint32_t)(base))+((uint32_t)0x7fffefff)));
587     }
588     /* otherwise 16MB since NULL ptr is not checkable or the ptr is not TERASPACE */
589     return ((void *)(((char *)base)-((uint32_t)(base))+((uint32_t)0xffefff)));
590
591 #else
592     return U_MAX_PTR(base);
593 #endif
594 }
595
596 /*---------------------------------------------------------------------------
597   Platform-specific Implementations
598   Try these, and if they don't work on your platform, then special case your
599   platform with new implementations.
600   ---------------------------------------------------------------------------*/
601
602 /* Generic time zone layer -------------------------------------------------- */
603
604 /* Time zone utilities */
605 U_CAPI void U_EXPORT2
606 uprv_tzset()
607 {
608 #if defined(U_TZSET)
609     U_TZSET();
610 #else
611     /* no initialization*/
612 #endif
613 }
614
615 U_CAPI int32_t U_EXPORT2
616 uprv_timezone()
617 {
618 #ifdef U_TIMEZONE
619     return U_TIMEZONE;
620 #else
621     time_t t, t1, t2;
622     struct tm tmrec;
623     int32_t tdiff = 0;
624
625     time(&t);
626     uprv_memcpy( &tmrec, localtime(&t), sizeof(tmrec) );
627 #if U_PLATFORM != U_PF_IPHONE
628     UBool dst_checked = (tmrec.tm_isdst != 0); /* daylight savings time is checked*/
629 #endif
630     t1 = mktime(&tmrec);                 /* local time in seconds*/
631     uprv_memcpy( &tmrec, gmtime(&t), sizeof(tmrec) );
632     t2 = mktime(&tmrec);                 /* GMT (or UTC) in seconds*/
633     tdiff = t2 - t1;
634
635 #if U_PLATFORM != U_PF_IPHONE
636     /* imitate NT behaviour, which returns same timezone offset to GMT for
637        winter and summer.
638        This does not work on all platforms. For instance, on glibc on Linux
639        and on Mac OS 10.5, tdiff calculated above remains the same
640        regardless of whether DST is in effect or not. iOS is another
641        platform where this does not work. Linux + glibc and Mac OS 10.5
642        have U_TIMEZONE defined so that this code is not reached.
643     */
644     if (dst_checked)
645         tdiff += 3600;
646 #endif
647     return tdiff;
648 #endif
649 }
650
651 /* Note that U_TZNAME does *not* have to be tzname, but if it is,
652    some platforms need to have it declared here. */
653
654 #if defined(U_TZNAME) && (U_PLATFORM == U_PF_IRIX || U_PLATFORM_IS_DARWIN_BASED || (U_PLATFORM == U_PF_CYGWIN && !U_PLATFORM_USES_ONLY_WIN32_API))
655 /* RS6000 and others reject char **tzname.  */
656 extern U_IMPORT char *U_TZNAME[];
657 #endif
658
659 #if !UCONFIG_NO_FILE_IO && ((U_PLATFORM_IS_DARWIN_BASED && (U_PLATFORM != U_PF_IPHONE || defined(U_TIMEZONE))) || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD || U_PLATFORM == U_PF_SOLARIS)
660 /* These platforms are likely to use Olson timezone IDs. */
661 #define CHECK_LOCALTIME_LINK 1
662 #if U_PLATFORM_IS_DARWIN_BASED
663 #include <tzfile.h>
664 #define TZZONEINFO      (TZDIR "/")
665 #elif U_PLATFORM == U_PF_SOLARIS
666 #define TZDEFAULT       "/etc/localtime"
667 #define TZZONEINFO      "/usr/share/lib/zoneinfo/"
668 #define TZZONEINFO2     "../usr/share/lib/zoneinfo/"
669 #define TZ_ENV_CHECK    "localtime"
670 #else
671 #define TZDEFAULT       "/etc/localtime"
672 #define TZZONEINFO      "/usr/share/zoneinfo/"
673 #endif
674 #if U_HAVE_DIRENT_H
675 #define TZFILE_SKIP     "posixrules" /* tz file to skip when searching. */
676 /* Some Linux distributions have 'localtime' in /usr/share/zoneinfo
677    symlinked to /etc/localtime, which makes searchForTZFile return
678    'localtime' when it's the first match. */
679 #define TZFILE_SKIP2    "localtime"
680 #define SEARCH_TZFILE
681 #include <dirent.h>  /* Needed to search through system timezone files */
682 #endif
683 static char gTimeZoneBuffer[PATH_MAX];
684 static char *gTimeZoneBufferPtr = NULL;
685 #endif
686
687 #if !U_PLATFORM_USES_ONLY_WIN32_API
688 #define isNonDigit(ch) (ch < '0' || '9' < ch)
689 static UBool isValidOlsonID(const char *id) {
690     int32_t idx = 0;
691
692     /* Determine if this is something like Iceland (Olson ID)
693     or AST4ADT (non-Olson ID) */
694     while (id[idx] && isNonDigit(id[idx]) && id[idx] != ',') {
695         idx++;
696     }
697
698     /* If we went through the whole string, then it might be okay.
699     The timezone is sometimes set to "CST-7CDT", "CST6CDT5,J129,J131/19:30",
700     "GRNLNDST3GRNLNDDT" or similar, so we cannot use it.
701     The rest of the time it could be an Olson ID. George */
702     return (UBool)(id[idx] == 0
703         || uprv_strcmp(id, "PST8PDT") == 0
704         || uprv_strcmp(id, "MST7MDT") == 0
705         || uprv_strcmp(id, "CST6CDT") == 0
706         || uprv_strcmp(id, "EST5EDT") == 0);
707 }
708
709 /* On some Unix-like OS, 'posix' subdirectory in
710    /usr/share/zoneinfo replicates the top-level contents. 'right'
711    subdirectory has the same set of files, but individual files
712    are different from those in the top-level directory or 'posix'
713    because 'right' has files for TAI (Int'l Atomic Time) while 'posix'
714    has files for UTC.
715    When the first match for /etc/localtime is in either of them
716    (usually in posix because 'right' has different file contents),
717    or TZ environment variable points to one of them, createTimeZone
718    fails because, say, 'posix/America/New_York' is not an Olson
719    timezone id ('America/New_York' is). So, we have to skip
720    'posix/' and 'right/' at the beginning. */
721 static void skipZoneIDPrefix(const char** id) {
722     if (uprv_strncmp(*id, "posix/", 6) == 0
723         || uprv_strncmp(*id, "right/", 6) == 0)
724     {
725         *id += 6;
726     }
727 }
728 #endif
729
730 #if defined(U_TZNAME) && !U_PLATFORM_USES_ONLY_WIN32_API
731
732 #define CONVERT_HOURS_TO_SECONDS(offset) (int32_t)(offset*3600)
733 typedef struct OffsetZoneMapping {
734     int32_t offsetSeconds;
735     int32_t daylightType; /* 0=U_DAYLIGHT_NONE, 1=daylight in June-U_DAYLIGHT_JUNE, 2=daylight in December=U_DAYLIGHT_DECEMBER*/
736     const char *stdID;
737     const char *dstID;
738     const char *olsonID;
739 } OffsetZoneMapping;
740
741 enum { U_DAYLIGHT_NONE=0,U_DAYLIGHT_JUNE=1,U_DAYLIGHT_DECEMBER=2 };
742
743 /*
744 This list tries to disambiguate a set of abbreviated timezone IDs and offsets
745 and maps it to an Olson ID.
746 Before adding anything to this list, take a look at
747 icu/source/tools/tzcode/tz.alias
748 Sometimes no daylight savings (0) is important to define due to aliases.
749 This list can be tested with icu/source/test/compat/tzone.pl
750 More values could be added to daylightType to increase precision.
751 */
752 static const struct OffsetZoneMapping OFFSET_ZONE_MAPPINGS[] = {
753     {-45900, 2, "CHAST", "CHADT", "Pacific/Chatham"},
754     {-43200, 1, "PETT", "PETST", "Asia/Kamchatka"},
755     {-43200, 2, "NZST", "NZDT", "Pacific/Auckland"},
756     {-43200, 1, "ANAT", "ANAST", "Asia/Anadyr"},
757     {-39600, 1, "MAGT", "MAGST", "Asia/Magadan"},
758     {-37800, 2, "LHST", "LHST", "Australia/Lord_Howe"},
759     {-36000, 2, "EST", "EST", "Australia/Sydney"},
760     {-36000, 1, "SAKT", "SAKST", "Asia/Sakhalin"},
761     {-36000, 1, "VLAT", "VLAST", "Asia/Vladivostok"},
762     {-34200, 2, "CST", "CST", "Australia/South"},
763     {-32400, 1, "YAKT", "YAKST", "Asia/Yakutsk"},
764     {-32400, 1, "CHOT", "CHOST", "Asia/Choibalsan"},
765     {-31500, 2, "CWST", "CWST", "Australia/Eucla"},
766     {-28800, 1, "IRKT", "IRKST", "Asia/Irkutsk"},
767     {-28800, 1, "ULAT", "ULAST", "Asia/Ulaanbaatar"},
768     {-28800, 2, "WST", "WST", "Australia/West"},
769     {-25200, 1, "HOVT", "HOVST", "Asia/Hovd"},
770     {-25200, 1, "KRAT", "KRAST", "Asia/Krasnoyarsk"},
771     {-21600, 1, "NOVT", "NOVST", "Asia/Novosibirsk"},
772     {-21600, 1, "OMST", "OMSST", "Asia/Omsk"},
773     {-18000, 1, "YEKT", "YEKST", "Asia/Yekaterinburg"},
774     {-14400, 1, "SAMT", "SAMST", "Europe/Samara"},
775     {-14400, 1, "AMT", "AMST", "Asia/Yerevan"},
776     {-14400, 1, "AZT", "AZST", "Asia/Baku"},
777     {-10800, 1, "AST", "ADT", "Asia/Baghdad"},
778     {-10800, 1, "MSK", "MSD", "Europe/Moscow"},
779     {-10800, 1, "VOLT", "VOLST", "Europe/Volgograd"},
780     {-7200, 0, "EET", "CEST", "Africa/Tripoli"},
781     {-7200, 1, "EET", "EEST", "Europe/Athens"}, /* Conflicts with Africa/Cairo */
782     {-7200, 1, "IST", "IDT", "Asia/Jerusalem"},
783     {-3600, 0, "CET", "WEST", "Africa/Algiers"},
784     {-3600, 2, "WAT", "WAST", "Africa/Windhoek"},
785     {0, 1, "GMT", "IST", "Europe/Dublin"},
786     {0, 1, "GMT", "BST", "Europe/London"},
787     {0, 0, "WET", "WEST", "Africa/Casablanca"},
788     {0, 0, "WET", "WET", "Africa/El_Aaiun"},
789     {3600, 1, "AZOT", "AZOST", "Atlantic/Azores"},
790     {3600, 1, "EGT", "EGST", "America/Scoresbysund"},
791     {10800, 1, "PMST", "PMDT", "America/Miquelon"},
792     {10800, 2, "UYT", "UYST", "America/Montevideo"},
793     {10800, 1, "WGT", "WGST", "America/Godthab"},
794     {10800, 2, "BRT", "BRST", "Brazil/East"},
795     {12600, 1, "NST", "NDT", "America/St_Johns"},
796     {14400, 1, "AST", "ADT", "Canada/Atlantic"},
797     {14400, 2, "AMT", "AMST", "America/Cuiaba"},
798     {14400, 2, "CLT", "CLST", "Chile/Continental"},
799     {14400, 2, "FKT", "FKST", "Atlantic/Stanley"},
800     {14400, 2, "PYT", "PYST", "America/Asuncion"},
801     {18000, 1, "CST", "CDT", "America/Havana"},
802     {18000, 1, "EST", "EDT", "US/Eastern"}, /* Conflicts with America/Grand_Turk */
803     {21600, 2, "EAST", "EASST", "Chile/EasterIsland"},
804     {21600, 0, "CST", "MDT", "Canada/Saskatchewan"},
805     {21600, 0, "CST", "CDT", "America/Guatemala"},
806     {21600, 1, "CST", "CDT", "US/Central"}, /* Conflicts with Mexico/General */
807     {25200, 1, "MST", "MDT", "US/Mountain"}, /* Conflicts with Mexico/BajaSur */
808     {28800, 0, "PST", "PST", "Pacific/Pitcairn"},
809     {28800, 1, "PST", "PDT", "US/Pacific"}, /* Conflicts with Mexico/BajaNorte */
810     {32400, 1, "AKST", "AKDT", "US/Alaska"},
811     {36000, 1, "HAST", "HADT", "US/Aleutian"}
812 };
813
814 /*#define DEBUG_TZNAME*/
815
816 static const char* remapShortTimeZone(const char *stdID, const char *dstID, int32_t daylightType, int32_t offset)
817 {
818     int32_t idx;
819 #ifdef DEBUG_TZNAME
820     fprintf(stderr, "TZ=%s std=%s dst=%s daylight=%d offset=%d\n", getenv("TZ"), stdID, dstID, daylightType, offset);
821 #endif
822     for (idx = 0; idx < UPRV_LENGTHOF(OFFSET_ZONE_MAPPINGS); idx++)
823     {
824         if (offset == OFFSET_ZONE_MAPPINGS[idx].offsetSeconds
825             && daylightType == OFFSET_ZONE_MAPPINGS[idx].daylightType
826             && strcmp(OFFSET_ZONE_MAPPINGS[idx].stdID, stdID) == 0
827             && strcmp(OFFSET_ZONE_MAPPINGS[idx].dstID, dstID) == 0)
828         {
829             return OFFSET_ZONE_MAPPINGS[idx].olsonID;
830         }
831     }
832     return NULL;
833 }
834 #endif
835
836 #ifdef SEARCH_TZFILE
837 #define MAX_READ_SIZE 512
838
839 typedef struct DefaultTZInfo {
840     char* defaultTZBuffer;
841     int64_t defaultTZFileSize;
842     FILE* defaultTZFilePtr;
843     UBool defaultTZstatus;
844     int32_t defaultTZPosition;
845 } DefaultTZInfo;
846
847 /*
848  * This method compares the two files given to see if they are a match.
849  * It is currently use to compare two TZ files.
850  */
851 static UBool compareBinaryFiles(const char* defaultTZFileName, const char* TZFileName, DefaultTZInfo* tzInfo) {
852     FILE* file; 
853     int64_t sizeFile;
854     int64_t sizeFileLeft;
855     int32_t sizeFileRead;
856     int32_t sizeFileToRead;
857     char bufferFile[MAX_READ_SIZE];
858     UBool result = TRUE;
859
860     if (tzInfo->defaultTZFilePtr == NULL) {
861         tzInfo->defaultTZFilePtr = fopen(defaultTZFileName, "r");
862     }
863     file = fopen(TZFileName, "r");
864
865     tzInfo->defaultTZPosition = 0; /* reset position to begin search */
866
867     if (file != NULL && tzInfo->defaultTZFilePtr != NULL) {
868         /* First check that the file size are equal. */
869         if (tzInfo->defaultTZFileSize == 0) {
870             fseek(tzInfo->defaultTZFilePtr, 0, SEEK_END);
871             tzInfo->defaultTZFileSize = ftell(tzInfo->defaultTZFilePtr);
872         }
873         fseek(file, 0, SEEK_END);
874         sizeFile = ftell(file);
875         sizeFileLeft = sizeFile;
876
877         if (sizeFile != tzInfo->defaultTZFileSize) {
878             result = FALSE;
879         } else {
880             /* Store the data from the files in seperate buffers and
881              * compare each byte to determine equality.
882              */
883             if (tzInfo->defaultTZBuffer == NULL) {
884                 rewind(tzInfo->defaultTZFilePtr);
885                 tzInfo->defaultTZBuffer = (char*)uprv_malloc(sizeof(char) * tzInfo->defaultTZFileSize);
886                 sizeFileRead = fread(tzInfo->defaultTZBuffer, 1, tzInfo->defaultTZFileSize, tzInfo->defaultTZFilePtr);
887             }
888             rewind(file);
889             while(sizeFileLeft > 0) {
890                 uprv_memset(bufferFile, 0, MAX_READ_SIZE);
891                 sizeFileToRead = sizeFileLeft < MAX_READ_SIZE ? sizeFileLeft : MAX_READ_SIZE;
892
893                 sizeFileRead = fread(bufferFile, 1, sizeFileToRead, file);
894                 if (memcmp(tzInfo->defaultTZBuffer + tzInfo->defaultTZPosition, bufferFile, sizeFileRead) != 0) {
895                     result = FALSE;
896                     break;
897                 }
898                 sizeFileLeft -= sizeFileRead;
899                 tzInfo->defaultTZPosition += sizeFileRead;
900             }
901         }
902     } else {
903         result = FALSE;
904     }
905
906     if (file != NULL) {
907         fclose(file);
908     }
909
910     return result;
911 }
912
913
914 /* dirent also lists two entries: "." and ".." that we can safely ignore. */
915 #define SKIP1 "."
916 #define SKIP2 ".."
917 static UBool U_CALLCONV putil_cleanup(void);
918 static CharString *gSearchTZFileResult = NULL;
919
920 /*
921  * This method recursively traverses the directory given for a matching TZ file and returns the first match.
922  * This function is not thread safe - it uses a global, gSearchTZFileResult, to hold its results.
923  */
924 static char* searchForTZFile(const char* path, DefaultTZInfo* tzInfo) {
925     DIR* dirp = opendir(path);
926     DIR* subDirp = NULL;
927     struct dirent* dirEntry = NULL;
928
929     char* result = NULL;
930     if (dirp == NULL) {
931         return result;
932     }
933
934     if (gSearchTZFileResult == NULL) {
935         gSearchTZFileResult = new CharString;
936         if (gSearchTZFileResult == NULL) {
937             return NULL;
938         }
939         ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
940     }
941
942     /* Save the current path */
943     UErrorCode status = U_ZERO_ERROR;
944     CharString curpath(path, -1, status);
945     if (U_FAILURE(status)) {
946         return NULL;
947     }
948
949     /* Check each entry in the directory. */
950     while((dirEntry = readdir(dirp)) != NULL) {
951         const char* dirName = dirEntry->d_name;
952         if (uprv_strcmp(dirName, SKIP1) != 0 && uprv_strcmp(dirName, SKIP2) != 0) {
953             /* Create a newpath with the new entry to test each entry in the directory. */
954             CharString newpath(curpath, status);
955             newpath.append(dirName, -1, status);
956             if (U_FAILURE(status)) {
957                 return NULL;
958             }
959
960             if ((subDirp = opendir(newpath.data())) != NULL) {
961                 /* If this new path is a directory, make a recursive call with the newpath. */
962                 closedir(subDirp);
963                 newpath.append('/', status);
964                 if (U_FAILURE(status)) {
965                     return NULL;
966                 }
967                 result = searchForTZFile(newpath.data(), tzInfo);
968                 /*
969                  Have to get out here. Otherwise, we'd keep looking
970                  and return the first match in the top-level directory
971                  if there's a match in the top-level. If not, this function
972                  would return NULL and set gTimeZoneBufferPtr to NULL in initDefault().
973                  It worked without this in most cases because we have a fallback of calling
974                  localtime_r to figure out the default timezone.
975                 */
976                 if (result != NULL)
977                     break;
978             } else if (uprv_strcmp(TZFILE_SKIP, dirName) != 0 && uprv_strcmp(TZFILE_SKIP2, dirName) != 0) {
979                 if(compareBinaryFiles(TZDEFAULT, newpath.data(), tzInfo)) {
980                     int32_t amountToSkip = sizeof(TZZONEINFO) - 1;
981                     if (amountToSkip > newpath.length()) {
982                         amountToSkip = newpath.length();
983                     }
984                     const char* zoneid = newpath.data() + amountToSkip;
985                     skipZoneIDPrefix(&zoneid);
986                     gSearchTZFileResult->clear();
987                     gSearchTZFileResult->append(zoneid, -1, status);
988                     if (U_FAILURE(status)) {
989                         return NULL;
990                     }
991                     result = gSearchTZFileResult->data();
992                     /* Get out after the first one found. */
993                     break;
994                 }
995             }
996         }
997     }
998     closedir(dirp);
999     return result;
1000 }
1001 #endif
1002
1003 U_CAPI void U_EXPORT2
1004 uprv_tzname_clear_cache()
1005 {
1006 #if defined(CHECK_LOCALTIME_LINK) && !defined(DEBUG_SKIP_LOCALTIME_LINK)
1007     gTimeZoneBufferPtr = NULL;
1008 #endif
1009 }
1010
1011 U_CAPI const char* U_EXPORT2
1012 uprv_tzname(int n)
1013 {
1014     const char *tzid = NULL;
1015 #if U_PLATFORM_USES_ONLY_WIN32_API
1016     tzid = uprv_detectWindowsTimeZone();
1017
1018     if (tzid != NULL) {
1019         return tzid;
1020     }
1021 #else
1022
1023 /*#if U_PLATFORM_IS_DARWIN_BASED
1024     int ret;
1025
1026     tzid = getenv("TZFILE");
1027     if (tzid != NULL) {
1028         return tzid;
1029     }
1030 #endif*/
1031
1032 /* This code can be temporarily disabled to test tzname resolution later on. */
1033 #ifndef DEBUG_TZNAME
1034     tzid = getenv("TZ");
1035     if (tzid != NULL && isValidOlsonID(tzid)
1036 #if U_PLATFORM == U_PF_SOLARIS
1037     /* When TZ equals localtime on Solaris, check the /etc/localtime file. */
1038         && uprv_strcmp(tzid, TZ_ENV_CHECK) != 0
1039 #endif
1040     ) {
1041         /* The colon forces tzset() to treat the remainder as zoneinfo path */ 
1042         if (tzid[0] == ':') { 
1043             tzid++; 
1044         } 
1045         /* This might be a good Olson ID. */
1046         skipZoneIDPrefix(&tzid);
1047         return tzid;
1048     }
1049     /* else U_TZNAME will give a better result. */
1050 #endif
1051
1052 #if defined(CHECK_LOCALTIME_LINK) && !defined(DEBUG_SKIP_LOCALTIME_LINK)
1053     /* Caller must handle threading issues */
1054     if (gTimeZoneBufferPtr == NULL) {
1055         /*
1056         This is a trick to look at the name of the link to get the Olson ID
1057         because the tzfile contents is underspecified.
1058         This isn't guaranteed to work because it may not be a symlink.
1059         */
1060         int32_t ret = (int32_t)readlink(TZDEFAULT, gTimeZoneBuffer, sizeof(gTimeZoneBuffer)-1);
1061         if (0 < ret) {
1062             int32_t tzZoneInfoLen = uprv_strlen(TZZONEINFO);
1063             gTimeZoneBuffer[ret] = 0;
1064             if (uprv_strncmp(gTimeZoneBuffer, TZZONEINFO, tzZoneInfoLen) == 0
1065                 && isValidOlsonID(gTimeZoneBuffer + tzZoneInfoLen))
1066             {
1067                 return (gTimeZoneBufferPtr = gTimeZoneBuffer + tzZoneInfoLen);
1068             }
1069 #if U_PLATFORM == U_PF_SOLARIS
1070             else
1071             {
1072                 tzZoneInfoLen = uprv_strlen(TZZONEINFO2);
1073                 if (uprv_strncmp(gTimeZoneBuffer, TZZONEINFO2, tzZoneInfoLen) == 0
1074                                 && isValidOlsonID(gTimeZoneBuffer + tzZoneInfoLen))
1075                 {
1076                     return (gTimeZoneBufferPtr = gTimeZoneBuffer + tzZoneInfoLen);
1077                 }
1078             }
1079 #endif
1080         } else {
1081 #if defined(SEARCH_TZFILE)
1082             DefaultTZInfo* tzInfo = (DefaultTZInfo*)uprv_malloc(sizeof(DefaultTZInfo));
1083             if (tzInfo != NULL) {
1084                 tzInfo->defaultTZBuffer = NULL;
1085                 tzInfo->defaultTZFileSize = 0;
1086                 tzInfo->defaultTZFilePtr = NULL;
1087                 tzInfo->defaultTZstatus = FALSE;
1088                 tzInfo->defaultTZPosition = 0;
1089
1090                 gTimeZoneBufferPtr = searchForTZFile(TZZONEINFO, tzInfo);
1091
1092                 /* Free previously allocated memory */
1093                 if (tzInfo->defaultTZBuffer != NULL) {
1094                     uprv_free(tzInfo->defaultTZBuffer);
1095                 }
1096                 if (tzInfo->defaultTZFilePtr != NULL) {
1097                     fclose(tzInfo->defaultTZFilePtr);
1098                 }
1099                 uprv_free(tzInfo);
1100             }
1101
1102             if (gTimeZoneBufferPtr != NULL && isValidOlsonID(gTimeZoneBufferPtr)) {
1103                 return gTimeZoneBufferPtr;
1104             }
1105 #endif
1106         }
1107     }
1108     else {
1109         return gTimeZoneBufferPtr;
1110     }
1111 #endif
1112 #endif
1113
1114 #ifdef U_TZNAME
1115 #if U_PLATFORM_USES_ONLY_WIN32_API
1116     /* The return value is free'd in timezone.cpp on Windows because
1117      * the other code path returns a pointer to a heap location. */
1118     return uprv_strdup(U_TZNAME[n]);
1119 #else
1120     /*
1121     U_TZNAME is usually a non-unique abbreviation, which isn't normally usable.
1122     So we remap the abbreviation to an olson ID.
1123
1124     Since Windows exposes a little more timezone information,
1125     we normally don't use this code on Windows because
1126     uprv_detectWindowsTimeZone should have already given the correct answer.
1127     */
1128     {
1129         struct tm juneSol, decemberSol;
1130         int daylightType;
1131         static const time_t juneSolstice=1182478260; /*2007-06-21 18:11 UT*/
1132         static const time_t decemberSolstice=1198332540; /*2007-12-22 06:09 UT*/
1133
1134         /* This probing will tell us when daylight savings occurs.  */
1135         localtime_r(&juneSolstice, &juneSol);
1136         localtime_r(&decemberSolstice, &decemberSol);
1137         if(decemberSol.tm_isdst > 0) {
1138           daylightType = U_DAYLIGHT_DECEMBER;
1139         } else if(juneSol.tm_isdst > 0) {
1140           daylightType = U_DAYLIGHT_JUNE;
1141         } else {
1142           daylightType = U_DAYLIGHT_NONE;
1143         }
1144         tzid = remapShortTimeZone(U_TZNAME[0], U_TZNAME[1], daylightType, uprv_timezone());
1145         if (tzid != NULL) {
1146             return tzid;
1147         }
1148     }
1149     return U_TZNAME[n];
1150 #endif
1151 #else
1152     return "";
1153 #endif
1154 }
1155
1156 /* Get and set the ICU data directory --------------------------------------- */
1157
1158 static icu::UInitOnce gDataDirInitOnce = U_INITONCE_INITIALIZER;
1159 static char *gDataDirectory = NULL;
1160
1161 UInitOnce gTimeZoneFilesInitOnce = U_INITONCE_INITIALIZER;
1162 static CharString *gTimeZoneFilesDirectory = NULL;
1163
1164 #if U_POSIX_LOCALE || U_PLATFORM_USES_ONLY_WIN32_API
1165  static char *gCorrectedPOSIXLocale = NULL; /* Heap allocated */
1166 #endif
1167
1168 static UBool U_CALLCONV putil_cleanup(void)
1169 {
1170     if (gDataDirectory && *gDataDirectory) {
1171         uprv_free(gDataDirectory);
1172     }
1173     gDataDirectory = NULL;
1174     gDataDirInitOnce.reset();
1175
1176     delete gTimeZoneFilesDirectory;
1177     gTimeZoneFilesDirectory = NULL;
1178     gTimeZoneFilesInitOnce.reset();
1179
1180 #ifdef SEARCH_TZFILE
1181     delete gSearchTZFileResult;
1182     gSearchTZFileResult = NULL;
1183 #endif
1184
1185 #if U_POSIX_LOCALE || U_PLATFORM_USES_ONLY_WIN32_API
1186     if (gCorrectedPOSIXLocale) {
1187         uprv_free(gCorrectedPOSIXLocale);
1188         gCorrectedPOSIXLocale = NULL;
1189     }
1190 #endif
1191     return TRUE;
1192 }
1193
1194 /*
1195  * Set the data directory.
1196  *    Make a copy of the passed string, and set the global data dir to point to it.
1197  */
1198 U_CAPI void U_EXPORT2
1199 u_setDataDirectory(const char *directory) {
1200     char *newDataDir;
1201     int32_t length;
1202
1203     if(directory==NULL || *directory==0) {
1204         /* A small optimization to prevent the malloc and copy when the
1205         shared library is used, and this is a way to make sure that NULL
1206         is never returned.
1207         */
1208         newDataDir = (char *)"";
1209     }
1210     else {
1211         length=(int32_t)uprv_strlen(directory);
1212         newDataDir = (char *)uprv_malloc(length + 2);
1213         /* Exit out if newDataDir could not be created. */
1214         if (newDataDir == NULL) {
1215             return;
1216         }
1217         uprv_strcpy(newDataDir, directory);
1218
1219 #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
1220         {
1221             char *p;
1222             while(p = uprv_strchr(newDataDir, U_FILE_ALT_SEP_CHAR)) {
1223                 *p = U_FILE_SEP_CHAR;
1224             }
1225         }
1226 #endif
1227     }
1228
1229     if (gDataDirectory && *gDataDirectory) {
1230         uprv_free(gDataDirectory);
1231     }
1232     gDataDirectory = newDataDir;
1233     ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
1234 }
1235
1236 U_CAPI UBool U_EXPORT2
1237 uprv_pathIsAbsolute(const char *path)
1238 {
1239   if(!path || !*path) {
1240     return FALSE;
1241   }
1242
1243   if(*path == U_FILE_SEP_CHAR) {
1244     return TRUE;
1245   }
1246
1247 #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
1248   if(*path == U_FILE_ALT_SEP_CHAR) {
1249     return TRUE;
1250   }
1251 #endif
1252
1253 #if U_PLATFORM_USES_ONLY_WIN32_API
1254   if( (((path[0] >= 'A') && (path[0] <= 'Z')) ||
1255        ((path[0] >= 'a') && (path[0] <= 'z'))) &&
1256       path[1] == ':' ) {
1257     return TRUE;
1258   }
1259 #endif
1260
1261   return FALSE;
1262 }
1263
1264 /* Temporary backup setting of ICU_DATA_DIR_PREFIX_ENV_VAR
1265    until some client wrapper makefiles are updated */
1266 #if U_PLATFORM_IS_DARWIN_BASED && TARGET_IPHONE_SIMULATOR
1267 # if !defined(ICU_DATA_DIR_PREFIX_ENV_VAR)
1268 #  define ICU_DATA_DIR_PREFIX_ENV_VAR "IPHONE_SIMULATOR_ROOT"
1269 # endif
1270 #endif
1271
1272 static void U_CALLCONV dataDirectoryInitFn() {
1273     /* If we already have the directory, then return immediately. Will happen if user called
1274      * u_setDataDirectory().
1275      */
1276     if (gDataDirectory) {
1277         return;
1278     }
1279
1280     const char *path = NULL;
1281 #if defined(ICU_DATA_DIR_PREFIX_ENV_VAR)
1282     char datadir_path_buffer[PATH_MAX];
1283 #endif
1284
1285     /*
1286     When ICU_NO_USER_DATA_OVERRIDE is defined, users aren't allowed to
1287     override ICU's data with the ICU_DATA environment variable. This prevents
1288     problems where multiple custom copies of ICU's specific version of data
1289     are installed on a system. Either the application must define the data
1290     directory with u_setDataDirectory, define ICU_DATA_DIR when compiling
1291     ICU, set the data with udata_setCommonData or trust that all of the
1292     required data is contained in ICU's data library that contains
1293     the entry point defined by U_ICUDATA_ENTRY_POINT.
1294
1295     There may also be some platforms where environment variables
1296     are not allowed.
1297     */
1298 #   if !defined(ICU_NO_USER_DATA_OVERRIDE) && !UCONFIG_NO_FILE_IO
1299     /* First try to get the environment variable */
1300     path=getenv("ICU_DATA");
1301 #   endif
1302
1303     /* ICU_DATA_DIR may be set as a compile option.
1304      * U_ICU_DATA_DEFAULT_DIR is provided and is set by ICU at compile time
1305      * and is used only when data is built in archive mode eliminating the need
1306      * for ICU_DATA_DIR to be set. U_ICU_DATA_DEFAULT_DIR is set to the installation
1307      * directory of the data dat file. Users should use ICU_DATA_DIR if they want to
1308      * set their own path.
1309      */
1310 #if defined(ICU_DATA_DIR) || defined(U_ICU_DATA_DEFAULT_DIR)
1311     if(path==NULL || *path==0) {
1312 # if defined(ICU_DATA_DIR_PREFIX_ENV_VAR)
1313         const char *prefix = getenv(ICU_DATA_DIR_PREFIX_ENV_VAR);
1314 # endif
1315 # ifdef ICU_DATA_DIR
1316         path=ICU_DATA_DIR;
1317 # else
1318         path=U_ICU_DATA_DEFAULT_DIR;
1319 # endif
1320 # if defined(ICU_DATA_DIR_PREFIX_ENV_VAR)
1321         if (prefix != NULL) {
1322             snprintf(datadir_path_buffer, PATH_MAX, "%s%s", prefix, path);
1323             path=datadir_path_buffer;
1324         }
1325 # endif
1326     }
1327 #endif
1328
1329     if(path==NULL) {
1330         /* It looks really bad, set it to something. */
1331         path = "";
1332     }
1333
1334     u_setDataDirectory(path);
1335     return;
1336 }
1337
1338 U_CAPI const char * U_EXPORT2
1339 u_getDataDirectory(void) {
1340     umtx_initOnce(gDataDirInitOnce, &dataDirectoryInitFn);
1341     return gDataDirectory;
1342 }
1343
1344 static void setTimeZoneFilesDir(const char *path, UErrorCode &status) {
1345     if (U_FAILURE(status)) {
1346         return;
1347     }
1348     gTimeZoneFilesDirectory->clear();
1349     gTimeZoneFilesDirectory->append(path, status);
1350 #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR)
1351     char *p = gTimeZoneFilesDirectory->data();
1352     while (p = uprv_strchr(p, U_FILE_ALT_SEP_CHAR)) {
1353         *p = U_FILE_SEP_CHAR;
1354     }
1355 #endif
1356 }
1357
1358 #define TO_STRING(x) TO_STRING_2(x) 
1359 #define TO_STRING_2(x) #x
1360
1361 static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) {
1362     U_ASSERT(gTimeZoneFilesDirectory == NULL);
1363     ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
1364     gTimeZoneFilesDirectory = new CharString();
1365     if (gTimeZoneFilesDirectory == NULL) {
1366         status = U_MEMORY_ALLOCATION_ERROR;
1367         return;
1368     }
1369     const char *dir = getenv("ICU_TIMEZONE_FILES_DIR");
1370 #if defined(U_TIMEZONE_FILES_DIR)
1371     if (dir == NULL) {
1372         dir = TO_STRING(U_TIMEZONE_FILES_DIR);
1373     }
1374 #endif
1375     if (dir == NULL) {
1376         dir = "";
1377     }
1378     setTimeZoneFilesDir(dir, status);
1379 }
1380
1381
1382 U_CAPI const char * U_EXPORT2
1383 u_getTimeZoneFilesDirectory(UErrorCode *status) {
1384     umtx_initOnce(gTimeZoneFilesInitOnce, &TimeZoneDataDirInitFn, *status);
1385     return U_SUCCESS(*status) ? gTimeZoneFilesDirectory->data() : "";
1386 }
1387
1388 U_CAPI void U_EXPORT2
1389 u_setTimeZoneFilesDirectory(const char *path, UErrorCode *status) {
1390     umtx_initOnce(gTimeZoneFilesInitOnce, &TimeZoneDataDirInitFn, *status);
1391     setTimeZoneFilesDir(path, *status);
1392
1393     // Note: this function does some extra churn, first setting based on the
1394     //       environment, then immediately replacing with the value passed in.
1395     //       The logic is simpler that way, and performance shouldn't be an issue.
1396 }
1397
1398
1399 #if U_POSIX_LOCALE
1400 /* A helper function used by uprv_getPOSIXIDForDefaultLocale and
1401  * uprv_getPOSIXIDForDefaultCodepage. Returns the posix locale id for
1402  * LC_CTYPE and LC_MESSAGES. It doesn't support other locale categories.
1403  */
1404 static const char *uprv_getPOSIXIDForCategory(int category)
1405 {
1406     const char* posixID = NULL;
1407     if (category == LC_MESSAGES || category == LC_CTYPE) {
1408         /*
1409         * On Solaris two different calls to setlocale can result in
1410         * different values. Only get this value once.
1411         *
1412         * We must check this first because an application can set this.
1413         *
1414         * LC_ALL can't be used because it's platform dependent. The LANG
1415         * environment variable seems to affect LC_CTYPE variable by default.
1416         * Here is what setlocale(LC_ALL, NULL) can return.
1417         * HPUX can return 'C C C C C C C'
1418         * Solaris can return /en_US/C/C/C/C/C on the second try.
1419         * Linux can return LC_CTYPE=C;LC_NUMERIC=C;...
1420         *
1421         * The default codepage detection also needs to use LC_CTYPE.
1422         *
1423         * Do not call setlocale(LC_*, "")! Using an empty string instead
1424         * of NULL, will modify the libc behavior.
1425         */
1426         posixID = setlocale(category, NULL);
1427         if ((posixID == 0)
1428             || (uprv_strcmp("C", posixID) == 0)
1429             || (uprv_strcmp("POSIX", posixID) == 0))
1430         {
1431             /* Maybe we got some garbage.  Try something more reasonable */
1432             posixID = getenv("LC_ALL");
1433             /* Solaris speaks POSIX -  See IEEE Std 1003.1-2008 
1434              * This is needed to properly handle empty env. variables
1435              */
1436 #if U_PLATFORM == U_PF_SOLARIS
1437             if ((posixID == 0) || (posixID[0] == '\0')) {
1438                 posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE");
1439                 if ((posixID == 0) || (posixID[0] == '\0')) {
1440 #else
1441             if (posixID == 0) {
1442                 posixID = getenv(category == LC_MESSAGES ? "LC_MESSAGES" : "LC_CTYPE");
1443                 if (posixID == 0) {
1444 #endif                    
1445                     posixID = getenv("LANG");
1446                 }
1447             }
1448         }
1449     }
1450     if ((posixID==0)
1451         || (uprv_strcmp("C", posixID) == 0)
1452         || (uprv_strcmp("POSIX", posixID) == 0))
1453     {
1454         /* Nothing worked.  Give it a nice POSIX default value. */
1455         posixID = "en_US_POSIX";
1456     }
1457     return posixID;
1458 }
1459
1460 /* Return just the POSIX id for the default locale, whatever happens to be in
1461  * it. It gets the value from LC_MESSAGES and indirectly from LC_ALL and LANG.
1462  */
1463 static const char *uprv_getPOSIXIDForDefaultLocale(void)
1464 {
1465     static const char* posixID = NULL;
1466     if (posixID == 0) {
1467         posixID = uprv_getPOSIXIDForCategory(LC_MESSAGES);
1468     }
1469     return posixID;
1470 }
1471
1472 #if !U_CHARSET_IS_UTF8
1473 /* Return just the POSIX id for the default codepage, whatever happens to be in
1474  * it. It gets the value from LC_CTYPE and indirectly from LC_ALL and LANG.
1475  */
1476 static const char *uprv_getPOSIXIDForDefaultCodepage(void)
1477 {
1478     static const char* posixID = NULL;
1479     if (posixID == 0) {
1480         posixID = uprv_getPOSIXIDForCategory(LC_CTYPE);
1481     }
1482     return posixID;
1483 }
1484 #endif
1485 #endif
1486
1487 /* NOTE: The caller should handle thread safety */
1488 U_CAPI const char* U_EXPORT2
1489 uprv_getDefaultLocaleID()
1490 {
1491 #if U_POSIX_LOCALE
1492 /*
1493   Note that:  (a '!' means the ID is improper somehow)
1494      LC_ALL  ---->     default_loc          codepage
1495 --------------------------------------------------------
1496      ab.CD             ab                   CD
1497      ab@CD             ab__CD               -
1498      ab@CD.EF          ab__CD               EF
1499
1500      ab_CD.EF@GH       ab_CD_GH             EF
1501
1502 Some 'improper' ways to do the same as above:
1503   !  ab_CD@GH.EF       ab_CD_GH             EF
1504   !  ab_CD.EF@GH.IJ    ab_CD_GH             EF
1505   !  ab_CD@ZZ.EF@GH.IJ ab_CD_GH             EF
1506
1507      _CD@GH            _CD_GH               -
1508      _CD.EF@GH         _CD_GH               EF
1509
1510 The variant cannot have dots in it.
1511 The 'rightmost' variant (@xxx) wins.
1512 The leftmost codepage (.xxx) wins.
1513 */
1514     char *correctedPOSIXLocale = 0;
1515     const char* posixID = uprv_getPOSIXIDForDefaultLocale();
1516     const char *p;
1517     const char *q;
1518     int32_t len;
1519
1520     /* Format: (no spaces)
1521     ll [ _CC ] [ . MM ] [ @ VV]
1522
1523       l = lang, C = ctry, M = charmap, V = variant
1524     */
1525
1526     if (gCorrectedPOSIXLocale != NULL) {
1527         return gCorrectedPOSIXLocale;
1528     }
1529
1530     if ((p = uprv_strchr(posixID, '.')) != NULL) {
1531         /* assume new locale can't be larger than old one? */
1532         correctedPOSIXLocale = static_cast<char *>(uprv_malloc(uprv_strlen(posixID)+1));
1533         /* Exit on memory allocation error. */
1534         if (correctedPOSIXLocale == NULL) {
1535             return NULL;
1536         }
1537         uprv_strncpy(correctedPOSIXLocale, posixID, p-posixID);
1538         correctedPOSIXLocale[p-posixID] = 0;
1539
1540         /* do not copy after the @ */
1541         if ((p = uprv_strchr(correctedPOSIXLocale, '@')) != NULL) {
1542             correctedPOSIXLocale[p-correctedPOSIXLocale] = 0;
1543         }
1544     }
1545
1546     /* Note that we scan the *uncorrected* ID. */
1547     if ((p = uprv_strrchr(posixID, '@')) != NULL) {
1548         if (correctedPOSIXLocale == NULL) {
1549             correctedPOSIXLocale = static_cast<char *>(uprv_malloc(uprv_strlen(posixID)+1));
1550             /* Exit on memory allocation error. */
1551             if (correctedPOSIXLocale == NULL) {
1552                 return NULL;
1553             }
1554             uprv_strncpy(correctedPOSIXLocale, posixID, p-posixID);
1555             correctedPOSIXLocale[p-posixID] = 0;
1556         }
1557         p++;
1558
1559         /* Take care of any special cases here.. */
1560         if (!uprv_strcmp(p, "nynorsk")) {
1561             p = "NY";
1562             /* Don't worry about no__NY. In practice, it won't appear. */
1563         }
1564
1565         if (uprv_strchr(correctedPOSIXLocale,'_') == NULL) {
1566             uprv_strcat(correctedPOSIXLocale, "__"); /* aa@b -> aa__b */
1567         }
1568         else {
1569             uprv_strcat(correctedPOSIXLocale, "_"); /* aa_CC@b -> aa_CC_b */
1570         }
1571
1572         if ((q = uprv_strchr(p, '.')) != NULL) {
1573             /* How big will the resulting string be? */
1574             len = (int32_t)(uprv_strlen(correctedPOSIXLocale) + (q-p));
1575             uprv_strncat(correctedPOSIXLocale, p, q-p);
1576             correctedPOSIXLocale[len] = 0;
1577         }
1578         else {
1579             /* Anything following the @ sign */
1580             uprv_strcat(correctedPOSIXLocale, p);
1581         }
1582
1583         /* Should there be a map from 'no@nynorsk' -> no_NO_NY here?
1584          * How about 'russian' -> 'ru'?
1585          * Many of the other locales using ISO codes will be handled by the
1586          * canonicalization functions in uloc_getDefault.
1587          */
1588     }
1589
1590     /* Was a correction made? */
1591     if (correctedPOSIXLocale != NULL) {
1592         posixID = correctedPOSIXLocale;
1593     }
1594     else {
1595         /* copy it, just in case the original pointer goes away.  See j2395 */
1596         correctedPOSIXLocale = (char *)uprv_malloc(uprv_strlen(posixID) + 1);
1597         /* Exit on memory allocation error. */
1598         if (correctedPOSIXLocale == NULL) {
1599             return NULL;
1600         }
1601         posixID = uprv_strcpy(correctedPOSIXLocale, posixID);
1602     }
1603
1604     if (gCorrectedPOSIXLocale == NULL) {
1605         gCorrectedPOSIXLocale = correctedPOSIXLocale;
1606         ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
1607         correctedPOSIXLocale = NULL;
1608     }
1609
1610     if (correctedPOSIXLocale != NULL) {  /* Was already set - clean up. */
1611         uprv_free(correctedPOSIXLocale);
1612     }
1613
1614     return posixID;
1615
1616 #elif U_PLATFORM_USES_ONLY_WIN32_API
1617 #define POSIX_LOCALE_CAPACITY 64
1618     UErrorCode status = U_ZERO_ERROR;
1619     char *correctedPOSIXLocale = 0;
1620
1621     if (gCorrectedPOSIXLocale != NULL) {
1622         return gCorrectedPOSIXLocale;
1623     }
1624
1625     LCID id = GetThreadLocale();
1626     correctedPOSIXLocale = static_cast<char *>(uprv_malloc(POSIX_LOCALE_CAPACITY + 1));
1627     if (correctedPOSIXLocale) {
1628         int32_t posixLen = uprv_convertToPosix(id, correctedPOSIXLocale, POSIX_LOCALE_CAPACITY, &status);
1629         if (U_SUCCESS(status)) {
1630             *(correctedPOSIXLocale + posixLen) = 0;
1631             gCorrectedPOSIXLocale = correctedPOSIXLocale;
1632             ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup);
1633         } else {
1634             uprv_free(correctedPOSIXLocale);
1635         }
1636     }
1637
1638     if (gCorrectedPOSIXLocale == NULL) {
1639         return "en_US";
1640     }
1641     return gCorrectedPOSIXLocale;
1642
1643 #elif U_PLATFORM == U_PF_OS400
1644     /* locales are process scoped and are by definition thread safe */
1645     static char correctedLocale[64];
1646     const  char *localeID = getenv("LC_ALL");
1647            char *p;
1648
1649     if (localeID == NULL)
1650         localeID = getenv("LANG");
1651     if (localeID == NULL)
1652         localeID = setlocale(LC_ALL, NULL);
1653     /* Make sure we have something... */
1654     if (localeID == NULL)
1655         return "en_US_POSIX";
1656
1657     /* Extract the locale name from the path. */
1658     if((p = uprv_strrchr(localeID, '/')) != NULL)
1659     {
1660         /* Increment p to start of locale name. */
1661         p++;
1662         localeID = p;
1663     }
1664
1665     /* Copy to work location. */
1666     uprv_strcpy(correctedLocale, localeID);
1667
1668     /* Strip off the '.locale' extension. */
1669     if((p = uprv_strchr(correctedLocale, '.')) != NULL) {
1670         *p = 0;
1671     }
1672
1673     /* Upper case the locale name. */
1674     T_CString_toUpperCase(correctedLocale);
1675
1676     /* See if we are using the POSIX locale.  Any of the
1677     * following are equivalent and use the same QLGPGCMA
1678     * (POSIX) locale.
1679     * QLGPGCMA2 means UCS2
1680     * QLGPGCMA_4 means UTF-32
1681     * QLGPGCMA_8 means UTF-8
1682     */
1683     if ((uprv_strcmp("C", correctedLocale) == 0) ||
1684         (uprv_strcmp("POSIX", correctedLocale) == 0) ||
1685         (uprv_strncmp("QLGPGCMA", correctedLocale, 8) == 0))
1686     {
1687         uprv_strcpy(correctedLocale, "en_US_POSIX");
1688     }
1689     else
1690     {
1691         int16_t LocaleLen;
1692
1693         /* Lower case the lang portion. */
1694         for(p = correctedLocale; *p != 0 && *p != '_'; p++)
1695         {
1696             *p = uprv_tolower(*p);
1697         }
1698
1699         /* Adjust for Euro.  After '_E' add 'URO'. */
1700         LocaleLen = uprv_strlen(correctedLocale);
1701         if (correctedLocale[LocaleLen - 2] == '_' &&
1702             correctedLocale[LocaleLen - 1] == 'E')
1703         {
1704             uprv_strcat(correctedLocale, "URO");
1705         }
1706
1707         /* If using Lotus-based locale then convert to
1708          * equivalent non Lotus.
1709          */
1710         else if (correctedLocale[LocaleLen - 2] == '_' &&
1711             correctedLocale[LocaleLen - 1] == 'L')
1712         {
1713             correctedLocale[LocaleLen - 2] = 0;
1714         }
1715
1716         /* There are separate simplified and traditional
1717          * locales called zh_HK_S and zh_HK_T.
1718          */
1719         else if (uprv_strncmp(correctedLocale, "zh_HK", 5) == 0)
1720         {
1721             uprv_strcpy(correctedLocale, "zh_HK");
1722         }
1723
1724         /* A special zh_CN_GBK locale...
1725         */
1726         else if (uprv_strcmp(correctedLocale, "zh_CN_GBK") == 0)
1727         {
1728             uprv_strcpy(correctedLocale, "zh_CN");
1729         }
1730
1731     }
1732
1733     return correctedLocale;
1734 #endif
1735
1736 }
1737
1738 #if !U_CHARSET_IS_UTF8
1739 #if U_POSIX_LOCALE
1740 /*
1741 Due to various platform differences, one platform may specify a charset,
1742 when they really mean a different charset. Remap the names so that they are
1743 compatible with ICU. Only conflicting/ambiguous aliases should be resolved
1744 here. Before adding anything to this function, please consider adding unique
1745 names to the ICU alias table in the data directory.
1746 */
1747 static const char*
1748 remapPlatformDependentCodepage(const char *locale, const char *name) {
1749     if (locale != NULL && *locale == 0) {
1750         /* Make sure that an empty locale is handled the same way. */
1751         locale = NULL;
1752     }
1753     if (name == NULL) {
1754         return NULL;
1755     }
1756 #if U_PLATFORM == U_PF_AIX
1757     if (uprv_strcmp(name, "IBM-943") == 0) {
1758         /* Use the ASCII compatible ibm-943 */
1759         name = "Shift-JIS";
1760     }
1761     else if (uprv_strcmp(name, "IBM-1252") == 0) {
1762         /* Use the windows-1252 that contains the Euro */
1763         name = "IBM-5348";
1764     }
1765 #elif U_PLATFORM == U_PF_SOLARIS
1766     if (locale != NULL && uprv_strcmp(name, "EUC") == 0) {
1767         /* Solaris underspecifies the "EUC" name. */
1768         if (uprv_strcmp(locale, "zh_CN") == 0) {
1769             name = "EUC-CN";
1770         }
1771         else if (uprv_strcmp(locale, "zh_TW") == 0) {
1772             name = "EUC-TW";
1773         }
1774         else if (uprv_strcmp(locale, "ko_KR") == 0) {
1775             name = "EUC-KR";
1776         }
1777     }
1778     else if (uprv_strcmp(name, "eucJP") == 0) {
1779         /*
1780         ibm-954 is the best match.
1781         ibm-33722 is the default for eucJP (similar to Windows).
1782         */
1783         name = "eucjis";
1784     }
1785     else if (uprv_strcmp(name, "646") == 0) {
1786         /*
1787          * The default codepage given by Solaris is 646 but the C library routines treat it as if it was
1788          * ISO-8859-1 instead of US-ASCII(646).
1789          */
1790         name = "ISO-8859-1";
1791     }
1792 #elif U_PLATFORM_IS_DARWIN_BASED
1793     if (locale == NULL && *name == 0) {
1794         /*
1795         No locale was specified, and an empty name was passed in.
1796         This usually indicates that nl_langinfo didn't return valid information.
1797         Mac OS X uses UTF-8 by default (especially the locale data and console).
1798         */
1799         name = "UTF-8";
1800     }
1801     else if (uprv_strcmp(name, "CP949") == 0) {
1802         /* Remap CP949 to a similar codepage to avoid issues with backslash and won symbol. */
1803         name = "EUC-KR";
1804     }
1805     else if (locale != NULL && uprv_strcmp(locale, "en_US_POSIX") != 0 && uprv_strcmp(name, "US-ASCII") == 0) {
1806         /*
1807          * For non C/POSIX locale, default the code page to UTF-8 instead of US-ASCII.
1808          */
1809         name = "UTF-8";
1810     }
1811 #elif U_PLATFORM == U_PF_BSD
1812     if (uprv_strcmp(name, "CP949") == 0) {
1813         /* Remap CP949 to a similar codepage to avoid issues with backslash and won symbol. */
1814         name = "EUC-KR";
1815     }
1816 #elif U_PLATFORM == U_PF_HPUX
1817     if (locale != NULL && uprv_strcmp(locale, "zh_HK") == 0 && uprv_strcmp(name, "big5") == 0) {
1818         /* HP decided to extend big5 as hkbig5 even though it's not compatible :-( */
1819         /* zh_TW.big5 is not the same charset as zh_HK.big5! */
1820         name = "hkbig5";
1821     }
1822     else if (uprv_strcmp(name, "eucJP") == 0) {
1823         /*
1824         ibm-1350 is the best match, but unavailable.
1825         ibm-954 is mostly a superset of ibm-1350.
1826         ibm-33722 is the default for eucJP (similar to Windows).
1827         */
1828         name = "eucjis";
1829     }
1830 #elif U_PLATFORM == U_PF_LINUX
1831     if (locale != NULL && uprv_strcmp(name, "euc") == 0) {
1832         /* Linux underspecifies the "EUC" name. */
1833         if (uprv_strcmp(locale, "korean") == 0) {
1834             name = "EUC-KR";
1835         }
1836         else if (uprv_strcmp(locale, "japanese") == 0) {
1837             /* See comment below about eucJP */
1838             name = "eucjis";
1839         }
1840     }
1841     else if (uprv_strcmp(name, "eucjp") == 0) {
1842         /*
1843         ibm-1350 is the best match, but unavailable.
1844         ibm-954 is mostly a superset of ibm-1350.
1845         ibm-33722 is the default for eucJP (similar to Windows).
1846         */
1847         name = "eucjis";
1848     }
1849     else if (locale != NULL && uprv_strcmp(locale, "en_US_POSIX") != 0 &&
1850             (uprv_strcmp(name, "ANSI_X3.4-1968") == 0 || uprv_strcmp(name, "US-ASCII") == 0)) {
1851         /*
1852          * For non C/POSIX locale, default the code page to UTF-8 instead of US-ASCII.
1853          */
1854         name = "UTF-8";
1855     }
1856     /*
1857      * Linux returns ANSI_X3.4-1968 for C/POSIX, but the call site takes care of
1858      * it by falling back to 'US-ASCII' when NULL is returned from this
1859      * function. So, we don't have to worry about it here.
1860      */
1861 #endif
1862     /* return NULL when "" is passed in */
1863     if (*name == 0) {
1864         name = NULL;
1865     }
1866     return name;
1867 }
1868
1869 static const char*
1870 getCodepageFromPOSIXID(const char *localeName, char * buffer, int32_t buffCapacity)
1871 {
1872     char localeBuf[100];
1873     const char *name = NULL;
1874     char *variant = NULL;
1875
1876     if (localeName != NULL && (name = (uprv_strchr(localeName, '.'))) != NULL) {
1877         size_t localeCapacity = uprv_min(sizeof(localeBuf), (name-localeName)+1);
1878         uprv_strncpy(localeBuf, localeName, localeCapacity);
1879         localeBuf[localeCapacity-1] = 0; /* ensure NULL termination */
1880         name = uprv_strncpy(buffer, name+1, buffCapacity);
1881         buffer[buffCapacity-1] = 0; /* ensure NULL termination */
1882         if ((variant = const_cast<char *>(uprv_strchr(name, '@'))) != NULL) {
1883             *variant = 0;
1884         }
1885         name = remapPlatformDependentCodepage(localeBuf, name);
1886     }
1887     return name;
1888 }
1889 #endif
1890
1891 static const char*
1892 int_getDefaultCodepage()
1893 {
1894 #if U_PLATFORM == U_PF_OS400
1895     uint32_t ccsid = 37; /* Default to ibm-37 */
1896     static char codepage[64];
1897     Qwc_JOBI0400_t jobinfo;
1898     Qus_EC_t error = { sizeof(Qus_EC_t) }; /* SPI error code */
1899
1900     EPT_CALL(QUSRJOBI)(&jobinfo, sizeof(jobinfo), "JOBI0400",
1901         "*                         ", "                ", &error);
1902
1903     if (error.Bytes_Available == 0) {
1904         if (jobinfo.Coded_Char_Set_ID != 0xFFFF) {
1905             ccsid = (uint32_t)jobinfo.Coded_Char_Set_ID;
1906         }
1907         else if (jobinfo.Default_Coded_Char_Set_Id != 0xFFFF) {
1908             ccsid = (uint32_t)jobinfo.Default_Coded_Char_Set_Id;
1909         }
1910         /* else use the default */
1911     }
1912     sprintf(codepage,"ibm-%d", ccsid);
1913     return codepage;
1914
1915 #elif U_PLATFORM == U_PF_OS390
1916     static char codepage[64];
1917
1918     strncpy(codepage, nl_langinfo(CODESET),63-strlen(UCNV_SWAP_LFNL_OPTION_STRING));
1919     strcat(codepage,UCNV_SWAP_LFNL_OPTION_STRING);
1920     codepage[63] = 0; /* NULL terminate */
1921
1922     return codepage;
1923
1924 #elif U_PLATFORM_USES_ONLY_WIN32_API
1925     static char codepage[64];
1926     sprintf(codepage, "windows-%d", GetACP());
1927     return codepage;
1928
1929 #elif U_POSIX_LOCALE
1930     static char codesetName[100];
1931     const char *localeName = NULL;
1932     const char *name = NULL;
1933
1934     localeName = uprv_getPOSIXIDForDefaultCodepage();
1935     uprv_memset(codesetName, 0, sizeof(codesetName));
1936     /* On Solaris nl_langinfo returns C locale values unless setlocale
1937      * was called earlier.
1938      */
1939 #if (U_HAVE_NL_LANGINFO_CODESET && U_PLATFORM != U_PF_SOLARIS)
1940     /* When available, check nl_langinfo first because it usually gives more
1941        useful names. It depends on LC_CTYPE.
1942        nl_langinfo may use the same buffer as setlocale. */
1943     {
1944         const char *codeset = nl_langinfo(U_NL_LANGINFO_CODESET);
1945 #if U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED
1946         /*
1947          * On Linux and MacOSX, ensure that default codepage for non C/POSIX locale is UTF-8
1948          * instead of ASCII.
1949          */
1950         if (uprv_strcmp(localeName, "en_US_POSIX") != 0) {
1951             codeset = remapPlatformDependentCodepage(localeName, codeset);
1952         } else
1953 #endif
1954         {
1955             codeset = remapPlatformDependentCodepage(NULL, codeset);
1956         }
1957
1958         if (codeset != NULL) {
1959             uprv_strncpy(codesetName, codeset, sizeof(codesetName));
1960             codesetName[sizeof(codesetName)-1] = 0;
1961             return codesetName;
1962         }
1963     }
1964 #endif
1965
1966     /* Use setlocale in a nice way, and then check some environment variables.
1967        Maybe the application used setlocale already.
1968     */
1969     uprv_memset(codesetName, 0, sizeof(codesetName));
1970     name = getCodepageFromPOSIXID(localeName, codesetName, sizeof(codesetName));
1971     if (name) {
1972         /* if we can find the codeset name from setlocale, return that. */
1973         return name;
1974     }
1975
1976     if (*codesetName == 0)
1977     {
1978         /* Everything failed. Return US ASCII (ISO 646). */
1979         (void)uprv_strcpy(codesetName, "US-ASCII");
1980     }
1981     return codesetName;
1982 #else
1983     return "US-ASCII";
1984 #endif
1985 }
1986
1987
1988 U_CAPI const char*  U_EXPORT2
1989 uprv_getDefaultCodepage()
1990 {
1991     static char const  *name = NULL;
1992     umtx_lock(NULL);
1993     if (name == NULL) {
1994         name = int_getDefaultCodepage();
1995     }
1996     umtx_unlock(NULL);
1997     return name;
1998 }
1999 #endif  /* !U_CHARSET_IS_UTF8 */
2000
2001
2002 /* end of platform-specific implementation -------------- */
2003
2004 /* version handling --------------------------------------------------------- */
2005
2006 U_CAPI void U_EXPORT2
2007 u_versionFromString(UVersionInfo versionArray, const char *versionString) {
2008     char *end;
2009     uint16_t part=0;
2010
2011     if(versionArray==NULL) {
2012         return;
2013     }
2014
2015     if(versionString!=NULL) {
2016         for(;;) {
2017             versionArray[part]=(uint8_t)uprv_strtoul(versionString, &end, 10);
2018             if(end==versionString || ++part==U_MAX_VERSION_LENGTH || *end!=U_VERSION_DELIMITER) {
2019                 break;
2020             }
2021             versionString=end+1;
2022         }
2023     }
2024
2025     while(part<U_MAX_VERSION_LENGTH) {
2026         versionArray[part++]=0;
2027     }
2028 }
2029
2030 U_CAPI void U_EXPORT2
2031 u_versionFromUString(UVersionInfo versionArray, const UChar *versionString) {
2032     if(versionArray!=NULL && versionString!=NULL) {
2033         char versionChars[U_MAX_VERSION_STRING_LENGTH+1];
2034         int32_t len = u_strlen(versionString);
2035         if(len>U_MAX_VERSION_STRING_LENGTH) {
2036             len = U_MAX_VERSION_STRING_LENGTH;
2037         }
2038         u_UCharsToChars(versionString, versionChars, len);
2039         versionChars[len]=0;
2040         u_versionFromString(versionArray, versionChars);
2041     }
2042 }
2043
2044 U_CAPI void U_EXPORT2
2045 u_versionToString(const UVersionInfo versionArray, char *versionString) {
2046     uint16_t count, part;
2047     uint8_t field;
2048
2049     if(versionString==NULL) {
2050         return;
2051     }
2052
2053     if(versionArray==NULL) {
2054         versionString[0]=0;
2055         return;
2056     }
2057
2058     /* count how many fields need to be written */
2059     for(count=4; count>0 && versionArray[count-1]==0; --count) {
2060     }
2061
2062     if(count <= 1) {
2063         count = 2;
2064     }
2065
2066     /* write the first part */
2067     /* write the decimal field value */
2068     field=versionArray[0];
2069     if(field>=100) {
2070         *versionString++=(char)('0'+field/100);
2071         field%=100;
2072     }
2073     if(field>=10) {
2074         *versionString++=(char)('0'+field/10);
2075         field%=10;
2076     }
2077     *versionString++=(char)('0'+field);
2078
2079     /* write the following parts */
2080     for(part=1; part<count; ++part) {
2081         /* write a dot first */
2082         *versionString++=U_VERSION_DELIMITER;
2083
2084         /* write the decimal field value */
2085         field=versionArray[part];
2086         if(field>=100) {
2087             *versionString++=(char)('0'+field/100);
2088             field%=100;
2089         }
2090         if(field>=10) {
2091             *versionString++=(char)('0'+field/10);
2092             field%=10;
2093         }
2094         *versionString++=(char)('0'+field);
2095     }
2096
2097     /* NUL-terminate */
2098     *versionString=0;
2099 }
2100
2101 U_CAPI void U_EXPORT2
2102 u_getVersion(UVersionInfo versionArray) {
2103     (void)copyright;   // Suppress unused variable warning from clang.
2104     u_versionFromString(versionArray, U_ICU_VERSION);
2105 }
2106
2107 /**
2108  * icucfg.h dependent code 
2109  */
2110
2111 #if U_ENABLE_DYLOAD
2112  
2113 #if HAVE_DLOPEN && !U_PLATFORM_USES_ONLY_WIN32_API
2114
2115 #if HAVE_DLFCN_H
2116
2117 #ifdef __MVS__
2118 #ifndef __SUSV3
2119 #define __SUSV3 1
2120 #endif
2121 #endif
2122 #include <dlfcn.h>
2123 #endif
2124
2125 U_INTERNAL void * U_EXPORT2
2126 uprv_dl_open(const char *libName, UErrorCode *status) {
2127   void *ret = NULL;
2128   if(U_FAILURE(*status)) return ret;
2129   ret =  dlopen(libName, RTLD_NOW|RTLD_GLOBAL);
2130   if(ret==NULL) {
2131 #ifdef U_TRACE_DYLOAD
2132     printf("dlerror on dlopen(%s): %s\n", libName, dlerror());
2133 #endif
2134     *status = U_MISSING_RESOURCE_ERROR;
2135   }
2136   return ret;
2137 }
2138
2139 U_INTERNAL void U_EXPORT2
2140 uprv_dl_close(void *lib, UErrorCode *status) {
2141   if(U_FAILURE(*status)) return;
2142   dlclose(lib);
2143 }
2144
2145 U_INTERNAL UVoidFunction* U_EXPORT2
2146 uprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) {
2147   union {
2148       UVoidFunction *fp;
2149       void *vp;
2150   } uret;
2151   uret.fp = NULL;
2152   if(U_FAILURE(*status)) return uret.fp;
2153   uret.vp = dlsym(lib, sym);
2154   if(uret.vp == NULL) {
2155 #ifdef U_TRACE_DYLOAD
2156     printf("dlerror on dlsym(%p,%s): %s\n", lib,sym, dlerror());
2157 #endif
2158     *status = U_MISSING_RESOURCE_ERROR;
2159   }
2160   return uret.fp;
2161 }
2162
2163 #else
2164
2165 /* null (nonexistent) implementation. */
2166
2167 U_INTERNAL void * U_EXPORT2
2168 uprv_dl_open(const char *libName, UErrorCode *status) {
2169   if(U_FAILURE(*status)) return NULL;
2170   *status = U_UNSUPPORTED_ERROR;
2171   return NULL;
2172 }
2173
2174 U_INTERNAL void U_EXPORT2
2175 uprv_dl_close(void *lib, UErrorCode *status) {
2176   if(U_FAILURE(*status)) return;
2177   *status = U_UNSUPPORTED_ERROR;
2178   return;
2179 }
2180
2181
2182 U_INTERNAL UVoidFunction* U_EXPORT2
2183 uprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) {
2184   if(U_SUCCESS(*status)) {
2185     *status = U_UNSUPPORTED_ERROR;
2186   }
2187   return (UVoidFunction*)NULL;
2188 }
2189
2190
2191
2192 #endif
2193
2194 #elif U_PLATFORM_USES_ONLY_WIN32_API
2195
2196 U_INTERNAL void * U_EXPORT2
2197 uprv_dl_open(const char *libName, UErrorCode *status) {
2198   HMODULE lib = NULL;
2199   
2200   if(U_FAILURE(*status)) return NULL;
2201   
2202   lib = LoadLibraryA(libName);
2203   
2204   if(lib==NULL) {
2205     *status = U_MISSING_RESOURCE_ERROR;
2206   }
2207   
2208   return (void*)lib;
2209 }
2210
2211 U_INTERNAL void U_EXPORT2
2212 uprv_dl_close(void *lib, UErrorCode *status) {
2213   HMODULE handle = (HMODULE)lib;
2214   if(U_FAILURE(*status)) return;
2215   
2216   FreeLibrary(handle);
2217   
2218   return;
2219 }
2220
2221
2222 U_INTERNAL UVoidFunction* U_EXPORT2
2223 uprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) {
2224   HMODULE handle = (HMODULE)lib;
2225   UVoidFunction* addr = NULL;
2226   
2227   if(U_FAILURE(*status) || lib==NULL) return NULL;
2228   
2229   addr = (UVoidFunction*)GetProcAddress(handle, sym);
2230   
2231   if(addr==NULL) {
2232     DWORD lastError = GetLastError();
2233     if(lastError == ERROR_PROC_NOT_FOUND) {
2234       *status = U_MISSING_RESOURCE_ERROR;
2235     } else {
2236       *status = U_UNSUPPORTED_ERROR; /* other unknown error. */
2237     }
2238   }
2239   
2240   return addr;
2241 }
2242
2243
2244 #else
2245
2246 /* No dynamic loading set. */
2247
2248 U_INTERNAL void * U_EXPORT2
2249 uprv_dl_open(const char *libName, UErrorCode *status) {
2250     (void)libName;
2251     if(U_FAILURE(*status)) return NULL;
2252     *status = U_UNSUPPORTED_ERROR;
2253     return NULL;
2254 }
2255
2256 U_INTERNAL void U_EXPORT2
2257 uprv_dl_close(void *lib, UErrorCode *status) {
2258     (void)lib;
2259     if(U_FAILURE(*status)) return;
2260     *status = U_UNSUPPORTED_ERROR;
2261     return;
2262 }
2263
2264
2265 U_INTERNAL UVoidFunction* U_EXPORT2
2266 uprv_dlsym_func(void *lib, const char* sym, UErrorCode *status) {
2267   (void)lib;
2268   (void)sym;
2269   if(U_SUCCESS(*status)) {
2270     *status = U_UNSUPPORTED_ERROR;
2271   }
2272   return (UVoidFunction*)NULL;
2273 }
2274
2275 #endif /* U_ENABLE_DYLOAD */
2276
2277 /*
2278  * Hey, Emacs, please set the following:
2279  *
2280  * Local Variables:
2281  * indent-tabs-mode: nil
2282  * End:
2283  *
2284  */