Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/nsprpub/pr/src/io/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 15 kB image not shown  

Quelle  prlog.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "primpl.h"
#include "prenv.h"
#include "prprf.h"
#include <string.h>
#ifdef ANDROID
#  include <android/log.h>
#endif

/*
 * Lock used to lock the log.
 *
 * We can't define _PR_LOCK_LOG simply as PR_Lock because PR_Lock may
 * contain assertions.  We have to avoid assertions in _PR_LOCK_LOG
 * because PR_ASSERT calls PR_LogPrint, which in turn calls _PR_LOCK_LOG.
 * This can lead to infinite recursion.
 */

static PRLock* _pr_logLock;
#if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
#  define _PR_LOCK_LOG() PR_Lock(_pr_logLock);
#  define _PR_UNLOCK_LOG() PR_Unlock(_pr_logLock);
#elif defined(_PR_GLOBAL_THREADS_ONLY)
#  define _PR_LOCK_LOG() \
    {                    \
      _PR_LOCK_LOCK(_pr_logLock)
#  define _PR_UNLOCK_LOG()        \
    _PR_LOCK_UNLOCK(_pr_logLock); \
    }
#else

#  define _PR_LOCK_LOG()                                \
    {                                                   \
      PRIntn _is;                                       \
      PRThread* _me = _PR_MD_CURRENT_THREAD();          \
      if (!_PR_IS_NATIVE_THREAD(_me)) _PR_INTSOFF(_is); \
      _PR_LOCK_LOCK(_pr_logLock)

#  define _PR_UNLOCK_LOG()                           \
    _PR_LOCK_UNLOCK(_pr_logLock);                    \
    PR_ASSERT(_me == _PR_MD_CURRENT_THREAD());       \
    if (!_PR_IS_NATIVE_THREAD(_me)) _PR_INTSON(_is); \
    }

#endif

#if defined(XP_PC)
#  define strcasecmp stricmp
#endif

/*
 * On NT, we can't define _PUT_LOG as PR_Write or _PR_MD_WRITE,
 * because every asynchronous file io operation leads to a fiber context
 * switch.  So we define _PUT_LOG as fputs (from stdio.h).  A side
 * benefit is that fputs handles the LF->CRLF translation.  This
 * code can also be used on other platforms with file stream io.
 */

#if defined(WIN32)
#  define _PR_USE_STDIO_FOR_LOGGING
#endif

/*
** Coerce Win32 log output to use OutputDebugString() when
** NSPR_LOG_FILE is set to "WinDebug".
*/

#if defined(XP_PC)
#  define WIN32_DEBUG_FILE (FILE*)-2
#endif

#ifdef WINCE
static void OutputDebugStringA(const char* msg) {
  int len = MultiByteToWideChar(CP_ACP, 0, msg, -1, 0, 0);
  WCHAR* wMsg = (WCHAR*)PR_Malloc(len * sizeof(WCHAR));
  MultiByteToWideChar(CP_ACP, 0, msg, -1, wMsg, len);
  OutputDebugStringW(wMsg);
  PR_Free(wMsg);
}
#endif

/* Macros used to reduce #ifdef pollution */

#if defined(_PR_USE_STDIO_FOR_LOGGING) && defined(XP_PC)
#  define _PUT_LOG(fd, buf, nb)        \
    PR_BEGIN_MACRO                     \
    if (logFile == WIN32_DEBUG_FILE) { \
      char savebyte = buf[nb];         \
      buf[nb] = '\0';                  \
      OutputDebugStringA(buf);         \
      buf[nb] = savebyte;              \
    } else {                           \
      fwrite(buf, 1, nb, fd);          \
      fflush(fd);                      \
    }                                  \
    PR_END_MACRO
#elif defined(_PR_USE_STDIO_FOR_LOGGING)
#  define _PUT_LOG(fd, buf, nb) \
    {                           \
      fwrite(buf, 1, nb, fd);   \
      fflush(fd);               \
    }
#elif defined(ANDROID)
#  define _PUT_LOG(fd, buf, nb)                            \
    PR_BEGIN_MACRO                                         \
    if (fd == _pr_stderr) {                                \
      char savebyte = buf[nb];                             \
      buf[nb] = '\0';                                      \
      __android_log_write(ANDROID_LOG_INFO, "PRLog", buf); \
      buf[nb] = savebyte;                                  \
    } else {                                               \
      PR_Write(fd, buf, nb);                               \
    }                                                      \
    PR_END_MACRO
#elif defined(_PR_PTHREADS)
#  define _PUT_LOG(fd, buf, nb) PR_Write(fd, buf, nb)
#else
#  define _PUT_LOG(fd, buf, nb) _PR_MD_WRITE(fd, buf, nb)
#endif

