From ffc55edf36ab3a372bac036ecda6a10177669f20 Mon Sep 17 00:00:00 2001 From: George Rhoten Date: Thu, 30 Aug 2007 22:17:58 +0000 Subject: [PATCH] ICU-4894 Improve U_MAX_PTR for i5/OS. X-SVN-Rev: 22578 --- icu4c/source/common/putil.c | 70 +++++++++++---------------- icu4c/source/common/putilimp.h | 24 ++++----- icu4c/source/common/unicode/urename.h | 1 + 3 files changed, 40 insertions(+), 55 deletions(-) diff --git a/icu4c/source/common/putil.c b/icu4c/source/common/putil.c index a27078c3da..9f44a40fe7 100644 --- a/icu4c/source/common/putil.c +++ b/icu4c/source/common/putil.c @@ -94,6 +94,7 @@ Cleanly installed Solaris can use this #define. # include /* error code structure */ # include # include /* EPT_CALL macro - this include must be after all other "QSYSINCs" */ +# include /* For uprv_maximumPtr */ #elif defined(XP_MAC) # include # include @@ -486,51 +487,38 @@ uprv_log(double d) return log(d); } -#if 0 -/* This isn't used. If it's readded, readd putiltst.c tests */ -U_CAPI int32_t U_EXPORT2 -uprv_digitsAfterDecimal(double x) +U_CAPI void * U_EXPORT2 +uprv_maximumPtr(void * base) { - char buffer[20]; - int32_t numDigits, bytesWritten; - char *p = buffer; - int32_t ptPos, exponent; - - /* cheat and use the string-format routine to get a string representation*/ - /* (it handles mathematical inaccuracy better than we can), then find out */ - /* many characters are to the right of the decimal point */ - bytesWritten = sprintf(buffer, "%+.9g", x); - while (isdigit(*(++p))) { +#if defined(OS400) + /* + * With the provided function we should never be out of range of a given segment + * (a traditional/typical segment that is). Our segments have 5 bytes for the + * id and 3 bytes for the offset. The key is that the casting takes care of + * only retrieving the offset portion minus x1000. Hence, the smallest offset + * seen in a program is x001000 and when casted to an int would be 0. + * That's why we can only add 0xffefff. Otherwise, we would exceed the segment. + * + * Currently, 16MB is the current addressing limitation on i5/OS if the activation is + * non-TERASPACE. If it is TERASPACE it is 2GB - 4k(header information). + * This function determines the activation based on the pointer that is passed in and + * calculates the appropriate maximum available size for + * each pointer type (TERASPACE and non-TERASPACE) + * + * Unlike other operating systems, the pointer model isn't determined at + * compile time on i5/OS. + */ + if ((base != NULL) && (_TESTPTR(base, _C_TERASPACE_CHECK))) { + /* if it is a TERASPACE pointer the max is 2GB - 4k */ + return ((void *)(((char *)base)-((uint32_t)(base))+((uint32_t)0x7fffefff))); } + /* otherwise 16MB since NULL ptr is not checkable or the ptr is not TERASPACE */ + return ((void *)(((char *)base)-((uint32_t)(base))+((uint32_t)0xffefff))); - ptPos = (int32_t)(p - buffer); - numDigits = (int32_t)(bytesWritten - ptPos - 1); - - /* if the number's string representation is in scientific notation, find */ - /* the exponent and take it into account*/ - exponent = 0; - p = uprv_strchr(buffer, 'e'); - if (p != 0) { - int16_t expPos = (int16_t)(p - buffer); - numDigits -= bytesWritten - expPos; - exponent = (int32_t)(atol(p + 1)); - } - - /* the string representation may still have spurious decimal digits in it, */ - /* so we cut off at the ninth digit to the right of the decimal, and have */ - /* to search backward from there to the first non-zero digit*/ - if (numDigits > 9) { - numDigits = 9; - while (numDigits > 0 && buffer[ptPos + numDigits] == '0') - --numDigits; - } - numDigits -= exponent; - if (numDigits < 0) { - return 0; - } - return numDigits; -} +#else + return U_MAX_PTR(base); #endif +} /*--------------------------------------------------------------------------- Platform-specific Implementations diff --git a/icu4c/source/common/putilimp.h b/icu4c/source/common/putilimp.h index 04c91b3903..c516821e84 100644 --- a/icu4c/source/common/putilimp.h +++ b/icu4c/source/common/putilimp.h @@ -226,6 +226,14 @@ U_INTERNAL UDate U_EXPORT2 uprv_getUTCtime(void); */ U_INTERNAL UBool U_EXPORT2 uprv_pathIsAbsolute(const char *path); +/** + * Use U_MAX_PTR instead of this function. + * @param void pointer to test + * @return the largest possible pointer greater than the base + * @internal (ICU 3.8) + */ +U_INTERNAL void * U_EXPORT2 uprv_maximumPtr(void *base); + /** * Maximum value of a (void*) - use to indicate the limit of an 'infinite' buffer. * In fact, buffer sizes must not exceed 2GB so that the difference between @@ -245,26 +253,14 @@ U_INTERNAL UBool U_EXPORT2 uprv_pathIsAbsolute(const char *path); /* We have 31-bit pointers. */ # define U_MAX_PTR(base) ((void *)0x7fffffff) # elif defined(OS400) -/* - * With the provided macro we should never be out of range of a given segment - * (a traditional/typical segment that is). Our segments have 5 bytes for the - * id and 3 bytes for the offset. The key is that the casting takes care of - * only retrieving the offset portion minus x1000. Hence, the smallest offset - * seen in a program is x001000 and when casted to an int would be 0. - * That's why we can only add 0xffefff. Otherwise, we would exceed the segment. - * - * Currently, 16MB is the current addressing limitation on as/400. This macro - * may eventually be changed to use 2GB addressability for the newer version of - * as/400 machines. - */ -# define U_MAX_PTR(base) ((void *)(((char *)base)-((int32_t)(base))+((int32_t)0xffefff))) +# define U_MAX_PTR(base) uprv_maximumPtr((void *)base) # elif defined(__GNUC__) && __GNUC__ >= 4 /* * Due to a compiler optimization bug, gcc 4 causes test failures when doing * this math arithmetic on pointers on some platforms. It seems like the * pointers are considered signed instead of unsigned. The uintptr_t type * isn't available on all platforms (i.e MSVC 6) and pointers aren't always - * a scalar value (i.e. i5/OS in the lines above). + * a scalar value (i.e. i5/OS see uprv_maximumPtr function). */ # define U_MAX_PTR(base) \ ((void *)(((uintptr_t)(base)+0x7fffffffu) > (uintptr_t)(base) \ diff --git a/icu4c/source/common/unicode/urename.h b/icu4c/source/common/unicode/urename.h index 7ea7260b4e..8a2b5c344c 100644 --- a/icu4c/source/common/unicode/urename.h +++ b/icu4c/source/common/unicode/urename.h @@ -1053,6 +1053,7 @@ #define uprv_malloc uprv_malloc_3_8 #define uprv_mapFile uprv_mapFile_3_8 #define uprv_max uprv_max_3_8 +#define uprv_maximumPtr uprv_maximumPtr_3_8 #define uprv_maxMantissa uprv_maxMantissa_3_8 #define uprv_min uprv_min_3_8 #define uprv_modf uprv_modf_3_8