ICU-2403 Tracing, partial checkin only.

X-SVN-Rev: 13149
This commit is contained in:
Andy Heninger 2003-09-20 01:21:23 +00:00
parent e7109a24b7
commit 2781c969ac
8 changed files with 539 additions and 223 deletions

View File

@ -133,50 +133,45 @@ T_CString_toUpperCase(char* str)
/*
* Takes a int32_t and fills in a char* string with that number "radix"-based.
* Does not handle negative values (makes an empty string for them).
* Writes at most 11 chars ("2147483647" plus NUL).
* Writes at most 12 chars ("-2147483647" plus NUL).
* Returns the length of the string (not including the NUL).
*/
U_CAPI int32_t U_EXPORT2
T_CString_integerToString(char* buffer, int32_t i, int32_t radix)
T_CString_integerToString(char* buffer, int32_t v, int32_t radix)
{
int32_t length;
int32_t num;
int8_t digit;
char temp;
char tbuf[30];
int32_t tbx = sizeof(tbuf);
uint8_t digit;
int32_t length = 0;
uint32_t uval;
if(i<0) {
*buffer = 0;
return 0;
}
length = 0;
while (i>=radix)
{
num = i/radix;
digit = (int8_t)(i - num*radix);
buffer[length++] = (char)(T_CString_itosOffset(digit));
i = num;
U_ASSERT(radix>=2 && radix<=16);
uval = (uint32_t) v;
if(v<0 && radix == 10) {
/* Only in base 10 do we conside numbers to be signed. */
uval = (uint32_t)(-v);
buffer[length++] = '-';
}
buffer[length] = (char)(T_CString_itosOffset(i));
buffer[++length] = '\0';
tbx = sizeof(tbuf)-1;
tbuf[tbx] = 0; /* We are generating the digits backwards. Null term the end. */
do {
digit = (uint8_t)(uval % radix);
tbuf[--tbx] = (char)(T_CString_itosOffset(digit));
uval = uval / radix;
} while (uval != 0);
/* Reverses the string, swap digits at buffer[0]..buffer[num] */
num = length - 1;
for (i = 0; i < num; ++i, --num) {
temp = buffer[num];
buffer[num] = buffer[i];
buffer[i] = temp;
}
return length;
/* copy converted number into user buffer */
uprv_strcpy(buffer+length, tbuf+tbx);
length += sizeof(tbuf) - tbx -1;
return length;
}
/*
* Takes a int64_t and fills in a char* string with that number "radix"-based.
* Writes at most TODO: chars ("??????" plus NUL).
* Writes at most 21: chars ("-9223372036854775807" plus NUL).
* Returns the length of the string, not including the terminating NULL.
*/
U_CAPI int32_t U_EXPORT2
@ -190,7 +185,8 @@ T_CString_int64ToString(char* buffer, int64_t v, uint32_t radix)
U_ASSERT(radix>=2 && radix<=16);
uval = (uint64_t) v;
if(v<0) {
if(v<0 && radix == 10) {
/* Only in base 10 do we conside numbers to be signed. */
uval = (uint64_t)(-v);
buffer[length++] = '-';
}

View File

@ -112,6 +112,20 @@ utrace_setLevel(int32_t traceLevel);
utrace_entry(fnNumber); \
}
/* Function Exit return types. Internal
* Bits 0-3: The function return type. First variable param.
* Bit 4: Flag for presence of U_ErrorCode status param.
*/
enum UTraceExitVal {
UTRACE_EXITV_NONE = 0,
UTRACE_EXITV_I32 = 1,
UTRACE_EXITV_PTR = 2,
UTRACE_EXITV_BOOL = 3,
UTRACE_EXITV_MASK = 0xf,
UTRACE_EXITV_STATUS = 0x10
};
typedef enum UTraceExitVal UTraceExitVal;
/**
* Trace statement for each exit point of a function that has a UTRACE_ENTRY()
* statement.
@ -124,11 +138,30 @@ utrace_setLevel(int32_t traceLevel);
*
* @draft ICU 2.8
*/
#define UTRACE_EXIT(errorCode) \
#define UTRACE_EXIT() \
if(UTRACE_IS_ON) { \
utrace_exit(utraceFnNumber, errorCode); \
utrace_exit(utraceFnNumber, UTRACE_EXITV_NONE); \
}
/**
* Trace statement for each exit point of a function that has a UTRACE_ENTRY()
* statement, and that returns a value.
*
* @param val The function's return value, int32_t or comatible type.
*
* @draft ICU 2.8
*/
#define UTRACE_EXIT_D(val) \
if(UTRACE_IS_ON) { \
utrace_exit(utraceFnNumber, UTRACE_EXITV_I32, val); \
}
#define UTRACE_EXIT_S(status) \
if(UTRACE_IS_ON) { \
utrace_exit(utraceFnNumber, UTRACE_EXITV_STATUS, status); \
}
/**
* Trace function for the entry point of a function.
* Do not use directly, use UTRACE_ENTRY instead.
@ -140,13 +173,15 @@ utrace_entry(int32_t fnNumber);
/**
* Trace function for each exit point of a function.
* Do not use directly, use UTRACE_EXIT instead.
* Do not use directly, use UTRACE_EXIT* instead.
* @param fnNumber The UTraceFunctionNumber for the current function.
* @param returnType The type of the value returned by the function.
* @param errorCode The UErrorCode value at function exit. See UTRACE_EXIT.
* @internal
*/
U_CAPI void U_EXPORT2
utrace_exit(int32_t fnNumber, UErrorCode errorCode);
utrace_exit(int32_t fnNumber, UTraceExitVal returnType, ...);
/**
* Trace function used inside functions that have a UTRACE_ENTRY() statement.
@ -363,7 +398,8 @@ typedef void U_CALLCONV
UTraceEntry(const void *context, int32_t fnNumber);
typedef void U_CALLCONV
UTraceExit(const void *context, int32_t fnNumber, UErrorCode errorCode);
UTraceExit(const void *context, int32_t fnNumber,
UTraceExitVal retType, va_list args);
typedef void U_CALLCONV
UTraceData(const void *context, int32_t fnNumber, int32_t level,
@ -377,12 +413,21 @@ utrace_setFunctions(const void *context,
/**
* Trace output Formatter. Application tracing functions may call
* back to this function to format the trace output.
* Trace output Formatter. Application tracing functions may call
* back to this function to format the trace output.
* @param outBuf pointer to a buffer to receive the formatted output. Output
* will be null terminated if there is space in the buffer -
* if the length of the requested output < the output buffer size.
* @param capacity Length of the output buffer.
* @param indent Number of spaces to indent the output. Intended to allow
* data displayed from nested functions to be indented for readability.
* @param fmt Format specification for the data to output
* @param args Data to be formatted.
* @return Length of formatted output, including the terminating NULL if present.
*/
U_CAPI int32_t U_EXPORT2
utrace_format(char *outBuf, int32_t capacity,
const char *fmt, va_list args);
int32_t indent, const char *fmt, va_list args);
/* Trace function numbers --------------------------------------------------- */
@ -400,22 +445,24 @@ U_CAPI const char * U_EXPORT2
utrace_functionName(int32_t fnNumber);
enum UTraceFunctionNumber {
UTRACE_U_CLEANUP=0,
UTRACE_FUNCTION_START=UTRACE_U_CLEANUP,
UTRACE_FUNCTION_START=0,
UTRACE_U_INIT=UTRACE_FUNCTION_START,
UTRACE_U_CLEANUP,
UTRACE_FUNCTION_LIMIT,
UTRACE_UCNV_OPEN=0x1000,
UTRACE_CONVERSION_START=UTRACE_UCNV_OPEN,
UTRACE_CONVERSION_START=0x1000,
UTRACE_UCNV_OPEN=UTRACE_CONVERSION_START,
UTRACE_UCNV_CLOSE,
UTRACE_UCNV_FLUSH_CACHE,
UTRACE_CONVERSION_LIMIT,
UTRACE_UCOL_OPEN=0x2000,
UTRACE_COLLATION_START=UTRACE_UCOL_OPEN,
UTRACE_COLLATION_START=0x2000,
UTRACE_UCOL_OPEN=UTRACE_COLLATION_START,
UTRACE_UCOL_CLOSE,
UTRACE_UCOL_STRCOLL,
UTRACE_UCOL_GET_SORTKEY,
UTRACE_COLLATION_LIMIT,
UTRACE_FUNCTION_LIMIT=UTRACE_COLLATION_LIMIT
UTRACE_COLLATION_GETLOCALE
};
typedef enum UTraceFunctionNumber UTraceFunctionNumber;