/************************************************************************/

static PRLogModuleInfo* logModules;

static char* logBuf = NULL;
static char* logp;
static char* logEndp;
#ifdef _PR_USE_STDIO_FOR_LOGGING
static FILE* logFile = NULL;
#else
static PRFileDesc* logFile = 0;
#endif
static PRBool outputTimeStamp = PR_FALSE;
static PRBool appendToLog = PR_FALSE;

#define LINE_BUF_SIZE 512
#define DEFAULT_BUF_SIZE 16384

#ifdef _PR_NEED_STRCASECMP

/*
 * strcasecmp is defined in /usr/ucblib/libucb.a on some platforms
 * such as NCR.  Linking with both libc and libucb
 * may cause some problem, so I just provide our own implementation
 * of strcasecmp here.
 */


static const unsigned char uc[] = {
    '\000''\001''\002''\003''\004''\005''\006''\007''\010',
    '\011''\012''\013''\014''\015''\016''\017''\020''\021',
    '\022''\023''\024''\025''\026''\027''\030''\031''\032',
    '\033''\034''\035''\036''\037'' ',    '!',    '"',    '#',
    '$',    '%',    '&',    '\'', '(', ')', '*', '+', ',',
    '-',    '.',    '/',    '0',    '1',    '2',    '3',    '4',    '5',
    '6',    '7',    '8',    '9',    ':',    ';',    '<',    '=',    '>',
    '?',    '@',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
    'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',    'P',
    'Q',    'R',    'S',    'T',    'U',    'V',    'W',    'X',    'Y',
    'Z',    '[',    '\\',   ']',    '^',    '_',    '`',    'A',    'B',
    'C',    'D',    'E',    'F',    'G',    'H',    'I',    'J',    'K',
    'L',    'M',    'N',    'O',    'P',    'Q',    'R',    'S',    'T',
    'U',    'V',    'W',    'X',    'Y',    'Z',    '{',    '|',    '}',
    '~',    '\177'};

PRIntn strcasecmp(const char* a, const char* b) {
  const unsigned char* ua = (const unsigned char*)a;
  const unsigned char* ub = (const unsigned char*)b;

  if (((const char*)0 == a) || (const char*)0 == b) {
    return (PRIntn)(a - b);
  }

  while ((uc[*ua] == uc[*ub]) && ('\0' != *a)) {
    a++;
    ua++;
    ub++;
  }

  return (PRIntn)(uc[*ua] - uc[*ub]);
}

#endif /* _PR_NEED_STRCASECMP */

void _PR_InitLog(void) {
  char* ev;

  _pr_logLock = PR_NewLock();

  ev = PR_GetEnv("NSPR_LOG_MODULES");
  if (ev && ev[0]) {
    char module[64]; /* Security-Critical: If you change this
                      * size, you must also change the sscanf
                      * format string to be size-1.
                      */

    PRBool isSync = PR_FALSE;
    PRIntn evlen = strlen(ev), pos = 0;
    PRInt32 bufSize = DEFAULT_BUF_SIZE;
    while (pos < evlen) {
      PRIntn level = 1, count = 0, delta = 0;
      count = sscanf(
          &ev[pos],
          "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
          "]%n:%d%n",
          module, &delta, &level, &delta);
      pos += delta;
      if (count == 0) {
        break;
      }

      /*
      ** If count == 2, then we got module and level. If count
      ** == 1, then level defaults to 1 (module enabled).
      */

      if (strcasecmp(module, "sync") == 0) {
        isSync = PR_TRUE;
      } else if (strcasecmp(module, "bufsize") == 0) {
        if (level >= LINE_BUF_SIZE) {
          bufSize = level;
        }
      } else if (strcasecmp(module, "timestamp") == 0) {
        outputTimeStamp = PR_TRUE;
      } else if (strcasecmp(module, "append") == 0) {
        appendToLog = PR_TRUE;
      } else {
        PRLogModuleInfo* lm = logModules;
        PRBool skip_modcheck =
            (0 == strcasecmp(module, "all")) ? PR_TRUE : PR_FALSE;

        while (lm != NULL) {
          if (skip_modcheck) {
            lm->level = (PRLogModuleLevel)level;
          } else if (strcasecmp(module, lm->name) == 0) {
            lm->level = (PRLogModuleLevel)level;
            break;
          }
          lm = lm->next;
        }
      }
      /*found:*/
      count = sscanf(&ev[pos], " , %n", &delta);
      pos += delta;
      if (count == EOF) {
        break;
      }
    }
    PR_SetLogBuffering(isSync ? 0 : bufSize);

    ev = PR_GetEnvSecure("NSPR_LOG_FILE");
    if (ev && ev[0]) {
      if (!PR_SetLogFile(ev)) {
#ifdef XP_PC
        char* str = PR_smprintf("Unable to create nspr log file '%s'\n", ev);
        if (str) {
          OutputDebugStringA(str);
          PR_smprintf_free(str);
        }
#else
        fprintf(stderr, "Unable to create nspr log file '%s'\n", ev);
#endif
      }
    } else {
#ifdef _PR_USE_STDIO_FOR_LOGGING
      logFile = stderr;
#else
      logFile = _pr_stderr;
#endif
    }
  }
}

