1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho*   Copyright (C) 2003-2008, International Business Machines
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   file name:  utrace.c
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   encoding:   US-ASCII
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   tab size:   8 (not used)
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   indentation:4
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define   UTRACE_IMPL
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utrace.h"
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "utracimp.h"
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uassert.h"
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ucln_cmn.h"
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UTraceEntry     *pTraceEntryFunc = NULL;
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UTraceExit      *pTraceExitFunc  = NULL;
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UTraceData      *pTraceDataFunc  = NULL;
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const void      *gTraceContext   = NULL;
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_EXPORT int32_t
2685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Houtrace_level = UTRACE_ERROR;
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_entry(int32_t fnNumber) {
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (pTraceEntryFunc != NULL) {
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (*pTraceEntryFunc)(gTraceContext, fnNumber);
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char gExitFmt[]             = "Returns.";
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char gExitFmtValue[]        = "Returns %d.";
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char gExitFmtStatus[]       = "Returns.  Status = %d.";
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char gExitFmtValueStatus[]  = "Returns %d.  Status = %d.";
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char gExitFmtPtrStatus[]    = "Returns %d.  Status = %p.";
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_exit(int32_t fnNumber, int32_t returnType, ...) {
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (pTraceExitFunc != NULL) {
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        va_list     args;
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const char *fmt;
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch (returnType) {
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 0:
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = gExitFmt;
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case UTRACE_EXITV_I32:
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = gExitFmtValue;
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case UTRACE_EXITV_STATUS:
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = gExitFmtStatus;
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS:
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = gExitFmtValueStatus;
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS:
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = gExitFmtPtrStatus;
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default:
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            U_ASSERT(FALSE);
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = gExitFmt;
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        va_start(args, returnType);
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (*pTraceExitFunc)(gTraceContext, fnNumber, fmt, args);
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        va_end(args);
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_data(int32_t fnNumber, int32_t level, const char *fmt, ...) {
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (pTraceDataFunc != NULL) {
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           va_list args;
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           va_start(args, fmt );
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           (*pTraceDataFunc)(gTraceContext, fnNumber, level, fmt, args);
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru           va_end(args);
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void outputChar(char c, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) {
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i;
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Check whether a start of line indenting is needed.  Three cases:
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   1.  At the start of the first line  (output index == 0).
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   2.  At the start of subsequent lines  (preceeding char in buffer == '\n')
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *   3.  When preflighting buffer len (buffer capacity is exceeded), when
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *       a \n is output.  Ideally we wouldn't do the indent until the following char
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *       is received, but that won't work because there's no place to remember that
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *       the preceding char was \n.  Meaning that we may overstimate the
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     *       buffer size needed.  No harm done.
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (*outIx==0 ||   /* case 1. */
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (c!='\n' && c!=0 && *outIx < capacity && outBuf[(*outIx)-1]=='\n') ||  /* case 2. */
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (c=='\n' && *outIx>=capacity))    /* case 3 */
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* At the start of a line.  Indent. */
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for(i=0; i<indent; i++) {
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (*outIx < capacity) {
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                outBuf[*outIx] = ' ';
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (*outIx)++;
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (*outIx < capacity) {
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outBuf[*outIx] = c;
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (c != 0) {
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* Nulls only appear as end-of-string terminators.  Move them to the output
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *  buffer, but do not update the length of the buffer, so that any
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru         *  following output will overwrite the null. */
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        (*outIx)++;
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void outputHexBytes(int64_t val, int32_t charsToOutput,
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                           char *outBuf, int32_t *outIx, int32_t capacity) {
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static const char gHexChars[] = "0123456789abcdef";
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t shiftCount;
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for  (shiftCount=(charsToOutput-1)*4; shiftCount >= 0; shiftCount-=4) {
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char c = gHexChars[(val >> shiftCount) & 0xf];
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outputChar(c, outBuf, outIx, capacity, 0);
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* Output a pointer value in hex.  Work with any size of pointer   */
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void outputPtrBytes(void *val, char *outBuf, int32_t *outIx, int32_t capacity) {
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t  i;
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t  incVal = 1;              /* +1 for big endian, -1 for little endian          */
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char     *p     = (char *)&val;   /* point to current byte to output in the ptr val  */
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !U_IS_BIG_ENDIAN
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Little Endian.  Move p to most significant end of the value      */
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    incVal = -1;
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    p += sizeof(void *) - 1;
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Loop through the bytes of the ptr as it sits in memory, from
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     * most significant to least significant end                    */
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (i=0; i<sizeof(void *); i++) {
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outputHexBytes(*p, 2, outBuf, outIx, capacity);
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        p += incVal;
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void outputString(const char *s, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) {
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i = 0;
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char    c;
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (s==NULL) {
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        s = "*NULL*";
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    do {
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        c = s[i++];
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outputChar(c, outBuf, outIx, capacity, indent);
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } while (c != 0);
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void outputUString(const UChar *s, int32_t len,
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) {
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t i = 0;
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar   c;
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (s==NULL) {
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outputString(NULL, outBuf, outIx, capacity, indent);
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (i=0; i<len || len==-1; i++) {
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        c = s[i];
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outputHexBytes(c, 4, outBuf, outIx, capacity);
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        outputChar(' ', outBuf, outIx, capacity, indent);
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (len == -1 && c==0) {
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_vformat(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, va_list args) {
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t   outIx  = 0;
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t   fmtIx  = 0;
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char      fmtC;
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char      c;
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t   intArg;
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int64_t   longArg = 0;
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char      *ptrArg;
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*   Loop runs once for each character in the format string.
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru     */
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (;;) {
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fmtC = fmt[fmtIx++];
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fmtC != '%') {
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Literal character, not part of a %sequence.  Just copy it to the output. */
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputChar(fmtC, outBuf, &outIx, capacity, indent);
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (fmtC == 0) {
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* We hit the null that terminates the format string.
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * This is the normal (and only) exit from the loop that
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 * interprets the format
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                 */
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            continue;
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        /* We encountered a '%'.  Pick up the following format char */
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fmtC = fmt[fmtIx++];
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        switch (fmtC) {
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 'c':
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* single 8 bit char   */
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            c = (char)va_arg(args, int32_t);
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputChar(c, outBuf, &outIx, capacity, indent);
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 's':
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* char * string, null terminated.  */
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ptrArg = va_arg(args, char *);
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputString((const char *)ptrArg, outBuf, &outIx, capacity, indent);
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 'S':
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* UChar * string, with length, len==-1 for null terminated. */
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ptrArg = va_arg(args, void *);             /* Ptr    */
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            intArg =(int32_t)va_arg(args, int32_t);    /* Length */
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputUString((const UChar *)ptrArg, intArg, outBuf, &outIx, capacity, indent);
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 'b':
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*  8 bit int  */
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            intArg = va_arg(args, int);
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputHexBytes(intArg, 2, outBuf, &outIx, capacity);
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 'h':
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*  16 bit int  */
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            intArg = va_arg(args, int);
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputHexBytes(intArg, 4, outBuf, &outIx, capacity);
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 'd':
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*  32 bit int  */
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            intArg = va_arg(args, int);
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputHexBytes(intArg, 8, outBuf, &outIx, capacity);
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 'l':
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*  64 bit long  */
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            longArg = va_arg(args, int64_t);
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputHexBytes(longArg, 16, outBuf, &outIx, capacity);
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 'p':
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /*  Pointers.   */
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ptrArg = va_arg(args, void *);
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputPtrBytes(ptrArg, outBuf, &outIx, capacity);
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 0:
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* Single '%' at end of fmt string.  Output as literal '%'.
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * Back up index into format string so that the terminating null will be
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             * re-fetched in the outer loop, causing it to terminate.
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            outputChar('%', outBuf, &outIx, capacity, indent);
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmtIx--;
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 'v':
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            {
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                /* Vector of values, e.g. %vh */
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                char     vectorType;
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t  vectorLen;
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                const char   *i8Ptr;
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int16_t  *i16Ptr;
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t  *i32Ptr;
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int64_t  *i64Ptr;
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                void     **ptrPtr;
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t   charsToOutput = 0;
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t   i;
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                vectorType = fmt[fmtIx];    /* b, h, d, l, p, etc. */
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (vectorType != 0) {
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    fmtIx++;
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                i8Ptr = (const char *)va_arg(args, void*);
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                i16Ptr = (int16_t *)i8Ptr;
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                i32Ptr = (int32_t *)i8Ptr;
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                i64Ptr = (int64_t *)i8Ptr;
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ptrPtr = (void **)i8Ptr;
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                vectorLen =(int32_t)va_arg(args, int32_t);
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (ptrPtr == NULL) {
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    outputString("*NULL* ", outBuf, &outIx, capacity, indent);
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    for (i=0; i<vectorLen || vectorLen==-1; i++) {
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        switch (vectorType) {
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'b':
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charsToOutput = 2;
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            longArg = *i8Ptr++;
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'h':
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charsToOutput = 4;
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            longArg = *i16Ptr++;
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'd':
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charsToOutput = 8;
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            longArg = *i32Ptr++;
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'l':
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charsToOutput = 16;
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            longArg = *i64Ptr++;
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'p':
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charsToOutput = 0;
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outputPtrBytes(*ptrPtr, outBuf, &outIx, capacity);
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            longArg = *ptrPtr==NULL? 0: 1;    /* test for null terminated array. */
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            ptrPtr++;
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'c':
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charsToOutput = 0;
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outputChar(*i8Ptr, outBuf, &outIx, capacity, indent);
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            longArg = *i8Ptr;    /* for test for null terminated array. */
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            i8Ptr++;
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 's':
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charsToOutput = 0;
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outputString(*ptrPtr, outBuf, &outIx, capacity, indent);
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outputChar('\n', outBuf, &outIx, capacity, indent);
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            longArg = *ptrPtr==NULL? 0: 1;   /* for test for null term. array. */
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            ptrPtr++;
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        case 'S':
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            charsToOutput = 0;
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outputUString((const UChar *)*ptrPtr, -1, outBuf, &outIx, capacity, indent);
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outputChar('\n', outBuf, &outIx, capacity, indent);
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            longArg = *ptrPtr==NULL? 0: 1;   /* for test for null term. array. */
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            ptrPtr++;
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (charsToOutput > 0) {
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outputHexBytes(longArg, charsToOutput, outBuf, &outIx, capacity);
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            outputChar(' ', outBuf, &outIx, capacity, indent);
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (vectorLen == -1 && longArg == 0) {
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            break;
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                outputChar('[', outBuf, &outIx, capacity, indent);
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                outputHexBytes(vectorLen, 8, outBuf, &outIx, capacity);
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                outputChar(']', outBuf, &outIx, capacity, indent);
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default:
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* %. in format string, where . is some character not in the set
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *    of recognized format chars.  Just output it as if % wasn't there.
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             *    (Covers "%%" outputing a single '%')
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             */
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru             outputChar(fmtC, outBuf, &outIx, capacity, indent);
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    outputChar(0, outBuf, &outIx, capacity, indent);  /* Make sure that output is null terminated  */
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return outIx + 1;     /* outIx + 1 because outIx does not increment when outputing final null. */
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_format(char *outBuf, int32_t capacity,
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int32_t indent, const char *fmt,  ...) {
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t retVal;
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    va_list args;
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    va_start(args, fmt );
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    retVal = utrace_vformat(outBuf, capacity, indent, fmt, args);
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    va_end(args);
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return retVal;
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_setFunctions(const void *context,
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    UTraceEntry *e, UTraceExit *x, UTraceData *d) {
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pTraceEntryFunc = e;
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pTraceExitFunc  = x;
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pTraceDataFunc  = d;
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gTraceContext   = context;
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_getFunctions(const void **context,
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    UTraceEntry **e, UTraceExit **x, UTraceData **d) {
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *e = pTraceEntryFunc;
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *x = pTraceExitFunc;
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *d = pTraceDataFunc;
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *context = gTraceContext;
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI void U_EXPORT2
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_setLevel(int32_t level) {
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (level < UTRACE_OFF) {
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        level = UTRACE_OFF;
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (level > UTRACE_VERBOSE) {
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        level = UTRACE_VERBOSE;
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    utrace_level = level;
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_getLevel() {
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return utrace_level;
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CFUNC UBool
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_cleanup() {
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pTraceEntryFunc = NULL;
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pTraceExitFunc  = NULL;
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pTraceDataFunc  = NULL;
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    utrace_level    = UTRACE_OFF;
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    gTraceContext   = NULL;
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return TRUE;
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char * const
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerutrFnName[] = {
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "u_init",
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "u_cleanup",
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char * const
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerutrConvNames[] = {
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucnv_open",
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucnv_openPackage",
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucnv_openAlgorithmic",
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucnv_clone",
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucnv_close",
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucnv_flushCache",
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucnv_load",
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucnv_unload",
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const char * const
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QuerutrCollNames[] = {
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucol_open",
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucol_close",
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucol_strcoll",
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucol_getSortKey",
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucol_getLocale",
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucol_nextSortKeyPart",
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    "ucol_strcollIter",
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_CAPI const char * U_EXPORT2
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruutrace_functionName(int32_t fnNumber) {
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(UTRACE_FUNCTION_START <= fnNumber && fnNumber < UTRACE_FUNCTION_LIMIT) {
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return trFnName[fnNumber];
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(UTRACE_CONVERSION_START <= fnNumber && fnNumber < UTRACE_CONVERSION_LIMIT) {
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return trConvNames[fnNumber - UTRACE_CONVERSION_START];
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return trCollNames[fnNumber - UTRACE_COLLATION_START];
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return "[BOGUS Trace Function Number]";
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
487