View File

@ -11,6 +11,7 @@
#include "unicode/utrace.h"
#include "cstring.h"
#include "uassert.h"
static UTraceEntry *pTraceEntryFunc = NULL;
@ -28,13 +29,17 @@ utrace_entry(int32_t fnNumber) {
U_CAPI void U_EXPORT2
utrace_exit(int32_t fnNumber, UErrorCode status) {
utrace_exit(int32_t fnNumber, UTraceExitVal returnType, ...) {
if (pTraceExitFunc != NULL) {
(*pTraceExitFunc)(gTraceContext, fnNumber, status);
va_list args;
va_start(args, returnType);
(*pTraceExitFunc)(gTraceContext, fnNumber, returnType, args);
va_end(args);
}
}
U_CAPI void U_EXPORT2
utrace_data(int32_t fnNumber, int32_t level, const char *fmt, ...) {
if (pTraceDataFunc != NULL) {
@ -46,111 +51,225 @@ utrace_data(int32_t fnNumber, int32_t level, const char *fmt, ...) {
}
static void outputChar(char c, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) {
int32_t i;
if (*outIx < capacity) {
outBuf[*outIx] = c;
(*outIx)++;
}
if (c == '\n') {
for(i=0; i<indent; i++) {
if (*outIx < capacity) {
outBuf[*outIx] = ' ';
(*outIx)++;
}
}
}
}
static void outputHexBytes(int64_t val, int32_t charsToOutput,
char *outBuf, int32_t *outIx, int32_t capacity) {
static const char gHexChars[] = "0123456789abcdef";
int32_t shiftCount;
for (shiftCount=(charsToOutput-1)*4; shiftCount >= 0; shiftCount-=4) {
char c = gHexChars[(val >> shiftCount) & 0xf];
outputChar(c, outBuf, outIx, capacity, 0);
}
}
/* Output a pointer value in hex. Work with any size of pointer */
static void outputPtrBytes(void *val, char *outBuf, int32_t *outIx, int32_t capacity) {
static const int16_t endianTestVal = (int16_t)0xabcd;
int32_t i;
int32_t incVal = 1; /* +1 for big endian, -1 for little endian */
char *p = (char *)&val; /* point to current byte to output in the ptr val */
if (*(uint8_t *)&endianTestVal == (uint8_t)0xcd) {
/* Little Endian. Move p to most significant end of the value */
incVal = -1;
p += sizeof(void *) - 1;
}
/* Loop through the bytes of the ptr as it sits in memory, from
* most significant to least significant end */
for (i=0; i<sizeof(void *); i++) {
outputHexBytes(*p, 2, outBuf, outIx, capacity);
p += incVal;
}
}
static void outputString(const char *s, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) {
int32_t i = 0;
char c;
if (s==NULL) {
s = "*NULL*";
}
do {
c = s[i++];
outputChar(c, outBuf, outIx, capacity, indent);
} while (c != 0);
}
U_CAPI int32_t U_EXPORT2
utrace_format(char *outBuf, int32_t capacity, const char *fmt, va_list args) {
int32_t outIx = 0;
int32_t fmtIx = 0;
int32_t tbufIx = 0;
char fmtC;
int32_t intArg;
char *ptrArg;
char tbuf[32]; /* Small buffer to hold numeric conversions, which may
* not fit in output buffer without overflow. */
utrace_format(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, va_list args) {
int32_t outIx = 0;
int32_t fmtIx = 0;
int32_t tbufIx = 0;
char fmtC;
char c;
int32_t intArg;
int64_t longArg;
char *ptrArg;
int32_t i;
for (i=0; i<indent; i++) {
outputChar(' ', outBuf, &outIx, capacity, indent);
}
/* Loop runs once for each character in the format string.
* Break out when format is exhausted or the output buffer fills, whichever comes first.
*/
for (;;) {
if (outIx >= capacity) {
break;
}
fmtC = fmt[fmtIx++];
if (fmtC != '%') {
outBuf[outIx++] = fmtC;
/* Literal character, not part of a %sequence. Just copy it to the output. */
outputChar(fmtC, outBuf, &outIx, capacity, indent);
if (fmtC == 0) {
/* We hit the null that terminates the format string.
* This is the normal (and only) exit from the loop that
* interprets the format
*/
break;
}
continue;
}
/* We encountered a '%'. Pick up the following format char */
fmtC = fmt[fmtIx++];
if (fmtC == '%' || fmtC == 0) {
outBuf[outIx++] = '%';
if (fmtC == 0) {
/* Single '%' at end of fmt string. Treat as literal. */
break;
} else {
/* %% in string, outputs a single %. */
continue;
}
}
if (fmtC == 'v') {
/* TODO: vector handling... */
}
switch (fmtC) {
case 'c':
outBuf[outIx++] = (char)va_arg(args, int32_t);
/* single 8 bit char */
c = (char)va_arg(args, int32_t);
outputChar(c, outBuf, &outIx, capacity, indent);
break;
case 's':
/* char * string, null terminated. */
ptrArg = va_arg(args, char *);
if (ptrArg == NULL) {
if (capacity - outIx > 6) {
uprv_strcpy(outBuf+outIx, "*NULL*");
outIx += 6;
} else {
outBuf[outIx++] = '0';
}
break;
}
while (*ptrArg != 0 && outIx < capacity) {
outBuf[outIx++] = *ptrArg++;
}
outputString((const char *)ptrArg, outBuf, &outIx, capacity, indent);
break;
case 'b':
case 'h':
case 'd':
/* 8, 16, 32 bit ints. Not in a vector, so these all are passed
* in the same way, as a plain in32_t
*/
intArg = va_arg(args, int32_t);
tbufIx = 0;
if (intArg < 0) {
tbuf[0] = '-';
tbufIx = 1;
intArg = -intArg;
}
T_CString_integerToString(tbuf + tbufIx, intArg, 10);
for (tbufIx = 0; tbuf[tbufIx] != 0 && outIx < capacity; tbufIx++) {
outBuf[outIx++] = tbuf[tbufIx];
}
/* 8 bit int */
intArg = va_arg(args, int);
outputHexBytes(intArg, 2, outBuf, &outIx, capacity);
break;
case 'p':
/* Pointers */
ptrArg = va_arg(args, char *);
/* TODO: handle 64 bit ptrs. */
intArg = (int)ptrArg;
T_CString_integerToString(tbuf, intArg, 16);
for (tbufIx = 0; tbuf[tbufIx] != 0 && outIx < capacity; tbufIx++) {
outBuf[outIx++] = tbuf[tbufIx];
}
case 'h':
/* 16 bit int */
intArg = va_arg(args, int);
outputHexBytes(intArg, 4, outBuf, &outIx, capacity);
break;
case 'd':
/* 32 bit int */
intArg = va_arg(args, int);
outputHexBytes(intArg, 8, outBuf, &outIx, capacity);
break;
case 'l':
/* TODO: 64 bit longs */
outBuf[outIx++] = 'X';
/* 64 bit long */
longArg = va_arg(args, int64_t);
outputHexBytes(longArg, 16, outBuf, &outIx, capacity);
break;
default:
/* %? in format string, where ? is some character not in the set
* of recognized format chars. Just output it as if % wasn't there.
case 'p':
/* Pointers. */
ptrArg = va_arg(args, void *);
outputPtrBytes(ptrArg, outBuf, &outIx, capacity);
break;
case 0:
/* Single '%' at end of fmt string. Output as literal '%'.
* Back up index into format string so that the terminating null will be
* re-fetched in the outer loop, causing it to terminate.
*/
outBuf[outIx++] = fmtC;
outputChar('%', outBuf, &outIx, capacity, indent);
fmtIx--;
break;
case 'v':
{
/* Vector of values, e.g. %vh */
char vectorType;
int32_t vectorLen;
const char *i8Ptr;
int16_t *i16Ptr;
int32_t *i32Ptr;
int64_t *i64Ptr;
void **ptrPtr;
int32_t charsToOutput;
int32_t i;
vectorType = fmt[fmtIx];
if (vectorType != 0) {
fmtIx++;
}
i8Ptr = (const char *)va_arg(args, void*);
i16Ptr = (int16_t *)i8Ptr;
i32Ptr = (int32_t *)i8Ptr;
i64Ptr = (int64_t *)i8Ptr;
ptrPtr = (void **)i8Ptr;
vectorLen =(int32_t)va_arg(args, int32_t);
for (i=0; i<vectorLen; i++) {
switch (vectorType) {
case 'b':
charsToOutput = 2;
longArg = *i8Ptr++;
break;
case 'h':
charsToOutput = 4;
longArg = *i16Ptr++;
break;
case 'd':
charsToOutput = 8;
longArg = *i32Ptr++;
break;
case 'l':
charsToOutput = 16;
longArg = *i64Ptr++;
break;
case 'p':
charsToOutput = 0;
outputPtrBytes(*ptrPtr, outBuf, &outIx, capacity);
ptrPtr++;
break;
case 'c':
charsToOutput = 0;
outputChar(*i8Ptr, outBuf, &outIx, capacity, indent);
i8Ptr++;
break;
case 's':
charsToOutput = 0;
outputString(i8Ptr, outBuf, &outIx, capacity, indent);
outputChar('\n', outBuf, &outIx, capacity, indent);
}
if (charsToOutput > 0) {
outputHexBytes(longArg, charsToOutput, outBuf, &outIx, capacity);
outputChar(' ', outBuf, &outIx, capacity, indent);
}
}
}
break;
default:
/* %. in format string, where . is some character not in the set
* of recognized format chars. Just output it as if % wasn't there.
* (Covers "%%" outputing a single '%')
*/
outputChar(fmtC, outBuf, &outIx, capacity, indent);
}
}
return outIx;
@ -177,3 +296,42 @@ utrace_setFunctions(const void *context,
pTraceDataFunc = d;
utrace_level = traceLevel;
}
static const char * const
trFnName[] = {"u_init",
"u_cleanup",
0};
static const char * const
trConvNames[] = {
"ucnv_open",
"ucnv_close",
"ucnv_flushCache",
0};
static const char * const
trCollNames[] = {
"ucol_open",
"ucol_close",
"ucol_strcoll",
"ucol_getSortKey",
"ucol_getLocale",
0};
U_CAPI const char * U_EXPORT2
utrace_functionName(int32_t fnNumber) {
if(UTRACE_FUNCTION_START <= fnNumber && fnNumber < UTRACE_FUNCTION_LIMIT) {
return trFnName[fnNumber];
} else if(UTRACE_CONVERSION_START <= fnNumber && fnNumber < UTRACE_CONVERSION_LIMIT) {
return trConvNames[fnNumber - UTRACE_CONVERSION_START];
} else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){
return trCollNames[fnNumber - UTRACE_COLLATION_START];
} else {
return "[BOGUS Trace Function Number]";
}
}

View File

@ -352,7 +352,7 @@ ucol_open(const char *loc,
result = ucol_open_internal(loc, status);
}
UTRACE_DATA1(UTRACE_INFO, "Returning %p", result);
UTRACE_EXIT(*status);
UTRACE_EXIT_S(*status);
return result;
}
@ -471,49 +471,53 @@ ucol_setReqValidLocales(UCollator *coll, char *requestedLocaleToAdopt, char *val
U_CAPI void U_EXPORT2
ucol_close(UCollator *coll)
{
UTRACE_ENTRY(UTRACE_UCNV_CLOSE);
UTRACE_DATA1(UTRACE_INFO, "coll = %p", coll);
if(coll != NULL) {
// these are always owned by each UCollator struct,
// so we always free them
if(coll->validLocale != NULL) {
uprv_free(coll->validLocale);
}
if(coll->requestedLocale != NULL) {
uprv_free(coll->requestedLocale);
}
/* Here, it would be advisable to close: */
/* - UData for UCA (unless we stuff it in the root resb */
/* Again, do we need additional housekeeping... HMMM! */
if(coll->freeOnClose == FALSE){
return; /* for safeClone, if freeOnClose is FALSE,
don't free the other instance data */
}
if(coll->freeOptionsOnClose != FALSE) {
if(coll->options != NULL) {
uprv_free(coll->options);
// these are always owned by each UCollator struct,
// so we always free them
if(coll->validLocale != NULL) {
uprv_free(coll->validLocale);
}
if(coll->requestedLocale != NULL) {
uprv_free(coll->requestedLocale);
}
/* Here, it would be advisable to close: */
/* - UData for UCA (unless we stuff it in the root resb */
/* Again, do we need additional housekeeping... HMMM! */
UTRACE_DATA1(UTRACE_INFO, "coll->freeOnClose: %d", coll->freeOnClose);
if(coll->freeOnClose){
/* for safeClone, if freeOnClose is FALSE,
don't free the other instance data */
if(coll->freeOptionsOnClose != FALSE) {
if(coll->options != NULL) {
uprv_free(coll->options);
}
}
if(coll->mapping != NULL) {
/*ucmpe32_close(coll->mapping);*/
uprv_free(coll->mapping);
}
if(coll->rules != NULL && coll->freeRulesOnClose) {
uprv_free((UChar *)coll->rules);
}
if(coll->rb != NULL) { /* pointing to read-only memory */
ures_close(coll->rb);
}
if(coll->freeImageOnClose == TRUE) {
uprv_free((UCATableHeader *)coll->image);
}
if(coll->elements != NULL) {
ures_close(coll->elements);
}
if(coll->latinOneCEs != NULL) {
uprv_free(coll->latinOneCEs);
}
uprv_free(coll);
}
}
if(coll->mapping != NULL) {
/*ucmpe32_close(coll->mapping);*/
uprv_free(coll->mapping);
}
if(coll->rules != NULL && coll->freeRulesOnClose) {
uprv_free((UChar *)coll->rules);
}
if(coll->rb != NULL) { /* pointing to read-only memory */
ures_close(coll->rb);
}
if(coll->freeImageOnClose == TRUE) {
uprv_free((UCATableHeader *)coll->image);
}
if(coll->elements != NULL) {
ures_close(coll->elements);
}
if(coll->latinOneCEs != NULL) {
uprv_free(coll->latinOneCEs);
}
uprv_free(coll);
}
UTRACE_EXIT();
}
U_CAPI UCollator* U_EXPORT2
@ -4279,21 +4283,33 @@ ucol_getSortKey(const UCollator *coll,
uint8_t *result,
int32_t resultLength)
{
UErrorCode status = U_ZERO_ERROR;
if(source == NULL) {
// this is actually an error situation, but we would need to
// have an error code to return it. Until we introduce a new
// API, it stays like this
return 0;
UTRACE_ENTRY(UTRACE_UCOL_GET_SORTKEY);
if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
int32_t actualSrcLen = sourceLength;
if (actualSrcLen==0 && source!=NULL) {
actualSrcLen = u_strlen(source);
}
UTRACE_DATA2(UTRACE_VERBOSE, "source string %vh", source, actualSrcLen);
}
/* this uses the function pointer that is set in updateinternalstate */
/* currently, there are two funcs: */
/*ucol_calcSortKey(...);*/
/*ucol_calcSortKeySimpleTertiary(...);*/
int32_t keySize = coll->sortKeyGen(coll, source, sourceLength, &result, resultLength, FALSE, &status);
//((UCollator *)coll)->errorCode = status; /*semantically const */
UErrorCode status = U_ZERO_ERROR;
int32_t keySize = 0;
if(source != NULL) {
// source == NULL is actually an error situation, but we would need to
// have an error code to return it. Until we introduce a new
// API, it stays like this
/* this uses the function pointer that is set in updateinternalstate */
/* currently, there are two funcs: */
/*ucol_calcSortKey(...);*/
/*ucol_calcSortKeySimpleTertiary(...);*/
keySize = coll->sortKeyGen(coll, source, sourceLength, &result, resultLength, FALSE, &status);
//((UCollator *)coll)->errorCode = status; /*semantically const */
}
UTRACE_DATA2(UTRACE_VERBOSE, "Sort Key = %vb", result, keySize);
UTRACE_EXIT_S(status);
return keySize;
}
@ -8560,10 +8576,14 @@ ucol_strcoll( const UCollator *coll,
const UChar *target,
int32_t targetLength) {
U_ALIGN_CODE(16);
UTRACE_ENTRY(UTRACE_UCOL_STRCOLL);
UTRACE_DATA5(UTRACE_VERBOSE, "coll=%p, source=%p, sourceLength=%d, target=%p, targetLength=%d",
coll, source, sourceLength, target, targetLength);
UErrorCode status = U_ZERO_ERROR;
if(source == NULL || target == NULL) {
// do not crash, but return. Should have
// status argument to return error.
UTRACE_EXIT_D(UTRACE_UCOL_STRCOLL);
return UCOL_EQUAL;
}
collIterate sColl, tColl;
@ -8580,6 +8600,7 @@ ucol_strcoll( const UCollator *coll,
// Check for them being the same string, and scan through
// any leading equal portion.
if (source==target) {
UTRACE_EXIT_D(UCOL_EQUAL);
return UCOL_EQUAL;
}
@ -8594,6 +8615,7 @@ ucol_strcoll( const UCollator *coll,
pTarg++;
}
if (*pSrc == 0 && *pTarg == 0) {
UTRACE_EXIT_D(UCOL_EQUAL);
return UCOL_EQUAL;
}
equalLength = pSrc - source;
@ -8604,6 +8626,7 @@ ucol_strcoll( const UCollator *coll,
/* check if source and target are same strings */
if (source==target && sourceLength==targetLength) {
UTRACE_EXIT_D(UCOL_EQUAL);
return UCOL_EQUAL;
}
const UChar *pSrcEnd = source + sourceLength;
@ -8632,6 +8655,7 @@ ucol_strcoll( const UCollator *coll,
// If we made it all the way through both strings, we are done. They are ==
if ((pSrc ==pSrcEnd || (pSrcEnd <pSrc && *pSrc==0)) && /* At end of src string, however it was specified. */
(pTarg==pTargEnd || (pTargEnd<pTarg && *pTarg==0))) { /* and also at end of dest string */
UTRACE_EXIT_D(UCOL_EQUAL);
return UCOL_EQUAL;
}
}
@ -8665,14 +8689,17 @@ ucol_strcoll( const UCollator *coll,
}
}
UCollationResult returnVal;
if(!coll->latinOneUse || (sourceLength > 0 && *source&0xff00) || (targetLength > 0 && *target&0xff00)) {
// Preparing the context objects for iterating over strings
IInit_collIterate(coll, source, sourceLength, &sColl);
IInit_collIterate(coll, target, targetLength, &tColl);
return ucol_strcollRegular(&sColl, &tColl, &status);
returnVal = ucol_strcollRegular(&sColl, &tColl, &status);
} else {
return ucol_strcollUseLatin1(coll, source, sourceLength, target, targetLength, &status);
returnVal = ucol_strcollUseLatin1(coll, source, sourceLength, target, targetLength, &status);
}
UTRACE_EXIT_D(returnVal);
return returnVal;
}
/* convenience function for comparing strings */
@ -8718,6 +8745,9 @@ ucol_getLocale(const UCollator *coll, ULocDataLocaleType type, UErrorCode *statu
if(status == NULL || U_FAILURE(*status)) {
return NULL;
}
UTRACE_ENTRY(UTRACE_COLLATION_GETLOCALE);
UTRACE_DATA1(UTRACE_INFO, "coll=%p", coll);
switch(type) {
case ULOC_ACTUAL_LOCALE:
// validLocale is set only if service registration has explicitly set the
@ -8742,6 +8772,8 @@ ucol_getLocale(const UCollator *coll, ULocDataLocaleType type, UErrorCode *statu
default:
*status = U_ILLEGAL_ARGUMENT_ERROR;
}
UTRACE_DATA1(UTRACE_INFO, "result = %s", result);
UTRACE_EXIT_S(*status);
return result;
}

View File

@ -33,23 +33,6 @@ static void TestAttribute(void);
int TestBufferSize(); /* defined in "colutil.c" */
/*
* Tracing functions.
*/
void U_CALLCONV TraceEntry(const void *context, int32_t fnNumber) {
fprintf(stderr, "Trace Entry %#x!!!\n", fnNumber);
}
void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, UErrorCode status) {
}
void U_CALLCONV TraceData(const void *context, int32_t fnNumber,
int32_t level, const char *fmt, va_list args) {
char buf[2000];
utrace_format(buf, sizeof(buf), fmt, args);
fprintf(stderr, "Trace Data fn %#x \"%s\"\n", fnNumber, buf);
}
/* next two function is modified from "i18n/ucol.cpp" to avoid include "ucol_imp.h" */
@ -448,11 +431,6 @@ void TestRuleBasedColl()
u_uastrcpy(ruleset1, "&9 < a, A < b, B < c, C; ch, cH, Ch, CH < d, D, e, E");
u_uastrcpy(ruleset2, "&9 < a, A < b, B < c, C < d, D, e, E");
utrace_setFunctions(NULL, TraceEntry, TraceExit, TraceData, UTRACE_VERBOSE, &status);
if (U_FAILURE(status)) {
log_err("utrace_setFunctions() failed.: %s\n", myErrorName(status));
return;
}
col1 = ucol_openRules(ruleset1, u_strlen(ruleset1), UCOL_DEFAULT, UCOL_DEFAULT_STRENGTH, NULL,&status);
if (U_FAILURE(status)) {

View File

@ -29,6 +29,7 @@
#include "unicode/ucnv.h"
#include "unicode/ures.h"
#include "unicode/uclean.h"
#include "uoptions.h"
#ifdef XP_MAC_CONSOLE
# include <console.h>
@ -57,6 +58,56 @@ void ctest_setICU_DATA(void);
# define TRY_CNV_2 "sjis"
#endif
/*
* Tracing functions.
*/
static int traceFnNestingDepth = 0;
void U_CALLCONV TraceEntry(const void *context, int32_t fnNumber) {
fprintf(stderr, "%s() Enter \n", utrace_functionName(fnNumber));
traceFnNestingDepth++;
}
void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, UTraceExitVal type, va_list args) {
int32_t intVal;
UBool boolVal;
void *ptrVal;
fprintf(stderr, "%s() returns", utrace_functionName(fnNumber));
switch (type & UTRACE_EXITV_MASK) {
case UTRACE_EXITV_NONE:
fprintf(stderr, ".");
break;
case UTRACE_EXITV_I32:
intVal = (int32_t)va_arg(args, int32_t);
fprintf(stderr, " %d", intVal);
break;
case UTRACE_EXITV_PTR:
ptrVal = (void *)va_arg(args, void *);
fprintf(stderr, " %x", ptrVal);
break;
case UTRACE_EXITV_BOOL:
boolVal = (UBool)va_arg(args, int32_t); /* gcc wants int, not UBool */
fprintf(stderr, boolVal? " TRUE": " FALSE");
}
if (type & UTRACE_EXITV_STATUS) {
UErrorCode status = (UErrorCode)va_arg(args, UErrorCode);
fprintf(stderr, " Status = %s.", u_errorName(status));
}
traceFnNestingDepth--;
fprintf(stderr, "\n");
}
void U_CALLCONV TraceData(const void *context, int32_t fnNumber,
int32_t level, const char *fmt, va_list args) {
char buf[2000];
utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args);
fprintf(stderr, "%s\n", buf);
}
int main(int argc, const char* const argv[])
{
int nerrors = 0;
@ -70,19 +121,43 @@ int main(int argc, const char* const argv[])
UResourceBundle *rb;
UConverter *cnv;
#ifdef XP_MAC_CONSOLE
argc = ccommand((char***)&argv);
#endif
U_MAIN_INIT_ARGS(argc, argv);
/* Checkargs */
/* TODO: Test framework arg handling needs to be decoupled from test execution
* so that the args being processed here don't need special handling,
* separate from the other test args.
*/
ICU_TRACE = UTRACE_OFF;
for(i=1;i<argc;i++) {
if(!strcmp(argv[i],"-w")) {
warnOnMissingData = 1;
warnOrErr = "Warning";
}
else if (strcmp( argv[i], "-t_info") == 0) {
ICU_TRACE = UTRACE_INFO;
}
else if (strcmp( argv[i], "-t_error") == 0) {
ICU_TRACE = UTRACE_ERROR;
}
else if (strcmp( argv[i], "-t_warn") == 0) {
ICU_TRACE = UTRACE_WARNING;
}
else if (strcmp( argv[i], "-t_verbose") == 0) {
ICU_TRACE = UTRACE_VERBOSE;
}
}
while (REPEAT_TESTS > 0) {
utrace_setFunctions(NULL, TraceEntry, TraceExit, TraceData, ICU_TRACE, &errorCode);
if (U_FAILURE(errorCode)) {
log_err("utrace_setFunctions() failed.: %s\n", myErrorName(errorCode));
return -1;
}
while (REPEAT_TESTS > 0) { /* Loop runs once per complete execution of the tests
* used for -r (repeat) test option. */
#ifdef CTST_LEAK_CHECK
ctst_init();
@ -156,21 +231,26 @@ int main(int argc, const char* const argv[])
fprintf(stdout, "Default locale for this run is %s\n", uloc_getDefault());
/* Build a tree of all tests.
* Subsequently will be used to find / iterate the tests to run */
root = NULL;
addAllTests(&root);
/* Tests acutally run HERE. TODO: separate command line option parsing & setting from test execution!! */
nerrors = processArgs(root, argc, argv);
if (--REPEAT_TESTS > 0) {
printf("Repeating tests %d more time(s)\n", REPEAT_TESTS);
}
cleanUpTestTree(root);
#ifdef CTST_LEAK_CHECK
ctst_freeAll();
/* To check for leaks */
u_cleanup(); /* nuke the hashtable.. so that any still-open cnvs are leaked */
#endif
}
} /* End of loop that repeats the entire test, if requested. (Normally doesn't loop) */
return nerrors ? 1 : 0;
}

View File

@ -12,6 +12,8 @@
#include <assert.h>
#include <stdarg.h>
#include "unicode/utrace.h"
/* NOTES:
3/20/1999 srl - strncpy called w/o setting nulls at the end
*/
@ -85,6 +87,7 @@ int VERBOSITY = 0; /* be No-verbose by default */
int ERR_MSG =1; /* error messages will be displayed by default*/
int QUICK = 1; /* Skip some of the slower tests? */
int WARN_ON_MISSING_DATA = 0; /* Reduce data errs to warnings? */
UTraceLevel ICU_TRACE = UTRACE_OFF; /* ICU tracing level */
/*-------------------------------------------*/
/* strncmp that also makes sure there's a \0 at s2[0] */
@ -580,7 +583,19 @@ int processArgs(const TestNode* root,
{
subtreeOptionSeen=FALSE;
}
else if (strcmp( argv[1], "-h" )==0 )
else if (strcmp( argv[i], "-t_info") == 0) {
ICU_TRACE = UTRACE_INFO;
}
else if (strcmp( argv[i], "-t_error") == 0) {
ICU_TRACE = UTRACE_ERROR;
}
else if (strcmp( argv[i], "-t_warn") == 0) {
ICU_TRACE = UTRACE_WARNING;
}
else if (strcmp( argv[i], "-t_verbose") == 0) {
ICU_TRACE = UTRACE_VERBOSE;
}
else if (strcmp( argv[i], "-h" )==0 || strcmp( argv[i], "--help" )==0)
{
help( argv[0] );
return 0;
@ -619,19 +634,21 @@ int processArgs(const TestNode* root,
static void help ( const char *argv0 )
{
printf("Usage: %s [ -l ] [ -v ] [ -verbose] [-a] [ -all] [-n] \n [ -no_err_msg] [ -h ] [ /path/to/test ]\n",
printf("Usage: %s [ -l ] [ -v ] [ -verbose] [-a] [ -all] [-n] [ -no_err_msg]\n"
" [ -h ] [-t_info | -t_error | -t_warn | -t_verbose] [ /path/to/test ]\n",
argv0);
printf(" -l To get a list of test names\n");
printf(" -e to do exhaustive testing\n");
printf(" -l To get a list of test names\n");
printf(" -e to do exhaustive testing\n");
printf(" -verbose To turn ON verbosity\n");
printf(" -v To turn ON verbosity(same as -verbose)\n");
printf(" -h To print this message\n");
printf(" -n To turn OFF printing error messages\n");
printf(" -w Don't fail on data-loading errs, just warn. Useful if\n"
printf(" -v To turn ON verbosity(same as -verbose)\n");
printf(" -h To print this message\n");
printf(" -n To turn OFF printing error messages\n");
printf(" -w Don't fail on data-loading errs, just warn. Useful if\n"
" user has reduced/changed the common set of ICU data \n");
printf(" -t_info | -t_error | -t_warn | -t_verbose Enable ICU tracing\n");
printf(" -no_err_msg (same as -n) \n");
printf(" -r repeat tests after calling u_cleanup \n");
printf(" -[/subtest] To run a subtest \n");
printf(" -r repeat tests after calling u_cleanup \n");
printf(" -[/subtest] To run a subtest \n");
printf(" eg: to run just the utility tests type: cintltest /tsutil) \n");
}

View File

@ -1,7 +1,7 @@
/*
*****************************************************************************************
*
* Copyright (C) 1996-2000, International Business Machines
* Copyright (C) 1996-2003, International Business Machines
* Corporation and others. All Rights Reserved.
*
*****************************************************************************************
@ -12,6 +12,7 @@
#define CTEST_H
#include "unicode/utypes.h"
#include "unicode/utrace.h"
/*Deals with imports and exports of the dynamic library*/
#if defined(_WIN32) || defined(U_CYGWIN)
@ -97,6 +98,13 @@ T_CTEST_EXPORT_API extern int QUICK;
*/
T_CTEST_EXPORT_API extern int WARN_ON_MISSING_DATA;
/**
* ICU tracing level, is set by command line option
*
* @internal
*/
T_CTEST_EXPORT_API extern UTraceLevel ICU_TRACE;
/**
* Show the names of all nodes.
*