void _PR_LogCleanup(void) {
  PRLogModuleInfo* lm = logModules;

  PR_LogFlush();

#ifdef _PR_USE_STDIO_FOR_LOGGING
  if (logFile && logFile != stdout && logFile != stderr
#  ifdef XP_PC
      && logFile != WIN32_DEBUG_FILE
#  endif
  ) {
    fclose(logFile);
  }
#else
  if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
    PR_Close(logFile);
  }
#endif
  logFile = NULL;

  if (logBuf) {
    PR_DELETE(logBuf);
  }

  while (lm != NULL) {
    PRLogModuleInfo* next = lm->next;
    free((/*const*/ char*)lm->name);
    PR_Free(lm);
    lm = next;
  }
  logModules = NULL;

  if (_pr_logLock) {
    PR_DestroyLock(_pr_logLock);
    _pr_logLock = NULL;
  }
}

static void _PR_SetLogModuleLevel(PRLogModuleInfo* lm) {
  char* ev;

  ev = PR_GetEnv("NSPR_LOG_MODULES");
  if (ev && ev[0]) {
    char module[64]; /* Security-Critical: If you change this
                      * size, you must also change the sscanf
                      * format string to be size-1.
                      */

    PRIntn evlen = strlen(ev), pos = 0;
    while (pos < evlen) {
      PRIntn level = 1, count = 0, delta = 0;

      count = sscanf(
          &ev[pos],
          "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
          "]%n:%d%n",
          module, &delta, &level, &delta);
      pos += delta;
      if (count == 0) {
        break;
      }

      /*
      ** If count == 2, then we got module and level. If count
      ** == 1, then level defaults to 1 (module enabled).
      */

      if (lm != NULL) {
        if ((strcasecmp(module, "all") == 0) ||
            (strcasecmp(module, lm->name) == 0)) {
          lm->level = (PRLogModuleLevel)level;
        }
      }
      count = sscanf(&ev[pos], " , %n", &delta);
      pos += delta;
      if (count == EOF) {
        break;
      }
    }
  }
/* end _PR_SetLogModuleLevel() */

PR_IMPLEMENT(PRLogModuleInfo*) PR_NewLogModule(const char* name) {
  PRLogModuleInfo* lm;

  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }

  lm = PR_NEWZAP(PRLogModuleInfo);
  if (lm) {
    lm->name = strdup(name);
    lm->level = PR_LOG_NONE;
    lm->next = logModules;
    logModules = lm;
    _PR_SetLogModuleLevel(lm);
  }
  return lm;
}

PR_IMPLEMENT(PRBool) PR_SetLogFile(const char* file) {
#ifdef _PR_USE_STDIO_FOR_LOGGING
  FILE* newLogFile;

#  ifdef XP_PC
  if (strcmp(file, "WinDebug") == 0) {
    newLogFile = WIN32_DEBUG_FILE;
  } else
#  endif
  {
    const char* mode = appendToLog ? "a" : "w";
    newLogFile = fopen(file, mode);
    if (!newLogFile) {
      return PR_FALSE;
    }

#  ifndef WINCE /* _IONBF does not exist in the Windows Mobile 6 SDK. */
    /* We do buffering ourselves. */
    setvbuf(newLogFile, NULL, _IONBF, 0);
#  endif
  }
  if (logFile && logFile != stdout && logFile != stderr
#  ifdef XP_PC
      && logFile != WIN32_DEBUG_FILE
#  endif
  ) {
    fclose(logFile);
  }
  logFile = newLogFile;
  return PR_TRUE;
#else
  PRFileDesc* newLogFile;
  PRIntn flags = PR_WRONLY | PR_CREATE_FILE;
  if (appendToLog) {
    flags |= PR_APPEND;
  } else {
    flags |= PR_TRUNCATE;
  }

  newLogFile = PR_Open(file, flags, 0666);
  if (newLogFile) {
    if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
      PR_Close(logFile);
    }
    logFile = newLogFile;
  }
  return (PRBool)(newLogFile != 0);
