ICU-2403 tracing, changes from code review
X-SVN-Rev: 13792
This commit is contained in:
parent
5538a4c0b7
commit
9ded263c4a
@ -31,21 +31,20 @@ U_CDECL_BEGIN
|
||||
* @draft ICU 2.8
|
||||
*/
|
||||
|
||||
enum UTraceLevel {
|
||||
/** Disable all tracing */
|
||||
typedef enum UTraceLevel {
|
||||
/** Disable all tracing @draft ICU 2.8*/
|
||||
UTRACE_OFF=-1,
|
||||
/** Trace error conditions only */
|
||||
/** Trace error conditions only @draft ICU 2.8*/
|
||||
UTRACE_ERROR=0,
|
||||
/** Trace errors and warnings */
|
||||
/** Trace errors and warnings @draft ICU 2.8*/
|
||||
UTRACE_WARNING=3,
|
||||
/** Trace opens and closes of ICU services */
|
||||
/** Trace opens and closes of ICU services @draft ICU 2.8*/
|
||||
UTRACE_OPEN_CLOSE=5,
|
||||
/** Trace an intermediate number of ICU operations */
|
||||
/** Trace an intermediate number of ICU operations @draft ICU 2.8*/
|
||||
UTRACE_INFO=7,
|
||||
/** Trace the maximum number of ICU operations */
|
||||
/** Trace the maximum number of ICU operations @draft ICU 2.8*/
|
||||
UTRACE_VERBOSE=9
|
||||
};
|
||||
typedef enum UTraceLevel UTraceLevel;
|
||||
} UTraceLevel;
|
||||
|
||||
|
||||
/**
|
||||
@ -89,7 +88,7 @@ UTraceEntry(const void *context, int32_t fnNumber);
|
||||
*/
|
||||
typedef void U_CALLCONV
|
||||
UTraceExit(const void *context, int32_t fnNumber,
|
||||
int32_t argType, va_list args);
|
||||
const char *fmt, va_list args);
|
||||
|
||||
/**
|
||||
* Type signature for the trace function to be called from within an ICU function
|
||||
@ -109,6 +108,12 @@ UTraceData(const void *context, int32_t fnNumber, int32_t level,
|
||||
* of the use of ICU. Passing a NULL pointer for a tracing function
|
||||
* is allowed, and inhibits tracing action at points where that function
|
||||
* would be called.
|
||||
* <p>
|
||||
* Tracing and Threads: Tracing functions are global to a process, and
|
||||
* will be called in response to ICU operations performed by any
|
||||
* thread. If tracing of an individual thread is desired, the
|
||||
* tracing functions must themselves filter by checking that the
|
||||
* current thread is the desired thread.
|
||||
*
|
||||
* @param context an uninterpretted pointer. Whatever is passed in
|
||||
* here will in turn be passed to each of the tracing
|
||||
@ -244,8 +249,8 @@ utrace_getFunctions(const void **context,
|
||||
/**
|
||||
* Trace output Formatter. An application's UTraceData tracing functions may call
|
||||
* back to this function to format the trace output in a
|
||||
* human readable form. Note that a UTraceData function is not
|
||||
* required to format the data; it could, for example, save it in
|
||||
* human readable form. Note that a UTraceData function may choose
|
||||
* to not format the data; it could, for example, save it in
|
||||
* in the raw form it was received (more compact), leaving
|
||||
* formatting for a later trace analyis tool.
|
||||
* @param outBuf pointer to a buffer to receive the formatted output. Output
|
||||
@ -264,56 +269,28 @@ U_CAPI int32_t U_EXPORT2
|
||||
utrace_format(char *outBuf, int32_t capacity,
|
||||
int32_t indent, const char *fmt, va_list args);
|
||||
|
||||
|
||||
/**
|
||||
* Traced Function Exit return types.
|
||||
* Flags indicating the number and types of varargs included in a call
|
||||
* to a UTraceExit function.
|
||||
* Bits 0-3: The function return type. First variable param.
|
||||
* Bit 4: Flag for presence of U_ErrorCode status param.
|
||||
* @draft ICU 2.8
|
||||
*/
|
||||
enum UTraceExitVal {
|
||||
/** The traced function returns no value */
|
||||
UTRACE_EXITV_NONE = 0,
|
||||
/** The traced function returns an int32_t, or compatible, type. */
|
||||
UTRACE_EXITV_I32 = 1,
|
||||
/** The traced function returns a pointer */
|
||||
UTRACE_EXITV_PTR = 2,
|
||||
/** The traced function returns a UBool */
|
||||
UTRACE_EXITV_BOOL = 3,
|
||||
/** Mask to extract the return type values from a UTraceExitVal */
|
||||
UTRACE_EXITV_MASK = 0xf,
|
||||
/** Bit indicating that the traced function includes a UErrorCode parameter */
|
||||
UTRACE_EXITV_STATUS = 0x10
|
||||
};
|
||||
typedef enum UTraceExitVal UTraceExitVal;
|
||||
|
||||
|
||||
/**
|
||||
* Trace formatter for UTraceExit, function exit tracing.
|
||||
* UTraceExit may optionally receive two data items: a function return value
|
||||
* and a UErrorCode status value.
|
||||
*
|
||||
* @param outBuf pointer to a buffer to receive the formatted output.Output
|
||||
* Trace output Formatter. An application's UTraceData tracing functions may call
|
||||
* this function to format any additional trace data, beyond that
|
||||
* provided by default, in human readable form with the same
|
||||
* formatting conventions used by utrace_format().
|
||||
* @param outBuf pointer to a buffer to receive the formatted output. Output
|
||||
* will be nul 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 fnNumber An index specifying the function that is exiting.
|
||||
* @param argType Flags specifying the number and types of data values.
|
||||
* @param args Data to be formatted. If argType parameter indicates that a function
|
||||
* return value exists, it will be the first varargs param. The
|
||||
* function's UErrorCode status will be next, when applicable.
|
||||
* @param fmt Format specification for the data to output
|
||||
* @param ... Data to be formatted.
|
||||
* @return Length of formatted output, including the terminating NUL.
|
||||
* If buffer capacity is insufficient, the required capacity is returned.
|
||||
* @draft ICU 2.8
|
||||
*/
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
utrace_formatA(char *outBuf, int32_t capacity,
|
||||
int32_t indent, const char *fmt, ...);
|
||||
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
utrace_formatExit(char *outBuf, int32_t capacity, int32_t indent,
|
||||
int32_t fnNumber, int32_t argtype, va_list args);
|
||||
|
||||
/* Trace function numbers --------------------------------------------------- */
|
||||
|
||||
@ -331,8 +308,9 @@ utrace_functionName(int32_t fnNumber);
|
||||
|
||||
/**
|
||||
* These are the ICU functions that will be traced when tracing is enabled.
|
||||
* @draft ICU 2.8
|
||||
*/
|
||||
enum UTraceFunctionNumber {
|
||||
typedef enum UTraceFunctionNumber {
|
||||
UTRACE_FUNCTION_START=0,
|
||||
UTRACE_U_INIT=UTRACE_FUNCTION_START,
|
||||
UTRACE_U_CLEANUP,
|
||||
@ -353,8 +331,7 @@ enum UTraceFunctionNumber {
|
||||
UTRACE_UCOL_NEXTSORTKEYPART,
|
||||
UTRACE_UCOL_STRCOLLITER,
|
||||
UTRACE_COLLATION_LIMIT
|
||||
};
|
||||
typedef enum UTraceFunctionNumber UTraceFunctionNumber;
|
||||
} UTraceFunctionNumber;
|
||||
|
||||
U_CDECL_END
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#define UTRACE_IMPL
|
||||
#include "unicode/utrace.h"
|
||||
#include "utracimp.h"
|
||||
#include "cstring.h"
|
||||
#include "uassert.h"
|
||||
|
||||
@ -31,13 +32,41 @@ utrace_entry(int32_t fnNumber) {
|
||||
}
|
||||
|
||||
|
||||
static const char gExitFmt[] = "Returns.";
|
||||
static const char gExitFmtValue[] = "Returns %d.";
|
||||
static const char gExitFmtStatus[] = "Returns. Status = %d.";
|
||||
static const char gExitFmtValueStatus[] = "Returns %d. Status = %d.";
|
||||
static const char gExitFmtPtrStatus[] = "Returns %d. Status = %p.";
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
utrace_exit(int32_t fnNumber, int32_t returnType, ...) {
|
||||
if (pTraceExitFunc != NULL) {
|
||||
va_list args;
|
||||
va_list args;
|
||||
const char *fmt;
|
||||
|
||||
switch (returnType) {
|
||||
case 0:
|
||||
fmt = gExitFmt;
|
||||
break;
|
||||
case UTRACE_EXITV_I32:
|
||||
fmt = gExitFmtValue;
|
||||
break;
|
||||
case UTRACE_EXITV_STATUS:
|
||||
fmt = gExitFmtStatus;
|
||||
break;
|
||||
case UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS:
|
||||
fmt = gExitFmtValueStatus;
|
||||
break;
|
||||
case UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS:
|
||||
fmt = gExitFmtPtrStatus;
|
||||
break;
|
||||
default:
|
||||
U_ASSERT(FALSE);
|
||||
fmt = gExitFmt;
|
||||
}
|
||||
|
||||
va_start(args, returnType);
|
||||
(*pTraceExitFunc)(gTraceContext, fnNumber, returnType, args);
|
||||
(*pTraceExitFunc)(gTraceContext, fnNumber, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
@ -57,6 +86,28 @@ 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;
|
||||
/* Check whether a start of line indenting is needed. Three cases:
|
||||
* 1. At the start of the first line (output index == 0).
|
||||
* 2. At the start of subsequent lines (preceeding char in buffer == '\n')
|
||||
* 3. When preflighting buffer len (buffer capacity is exceeded), when
|
||||
* a \n is output. Ideally we wouldn't do the indent until the following char
|
||||
* is received, but that won't work because there's no place to remember that
|
||||
* the preceding char was \n. Meaning that we may overstimate the
|
||||
* buffer size needed. No harm done.
|
||||
*/
|
||||
if (*outIx==0 || /* case 1. */
|
||||
c!='\n' && c!=0 && *outIx < capacity && outBuf[(*outIx)-1]=='\n' || /* case 2. */
|
||||
c=='\n' && *outIx>=capacity) /* case 3 */
|
||||
{
|
||||
/* At the start of a line. Indent. */
|
||||
for(i=0; i<indent; i++) {
|
||||
if (*outIx < capacity) {
|
||||
outBuf[*outIx] = ' ';
|
||||
}
|
||||
(*outIx)++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*outIx < capacity) {
|
||||
outBuf[*outIx] = c;
|
||||
}
|
||||
@ -66,16 +117,6 @@ static void outputChar(char c, char *outBuf, int32_t *outIx, int32_t capacity, i
|
||||
* following output will overwrite the null. */
|
||||
(*outIx)++;
|
||||
}
|
||||
|
||||
/* Handle indenting at the start of lines */
|
||||
if (c == '\n') {
|
||||
for(i=0; i<indent; i++) {
|
||||
if (*outIx < capacity) {
|
||||
outBuf[*outIx] = ' ';
|
||||
}
|
||||
(*outIx)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void outputHexBytes(int64_t val, int32_t charsToOutput,
|
||||
@ -261,7 +302,7 @@ utrace_format(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, v
|
||||
ptrPtr = (void **)i8Ptr;
|
||||
vectorLen =(int32_t)va_arg(args, int32_t);
|
||||
if (ptrPtr == NULL) {
|
||||
outputString("NULL", outBuf, &outIx, capacity, indent);
|
||||
outputString("*NULL* ", outBuf, &outIx, capacity, indent);
|
||||
} else {
|
||||
for (i=0; i<vectorLen || vectorLen==-1; i++) {
|
||||
switch (vectorType) {
|
||||
@ -340,41 +381,17 @@ utrace_format(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, v
|
||||
}
|
||||
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
utrace_formatExit(char *outBuf, int32_t capacity, int32_t indent,
|
||||
int32_t fnNumber, int32_t argType, va_list args) {
|
||||
int32_t outIx = 0;
|
||||
int32_t intVal;
|
||||
UBool boolVal;
|
||||
void *ptrVal;
|
||||
UErrorCode status;
|
||||
|
||||
outputString(utrace_functionName(fnNumber), outBuf, &outIx, capacity, indent);
|
||||
outputString(" returns", outBuf, &outIx, capacity, indent);
|
||||
switch (argType & UTRACE_EXITV_MASK) {
|
||||
case UTRACE_EXITV_I32:
|
||||
outputChar(' ', outBuf, &outIx, capacity, indent);
|
||||
intVal = (int32_t)va_arg(args, int32_t);
|
||||
outputHexBytes(intVal, 8, outBuf, &outIx, capacity);
|
||||
break;
|
||||
case UTRACE_EXITV_PTR:
|
||||
outputChar(' ', outBuf, &outIx, capacity, indent);
|
||||
ptrVal = (void *)va_arg(args, void *);
|
||||
outputPtrBytes(ptrVal, outBuf, &outIx, capacity);
|
||||
break;
|
||||
case UTRACE_EXITV_BOOL:
|
||||
outputChar(' ', outBuf, &outIx, capacity, indent);
|
||||
boolVal = (UBool)va_arg(args, int32_t); /* gcc wants int, not UBool */
|
||||
outputString(boolVal? "TRUE": "FALSE", outBuf, &outIx, capacity, indent);
|
||||
}
|
||||
|
||||
outputString(".", outBuf, &outIx, capacity, indent);
|
||||
if (argType & UTRACE_EXITV_STATUS) {
|
||||
outputString(" Status = ", outBuf, &outIx, capacity, indent);
|
||||
status = (UErrorCode)va_arg(args, UErrorCode);
|
||||
outputString(u_errorName(status), outBuf, &outIx, capacity, indent);
|
||||
}
|
||||
outputChar(0, outBuf, &outIx, capacity, indent);
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
utrace_formatA(char *outBuf, int32_t capacity,
|
||||
int32_t indent, const char *fmt, ...) {
|
||||
int32_t retVal;
|
||||
va_list args;
|
||||
va_start(args, fmt );
|
||||
retVal = utrace_format(outBuf, capacity, indent, fmt, args);
|
||||
va_end(args);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,6 +127,31 @@ utrace_level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Traced Function Exit return types.
|
||||
* Flags indicating the number and types of varargs included in a call
|
||||
* to a UTraceExit function.
|
||||
* Bits 0-3: The function return type. First variable param.
|
||||
* Bit 4: Flag for presence of U_ErrorCode status param.
|
||||
* @internal
|
||||
*/
|
||||
typedef enum UTraceExitVal {
|
||||
/** The traced function returns no value @internal */
|
||||
UTRACE_EXITV_NONE = 0,
|
||||
/** The traced function returns an int32_t, or compatible, type. @internal */
|
||||
UTRACE_EXITV_I32 = 1,
|
||||
/** The traced function returns a pointer @internal */
|
||||
UTRACE_EXITV_PTR = 2,
|
||||
/** The traced function returns a UBool @internal */
|
||||
UTRACE_EXITV_BOOL = 3,
|
||||
/** Mask to extract the return type values from a UTraceExitVal @internal */
|
||||
UTRACE_EXITV_MASK = 0xf,
|
||||
/** Bit indicating that the traced function includes a UErrorCode parameter @internal */
|
||||
UTRACE_EXITV_STATUS = 0x10
|
||||
} UTraceExitVal;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Trace statement for each exit point of a function that has a UTRACE_ENTRY()
|
||||
* statement.
|
||||
|
@ -8613,16 +8613,8 @@ ucol_strcoll( const UCollator *coll,
|
||||
UTRACE_ENTRY(UTRACE_UCOL_STRCOLL);
|
||||
if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
|
||||
UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source=%p, target=%p", coll, source, target);
|
||||
int32_t actualLen = sourceLength;
|
||||
if (actualLen==-1 && source!=NULL) {
|
||||
actualLen = u_strlen(source);
|
||||
}
|
||||
UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vh ", source, actualLen);
|
||||
actualLen = targetLength;
|
||||
if (actualLen==-1 && target!=NULL) {
|
||||
actualLen = u_strlen(target);
|
||||
}
|
||||
UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vh ", target, actualLen);
|
||||
UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vh ", source, sourceLength);
|
||||
UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vh ", target, targetLength);
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
@ -64,24 +64,31 @@ void ctest_setICU_DATA(void);
|
||||
*/
|
||||
static int traceFnNestingDepth = 0;
|
||||
void U_CALLCONV TraceEntry(const void *context, int32_t fnNumber) {
|
||||
fprintf(stdout, "%s() Enter \n", utrace_functionName(fnNumber));
|
||||
char buf[500];
|
||||
utrace_formatA(buf, sizeof(buf), traceFnNestingDepth*3, "%s() enter.\n", utrace_functionName(fnNumber));
|
||||
fputs(buf, stdout);
|
||||
traceFnNestingDepth++;
|
||||
}
|
||||
|
||||
void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, int32_t type, va_list args) {
|
||||
char buf[2000];
|
||||
void U_CALLCONV TraceExit(const void *context, int32_t fnNumber, const char *fmt, va_list args) {
|
||||
char buf[500];
|
||||
|
||||
if (traceFnNestingDepth>0) {
|
||||
traceFnNestingDepth--;
|
||||
}
|
||||
utrace_formatExit(buf, sizeof(buf), traceFnNestingDepth*3, fnNumber, type, args);
|
||||
fprintf(stdout, "%s\n", buf);
|
||||
utrace_formatA(buf, sizeof(buf), traceFnNestingDepth*3, "%s() ", utrace_functionName(fnNumber));
|
||||
fputs(buf, stdout);
|
||||
utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args);
|
||||
fputs(buf, stdout);
|
||||
putc('\n', stdout);
|
||||
}
|
||||
|
||||
void U_CALLCONV TraceData(const void *context, int32_t fnNumber,
|
||||
int32_t level, const char *fmt, va_list args) {
|
||||
char buf[2000];
|
||||
char buf[500];
|
||||
utrace_format(buf, sizeof(buf), traceFnNestingDepth*3, fmt, args);
|
||||
fprintf(stdout, "%s\n", buf);
|
||||
fputs(buf, stdout);
|
||||
putc('\n', stdout);
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,7 +95,7 @@ void testTraceEntry(const void *context, int32_t fnNumber) {
|
||||
}
|
||||
|
||||
void testTraceExit(const void *context, int32_t fnNumber,
|
||||
int32_t argType, va_list args) {
|
||||
const char *fmt, va_list args) {
|
||||
}
|
||||
|
||||
void testTraceData(const void *context, int32_t fnNumber, int32_t level,
|
||||
@ -185,11 +185,12 @@ static void TestTraceAPI() {
|
||||
test_format("a 32 bit val %d...", 50, 0, "a 32 bit val 6789abcd...", __LINE__, 0x6789abcd);
|
||||
test_format("a 64 bit val %l", 50, 0, "a 64 bit val 123456780abcdef0"
|
||||
, __LINE__, INT64_C(0x123456780abcdef0));
|
||||
|
||||
if (sizeof(ptr) == 4) {
|
||||
ptr = (void *)0xdeadbeef;
|
||||
test_format("a 32 bit ptr %p", 50, 0, "a 32 bit ptr deadbeef", __LINE__, ptr);
|
||||
} else if (sizeof(ptr) == 8) {
|
||||
ptr = (void *)0x1000200030004000;
|
||||
} else if (sizeof(void *) == 8) {
|
||||
ptr = (void *) INT64_C(0x1000200030004000);
|
||||
test_format("a 64 bit ptr %p", 50, 0, "a 64 bit ptr 1000200030004000", __LINE__, ptr);
|
||||
} else {
|
||||
TEST_ASSERT(FALSE);
|
||||
@ -202,6 +203,12 @@ static void TestTraceAPI() {
|
||||
|
||||
test_format("%vb", 100, 0, "41 42 43 [00000003]", __LINE__, "ABC", 3);
|
||||
|
||||
/* Null ptrs for strings, vectors */
|
||||
test_format("Null string - %s", 50, 0, "Null string - *NULL*", __LINE__, NULL);
|
||||
test_format("Null string - %S", 50, 0, "Null string - *NULL*", __LINE__, NULL);
|
||||
test_format("Null vector - %vc", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
|
||||
test_format("Null vector - %vC", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
|
||||
test_format("Null vector - %vd", 50, 0, "Null vector - *NULL* [00000002]", __LINE__, NULL, 2);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user