home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- #include "primpl.h"
- #include "prenv.h"
- #include "prprf.h"
- #include <string.h>
-
- /*
- * 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_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
-
- #ifdef XP_PC
- #define strcasecmp stricmp
- #define strncasecmp strnicmp
- #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) || defined(XP_OS2)
- #define _PR_USE_STDIO_FOR_LOGGING
- #endif
-
- /* Macros used to reduce #ifdef pollution */
-
- #if defined(_PR_USE_STDIO_FOR_LOGGING)
- #define _PUT_LOG(fd, buf, nb) fputs(buf, fd)
- #elif defined(_PR_PTHREADS)
- #define _PUT_LOG(fd, buf, nb) PR_Write(fd, buf, nb)
- #elif defined(XP_MAC)
- #define _PUT_LOG(fd, buf, nb) _PR_MD_WRITE_SYNC(fd, buf, nb)
- #else
- #define _PUT_LOG(fd, buf, nb) _PR_MD_WRITE(fd, buf, nb)
- #endif
-
- /************************************************************************/
-
- static PRLogModuleInfo *logModules;
-
- #ifdef PR_LOGGING
- 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
-
- #define LINE_BUF_SIZE 200
- #define DEFAULT_BUF_SIZE 16384
-
- #ifdef _PR_NEED_STRCASECMP
-
- /*
- * strcasecmp is defined in /usr/ucblib/libucb.a on some platforms
- * such as NCR and Unixware. 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];
- 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], "%64[A-Za-z0-9]%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 {
- 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;
- }
- if (NULL == lm) {
- #ifdef XP_PC
- char* str = PR_smprintf("Unrecognized NSPR_LOG_MODULE: %s=%d\n",
- module, level);
- if (str) {
- OutputDebugString(str);
- PR_smprintf_free(str);
- }
- #else
- fprintf(stderr, "Unrecognized NSPR_LOG_MODULE: %s=%d\n",
- module, level);
- #endif
- }
- }
- /*found:*/
- count = sscanf(&ev[pos], " , %n", &delta);
- pos += delta;
- if (count == -1) break;
- }
- PR_SetLogBuffering(isSync ? bufSize : 0);
-
- ev = PR_GetEnv("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) {
- OutputDebugString(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)
- {
- PR_LogFlush();
-
- #ifdef _PR_USE_STDIO_FOR_LOGGING
- if (logFile && logFile != stdout && logFile != stderr) {
- fclose(logFile);
- }
- #else
- if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
- PR_Close(logFile);
- }
- #endif
- }
-
- #endif /* PR_LOGGING */
-
- 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;
- }
- return lm;
- }
-
- PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file)
- {
- #ifdef PR_LOGGING
- #ifdef _PR_USE_STDIO_FOR_LOGGING
- FILE *newLogFile;
-
- newLogFile = fopen(file, "w");
- if (newLogFile) {
- /* We do buffering ourselves. */
- setvbuf(newLogFile, NULL, _IONBF, 0);
- if (logFile && logFile != stdout && logFile != stderr) {
- fclose(logFile);
- }
- logFile = newLogFile;
- }
- return (PRBool) (newLogFile != 0);
- #else
- PRFileDesc *newLogFile;
-
- newLogFile = PR_Open(file, PR_WRONLY|PR_CREATE_FILE, 0666);
- if (newLogFile) {
- if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
- PR_Close(logFile);
- }
- logFile = newLogFile;
- #if defined(XP_MAC)
- SetLogFileTypeCreator(file);
- #endif
- }
- return (PRBool) (newLogFile != 0);
- #endif /* _PR_USE_STDIO_FOR_LOGGING */
- #else /* PR_LOGGING */
- PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
- return PR_FALSE;
- #endif /* PR_LOGGING */
- }
-
- PR_IMPLEMENT(void) PR_SetLogBuffering(PRIntn buffer_size)
- {
- #ifdef PR_LOGGING
- PR_LogFlush();
-
- if (logBuf)
- PR_DELETE(logBuf);
- logBuf = 0;
-
- if (buffer_size >= LINE_BUF_SIZE) {
- logp = logBuf = (char*) PR_MALLOC(buffer_size);
- logEndp = logp + buffer_size;
- }
- #endif /* PR_LOGGING */
- }
-
- PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...)
- {
- #ifdef PR_LOGGING
- va_list ap;
- char line[LINE_BUF_SIZE];
- PRUint32 nb;
- PRThread *me;
-
- if (!_pr_initialized) _PR_ImplicitInitialization();
-
- if (!logFile) {
- return;
- }
-
- va_start(ap, fmt);
- me = PR_GetCurrentThread();
- nb = PR_snprintf(line, sizeof(line)-1, "%ld[%p]: ",
- #if defined(_PR_DCETHREADS)
- /* The problem is that for _PR_DCETHREADS, pthread_t is not a
- * pointer, but a structure; so you can't easily print it...
- */
- me ? &(me->id): 0L, me);
- #else
- me ? me->id : 0L, me);
- #endif
-
- nb += PR_vsnprintf(line+nb, sizeof(line)-nb-1, fmt, ap);
- if (nb && (line[nb-1] != '\n')) {
- #ifndef XP_MAC
- line[nb++] = '\n';
- #else
- line[nb++] = '\015';
- #endif
- line[nb] = '\0';
- } else {
- #ifdef XP_MAC
- line[nb-1] = '\015';
- #endif
- }
- va_end(ap);
-
- _PR_LOCK_LOG();
- if (logBuf == 0) {
- _PUT_LOG(logFile, line, nb);
- } else {
- if (logp + nb > logEndp) {
- _PUT_LOG(logFile, logBuf, logp - logBuf);
- logp = logBuf;
- }
- memcpy(logp, line, nb);
- logp += nb;
- }
- _PR_UNLOCK_LOG();
- PR_LogFlush();
- #endif /* PR_LOGGING */
- }
-
- PR_IMPLEMENT(void) PR_LogFlush(void)
- {
- #ifdef PR_LOGGING
- if (logBuf && logFile) {
- _PR_LOCK_LOG();
- if (logp > logBuf) {
- _PUT_LOG(logFile, logBuf, logp - logBuf);
- logp = logBuf;
- }
- _PR_UNLOCK_LOG();
- }
- #endif /* PR_LOGGING */
- }
-
- PR_IMPLEMENT(void) PR_Abort(void)
- {
- #ifdef PR_LOGGING
- PR_LogPrint("Aborting");
- abort();
- #endif /* PR_LOGGING */
- PR_ASSERT(1);
- }
-
- PR_IMPLEMENT(void) PR_Assert(const char *s, const char *file, PRIntn ln)
- {
- #ifdef PR_LOGGING
- PR_LogPrint("Assertion failure: %s, at %s:%d\n", s, file, ln);
- #if defined(XP_UNIX) || defined(XP_OS2)
- fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
- #endif
- #ifdef XP_MAC
- dprintf("Assertion failure: %s, at %s:%d\n", s, file, ln);
- #endif
- #ifdef WIN32
- DebugBreak();
- #endif
- #ifndef XP_MAC
- abort();
- #endif
- #endif /* PR_LOGGING */
- }
-