From 2781c969ac8e220472eb199a19fe5f489f0a99c3 Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Sat, 20 Sep 2003 01:21:23 +0000 Subject: [PATCH] ICU-2403 Tracing, partial checkin only. X-SVN-Rev: 13149 --- icu4c/source/common/cstring.c | 66 +++-- icu4c/source/common/unicode/utrace.h | 79 ++++-- icu4c/source/common/utrace.c | 308 ++++++++++++++++----- icu4c/source/i18n/ucol.cpp | 144 ++++++---- icu4c/source/test/cintltst/capitst.c | 22 -- icu4c/source/test/cintltst/cintltst.c | 96 ++++++- icu4c/source/tools/ctestfw/ctest.c | 37 ++- icu4c/source/tools/ctestfw/unicode/ctest.h | 10 +- 8 files changed, 539 insertions(+), 223 deletions(-) diff --git a/icu4c/source/common/cstring.c b/icu4c/source/common/cstring.c index 9786c7f0e6..a95fc6f101 100644 --- a/icu4c/source/common/cstring.c +++ b/icu4c/source/common/cstring.c @@ -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; - - 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; + char tbuf[30]; + int32_t tbx = sizeof(tbuf); + uint8_t digit; + int32_t length = 0; + uint32_t uval; + + 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'; - - - /* 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; + + 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); + + /* 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++] = '-'; } diff --git a/icu4c/source/common/unicode/utrace.h b/icu4c/source/common/unicode/utrace.h index 1672e00e17..3ce85aad48 100644 --- a/icu4c/source/common/unicode/utrace.h +++ b/icu4c/source/common/unicode/utrace.h @@ -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; diff --git a/icu4c/source/common/utrace.c b/icu4c/source/common/utrace.c index 0b7339c848..bc12858946 100644 --- a/icu4c/source/common/utrace.c +++ b/icu4c/source/common/utrace.c @@ -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= 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= 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 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]"; + } +} + diff --git a/icu4c/source/i18n/ucol.cpp b/icu4c/source/i18n/ucol.cpp index 949947641d..8c684db40c 100644 --- a/icu4c/source/i18n/ucol.cpp +++ b/icu4c/source/i18n/ucol.cpp @@ -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 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; } diff --git a/icu4c/source/test/cintltst/capitst.c b/icu4c/source/test/cintltst/capitst.c index 6a8a009275..a99d3d3309 100644 --- a/icu4c/source/test/cintltst/capitst.c +++ b/icu4c/source/test/cintltst/capitst.c @@ -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)) { diff --git a/icu4c/source/test/cintltst/cintltst.c b/icu4c/source/test/cintltst/cintltst.c index 4515874343..ced2a26326 100644 --- a/icu4c/source/test/cintltst/cintltst.c +++ b/icu4c/source/test/cintltst/cintltst.c @@ -29,6 +29,7 @@ #include "unicode/ucnv.h" #include "unicode/ures.h" #include "unicode/uclean.h" +#include "uoptions.h" #ifdef XP_MAC_CONSOLE # include @@ -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 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; } diff --git a/icu4c/source/tools/ctestfw/ctest.c b/icu4c/source/tools/ctestfw/ctest.c index f2190d4e94..ce930d8915 100644 --- a/icu4c/source/tools/ctestfw/ctest.c +++ b/icu4c/source/tools/ctestfw/ctest.c @@ -12,6 +12,8 @@ #include #include +#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"); } diff --git a/icu4c/source/tools/ctestfw/unicode/ctest.h b/icu4c/source/tools/ctestfw/unicode/ctest.h index 7d554b4c86..ac65de3d3c 100644 --- a/icu4c/source/tools/ctestfw/unicode/ctest.h +++ b/icu4c/source/tools/ctestfw/unicode/ctest.h @@ -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. *