LCOV - code coverage report
Current view: top level - intl/icu/source/common - utrace.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 217 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13