LCOV - code coverage report
Current view: top level - nsprpub/pr/src/io - prlog.c (source / functions) Hit Total Coverage
Test: output.info Lines: 18 159 11.3 %
Date: 2017-07-14 16:53:18 Functions: 2 3 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : 
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "primpl.h"
       8             : #include "prenv.h"
       9             : #include "prprf.h"
      10             : #include <string.h>
      11             : #ifdef ANDROID
      12             : #include <android/log.h>
      13             : #endif
      14             : 
      15             : /*
      16             :  * Lock used to lock the log.
      17             :  *
      18             :  * We can't define _PR_LOCK_LOG simply as PR_Lock because PR_Lock may
      19             :  * contain assertions.  We have to avoid assertions in _PR_LOCK_LOG
      20             :  * because PR_ASSERT calls PR_LogPrint, which in turn calls _PR_LOCK_LOG.
      21             :  * This can lead to infinite recursion.
      22             :  */
      23             : static PRLock *_pr_logLock;
      24             : #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
      25             : #define _PR_LOCK_LOG() PR_Lock(_pr_logLock);
      26             : #define _PR_UNLOCK_LOG() PR_Unlock(_pr_logLock);
      27             : #elif defined(_PR_GLOBAL_THREADS_ONLY)
      28             : #define _PR_LOCK_LOG() { _PR_LOCK_LOCK(_pr_logLock)
      29             : #define _PR_UNLOCK_LOG() _PR_LOCK_UNLOCK(_pr_logLock); }
      30             : #else
      31             : 
      32             : #define _PR_LOCK_LOG() \
      33             : { \
      34             :     PRIntn _is; \
      35             :     PRThread *_me = _PR_MD_CURRENT_THREAD(); \
      36             :     if (!_PR_IS_NATIVE_THREAD(_me)) \
      37             :         _PR_INTSOFF(_is); \
      38             :     _PR_LOCK_LOCK(_pr_logLock)
      39             : 
      40             : #define _PR_UNLOCK_LOG() \
      41             :     _PR_LOCK_UNLOCK(_pr_logLock); \
      42             :     PR_ASSERT(_me == _PR_MD_CURRENT_THREAD()); \
      43             :     if (!_PR_IS_NATIVE_THREAD(_me)) \
      44             :         _PR_INTSON(_is); \
      45             : }
      46             : 
      47             : #endif
      48             : 
      49             : #if defined(XP_PC)
      50             : #define strcasecmp stricmp
      51             : #endif
      52             : 
      53             : /*
      54             :  * On NT, we can't define _PUT_LOG as PR_Write or _PR_MD_WRITE,
      55             :  * because every asynchronous file io operation leads to a fiber context
      56             :  * switch.  So we define _PUT_LOG as fputs (from stdio.h).  A side
      57             :  * benefit is that fputs handles the LF->CRLF translation.  This
      58             :  * code can also be used on other platforms with file stream io.
      59             :  */
      60             : #if defined(WIN32) || defined(XP_OS2)
      61             : #define _PR_USE_STDIO_FOR_LOGGING
      62             : #endif
      63             : 
      64             : /*
      65             : ** Coerce Win32 log output to use OutputDebugString() when
      66             : ** NSPR_LOG_FILE is set to "WinDebug".
      67             : */
      68             : #if defined(XP_PC)
      69             : #define WIN32_DEBUG_FILE (FILE*)-2
      70             : #endif
      71             : 
      72             : #ifdef WINCE
      73             : static void OutputDebugStringA(const char* msg) {
      74             :     int len = MultiByteToWideChar(CP_ACP, 0, msg, -1, 0, 0);
      75             :     WCHAR *wMsg = (WCHAR *)PR_Malloc(len * sizeof(WCHAR));
      76             :     MultiByteToWideChar(CP_ACP, 0, msg, -1, wMsg, len);
      77             :     OutputDebugStringW(wMsg);
      78             :     PR_Free(wMsg);
      79             : }
      80             : #endif
      81             : 
      82             : /* Macros used to reduce #ifdef pollution */
      83             : 
      84             : #if defined(_PR_USE_STDIO_FOR_LOGGING) && defined(XP_PC)
      85             : #define _PUT_LOG(fd, buf, nb) \
      86             :     PR_BEGIN_MACRO \
      87             :     if (logFile == WIN32_DEBUG_FILE) { \
      88             :         char savebyte = buf[nb]; \
      89             :         buf[nb] = '\0'; \
      90             :         OutputDebugStringA(buf); \
      91             :         buf[nb] = savebyte; \
      92             :     } else { \
      93             :         fwrite(buf, 1, nb, fd); \
      94             :         fflush(fd); \
      95             :     } \
      96             :     PR_END_MACRO
      97             : #elif defined(_PR_USE_STDIO_FOR_LOGGING)
      98             : #define _PUT_LOG(fd, buf, nb) {fwrite(buf, 1, nb, fd); fflush(fd);}
      99             : #elif defined(ANDROID)
     100             : #define _PUT_LOG(fd, buf, nb)                                \
     101             :     PR_BEGIN_MACRO                                           \
     102             :     if (fd == _pr_stderr) {                                  \
     103             :         char savebyte = buf[nb];                             \
     104             :         buf[nb] = '\0';                                      \
     105             :         __android_log_write(ANDROID_LOG_INFO, "PRLog", buf); \
     106             :         buf[nb] = savebyte;                                  \
     107             :     } else {                                                 \
     108             :         PR_Write(fd, buf, nb);                               \
     109             :     }                                                        \
     110             :     PR_END_MACRO
     111             : #elif defined(_PR_PTHREADS)
     112             : #define _PUT_LOG(fd, buf, nb) PR_Write(fd, buf, nb)
     113             : #else
     114             : #define _PUT_LOG(fd, buf, nb) _PR_MD_WRITE(fd, buf, nb)
     115             : #endif
     116             : 
     117             : /************************************************************************/
     118             : 
     119             : static PRLogModuleInfo *logModules;
     120             : 
     121             : static char *logBuf = NULL;
     122             : static char *logp;
     123             : static char *logEndp;
     124             : #ifdef _PR_USE_STDIO_FOR_LOGGING
     125             : static FILE *logFile = NULL;
     126             : #else
     127             : static PRFileDesc *logFile = 0;
     128             : #endif
     129             : static PRBool outputTimeStamp = PR_FALSE;
     130             : static PRBool appendToLog = PR_FALSE;
     131             : 
     132             : #define LINE_BUF_SIZE           512
     133             : #define DEFAULT_BUF_SIZE        16384
     134             : 
     135             : #ifdef _PR_NEED_STRCASECMP
     136             : 
     137             : /*
     138             :  * strcasecmp is defined in /usr/ucblib/libucb.a on some platforms
     139             :  * such as NCR and Unixware.  Linking with both libc and libucb
     140             :  * may cause some problem, so I just provide our own implementation
     141             :  * of strcasecmp here.
     142             :  */
     143             : 
     144             : static const unsigned char uc[] =
     145             : {
     146             :     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
     147             :     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
     148             :     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
     149             :     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
     150             :     ' ',    '!',    '"',    '#',    '$',    '%',    '&',    '\'',
     151             :     '(',    ')',    '*',    '+',    ',',    '-',    '.',    '/',
     152             :     '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
     153             :     '8',    '9',    ':',    ';',    '<',    '=',    '>',    '?',
     154             :     '@',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
     155             :     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
     156             :     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
     157             :     'X',    'Y',    'Z',    '[',    '\\',   ']',    '^',    '_',
     158             :     '`',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
     159             :     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
     160             :     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
     161             :     'X',    'Y',    'Z',    '{',    '|',    '}',    '~',    '\177'
     162             : };
     163             : 
     164             : PRIntn strcasecmp(const char *a, const char *b)
     165             : {
     166             :     const unsigned char *ua = (const unsigned char *)a;
     167             :     const unsigned char *ub = (const unsigned char *)b;
     168             : 
     169             :     if( ((const char *)0 == a) || (const char *)0 == b ) 
     170             :         return (PRIntn)(a-b);
     171             : 
     172             :     while( (uc[*ua] == uc[*ub]) && ('\0' != *a) )
     173             :     {
     174             :         a++;
     175             :         ua++;
     176             :         ub++;
     177             :     }
     178             : 
     179             :     return (PRIntn)(uc[*ua] - uc[*ub]);
     180             : }
     181             : 
     182             : #endif /* _PR_NEED_STRCASECMP */
     183             : 
     184           3 : void _PR_InitLog(void)
     185             : {
     186             :     char *ev;
     187             : 
     188           3 :     _pr_logLock = PR_NewLock();
     189             : 
     190           3 :     ev = PR_GetEnv("NSPR_LOG_MODULES");
     191           3 :     if (ev && ev[0]) {
     192             :         char module[64];  /* Security-Critical: If you change this
     193             :                            * size, you must also change the sscanf
     194             :                            * format string to be size-1.
     195             :                            */
     196           0 :         PRBool isSync = PR_FALSE;
     197           0 :         PRIntn evlen = strlen(ev), pos = 0;
     198           0 :         PRInt32 bufSize = DEFAULT_BUF_SIZE;
     199           0 :         while (pos < evlen) {
     200           0 :             PRIntn level = 1, count = 0, delta = 0;
     201           0 :             count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-]%n:%d%n",
     202             :                            module, &delta, &level, &delta);
     203           0 :             pos += delta;
     204           0 :             if (count == 0) break;
     205             : 
     206             :             /*
     207             :             ** If count == 2, then we got module and level. If count
     208             :             ** == 1, then level defaults to 1 (module enabled).
     209             :             */
     210           0 :             if (strcasecmp(module, "sync") == 0) {
     211           0 :                 isSync = PR_TRUE;
     212           0 :             } else if (strcasecmp(module, "bufsize") == 0) {
     213           0 :                 if (level >= LINE_BUF_SIZE) {
     214           0 :                     bufSize = level;
     215             :                 }
     216           0 :             } else if (strcasecmp(module, "timestamp") == 0) {
     217           0 :                 outputTimeStamp = PR_TRUE;
     218           0 :             } else if (strcasecmp(module, "append") == 0) {
     219           0 :                 appendToLog = PR_TRUE;
     220             :             } else {
     221           0 :                 PRLogModuleInfo *lm = logModules;
     222           0 :                 PRBool skip_modcheck =
     223           0 :                     (0 == strcasecmp (module, "all")) ? PR_TRUE : PR_FALSE;
     224             : 
     225           0 :                 while (lm != NULL) {
     226           0 :                     if (skip_modcheck) lm -> level = (PRLogModuleLevel)level;
     227           0 :                     else if (strcasecmp(module, lm->name) == 0) {
     228           0 :                         lm->level = (PRLogModuleLevel)level;
     229           0 :                         break;
     230             :                     }
     231           0 :                     lm = lm->next;
     232             :                 }
     233             :             }
     234             :             /*found:*/
     235           0 :             count = sscanf(&ev[pos], " , %n", &delta);
     236           0 :             pos += delta;
     237           0 :             if (count == EOF) break;
     238             :         }
     239           0 :         PR_SetLogBuffering(isSync ? 0 : bufSize);
     240             : 
     241           0 :         ev = PR_GetEnvSecure("NSPR_LOG_FILE");
     242           0 :         if (ev && ev[0]) {
     243           0 :             if (!PR_SetLogFile(ev)) {
     244             : #ifdef XP_PC
     245             :                 char* str = PR_smprintf("Unable to create nspr log file '%s'\n", ev);
     246             :                 if (str) {
     247             :                     OutputDebugStringA(str);
     248             :                     PR_smprintf_free(str);
     249             :                 }
     250             : #else
     251           0 :                 fprintf(stderr, "Unable to create nspr log file '%s'\n", ev);
     252             : #endif
     253             :             }
     254             :         } else {
     255             : #ifdef _PR_USE_STDIO_FOR_LOGGING
     256             :             logFile = stderr;
     257             : #else
     258           0 :             logFile = _pr_stderr;
     259             : #endif
     260             :         }
     261             :     }
     262           3 : }
     263             : 
     264           0 : void _PR_LogCleanup(void)
     265             : {
     266           0 :     PRLogModuleInfo *lm = logModules;
     267             : 
     268           0 :     PR_LogFlush();
     269             : 
     270             : #ifdef _PR_USE_STDIO_FOR_LOGGING
     271             :     if (logFile
     272             :         && logFile != stdout
     273             :         && logFile != stderr
     274             : #ifdef XP_PC
     275             :         && logFile != WIN32_DEBUG_FILE
     276             : #endif
     277             :         ) {
     278             :         fclose(logFile);
     279             :     }
     280             : #else
     281           0 :     if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
     282           0 :         PR_Close(logFile);
     283             :     }
     284             : #endif
     285           0 :     logFile = NULL;
     286             : 
     287           0 :     if (logBuf)
     288           0 :         PR_DELETE(logBuf);
     289             : 
     290           0 :     while (lm != NULL) {
     291           0 :         PRLogModuleInfo *next = lm->next;
     292           0 :         free((/*const*/ char *)lm->name);
     293           0 :         PR_Free(lm);
     294           0 :         lm = next;
     295             :     }
     296           0 :     logModules = NULL;
     297             : 
     298           0 :     if (_pr_logLock) {
     299           0 :         PR_DestroyLock(_pr_logLock);
     300           0 :         _pr_logLock = NULL;
     301             :     }
     302           0 : }
     303             : 
     304          33 : static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm )
     305             : {
     306             :     char *ev;
     307             : 
     308          33 :     ev = PR_GetEnv("NSPR_LOG_MODULES");
     309          33 :     if (ev && ev[0]) {
     310             :         char module[64];  /* Security-Critical: If you change this
     311             :                            * size, you must also change the sscanf
     312             :                            * format string to be size-1.
     313             :                            */
     314           0 :         PRIntn evlen = strlen(ev), pos = 0;
     315           0 :         while (pos < evlen) {
     316           0 :             PRIntn level = 1, count = 0, delta = 0;
     317             : 
     318           0 :             count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-]%n:%d%n",
     319             :                            module, &delta, &level, &delta);
     320           0 :             pos += delta;
     321           0 :             if (count == 0) break;
     322             : 
     323             :             /*
     324             :             ** If count == 2, then we got module and level. If count
     325             :             ** == 1, then level defaults to 1 (module enabled).
     326             :             */
     327           0 :             if (lm != NULL)
     328             :             {
     329           0 :                 if ((strcasecmp(module, "all") == 0)
     330           0 :                     || (strcasecmp(module, lm->name) == 0))
     331             :                 {
     332           0 :                     lm->level = (PRLogModuleLevel)level;
     333             :                 }
     334             :             }
     335           0 :             count = sscanf(&ev[pos], " , %n", &delta);
     336           0 :             pos += delta;
     337           0 :             if (count == EOF) break;
     338             :         }
     339             :     }
     340          33 : } /* end _PR_SetLogModuleLevel() */
     341             : 
     342             : PR_IMPLEMENT(PRLogModuleInfo*) PR_NewLogModule(const char *name)
     343             : {
     344             :     PRLogModuleInfo *lm;
     345             : 
     346          33 :         if (!_pr_initialized) _PR_ImplicitInitialization();
     347             : 
     348          33 :     lm = PR_NEWZAP(PRLogModuleInfo);
     349          33 :     if (lm) {
     350          33 :         lm->name = strdup(name);
     351          33 :         lm->level = PR_LOG_NONE;
     352          33 :         lm->next = logModules;
     353          33 :         logModules = lm;
     354          33 :         _PR_SetLogModuleLevel(lm);
     355             :     }
     356          33 :     return lm;
     357             : }
     358             : 
     359             : PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file)
     360             : {
     361             : #ifdef _PR_USE_STDIO_FOR_LOGGING
     362             :     FILE *newLogFile;
     363             : 
     364             : #ifdef XP_PC
     365             :     if ( strcmp( file, "WinDebug") == 0)
     366             :     {
     367             :         newLogFile = WIN32_DEBUG_FILE;
     368             :     }
     369             :     else
     370             : #endif
     371             :     {
     372             :         const char *mode = appendToLog ? "a" : "w";
     373             :         newLogFile = fopen(file, mode);
     374             :         if (!newLogFile)
     375             :             return PR_FALSE;
     376             : 
     377             : #ifndef WINCE  /* _IONBF does not exist in the Windows Mobile 6 SDK. */
     378             :         /* We do buffering ourselves. */
     379             :         setvbuf(newLogFile, NULL, _IONBF, 0);
     380             : #endif
     381             :     }
     382             :     if (logFile
     383             :         && logFile != stdout
     384             :         && logFile != stderr
     385             : #ifdef XP_PC
     386             :         && logFile != WIN32_DEBUG_FILE
     387             : #endif
     388             :         ) {
     389             :         fclose(logFile);
     390             :     }
     391             :     logFile = newLogFile;
     392             :     return PR_TRUE;
     393             : #else
     394             :     PRFileDesc *newLogFile;
     395           0 :     PRIntn flags = PR_WRONLY|PR_CREATE_FILE;
     396           0 :     if (appendToLog) {
     397           0 :         flags |= PR_APPEND;
     398             :     } else {
     399           0 :         flags |= PR_TRUNCATE;
     400             :     }
     401             : 
     402           0 :     newLogFile = PR_Open(file, flags, 0666);
     403           0 :     if (newLogFile) {
     404           0 :         if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
     405           0 :             PR_Close(logFile);
     406             :         }
     407           0 :         logFile = newLogFile;
     408             :     }
     409           0 :     return (PRBool) (newLogFile != 0);
     410             : #endif /* _PR_USE_STDIO_FOR_LOGGING */
     411             : }
     412             : 
     413             : PR_IMPLEMENT(void) PR_SetLogBuffering(PRIntn buffer_size)
     414             : {
     415           0 :     PR_LogFlush();
     416             : 
     417           0 :     if (logBuf)
     418           0 :         PR_DELETE(logBuf);
     419             : 
     420           0 :     if (buffer_size >= LINE_BUF_SIZE) {
     421           0 :         logp = logBuf = (char*) PR_MALLOC(buffer_size);
     422           0 :         logEndp = logp + buffer_size;
     423             :     }
     424           0 : }
     425             : 
     426             : PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...)
     427             : {
     428             :     va_list ap;
     429             :     char line[LINE_BUF_SIZE];
     430           0 :     char *line_long = NULL;
     431           0 :     PRUint32 nb_tid = 0, nb;
     432             :     PRThread *me;
     433             :     PRExplodedTime now;
     434             : 
     435           0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     436             : 
     437           0 :     if (!logFile) {
     438           0 :         return;
     439             :     }
     440             : 
     441           0 :     if (outputTimeStamp) {
     442           0 :         PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now);
     443           0 :         nb_tid = PR_snprintf(line, sizeof(line)-1,
     444             :                              "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - ",
     445           0 :                              now.tm_year, now.tm_month + 1, now.tm_mday,
     446             :                              now.tm_hour, now.tm_min, now.tm_sec,
     447             :                              now.tm_usec);
     448             :     }
     449             : 
     450           0 :     me = PR_GetCurrentThread();
     451           0 :     nb_tid += PR_snprintf(line+nb_tid, sizeof(line)-nb_tid-1, "%ld[%p]: ",
     452             : #if defined(_PR_BTHREADS)
     453             :                           me, me);
     454             : #else
     455             :                           me ? me->id : 0L, me);
     456             : #endif
     457             : 
     458           0 :     va_start(ap, fmt);
     459           0 :     nb = nb_tid + PR_vsnprintf(line+nb_tid, sizeof(line)-nb_tid-1, fmt, ap);
     460           0 :     va_end(ap);
     461             : 
     462             :     /*
     463             :      * Check if we might have run out of buffer space (in case we have a
     464             :      * long line), and malloc a buffer just this once.
     465             :      */
     466           0 :     if (nb == sizeof(line)-2) {
     467           0 :         va_start(ap, fmt);
     468           0 :         line_long = PR_vsmprintf(fmt, ap);
     469           0 :         va_end(ap);
     470             :         /* If this failed, we'll fall back to writing the truncated line. */
     471             :     }
     472             : 
     473           0 :     if (line_long) {
     474           0 :         nb = strlen(line_long);
     475           0 :         _PR_LOCK_LOG();
     476           0 :         if (logBuf != 0) {
     477           0 :             _PUT_LOG(logFile, logBuf, logp - logBuf);
     478           0 :             logp = logBuf;
     479             :         }
     480             :         /*
     481             :          * Write out the thread id (with an optional timestamp) and the
     482             :          * malloc'ed buffer.
     483             :          */
     484           0 :         _PUT_LOG(logFile, line, nb_tid);
     485           0 :         _PUT_LOG(logFile, line_long, nb);
     486             :         /* Ensure there is a trailing newline. */
     487           0 :         if (!nb || (line_long[nb-1] != '\n')) {
     488             :             char eol[2];
     489           0 :             eol[0] = '\n';
     490           0 :             eol[1] = '\0';
     491           0 :             _PUT_LOG(logFile, eol, 1);
     492             :         }
     493           0 :         _PR_UNLOCK_LOG();
     494           0 :         PR_smprintf_free(line_long);
     495             :     } else {
     496             :         /* Ensure there is a trailing newline. */
     497           0 :         if (nb && (line[nb-1] != '\n')) {
     498           0 :             line[nb++] = '\n';
     499           0 :             line[nb] = '\0';
     500             :         }
     501           0 :         _PR_LOCK_LOG();
     502           0 :         if (logBuf == 0) {
     503           0 :             _PUT_LOG(logFile, line, nb);
     504             :         } else {
     505             :             /* If nb can't fit into logBuf, write out logBuf first. */
     506           0 :             if (logp + nb > logEndp) {
     507           0 :                 _PUT_LOG(logFile, logBuf, logp - logBuf);
     508           0 :                 logp = logBuf;
     509             :             }
     510             :             /* nb is guaranteed to fit into logBuf. */
     511           0 :             memcpy(logp, line, nb);
     512           0 :             logp += nb;
     513             :         }
     514           0 :         _PR_UNLOCK_LOG();
     515             :     }
     516           0 :     PR_LogFlush();
     517             : }
     518             : 
     519             : PR_IMPLEMENT(void) PR_LogFlush(void)
     520             : {
     521           0 :     if (logBuf && logFile) {
     522           0 :         _PR_LOCK_LOG();
     523           0 :             if (logp > logBuf) {
     524           0 :                 _PUT_LOG(logFile, logBuf, logp - logBuf);
     525           0 :                 logp = logBuf;
     526             :             }
     527           0 :         _PR_UNLOCK_LOG();
     528             :     }
     529           0 : }
     530             : 
     531             : PR_IMPLEMENT(void) PR_Abort(void)
     532             : {
     533           0 :     PR_LogPrint("Aborting");
     534             : #ifdef ANDROID
     535             :     __android_log_write(ANDROID_LOG_ERROR, "PRLog", "Aborting");
     536             : #endif
     537           0 :     abort();
     538             : }
     539             : 
     540             : PR_IMPLEMENT(void) PR_Assert(const char *s, const char *file, PRIntn ln)
     541             : {
     542           0 :     PR_LogPrint("Assertion failure: %s, at %s:%d\n", s, file, ln);
     543           0 :     fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
     544           0 :     fflush(stderr);
     545             : #ifdef WIN32
     546             :     DebugBreak();
     547             : #elif defined(XP_OS2)
     548             :     asm("int $3");
     549             : #elif defined(ANDROID)
     550             :     __android_log_assert(NULL, "PRLog", "Assertion failure: %s, at %s:%d\n",
     551             :                          s, file, ln);
     552             : #endif
     553           0 :     abort();
     554             : }

Generated by: LCOV version 1.13