blob: 303d893637315b2c5a3314fdb45a038657224967 [file] [log] [blame]
/* $Id$ */
/*
* Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <pj/types.h>
#include <pj/log.h>
#include <pj/string.h>
#include <pj/os.h>
#include <pj/compat/stdarg.h>
#if PJ_LOG_MAX_LEVEL >= 1
#if 0
PJ_DEF_DATA(int) pj_log_max_level = PJ_LOG_MAX_LEVEL;
#else
static int pj_log_max_level = PJ_LOG_MAX_LEVEL;
#endif
static pj_log_func *log_writer = &pj_log_write;
static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE |
PJ_LOG_HAS_SPACE
#if defined(PJ_WIN32) && PJ_WIN32!=0
| PJ_LOG_HAS_COLOR
#endif
;
static pj_color_t PJ_LOG_COLOR_0 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
static pj_color_t PJ_LOG_COLOR_1 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
static pj_color_t PJ_LOG_COLOR_2 = PJ_TERM_COLOR_BRIGHT |
PJ_TERM_COLOR_R |
PJ_TERM_COLOR_G;
static pj_color_t PJ_LOG_COLOR_3 = PJ_TERM_COLOR_BRIGHT |
PJ_TERM_COLOR_R |
PJ_TERM_COLOR_G |
PJ_TERM_COLOR_B;
static pj_color_t PJ_LOG_COLOR_4 = PJ_TERM_COLOR_R |
PJ_TERM_COLOR_G |
PJ_TERM_COLOR_B;
static pj_color_t PJ_LOG_COLOR_5 = PJ_TERM_COLOR_R |
PJ_TERM_COLOR_G |
PJ_TERM_COLOR_B;
static pj_color_t PJ_LOG_COLOR_6 = PJ_TERM_COLOR_R |
PJ_TERM_COLOR_G |
PJ_TERM_COLOR_B;
/* Default terminal color */
static pj_color_t PJ_LOG_COLOR_77 = PJ_TERM_COLOR_R |
PJ_TERM_COLOR_G |
PJ_TERM_COLOR_B;
#if PJ_LOG_USE_STACK_BUFFER==0
static char log_buffer[PJ_LOG_MAX_SIZE];
#endif
PJ_DEF(void) pj_log_set_decor(unsigned decor)
{
log_decor = decor;
}
PJ_DEF(unsigned) pj_log_get_decor(void)
{
return log_decor;
}
PJ_DEF(void) pj_log_set_color(int level, pj_color_t color)
{
switch (level)
{
case 0: PJ_LOG_COLOR_0 = color;
break;
case 1: PJ_LOG_COLOR_1 = color;
break;
case 2: PJ_LOG_COLOR_2 = color;
break;
case 3: PJ_LOG_COLOR_3 = color;
break;
case 4: PJ_LOG_COLOR_4 = color;
break;
case 5: PJ_LOG_COLOR_5 = color;
break;
case 6: PJ_LOG_COLOR_6 = color;
break;
/* Default terminal color */
case 77: PJ_LOG_COLOR_77 = color;
break;
default:
/* Do nothing */
break;
}
}
PJ_DEF(pj_color_t) pj_log_get_color(int level)
{
switch (level) {
case 0:
return PJ_LOG_COLOR_0;
case 1:
return PJ_LOG_COLOR_1;
case 2:
return PJ_LOG_COLOR_2;
case 3:
return PJ_LOG_COLOR_3;
case 4:
return PJ_LOG_COLOR_4;
case 5:
return PJ_LOG_COLOR_5;
case 6:
return PJ_LOG_COLOR_6;
default:
/* Return default terminal color */
return PJ_LOG_COLOR_77;
}
}
PJ_DEF(void) pj_log_set_level(int level)
{
pj_log_max_level = level;
}
#if 1
PJ_DEF(int) pj_log_get_level(void)
{
return pj_log_max_level;
}
#endif
PJ_DEF(void) pj_log_set_log_func( pj_log_func *func )
{
log_writer = func;
}
PJ_DEF(pj_log_func*) pj_log_get_log_func(void)
{
return log_writer;
}
PJ_DEF(void) pj_log( const char *sender, int level,
const char *format, va_list marker)
{
pj_time_val now;
pj_parsed_time ptime;
char *pre;
#if PJ_LOG_USE_STACK_BUFFER
char log_buffer[PJ_LOG_MAX_SIZE];
#endif
int len, print_len;
PJ_CHECK_STACK();
if (level > pj_log_max_level)
return;
/* Get current date/time. */
pj_gettimeofday(&now);
pj_time_decode(&now, &ptime);
pre = log_buffer;
if (log_decor & PJ_LOG_HAS_LEVEL_TEXT) {
static const char *ltexts[] = { "FATAL:", "ERROR:", " WARN:",
" INFO:", "DEBUG:", "TRACE:", "DETRC:"};
pj_ansi_strcpy(pre, ltexts[level]);
pre += 6;
}
if (log_decor & PJ_LOG_HAS_DAY_NAME) {
static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat"};
pj_ansi_strcpy(pre, wdays[ptime.wday]);
pre += 3;
}
if (log_decor & PJ_LOG_HAS_YEAR) {
*pre++ = ' ';
pre += pj_utoa(ptime.year, pre);
}
if (log_decor & PJ_LOG_HAS_MONTH) {
*pre++ = '-';
pre += pj_utoa_pad(ptime.mon+1, pre, 2, '0');
}
if (log_decor & PJ_LOG_HAS_DAY_OF_MON) {
*pre++ = '-';
pre += pj_utoa_pad(ptime.day, pre, 2, '0');
}
if (log_decor & PJ_LOG_HAS_TIME) {
*pre++ = ' ';
pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
*pre++ = ':';
pre += pj_utoa_pad(ptime.min, pre, 2, '0');
*pre++ = ':';
pre += pj_utoa_pad(ptime.sec, pre, 2, '0');
}
if (log_decor & PJ_LOG_HAS_MICRO_SEC) {
*pre++ = '.';
pre += pj_utoa_pad(ptime.msec, pre, 3, '0');
}
if (log_decor & PJ_LOG_HAS_SENDER) {
enum { SENDER_WIDTH = 14 };
int sender_len = strlen(sender);
*pre++ = ' ';
if (sender_len <= SENDER_WIDTH) {
while (sender_len < SENDER_WIDTH)
*pre++ = ' ', ++sender_len;
while (*sender)
*pre++ = *sender++;
} else {
int i;
for (i=0; i<SENDER_WIDTH; ++i)
*pre++ = *sender++;
}
}
if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE)
*pre++ = ' ';
if (log_decor & PJ_LOG_HAS_SPACE) {
*pre++ = ' ';
}
len = pre - log_buffer;
/* Print the whole message to the string log_buffer. */
print_len = pj_ansi_vsnprintf(pre, sizeof(log_buffer)-len, format,
marker);
if (print_len < 0) {
level = 1;
print_len = pj_ansi_snprintf(pre, sizeof(log_buffer)-len,
"<logging error: msg too long>");
}
len = len + print_len;
if (len > 0 && len < (int)sizeof(log_buffer)-2) {
if (log_decor & PJ_LOG_HAS_CR) {
log_buffer[len++] = '\r';
}
if (log_decor & PJ_LOG_HAS_NEWLINE) {
log_buffer[len++] = '\n';
}
log_buffer[len] = '\0';
} else {
len = sizeof(log_buffer)-1;
if (log_decor & PJ_LOG_HAS_CR) {
log_buffer[sizeof(log_buffer)-3] = '\r';
}
if (log_decor & PJ_LOG_HAS_NEWLINE) {
log_buffer[sizeof(log_buffer)-2] = '\n';
}
log_buffer[sizeof(log_buffer)-1] = '\0';
}
if (log_writer)
(*log_writer)(level, log_buffer, len);
}
/*
PJ_DEF(void) pj_log_0(const char *obj, const char *format, ...)
{
va_list arg;
va_start(arg, format);
pj_log(obj, 0, format, arg);
va_end(arg);
}
*/
PJ_DEF(void) pj_log_1(const char *obj, const char *format, ...)
{
va_list arg;
va_start(arg, format);
pj_log(obj, 1, format, arg);
va_end(arg);
}
#endif /* PJ_LOG_MAX_LEVEL >= 1 */
#if PJ_LOG_MAX_LEVEL >= 2
PJ_DEF(void) pj_log_2(const char *obj, const char *format, ...)
{
va_list arg;
va_start(arg, format);
pj_log(obj, 2, format, arg);
va_end(arg);
}
#endif
#if PJ_LOG_MAX_LEVEL >= 3
PJ_DEF(void) pj_log_3(const char *obj, const char *format, ...)
{
va_list arg;
va_start(arg, format);
pj_log(obj, 3, format, arg);
va_end(arg);
}
#endif
#if PJ_LOG_MAX_LEVEL >= 4
PJ_DEF(void) pj_log_4(const char *obj, const char *format, ...)
{
va_list arg;
va_start(arg, format);
pj_log(obj, 4, format, arg);
va_end(arg);
}
#endif
#if PJ_LOG_MAX_LEVEL >= 5
PJ_DEF(void) pj_log_5(const char *obj, const char *format, ...)
{
va_list arg;
va_start(arg, format);
pj_log(obj, 5, format, arg);
va_end(arg);
}
#endif
#if PJ_LOG_MAX_LEVEL >= 6
PJ_DEF(void) pj_log_6(const char *obj, const char *format, ...)
{
va_list arg;
va_start(arg, format);
pj_log(obj, 6, format, arg);
va_end(arg);
}
#endif