ICU-4894 Improve U_MAX_PTR for i5/OS.

X-SVN-Rev: 22578
This commit is contained in:
George Rhoten 2007-08-30 22:17:58 +00:00
parent e9f3e3e5e0
commit ffc55edf36
3 changed files with 40 additions and 55 deletions

View File

@ -94,6 +94,7 @@ Cleanly installed Solaris can use this #define.
# include <qusec.h> /* error code structure */
# include <qusrjobi.h>
# include <qliept.h> /* EPT_CALL macro - this include must be after all other "QSYSINCs" */
# include <mih/testptr.h> /* For uprv_maximumPtr */
#elif defined(XP_MAC)
# include <Files.h>
# include <IntlResources.h>
@ -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

View File

@ -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) \

View File

@ -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