forked from mirrors/gecko-dev
		
	Differential Revision: https://phabricator.services.mozilla.com/D49443 --HG-- rename : intl/icu/source/i18n/numparse_stringsegment.cpp => intl/icu/source/i18n/string_segment.cpp rename : intl/icu/source/data/buildtool/__init__.py => intl/icu/source/python/icutools/databuilder/__init__.py rename : intl/icu/source/data/buildtool/comment_stripper.py => intl/icu/source/python/icutools/databuilder/comment_stripper.py rename : intl/icu/source/data/buildtool/locale_dependencies.py => intl/icu/source/python/icutools/databuilder/locale_dependencies.py rename : intl/icu/source/data/buildtool/renderers/__init__.py => intl/icu/source/python/icutools/databuilder/renderers/__init__.py rename : intl/icu/source/data/buildtool/renderers/makefile.py => intl/icu/source/python/icutools/databuilder/renderers/makefile.py rename : intl/icu/source/data/buildtool/test/__init__.py => intl/icu/source/python/icutools/databuilder/test/__init__.py rename : intl/icu/source/data/buildtool/test/__main__.py => intl/icu/source/python/icutools/databuilder/test/__main__.py rename : intl/icu/source/data/buildtool/test/filtration_test.py => intl/icu/source/python/icutools/databuilder/test/filtration_test.py extra : moz-landing-system : lando
		
			
				
	
	
		
			504 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			504 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// © 2016 and later: Unicode, Inc. and others.
 | 
						|
// License & terms of use: http://www.unicode.org/copyright.html
 | 
						|
/*
 | 
						|
*******************************************************************************
 | 
						|
*   Copyright (C) 2003-2014, International Business Machines
 | 
						|
*   Corporation and others.  All Rights Reserved.
 | 
						|
*******************************************************************************
 | 
						|
*   file name:  utrace.c
 | 
						|
*   encoding:   UTF-8
 | 
						|
*   tab size:   8 (not used)
 | 
						|
*   indentation:4
 | 
						|
*/
 | 
						|
 | 
						|
#include "unicode/utrace.h"
 | 
						|
#include "utracimp.h"
 | 
						|
#include "cstring.h"
 | 
						|
#include "uassert.h"
 | 
						|
#include "ucln_cmn.h"
 | 
						|
 | 
						|
 | 
						|
static UTraceEntry     *pTraceEntryFunc = NULL;
 | 
						|
static UTraceExit      *pTraceExitFunc  = NULL;
 | 
						|
static UTraceData      *pTraceDataFunc  = NULL;
 | 
						|
static const void      *gTraceContext   = NULL;
 | 
						|
 | 
						|
/**
 | 
						|
 * \var utrace_level
 | 
						|
 * Trace level variable. Negative for "off".
 | 
						|
 */
 | 
						|
static int32_t
 | 
						|
utrace_level = UTRACE_ERROR;
 | 
						|
 | 
						|
U_CAPI void U_EXPORT2
 | 
						|
utrace_entry(int32_t fnNumber) {
 | 
						|
    if (pTraceEntryFunc != NULL) {
 | 
						|
        (*pTraceEntryFunc)(gTraceContext, 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;
 | 
						|
        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:
 | 
						|
            UPRV_UNREACHABLE;
 | 
						|
        }
 | 
						|
 | 
						|
        va_start(args, returnType);
 | 
						|
        (*pTraceExitFunc)(gTraceContext, fnNumber, fmt, args);
 | 
						|
        va_end(args);
 | 
						|
    }
 | 
						|
}
 | 
						|
 
 | 
						|
 | 
						|
 
 | 
						|
U_CAPI void U_EXPORT2 
 | 
						|