#endif /* _PR_USE_STDIO_FOR_LOGGING */
}

PR_IMPLEMENT(void) PR_SetLogBuffering(PRIntn buffer_size) {
  PR_LogFlush();

  if (logBuf) {
    PR_DELETE(logBuf);
  }

  if (buffer_size >= LINE_BUF_SIZE) {
    logp = logBuf = (char*)PR_MALLOC(buffer_size);
    logEndp = logp + buffer_size;
  }
}

PR_IMPLEMENT(void) PR_LogPrint(const char* fmt, ...) {
  va_list ap;
  char line[LINE_BUF_SIZE];
  char* line_long = NULL;
  PRUint32 nb_tid = 0, nb;
  PRThread* me;
  PRExplodedTime now;

  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }

  if (!logFile) {
    return;
  }

  if (outputTimeStamp) {
    PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now);
    nb_tid = PR_snprintf(line, sizeof(line) - 1,
                         "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - ",
                         now.tm_year, now.tm_month + 1, now.tm_mday,
                         now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec);
  }

  me = PR_GetCurrentThread();
  nb_tid += PR_snprintf(line + nb_tid, sizeof(line) - nb_tid - 1, "%ld[%p]: ",
#if defined(_PR_BTHREADS)
                        me, me);
#else
                        me ? me->id : 0L, me);
#endif

  va_start(ap, fmt);
  nb = nb_tid + PR_vsnprintf(line + nb_tid, sizeof(line) - nb_tid - 1, fmt, ap);
  va_end(ap);

  /*
   * Check if we might have run out of buffer space (in case we have a
   * long line), and malloc a buffer just this once.
   */

  if (nb == sizeof(line) - 2) {
    va_start(ap, fmt);
    line_long = PR_vsmprintf(fmt, ap);
    va_end(ap);
    /* If this failed, we'll fall back to writing the truncated line. */
  }

  if (line_long) {
    nb = strlen(line_long);
    _PR_LOCK_LOG();
    if (logBuf != 0) {
      _PUT_LOG(logFile, logBuf, logp - logBuf);
      logp = logBuf;
    }
    /*
     * Write out the thread id (with an optional timestamp) and the
     * malloc'ed buffer.
     */

    _PUT_LOG(logFile, line, nb_tid);
    _PUT_LOG(logFile, line_long, nb);
    /* Ensure there is a trailing newline. */
    if (!nb || (line_long[nb - 1] != '\n')) {
      char eol[2];
      eol[0] = '\n';
      eol[1] = '\0';
      _PUT_LOG(logFile, eol, 1);
    }
    _PR_UNLOCK_LOG();
    PR_smprintf_free(line_long);
  } else {
    /* Ensure there is a trailing newline. */
    if (nb && (line[nb - 1] != '\n')) {
      line[nb++] = '\n';
      line[nb] = '\0';
    }
    _PR_LOCK_LOG();
    if (logBuf == 0) {
      _PUT_LOG(logFile, line, nb);
    } else {
      /* If nb can't fit into logBuf, write out logBuf first. */
      if (logp + nb > logEndp) {
        _PUT_LOG(logFile, logBuf, logp - logBuf);
        logp = logBuf;
      }
      /* nb is guaranteed to fit into logBuf. */
      memcpy(logp, line, nb);
      logp += nb;
    }
    _PR_UNLOCK_LOG();
  }
  PR_LogFlush();
}

PR_IMPLEMENT(void) PR_LogFlush(void) {
  if (logBuf && logFile) {
    _PR_LOCK_LOG();
    if (logp > logBuf) {
      _PUT_LOG(logFile, logBuf, logp - logBuf);
      logp = logBuf;
    }
    _PR_UNLOCK_LOG();
  }
}

PR_IMPLEMENT(void) PR_Abort(void) {
  PR_LogPrint("Aborting");
#ifdef ANDROID
  __android_log_write(ANDROID_LOG_ERROR, "PRLog""Aborting");
#endif
  abort();
}

PR_IMPLEMENT(void) PR_Assert(const char* s, const char* file, PRIntn ln) {
  PR_LogPrint("Assertion failure: %s, at %s:%d\n", s, file, ln);
  fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
  fflush(stderr);
#ifdef WIN32
  DebugBreak();
#elif defined(ANDROID)
  __android_log_assert(NULL, "PRLog""Assertion failure: %s, at %s:%d\n", s,
                       file, ln);
#endif
  abort();
}

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.