home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / common / putil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-11  |  27.6 KB  |  1,041 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright Taligent, Inc.,  1997                                       *
  6. *   (C) Copyright International Business Machines Corporation,  1997-1998     *
  7. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  8. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  9. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  10. *                                                                             *
  11. *******************************************************************************
  12. *
  13. *  FILE NAME : putil.c (previously putil.cpp and ptypes.cpp)
  14. *
  15. *   Date        Name        Description
  16. *   04/14/97    aliu        Creation.
  17. *   04/24/97    aliu        Added getDefaultDataDirectory() and
  18. *                            getDefaultLocaleID().
  19. *   04/28/97    aliu        Rewritten to assume Unix and apply general methods 
  20. *                            for assumed case.  Non-UNIX platforms must be
  21. *                            special-cased.  Rewrote numeric methods dealing
  22. *                            with NaN and Infinity to be platform independent
  23. *                             over all IEEE 754 platforms.
  24. *   05/13/97    aliu        Restored sign of timezone 
  25. *                            (semantics are hours West of GMT)
  26. *   06/16/98    erm         Added IEEE_754 stuff, cleaned up isInfinite, isNan,
  27. *                             nextDouble..
  28. *   07/22/98    stephen     Added remainder, max, min, trunc
  29. *   08/13/98    stephen     Added isNegativeInfinity, isPositiveInfinity
  30. *   08/24/98    stephen     Added longBitsFromDouble
  31. *   09/08/98    stephen     Minor changes for Mac Port
  32. *   03/02/99    stephen     Removed openFile().  Added AS400 support.  
  33. *                            Fixed EBCDIC tables
  34. *   04/15/99    stephen     Converted to C.
  35. *   06/28/99    stephen     Removed mutex locking in u_isBigEndian().
  36. *   08/04/99    jeffrey R.  Added OS/2 changes
  37. *******************************************************************************
  38. */
  39.  
  40. #include <time.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <math.h>
  45. #include <locale.h>
  46.  
  47. #include "utypes.h"
  48.  
  49. #include "umutex.h"
  50. #include "cmemory.h"
  51. #include "cstring.h"
  52.  
  53. #ifdef OS400
  54. #include <float.h>
  55. #endif
  56.  
  57. #ifdef XP_MAC
  58. #include "Files.h"
  59. #include "IntlResources.h"
  60. #include "Script.h"
  61. #endif
  62.  
  63.  
  64. #ifdef WIN32
  65. #include "locmap.h"
  66. #include <wtypes.h>
  67. #include <winnls.h>
  68. #endif
  69.  
  70. #ifdef __amigaos__
  71. #include <proto/dos.h>
  72. #endif
  73.  
  74. /* We return QNAN rather than SNAN*/
  75. #define NAN_TOP ((int16_t)0x7FF8)
  76. #define INF_TOP ((int16_t)0x7FF0)
  77.  
  78. #define SIGN 0x80000000L
  79.  
  80. static char DEFAULT_CONVERTER_NAME[60] = "";
  81. static char tempString[10] = "";
  82.  
  83. /* statics */
  84. static bool_t fgNaNInitialized = FALSE;
  85. static double fgNan;
  86. static bool_t fgInfInitialized = FALSE;
  87. static double fgInf;
  88.  
  89. /* protos */
  90. static char* u_topNBytesOfDouble(double* d, int n);
  91. static char* u_bottomNBytesOfDouble(double* d, int n);
  92.  
  93.  
  94. /*---------------------------------------------------------------------------
  95.   Platform utilities
  96.   Our general strategy is to assume we're on a POSIX platform.  Platforms which
  97.   are non-POSIX must declare themselves so.  The default POSIX implementation
  98.   will sometimes work for non-POSIX platforms as well (e.g., the NaN-related
  99.   functions).
  100.   ---------------------------------------------------------------------------*/
  101.  
  102. /* Assume POSIX, and modify as necessary below*/
  103. #if defined(_WIN32) || defined(XP_MAC) || defined(OS400) || defined(OS2) || defined(__amigaos__)
  104. #   undef POSIX
  105. #else
  106. #   define POSIX
  107. #endif
  108.  
  109. /*---------------------------------------------------------------------------
  110.   Universal Implementations
  111.   These are designed to work on all platforms.  Try these, and if they don't
  112.   work on your platform, then special case your platform with new
  113.   implementations.
  114.   ---------------------------------------------------------------------------*/
  115.  
  116. /* Get UTC (GMT) time measured in seconds since 0:00 on 1/1/70.*/
  117. int32_t
  118. icu_getUTCtime()
  119. {
  120. #ifdef XP_MAC
  121.   time_t t, t1, t2;
  122.   struct tm tmrec;
  123.   
  124.   memset( &tmrec, 0, sizeof(tmrec) );
  125.   tmrec.tm_year = 70;
  126.   tmrec.tm_mon = 0;
  127.   tmrec.tm_mday = 1;
  128.   t1 = mktime(&tmrec);    /* seconds of 1/1/1970*/
  129.   
  130.   time(&t);
  131.   memcpy( &tmrec, gmtime(&t), sizeof(tmrec) );
  132.   t2 = mktime(&tmrec);    /* seconds of current GMT*/
  133.   return t2 - t1;         /* GMT (or UTC) in seconds since 1970*/
  134. #else
  135.   time_t epochtime;
  136.   time(&epochtime);
  137.   return epochtime;
  138. #endif
  139. }
  140.  
  141. /*-----------------------------------------------------------------------------
  142.   IEEE 754
  143.   These methods detect and return NaN and infinity values for doubles
  144.   conforming to IEEE 754.  Platforms which support this standard include X86,
  145.   Mac 680x0, Mac PowerPC, AIX RS/6000, and most others.
  146.   If this doesn't work on your platform, you have non-IEEE floating-point, and
  147.   will need to code your own versions.  A naive implementation is to return 0.0
  148.   for getNaN and getInfinity, and false for isNaN and isInfinite.
  149.   ---------------------------------------------------------------------------*/
  150.  
  151. bool_t 
  152. icu_isNaN(double number)
  153. {
  154. #ifdef IEEE_754
  155.   /* This should work in theory, but it doesn't, so we resort to the more*/
  156.   /* complicated method below.*/
  157.   /*  return number != number;*/
  158.   
  159.   /* You can't return number == getNaN() because, by definition, NaN != x for*/
  160.   /* all x, including NaN (that is, NaN != NaN).  So instead, we compare*/
  161.   /* against the known bit pattern.  We must be careful of endianism here.*/
  162.   /* The pattern we are looking for id:*/
  163.   
  164.   /*   7FFy yyyy yyyy yyyy  (some y non-zero)*/
  165.   
  166.   /* There are two different kinds of NaN, but we ignore the distinction*/
  167.   /* here.  Note that the y value must be non-zero; if it is zero, then we*/
  168.   /* have infinity.*/
  169.   
  170.   uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number, 
  171.                               sizeof(uint32_t));
  172.   uint32_t lowBits  = *(uint32_t*)u_bottomNBytesOfDouble(&number, 
  173.                              sizeof(uint32_t));
  174.  
  175.   return ((highBits & 0x7FF00000L) == 0x7FF00000L) && 
  176.     (((highBits & 0x000FFFFFL) != 0) || (lowBits != 0));
  177. #else
  178.   /* If your platform doesn't support IEEE 754 but *does* have an NaN value,*/
  179.   /* you'll need to replace this default implementation with what's correct*/
  180.   /* for your platform.*/
  181.   return number != number;
  182. #endif
  183. }
  184.  
  185. bool_t
  186. icu_isInfinite(double number)
  187. {
  188. #ifdef IEEE_754
  189.   /* We know the top bit is the sign bit, so we mask that off in a copy of */
  190.   /* the number and compare against infinity. [LIU]*/
  191.   /* The following approach doesn't work for some reason, so we go ahead and */
  192.   /* scrutinize the pattern itself. */
  193.   /*  double a = number; */
  194.   /*  *(int8_t*)u_topNBytesOfDouble(&a, 1) &= 0x7F;*/
  195.   /*  return a == icu_getInfinity();*/
  196.   /* Instead, We want to see either:*/
  197.   
  198.   /*   7FF0 0000 0000 0000*/
  199.   /*   FFF0 0000 0000 0000*/
  200.   
  201.   uint32_t highBits = *(uint32_t*)u_topNBytesOfDouble(&number, 
  202.                               sizeof(uint32_t));
  203.   uint32_t lowBits  = *(uint32_t*)u_bottomNBytesOfDouble(&number, 
  204.                              sizeof(uint32_t));
  205.   
  206.   return ((highBits  & ~SIGN) == 0x7FF00000L) && (lowBits == 0x00000000L);
  207. #else
  208.   /* If your platform doesn't support IEEE 754 but *does* have an infinity*/
  209.   /* value, you'll need to replace this default implementation with what's*/
  210.   /* correct for your platform.*/
  211.   return number == (2.0 * number);
  212. #endif
  213. }
  214.  
  215. bool_t   
  216. icu_isPositiveInfinity(double number)
  217. {
  218. #ifdef IEEE_754
  219.   return (number > 0 && icu_isInfinite(number));
  220. #else
  221.   return icu_isInfinite(number);
  222. #endif
  223. }
  224.  
  225. bool_t   
  226. icu_isNegativeInfinity(double number)
  227. {
  228. #ifdef IEEE_754
  229.   return (number < 0 && icu_isInfinite(number));
  230. #else
  231.   return icu_isInfinite(number);
  232. #endif
  233. }
  234.  
  235. double 
  236. icu_getNaN()
  237. {
  238. #ifdef IEEE_754  
  239.   if( ! fgNaNInitialized) {
  240.     umtx_lock(NULL);
  241.     if( ! fgNaNInitialized) {
  242.       int i;
  243.       int8_t* p = (int8_t*)&fgNan;
  244.       for(i = 0; i < sizeof(double); ++i) 
  245.     *p++ = 0;
  246.       *(int16_t*)u_topNBytesOfDouble(&fgNan, sizeof(NAN_TOP)) = NAN_TOP;
  247.       fgNaNInitialized = TRUE;
  248.     }
  249.     umtx_unlock(NULL);
  250.   }
  251.   return fgNan;
  252. #else
  253.   /* If your platform doesn't support IEEE 754 but *does* have an NaN value,*/
  254.   /* you'll need to replace this default implementation with what's correct*/
  255.   /* for your platform.*/
  256.   return 0.0;
  257. #endif
  258. }
  259.  
  260. double 
  261. icu_getInfinity()
  262. {
  263. #ifdef IEEE_754  
  264.   if (!fgInfInitialized)
  265.     {
  266.       int i;
  267.       int8_t* p = (int8_t*)&fgInf;
  268.       for(i = 0; i < sizeof(double); ++i) 
  269.     *p++ = 0;
  270.       *(int16_t*)u_topNBytesOfDouble(&fgInf, sizeof(INF_TOP)) = INF_TOP;
  271.       fgInfInitialized = TRUE;
  272.     }
  273.   return fgInf;
  274. #else
  275.   /* If your platform doesn't support IEEE 754 but *does* have an infinity*/
  276.   /* value, you'll need to replace this default implementation with what's*/
  277.   /* correct for your platform.*/
  278.   return 0.0;
  279. #endif
  280. }
  281.  
  282. double 
  283. icu_floor(double x)
  284. {
  285.   return floor(x);
  286. }
  287.  
  288. double 
  289. icu_ceil(double x)
  290. {
  291.   return ceil(x);
  292. }
  293.  
  294. double 
  295. icu_fabs(double x)
  296. {
  297.   return fabs(x);
  298. }
  299.  
  300. double 
  301. icu_modf(double x, double* y)
  302. {
  303.   return modf(x, y);
  304. }
  305.  
  306. double 
  307. icu_fmod(double x, double y)
  308. {
  309.   return fmod(x, y);
  310. }
  311.  
  312. double
  313. icu_pow10(int32_t x)
  314. {
  315. #ifdef XP_MAC
  316.   return pow(10.0, (double)x);
  317. #else
  318.   return pow(10.0, x);
  319. #endif
  320. }
  321.  
  322. double 
  323. icu_IEEEremainder(double x, double p)
  324. {
  325. #ifdef IEEE_754
  326.   int32_t hx, hp;
  327.   uint32_t sx, lx, lp;
  328.   double p_half;
  329.   
  330.   hx = *(int32_t*)u_topNBytesOfDouble(&x, sizeof(int32_t));
  331.   lx = *(uint32_t*)u_bottomNBytesOfDouble(&x, sizeof(uint32_t));
  332.   
  333.   hp = *(int32_t*)u_topNBytesOfDouble(&p, sizeof(int32_t));
  334.   lp = *(uint32_t*)u_bottomNBytesOfDouble(&p, sizeof(uint32_t));
  335.   
  336.   sx = hx & SIGN;
  337.   
  338.   hp &= 0x7fffffff;
  339.   hx &= 0x7fffffff;
  340.   
  341.   /* purge off exception values */
  342.   if((hp|lp) == 0) 
  343.     return (x*p) / (x*p);     /* p = 0 */
  344.   if((hx >= 0x7ff00000)||        /* x not finite */
  345.      ((hp>=0x7ff00000) &&    /* p is NaN */
  346.       (((hp-0x7ff00000)|lp) != 0)))
  347.     return (x*p) / (x*p);
  348.   
  349.   
  350.   if(hp <= 0x7fdfffff) 
  351.     x = icu_fmod(x, p + p);    /* now x < 2p */
  352.   if(((hx-hp)|(lx-lp)) == 0) 
  353.     return 0.0 * x;
  354.   x  = icu_fabs(x);
  355.   p  = icu_fabs(p);
  356.   if (hp < 0x00200000) {
  357.     if(x + x > p) {
  358.       x -= p;
  359.       if(x + x >= p) 
  360.     x -= p;
  361.     }
  362.   } 
  363.   else {
  364.     p_half = 0.5 * p;
  365.     if(x > p_half) {
  366.       x -= p;
  367.       if(x >= p_half) 
  368.     x -= p;
  369.     }
  370.   }
  371.   
  372.   *(int32_t*)u_topNBytesOfDouble(&x, sizeof(int32_t)) ^= sx;
  373.   
  374.   return x;
  375. #else
  376.   /* {sfb} need to fix this*/
  377.   return icu_fmod(x, p);
  378. #endif
  379. }
  380.  
  381. double 
  382. icu_fmax(double x, double y)
  383. {
  384. #ifdef IEEE_754
  385.   int32_t lowBits;
  386.   
  387.   /* first handle NaN*/
  388.   if(icu_isNaN(x) || icu_isNaN(y))
  389.     return icu_getNaN();
  390.   
  391.   /* check for -0 and 0*/
  392.   lowBits = *(uint32_t*) u_bottomNBytesOfDouble(&x, sizeof(uint32_t));
  393.   if(x == 0.0 && y == 0.0 && (lowBits & SIGN))
  394.     return y; 
  395.   
  396.   return (x > y ? x : y);
  397. #else
  398.   /* {sfb} fix this*/
  399.   return x;
  400. #endif
  401. }
  402.  
  403. int32_t 
  404. icu_max(int32_t x, int32_t y)
  405. {
  406.   return (x > y ? x : y);
  407. }
  408.  
  409. double 
  410. icu_fmin(double x, double y)
  411. {
  412. #ifdef IEEE_754
  413.   int32_t lowBits;
  414.  
  415.   /* first handle NaN*/
  416.   if(icu_isNaN(x) || icu_isNaN(y))
  417.     return icu_getNaN();
  418.   
  419.   /* check for -0 and 0*/
  420.   lowBits = *(uint32_t*) u_bottomNBytesOfDouble(&y, sizeof(uint32_t));
  421.   if(x == 0.0 && y == 0.0 && (lowBits & SIGN))
  422.     return y; 
  423.   
  424.   return (x > y ? y : x);
  425. #else
  426.   /* {sfb} fix this*/
  427.   return x;
  428. #endif
  429. }
  430.  
  431. int32_t 
  432. icu_min(int32_t x, int32_t y)
  433. {
  434.   return (x > y ? y : x);
  435. }
  436.  
  437. /**
  438.  * Truncates the given double.
  439.  * trunc(3.3) = 3.0, trunc (-3.3) = -3.0
  440.  * This is different than calling floor() or ceil():
  441.  * floor(3.3) = 3, floor(-3.3) = -4
  442.  * ceil(3.3) = 4, ceil(-3.3) = -3
  443.  */
  444. double 
  445. icu_trunc(double d)
  446. {
  447. #ifdef IEEE_754
  448.  
  449.   int32_t lowBits;
  450.   
  451.   /* handle error cases*/
  452.   if(icu_isNaN(d))        return icu_getNaN();
  453.   if(icu_isInfinite(d))        return icu_getInfinity();
  454.   
  455.   lowBits = *(uint32_t*) u_bottomNBytesOfDouble(&d, sizeof(uint32_t));
  456.   if( (d == 0.0 && (lowBits & SIGN)) || d < 0)
  457.     return ceil(d);
  458.   else
  459.     return floor(d);
  460. #else
  461.   return d >= 0 ? floor(d) : ceil(d);
  462. #endif
  463. }
  464.  
  465. void        
  466. icu_longBitsFromDouble(double d, int32_t *hi, uint32_t *lo)
  467. {
  468.   *hi = *(int32_t*)u_topNBytesOfDouble(&d, sizeof(int32_t));
  469.   *lo = *(uint32_t*)u_bottomNBytesOfDouble(&d, sizeof(uint32_t));
  470. }
  471.     
  472.  
  473. /**
  474.  * Return the floor of the log base 10 of a given double.
  475.  * This method compensates for inaccuracies which arise naturally when
  476.  * computing logs, and always give the correct value.  The parameter
  477.  * must be positive and finite.
  478.  * (Thanks to Alan Liu for supplying this function.)
  479.  */
  480. int16_t 
  481. icu_log10(double d)
  482. {
  483.   /* The reason this routine is needed is that simply taking the*/
  484.   /* log and dividing by log10 yields a result which may be off*/
  485.   /* by 1 due to rounding errors.  For example, the naive log10*/
  486.   /* of 1.0e300 taken this way is 299, rather than 300.*/
  487.   double log10 = log(d) / log(10.0);
  488.   int16_t ilog10 = (int16_t)floor(log10);
  489.   
  490.   /* Positive logs could be too small, e.g. 0.99 instead of 1.0*/
  491.   if (log10 > 0 && d >= pow(10.0, ilog10 + 1))
  492.     ++ilog10;
  493.   
  494.   /* Negative logs could be too big, e.g. -0.99 instead of -1.0*/
  495.   else if (log10 < 0 && d < pow(10.0, ilog10))
  496.     --ilog10;
  497.   
  498.   return ilog10;
  499. }
  500.  
  501. int32_t 
  502. icu_digitsAfterDecimal(double x)
  503. {
  504.   char buffer[20];
  505.   int16_t numDigits;
  506.   char *p;
  507.   int16_t ptPos, exponent;
  508.  
  509.   /* negative numbers throw off the calculations*/
  510.   x = fabs(x);
  511.   
  512.   /* cheat and use the string-format routine to get a string representation*/
  513.   /* (it handles mathematical inaccuracy better than we can), then find out */
  514.   /* many characters are to the right of the decimal point */
  515.   sprintf(buffer, "%.9g", x);
  516.   p = icu_strchr(buffer, '.');
  517.   if (p == 0)
  518.     return 0;
  519.   
  520.   ptPos = p - buffer;
  521.   numDigits = strlen(buffer) - ptPos - 1;
  522.   
  523.   /* if the number's string representation is in scientific notation, find */
  524.   /* the exponent and take it into account*/
  525.   exponent = 0;
  526.   p = icu_strchr(buffer, 'e');
  527.   if (p != 0) {
  528.     int16_t expPos = p - buffer;
  529.     numDigits -= strlen(buffer) - expPos;
  530.     exponent = atoi(p + 1);
  531.   }
  532.   
  533.   /* the string representation may still have spurious decimal digits in it, */
  534.   /* so we cut off at the ninth digit to the right of the decimal, and have */
  535.   /* to search backward from there to the first non-zero digit*/
  536.   if (numDigits > 9) {
  537.     numDigits = 9;
  538.     while (numDigits > 0 && buffer[ptPos + numDigits] == '0')
  539.       --numDigits;
  540.   }
  541.   numDigits -= exponent;
  542.   return numDigits;
  543. }
  544.  
  545. /*---------------------------------------------------------------------------
  546.   Platform-specific Implementations
  547.   Try these, and if they don't work on your platform, then special case your
  548.   platform with new implementations.
  549.   ---------------------------------------------------------------------------*/
  550.  
  551. /* Time zone utilities */
  552.  
  553. #ifdef __amigaos__
  554. static int tzone = 0;
  555. static char tzname1[20];
  556. static char tzname2[20];
  557. #endif
  558.  
  559. void 
  560. icu_tzset()
  561. {
  562. #ifdef POSIX
  563.   tzset();
  564. #endif
  565.  
  566. #if defined(OS400) || defined(XP_MAC)
  567.   /* no initialization*/
  568. #endif
  569.  
  570. #if defined(WIN32) || defined(OS2)
  571.   _tzset();
  572. #endif
  573.  
  574. #ifdef  __amigaos__
  575.   static char t[80];
  576.   int status;
  577.   int n;
  578.   status = GetVar("TZ", t, sizeof(t), GVF_GLOBAL_ONLY);
  579.   if (status == -1) {
  580.     tzone = 0;
  581.     strcpy(tzname1, "GMT");
  582.     tzone = 0;
  583.     strcpy(tzname2, "GMT");
  584.   }else{
  585.     n = sscanf(t, "%3s%d%s", tzname1, &tzone, tzname2);
  586.     switch (n) {
  587.       case 0:
  588.     strcpy(tzname1, "GMT");
  589.         tzone = 0;
  590.     strcpy(tzname2, "GMT");
  591.     break;
  592.       case 1:
  593.         tzone = 0;
  594.     strcpy(tzname2, tzname1);
  595.     break;
  596.       case 2:
  597.     strcpy(tzname2, tzname1);
  598.         break;
  599.       default:
  600.         tzone *= 3600;
  601.     break;
  602.     }
  603.   }
  604. #endif
  605. }
  606.  
  607. int32_t 
  608. icu_timezone()
  609. {
  610. #ifdef POSIX
  611.   return timezone;
  612. #endif
  613.  
  614. #if defined(OS400) || defined(XP_MAC)
  615.   time_t t, t1, t2;
  616.   struct tm tmrec;
  617.   bool_t dst_checked;
  618.   
  619.   time(&t);
  620.   memcpy( &tmrec, localtime(&t), sizeof(tmrec) );
  621.   dst_checked = (tmrec.tm_isdst != 0); /* daylight savings time is checked*/
  622.   t1 = mktime(&tmrec);                 /* local time in seconds*/
  623.   memcpy( &tmrec, gmtime(&t), sizeof(tmrec) );
  624.   t2 = mktime(&tmrec);                 /* GMT (or UTC) in seconds*/
  625.   int32_t tdiff = t2 - t1;
  626.   /* imitate NT behaviour, which returns same timezone offset to GMT for 
  627.      winter and summer*/
  628.   if (dst_checked) tdiff += 3600;
  629.   return tdiff;
  630. #endif
  631.  
  632. #if defined(WIN32) || defined(OS2)
  633.   return _timezone;
  634. #endif
  635.  
  636. #ifdef __amigaos__
  637.   return tzone;
  638. #endif
  639. }
  640.  
  641. char* 
  642. icu_tzname(int index)
  643. {
  644. #ifdef POSIX
  645.   return tzname[index];
  646. #endif
  647.  
  648. #if defined(OS400) || defined(XP_MAC)
  649.   return "";
  650. #endif
  651.  
  652. #if defined(WIN32) || defined(OS2)
  653.   return _tzname[index];
  654. #endif
  655.  
  656. #ifdef __amigaos__
  657.   if (index == 0) {
  658.     return tzname1;
  659.   }else{
  660.     return tzname2;
  661.   }
  662. #endif
  663. }
  664.  
  665. const char* 
  666. icu_getDefaultDataDirectory()
  667. {
  668. #if defined(POSIX) || defined(__amigaos__)
  669.   static char *PATH = 0;
  670.   if(PATH == 0) {
  671.     umtx_lock(NULL);
  672.     if(PATH == 0) {
  673.       /* Normally, the locale and converter data will be installed in
  674.          the same tree as the ICU libraries - typically /usr/local/lib
  675.          for the libraries, /usr/local/include for the headers, and
  676.          /usr/local/share for the binary data.  However, the directory
  677.          where the ICU looks for the binary data can be overridden by
  678.          setting the environment variable ICU_DATA */
  679.       char *dir = getenv("ICU_DATA");
  680.  
  681.       /* If the environment variable is set, use it */
  682.       if(dir != 0) {
  683.         PATH = dir;
  684.       }
  685.       /* Otherwise, use the compiled in default */
  686.       else {
  687.         PATH = ICU_DATA_DIR;
  688.       }
  689.     }
  690.     umtx_unlock(NULL);
  691.   }
  692.   return PATH;
  693. #endif
  694.  
  695. #ifdef OS400
  696.   return "/icu/data/";
  697. #endif
  698.  
  699. #ifdef XP_MAC
  700.   static char path[256];
  701.   char* mainDir;
  702.   char* relPath = ":icu:data:";
  703.   
  704.   Str255 volName;
  705.   int16_t volNum;
  706.   OSErr err = GetVol( volName, &volNum );
  707.   if (err != noErr) 
  708.     volName[0] = 0;
  709.   mainDir = (char*) &(volName[1]);
  710.   mainDir[volName[0]] = 0;
  711.   int32_t lenMainDir = strlen( mainDir );
  712.   int32_t lenRelPath = strlen( relPath );
  713.   if (sizeof(path) < lenMainDir + lenRelPath + 2) { 
  714.     path[0] = 0; 
  715.     return path; 
  716.   }
  717.   icu_strcpy( path, mainDir );
  718.   icu_strcat( path, relPath );
  719.   
  720.   return path;
  721. #endif
  722.  
  723. #ifdef WIN32
  724.   char * dpath;
  725.   dpath = getenv("ICU_DATA");
  726.   if (!dpath || !*dpath)
  727.       return "\\icu\\data\\";
  728.   return dpath;
  729. #endif
  730.  
  731. #ifdef OS2
  732.   char * dpath;
  733.   dpath = getenv("ICU_DATA");
  734.   if (!dpath || !*dpath)
  735.       return "\\icu\\data\\";
  736.   return dpath;
  737. #endif
  738.  
  739.  
  740. }
  741.  
  742. /* Macintosh-specific locale information */
  743. #ifdef XP_MAC
  744.  
  745. struct mac_lc_rec {
  746.   int32_t script;
  747.   int32_t region;
  748.   int32_t lang;
  749.   int32_t date_region;
  750.   char* posixID;
  751. };
  752. /* To do: This will be updated with a newer version from www.unicode.org web
  753.    page when it's available.*/
  754. #define MAC_LC_MAGIC_NUMBER -5
  755. #define MAC_LC_INIT_NUMBER -9
  756.  
  757. mac_lc_rec mac_lc_recs[] = {
  758.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 0, "en_US",  
  759.   /* United States*/
  760.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 1, "fr_FR",  
  761.   /* France*/
  762.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 2, "en_GB",  
  763.   /* Great Britain*/
  764.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 3, "de_DE",  
  765.   /* Germany*/
  766.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 4, "it_IT",  
  767.   /* Italy*/
  768.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 5, "nl_NL", 
  769.   /* Metherlands*/
  770.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 6, "fr_BE", 
  771.   /* French for Belgium or Lxembourg*/
  772.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 7, "sv_SE", 
  773.   /* Sweden*/
  774.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 9, "da_DK", 
  775.   /* Denmark*/
  776.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 10, "pt_PT", 
  777.   /* Portugal*/
  778.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 11, "fr_CA", 
  779.   /* French Canada*/
  780.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 13, "is_IS", 
  781.   /* Israel*/
  782.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 14, "ja_JP", 
  783.   /* Japan*/
  784.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 15, "en_AU", 
  785.   /* Australia*/
  786.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 16, "ar_AE", 
  787.   /* the Arabic world (?)*/
  788.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 17, "fi_FI", 
  789.   /* Finland*/
  790.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 18, "fr_CH", 
  791.   /* French for Switzerland*/
  792.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 19, "de_CH", 
  793.   /* German for Switzerland*/
  794.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 20, "EL_GR", 
  795.   /* Greece*/
  796.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 21, "is_IS", 
  797.   /* Iceland ===*/
  798.   /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 22, "", 
  799.     // Malta ===*/
  800.   /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 23, "", 
  801.     // Cyprus ===*/
  802.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 24, "tr_TR", 
  803.   /* Turkey ===*/
  804.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 25, "sh_YU", 
  805.   /* Croatian system for Yugoslavia*/
  806.   /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 33, "", 
  807.     // Hindi system for India*/
  808.   /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 34, "", 
  809.     // Pakistan*/
  810.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 41, "lt_LT", 
  811.   /* Lithuania*/
  812.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 42, "pl_PL", 
  813.   /* Poland*/
  814.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 43, "hu_HU", 
  815.   /* Hungary*/
  816.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 44, "et_EE", 
  817.   /* Estonia*/
  818.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 45, "lv_LV", 
  819.   /* Latvia*/
  820.   /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 46, "", 
  821.     // Lapland  [Ask Rich for the data. HS]*/
  822.   /*MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 47, "", 
  823.     // Faeroe Islands*/
  824.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 48, "fa_IR", 
  825.   /* Iran*/
  826.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 49, "ru_RU", 
  827.   /* Russia*/
  828.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 50, "en_IE", 
  829.   /* Ireland*/
  830.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 51, "ko_KR", 
  831.   /* Korea*/
  832.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 52, "zh_CN", 
  833.   /* People's Republic of China*/
  834.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 53, "zh_TW", 
  835.   /* Taiwan*/
  836.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 54, "th_TH", 
  837.   /* Thailand*/
  838.   
  839.   /* fallback is en_US*/
  840.   MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, MAC_LC_MAGIC_NUMBER, 
  841.   MAC_LC_MAGIC_NUMBER, "en_US"
  842. };
  843.  
  844. #endif
  845.  
  846. const char* 
  847. icu_getDefaultLocaleID()
  848. {
  849. #if defined(POSIX) || defined(__amigaos__)
  850.   char* posixID = getenv("LC_ALL");
  851.   if (posixID == 0) posixID = getenv("LANG");
  852.   if (posixID == 0) posixID = setlocale(LC_ALL, NULL);
  853.   if (icu_strcmp("C", posixID) == 0) posixID = "en_US";
  854.   return posixID;
  855. #endif
  856.  
  857. #ifdef OS400
  858.   /* TBD */
  859.   return "";
  860. #endif
  861.  
  862. #ifdef XP_MAC
  863.   int32_t script = MAC_LC_INIT_NUMBER; 
  864.   /* = IntlScript(); or GetScriptManagerVariable(smSysScript);*/
  865.   int32_t region = MAC_LC_INIT_NUMBER; 
  866.   /* = GetScriptManagerVariable(smRegionCode);*/
  867.   int32_t lang = MAC_LC_INIT_NUMBER;   
  868.   /* = GetScriptManagerVariable(smScriptLang);*/
  869.   int32_t date_region = MAC_LC_INIT_NUMBER;
  870.   char* posixID = 0;
  871.   Intl1Hndl ih;
  872.   
  873.   ih = (Intl1Hndl) GetIntlResource(1);
  874.   if (ih) date_region = ((uint16_t)(*ih)->intl1Vers) >> 8;
  875.   
  876.   int32_t count = sizeof(mac_lc_recs) / sizeof(mac_lc_rec);
  877.   for (int32_t i = 0; i < count; i++) {
  878.     if ( ((mac_lc_recs[i].script == MAC_LC_MAGIC_NUMBER)      
  879.       || (mac_lc_recs[i].script == script))
  880.      && ((mac_lc_recs[i].region == MAC_LC_MAGIC_NUMBER)
  881.          || (mac_lc_recs[i].region == region))
  882.      && ((mac_lc_recs[i].lang == MAC_LC_MAGIC_NUMBER)
  883.          || (mac_lc_recs[i].lang == lang))
  884.      && ((mac_lc_recs[i].date_region == MAC_LC_MAGIC_NUMBER) 
  885.          || (mac_lc_recs[i].date_region == date_region))
  886.      ) {
  887.       posixID = mac_lc_recs[i].posixID;
  888.       break;
  889.     }
  890.   }
  891.   
  892.   return posixID;
  893. #endif
  894.  
  895. #ifdef WIN32
  896.   LCID id = GetThreadLocale();
  897.   return T_convertToPosix(id);
  898. #endif
  899.  
  900. #ifdef OS2
  901.     char * locID;
  902.  
  903.     locID = getenv("LC_ALL");
  904.     if (!locID || !*locID)
  905.         locID = getenv("LANG");
  906.     if (!locID || !*locID) {
  907.         locID = "C";
  908.     }
  909.     if (!stricmp(locID, "c") || !stricmp(locID, "posix") ||
  910.         !stricmp(locID, "univ"))
  911.         locID = "en_US";
  912.     return locID;
  913. #endif
  914.  
  915. }
  916.  
  917. /* end of platform-specific implementation */
  918.  
  919. double 
  920. icu_nextDouble(double d, bool_t next)
  921. {
  922. #ifdef IEEE_754
  923.   int32_t highBits;
  924.   uint32_t lowBits;
  925.   int32_t highMagnitude;
  926.   uint32_t lowMagnitude;
  927.   double result;
  928.   uint32_t *highResult, *lowResult;
  929.   uint32_t signBit;
  930.  
  931.   /* filter out NaN's */
  932.   if (icu_isNaN(d)) {
  933.     return d;
  934.   }
  935.   
  936.   /* zero's are also a special case */
  937.   if (d == 0.0) {
  938.     double smallestPositiveDouble = 0.0;
  939.     uint32_t *lowBits = 
  940.       (uint32_t *)u_bottomNBytesOfDouble(&smallestPositiveDouble, 
  941.                      sizeof(uint32_t));
  942.     
  943.     *lowBits = 1;
  944.     
  945.     if (next) {
  946.       return smallestPositiveDouble;
  947.     } else {
  948.       return -smallestPositiveDouble;
  949.     }
  950.   }
  951.   
  952.   /* if we get here, d is a nonzero value */
  953.   
  954.   /* hold all bits for later use */
  955.   highBits = *(int32_t*)u_topNBytesOfDouble(&d, sizeof(uint32_t));
  956.   lowBits = *(uint32_t*)u_bottomNBytesOfDouble(&d, sizeof(uint32_t));
  957.   
  958.   /* strip off the sign bit */
  959.   highMagnitude = highBits & ~SIGN;
  960.   lowMagnitude = lowBits;
  961.   
  962.   /* if next double away from zero, increase magnitude */
  963.   if ((highBits >= 0) == next) {
  964.     if (highMagnitude != 0x7FF00000L || lowMagnitude != 0x00000000L) {
  965.       lowMagnitude += 1;
  966.       if (lowMagnitude == 0) {
  967.     highMagnitude += 1;
  968.       }
  969.     }
  970.   }
  971.   /* else decrease magnitude */
  972.   else {
  973.     lowMagnitude -= 1;
  974.     if (lowMagnitude > lowBits) {
  975.       highMagnitude -= 1;
  976.     }
  977.   }
  978.   
  979.   /* construct result and return */
  980.   signBit = highBits & SIGN;
  981.   highResult = (uint32_t *)u_topNBytesOfDouble(&result, sizeof(uint32_t));
  982.   lowResult  = (uint32_t *)u_bottomNBytesOfDouble(&result, sizeof(uint32_t));
  983.   
  984.   *highResult = signBit | highMagnitude;
  985.   *lowResult  = lowMagnitude;
  986.   return result;
  987. #else
  988.   /* This is the portable implementation...*/
  989.   /* a small coefficient within the precision of the mantissa*/
  990.   static const double smallValue = 1e-10;  
  991.   double epsilon = ((d<0)?-d:d) * smallValue; /* first approximation*/
  992.   if (epsilon == 0) epsilon = smallValue; /* for very small d's*/
  993.   if (!next) epsilon = -epsilon;
  994.   double last_eps = epsilon * 2.0;
  995.   /* avoid higher precision possibly used for temporay values*/
  996.   double sum = d + epsilon; 
  997.   while ((sum != d) && (epsilon != last_eps)) {
  998.     last_eps = epsilon;
  999.     epsilon /= 2.0;
  1000.     sum = d + epsilon;
  1001.   }
  1002.   return d + last_eps;
  1003. #endif
  1004. }
  1005.  
  1006. static char*
  1007. u_topNBytesOfDouble(double* d, int n)
  1008. {
  1009.   return U_IS_BIG_ENDIAN ? (char*)d : (char*)(d + 1) - n;
  1010. }
  1011.  
  1012. static char* u_bottomNBytesOfDouble(double* d, int n)
  1013. {
  1014.   return U_IS_BIG_ENDIAN ? (char*)(d + 1) - n : (char*)d;
  1015. }
  1016.  
  1017. const char* icu_getDefaultCodepage()
  1018. {
  1019.   /*Lazy evaluates DEFAULT_CONVERTER_NAME*/
  1020.   if (DEFAULT_CONVERTER_NAME[0]) return DEFAULT_CONVERTER_NAME;
  1021. #if defined(OS400)
  1022.   /* Currently TBD 
  1023.      in the future should use thread specific CP
  1024.   */
  1025. #elif defined(OS390)
  1026.   icu_strcpy(DEFAULT_CONVERTER_NAME, "ibm-1047");
  1027. #elif defined(XP_MAC)
  1028.   /* TBD */
  1029. #elif defined(WIN32) 
  1030.   icu_strcpy(DEFAULT_CONVERTER_NAME, "cp");
  1031.   icu_strcat(DEFAULT_CONVERTER_NAME, _itoa(GetACP(), tempString, 10));
  1032. #elif defined(POSIX)
  1033.   icu_strcpy(DEFAULT_CONVERTER_NAME, "LATIN_1");
  1034.  
  1035. #else 
  1036.   icu_strcpy(DEFAULT_CONVERTER_NAME, "LATIN_1");
  1037. #endif
  1038.   
  1039.   return DEFAULT_CONVERTER_NAME;
  1040. }
  1041.