utrace_data(int32_t fnNumber, int32_t level, const char *fmt, ...) {
 | 
						|
    if (pTraceDataFunc != NULL) {
 | 
						|
           va_list args;
 | 
						|
           va_start(args, fmt ); 
 | 
						|
           (*pTraceDataFunc)(gTraceContext, fnNumber, level, fmt, args);
 | 
						|
           va_end(args);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
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;
 | 
						|
    }
 | 
						|
    if (c != 0) {
 | 
						|
        /* Nulls only appear as end-of-string terminators.  Move them to the output
 | 
						|
         *  buffer, but do not update the length of the buffer, so that any
 | 
						|
         *  following output will overwrite the null. */
 | 
						|
        (*outIx)++;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void outputHexBytes(int64_t val, int32_t charsToOutput,
 | 
						|
                           char *outBuf, int32_t *outIx, int32_t capacity) {
 | 
						|
    static const char gHexChars[] = "0123456789abcdef";
 | 
						|
    int32_t shiftCount;
 | 
						|
    for  (shiftCount=(charsToOutput-1)*4; shiftCount >= 0; shiftCount-=4) {
 | 
						|
        char c = gHexChars[(val >> shiftCount) & 0xf];
 | 
						|
        outputChar(c, outBuf, outIx, capacity, 0);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* Output a pointer value in hex.  Work with any size of pointer   */
 | 
						|
static void outputPtrBytes(void *val, char *outBuf, int32_t *outIx, int32_t capacity) {
 | 
						|
    uint32_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 !U_IS_BIG_ENDIAN
 | 
						|
    /* Little Endian.  Move p to most significant end of the value      */
 | 
						|
    incVal = -1;
 | 
						|
    p += sizeof(void *) - 1;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Loop through the bytes of the ptr as it sits in memory, from 
 | 
						|
     * most significant to least significant end                    */
 | 
						|
    for (i=0; i<sizeof(void *); i++) {
 | 
						|
        outputHexBytes(*p, 2, outBuf, outIx, capacity);
 | 
						|
        p += incVal;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void outputString(const char *s, char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) {
 | 
						|
    int32_t i = 0;
 | 
						|
    char    c;
 | 
						|
    if (s==NULL) {
 | 
						|
        s = "*NULL*";
 | 
						|
    }
 | 
						|
    do {
 | 
						|
        c = s[i++];
 | 
						|
        outputChar(c, outBuf, outIx, capacity, indent);
 | 
						|
    } while (c != 0);
 | 
						|
}
 | 
						|
        
 | 
						|
 | 
						|
 | 
						|
static void outputUString(const UChar *s, int32_t len, 
 | 
						|
                          char *outBuf, int32_t *outIx, int32_t capacity, int32_t indent) {
 | 
						|
    int32_t i = 0;
 | 
						|
    UChar   c;
 | 
						|
    if (s==NULL) {
 | 
						|
        outputString(NULL, outBuf, outIx, capacity, indent);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i=0; i<len || len==-1; i++) {
 | 
						|
        c = s[i];
 | 
						|
        outputHexBytes(c, 4, outBuf, outIx, capacity);
 | 
						|
        outputChar(' ', outBuf, outIx, capacity, indent);
 | 
						|
        if (len == -1 && c==0) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
        
 | 
						|
U_CAPI int32_t U_EXPORT2
 | 
						|
utrace_vformat(char *outBuf, int32_t capacity, int32_t indent, const char *fmt, va_list args) {
 | 
						|
    int32_t   outIx  = 0;
 | 
						|
    int32_t   fmtIx  = 0;
 | 
						|
    char      fmtC;
 | 
						|
    char      c;
 | 
						|
    int32_t   intArg;
 | 
						|
    int64_t   longArg = 0;
 | 
						|
    char      *ptrArg;
 | 
						|
 | 
						|
    /*   Loop runs once for each character in the format string.
 | 
						|
     */
 | 
						|
    for (;;) {
 | 
						|
        fmtC = fmt[fmtIx++];
 | 
						|
        if (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++];
 | 
						|
 | 
						|
        switch (fmtC) {
 | 
						|
        case 'c':
 | 
						|
            /* 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 *);
 | 
						|
            outputString((const char *)ptrArg, outBuf, &outIx, capacity, indent);
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'S':
 | 
						|
            /* UChar * string, with length, len==-1 for null terminated. */
 | 
						|
            ptrArg = va_arg(args, char *);             /* Ptr    */
 | 
						|
            intArg =(int32_t)va_arg(args, int32_t);    /* Length */
 | 
						|
            outputUString((const UChar *)ptrArg, intArg, outBuf, &outIx, capacity, indent);
 | 
						|
            break;
 | 
						|
 | 
						|
        case 'b':
 | 
						|
            /*  8 bit int  */
 | 
						|
            intArg = va_arg(args, int);
 | 
						|
            outputHexBytes(intArg, 2, outBuf, &outIx, capacity);
 | 
						|
            break;
 | 
						|
 | 
						|
        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':
 | 
						|
            /*  64 bit long  */
 | 
						|
            longArg = va_arg(args, int64_t);
 | 
						|
            outputHexBytes(longArg, 16, outBuf, &outIx, capacity);
 | 
						|
            break;
 | 
						|
            
 | 
						|
        case 'p':
 | 
						|
            /*  Pointers.   */
 | 
						|
            ptrArg = va_arg(args, char *);
 | 
						|
            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.
 | 
						|
             */
 | 
						|
            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 = 0;
 | 
						|
                int32_t   i;
 | 
						|
                
 | 
						|
                vectorType = fmt[fmtIx];    /* b, h, d, l, p, etc. */
 | 
						|
                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);
 | 
						|
                if (ptrPtr == NULL) {
 | 
						|
                    outputString("*NULL* ", outBuf, &outIx, capacity, indent);
 | 
						|
                } else {
 | 
						|
                    for (i=0; i<vectorLen || vectorLen==-1; i++) { 
 | 
						|
                        switch (vectorType) {
 | 
						|
                        case 'b':
 | 
						|
                            charsToOutput = 2;
 | 
						|
                            longArg = *i8Ptr++;
 | 
						|
                            break;
 | 
						|
                        case 'h':
 | 
						|
                            charsToOutput = 4;
 | 
						|
                            longArg = *i16Ptr++;
 | 
						|
                            break;
 | 
						|
                        case 'd':
 | 
						|
                            charsToOutput = 8;
 | 
						|
                            longArg = *i32Ptr++;
 | 
						|
                            break;
 | 
						|
                        case 'l':
 | 
						|
                            charsToOutput = 16;
 | 
						|
                            longArg = *i64Ptr++;
 | 
						|
                            break;
 | 
						|
                        case 'p':
 | 
						|
                            charsToOutput = 0;
 | 
						|
                            outputPtrBytes(*ptrPtr, outBuf, &outIx, capacity);
 | 
						|
                            longArg = *ptrPtr==NULL? 0: 1;    /* test for null terminated array. */
 | 
						|
                            ptrPtr++;
 | 
						|
                            break;
 | 
						|
                        case 'c':
 | 
						|
                            charsToOutput = 0;
 | 
						|
                            outputChar(*i8Ptr, outBuf, &outIx, capacity, indent);
 | 
						|
                            longArg = *i8Ptr;    /* for test for null terminated array. */
 | 
						|
                            i8Ptr++;
 | 
						|
                            break;
 | 
						|
                        case 's':
 | 
						|
                            charsToOutput = 0;
 | 
						|
                            outputString((const char *)*ptrPtr, outBuf, &outIx, capacity, indent);
 | 
						|
                            outputChar('\n', outBuf, &outIx, capacity, indent);
 | 
						|
                            longArg = *ptrPtr==NULL? 0: 1;   /* for test for null term. array. */
 | 
						|
                            ptrPtr++;
 | 
						|
                            break;
 | 
						|
 | 
						|
                        case 'S':
 | 
						|
                            charsToOutput = 0;
 | 
						|
                            outputUString((const UChar *)*ptrPtr, -1, outBuf, &outIx, capacity, indent);
 | 
						|
                            outputChar('\n', outBuf, &outIx, capacity, indent);
 | 
						|
                            longArg = *ptrPtr==NULL? 0: 1;   /* for test for null term. array. */
 | 
						|
                            ptrPtr++;
 | 
						|
                            break;
 | 
						|
 | 
						|
                            
 | 
						|
                        }
 | 
						|
                        if (charsToOutput > 0) {
 | 
						|
                            outputHexBytes(longArg, charsToOutput, outBuf, &outIx, capacity);
 | 
						|
                            outputChar(' ', outBuf, &outIx, capacity, indent);
 | 
						|
                        }
 | 
						|
                        if (vectorLen == -1 && longArg == 0) {
 | 
						|
                            break;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                outputChar('[', outBuf, &outIx, capacity, indent);
 | 
						|
                outputHexBytes(vectorLen, 8, 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);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    outputChar(0, outBuf, &outIx, capacity, indent);  /* Make sure that output is null terminated  */
 | 
						|
    return outIx + 1;     /* outIx + 1 because outIx does not increment when outputing final null. */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
U_CAPI int32_t U_EXPORT2
 | 
						|
utrace_format(char *outBuf, int32_t capacity,
 | 
						|
                int32_t indent, const char *fmt,  ...) {
 | 
						|
    int32_t retVal;
 | 
						|
    va_list args;
 | 
						|
    va_start(args, fmt ); 
 | 
						|
    retVal = utrace_vformat(outBuf, capacity, indent, fmt, args);
 | 
						|
    va_end(args);
 | 
						|
    return retVal;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
U_CAPI void U_EXPORT2
 | 
						|
utrace_setFunctions(const void *context,
 | 
						|
                    UTraceEntry *e, UTraceExit *x, UTraceData *d) {
 | 
						|
    pTraceEntryFunc = e;
 | 
						|
    pTraceExitFunc  = x;
 | 
						|
    pTraceDataFunc  = d;
 | 
						|
    gTraceContext   = context;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
U_CAPI void U_EXPORT2
 | 
						|
utrace_getFunctions(const void **context,
 | 
						|
                    UTraceEntry **e, UTraceExit **x, UTraceData **d) {
 | 
						|
    *e = pTraceEntryFunc;
 | 
						|
    *x = pTraceExitFunc;
 | 
						|
    *d = pTraceDataFunc;
 | 
						|
    *context = gTraceContext;
 | 
						|
}
 | 
						|
 | 
						|
U_CAPI void U_EXPORT2
 | 
						|
utrace_setLevel(int32_t level) {
 | 
						|
    if (level < UTRACE_OFF) {
 | 
						|
        level = UTRACE_OFF;
 | 
						|
    }
 | 
						|
    if (level > UTRACE_VERBOSE) {
 | 
						|
        level = UTRACE_VERBOSE;
 | 
						|
    }
 | 
						|
    utrace_level = level;
 | 
						|
}
 | 
						|
 | 
						|
U_CAPI int32_t U_EXPORT2
 | 
						|
utrace_getLevel() {
 | 
						|
    return utrace_level;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
U_CFUNC UBool 
 | 
						|
utrace_cleanup() {
 | 
						|
    pTraceEntryFunc = NULL;
 | 
						|
    pTraceExitFunc  = NULL;
 | 
						|
    pTraceDataFunc  = NULL;
 | 
						|
    utrace_level    = UTRACE_OFF;
 | 
						|
    gTraceContext   = NULL;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static const char * const
 | 
						|
trFnName[] = {
 | 
						|
    "u_init",
 | 
						|
    "u_cleanup",
 | 
						|
    NULL
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static const char * const
 | 
						|
trConvNames[] = {
 | 
						|
    "ucnv_open",
 | 
						|
    "ucnv_openPackage",
 | 
						|
    "ucnv_openAlgorithmic",
 | 
						|
    "ucnv_clone",
 | 
						|
    "ucnv_close",
 | 
						|
    "ucnv_flushCache",
 | 
						|
    "ucnv_load",
 | 
						|
    "ucnv_unload",
 | 
						|
    NULL
 | 
						|
};
 | 
						|
 | 
						|
    
 | 
						|
static const char * const
 | 
						|
trCollNames[] = {
 | 
						|
    "ucol_open",
 | 
						|
    "ucol_close",
 | 
						|
    "ucol_strcoll",
 | 
						|
    "ucol_getSortKey",
 | 
						|
    "ucol_getLocale",
 | 
						|
    "ucol_nextSortKeyPart",
 | 
						|
    "ucol_strcollIter",
 | 
						|
    "ucol_openFromShortString",
 | 
						|
    "ucol_strcollUTF8",
 | 
						|
    NULL
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static const char* const
 | 
						|
trResDataNames[] = {
 | 
						|
    "resc",
 | 
						|
    "bundle-open",
 | 
						|
    "file-open",
 | 
						|
    "res-open",
 | 
						|
    NULL
 | 
						|
};
 | 
						|
 | 
						|
                
 | 
						|
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 if(UTRACE_UDATA_START <= fnNumber && fnNumber < UTRACE_RES_DATA_LIMIT){
 | 
						|
        return trResDataNames[fnNumber - UTRACE_UDATA_START];
 | 
						|
    } else {
 | 
						|
        return "[BOGUS Trace Function Number]";
 | 
						|
    }
 | 
						|
}
 | 
						|
 |