blob: 5b6dfe79bfe222dae1090cbb89f8878f91b604b9 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pj/types.h>
20#include <pj/log.h>
21#include <pj/string.h>
22#include <pj/os.h>
Benny Prijono9033e312005-11-21 02:08:39 +000023#include <pj/compat/stdarg.h>
24
25#if PJ_LOG_MAX_LEVEL >= 1
26
27static int log_max_level = PJ_LOG_MAX_LEVEL;
28static pj_log_func *log_writer = &pj_log_write;
29static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
30 PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE;
31
32#if PJ_LOG_USE_STACK_BUFFER==0
33static char log_buffer[PJ_LOG_MAX_SIZE];
34#endif
35
36PJ_DEF(void) pj_log_set_decor(unsigned decor)
37{
38 log_decor = decor;
39}
40
41PJ_DEF(unsigned) pj_log_get_decor(void)
42{
43 return log_decor;
44}
45
46PJ_DEF(void) pj_log_set_level(int level)
47{
48 log_max_level = level;
49}
50
51PJ_DEF(int) pj_log_get_level(void)
52{
53 return log_max_level;
54}
55
56PJ_DEF(void) pj_log_set_log_func( pj_log_func *func )
57{
58 log_writer = func;
59}
60
61PJ_DEF(pj_log_func*) pj_log_get_log_func(void)
62{
63 return log_writer;
64}
65
66PJ_DEF(void) pj_log( const char *sender, int level,
67 const char *format, va_list marker)
68{
69 pj_time_val now;
70 pj_parsed_time ptime;
71 char *pre;
72#if PJ_LOG_USE_STACK_BUFFER
73 char log_buffer[PJ_LOG_MAX_SIZE];
74#endif
Benny Prijonoccf95622006-02-07 18:48:01 +000075 int len, print_len;
Benny Prijono9033e312005-11-21 02:08:39 +000076
77 PJ_CHECK_STACK();
78
79 if (level > log_max_level)
80 return;
81
82 /* Get current date/time. */
83 pj_gettimeofday(&now);
84 pj_time_decode(&now, &ptime);
85
86 pre = log_buffer;
87 if (log_decor & PJ_LOG_HAS_DAY_NAME) {
88 static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed",
89 "Thu", "Fri", "Sat"};
Benny Prijonoed811d72006-03-10 12:57:12 +000090 pj_ansi_strcpy(pre, wdays[ptime.wday]);
Benny Prijono9033e312005-11-21 02:08:39 +000091 pre += 3;
92 }
93 if (log_decor & PJ_LOG_HAS_YEAR) {
94 *pre++ = ' ';
95 pre += pj_utoa(ptime.year, pre);
96 }
97 if (log_decor & PJ_LOG_HAS_MONTH) {
98 *pre++ = '-';
99 pre += pj_utoa_pad(ptime.mon, pre, 2, '0');
100 }
101 if (log_decor & PJ_LOG_HAS_DAY_OF_MON) {
102 *pre++ = ' ';
103 pre += pj_utoa_pad(ptime.day, pre, 2, '0');
104 }
105 if (log_decor & PJ_LOG_HAS_TIME) {
106 *pre++ = ' ';
107 pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
108 *pre++ = ':';
109 pre += pj_utoa_pad(ptime.min, pre, 2, '0');
110 *pre++ = ':';
111 pre += pj_utoa_pad(ptime.sec, pre, 2, '0');
112 }
113 if (log_decor & PJ_LOG_HAS_MICRO_SEC) {
114 *pre++ = '.';
115 pre += pj_utoa_pad(ptime.msec, pre, 3, '0');
116 }
117 if (log_decor & PJ_LOG_HAS_SENDER) {
118 enum { SENDER_WIDTH = 12 };
119 int sender_len = strlen(sender);
120 *pre++ = ' ';
121 if (sender_len <= SENDER_WIDTH) {
122 while (sender_len < SENDER_WIDTH)
123 *pre++ = ' ', ++sender_len;
124 while (*sender)
125 *pre++ = *sender++;
126 } else {
127 int i;
128 for (i=0; i<SENDER_WIDTH; ++i)
129 *pre++ = *sender++;
130 }
131 }
132
133 if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE)
134 *pre++ = ' ';
135
136 len = pre - log_buffer;
137
138 /* Print the whole message to the string log_buffer. */
Benny Prijonoed811d72006-03-10 12:57:12 +0000139 print_len = pj_ansi_vsnprintf(pre, sizeof(log_buffer)-len, format,
140 marker);
Benny Prijonoccf95622006-02-07 18:48:01 +0000141 if (print_len < 0) {
Benny Prijonoed811d72006-03-10 12:57:12 +0000142 print_len = pj_ansi_snprintf(pre, sizeof(log_buffer)-len,
143 "<logging error: msg too long>");
Benny Prijonoccf95622006-02-07 18:48:01 +0000144 }
145 len = len + print_len;
Benny Prijono9cf138e2006-01-19 03:58:29 +0000146 if (len > 0 && len < sizeof(log_buffer)-2) {
147 if (log_decor & PJ_LOG_HAS_CR) {
148 log_buffer[len++] = '\r';
149 }
Benny Prijono9033e312005-11-21 02:08:39 +0000150 if (log_decor & PJ_LOG_HAS_NEWLINE) {
151 log_buffer[len++] = '\n';
152 }
153 log_buffer[len++] = '\0';
154 } else {
155 len = sizeof(log_buffer)-1;
Benny Prijono9cf138e2006-01-19 03:58:29 +0000156 if (log_decor & PJ_LOG_HAS_CR) {
157 log_buffer[sizeof(log_buffer)-3] = '\r';
158 }
Benny Prijono9033e312005-11-21 02:08:39 +0000159 if (log_decor & PJ_LOG_HAS_NEWLINE) {
160 log_buffer[sizeof(log_buffer)-2] = '\n';
161 }
162 log_buffer[sizeof(log_buffer)-1] = '\0';
163 }
164
165 if (log_writer)
166 (*log_writer)(level, log_buffer, len);
167}
168
169PJ_DEF(void) pj_log_0(const char *obj, const char *format, ...)
170{
171 va_list arg;
172 va_start(arg, format);
173 pj_log(obj, 0, format, arg);
174 va_end(arg);
175}
176
177PJ_DEF(void) pj_log_1(const char *obj, const char *format, ...)
178{
179 va_list arg;
180 va_start(arg, format);
181 pj_log(obj, 1, format, arg);
182 va_end(arg);
183}
184#endif /* PJ_LOG_MAX_LEVEL >= 1 */
185
186#if PJ_LOG_MAX_LEVEL >= 2
187PJ_DEF(void) pj_log_2(const char *obj, const char *format, ...)
188{
189 va_list arg;
190 va_start(arg, format);
191 pj_log(obj, 2, format, arg);
192 va_end(arg);
193}
194#endif
195
196#if PJ_LOG_MAX_LEVEL >= 3
197PJ_DEF(void) pj_log_3(const char *obj, const char *format, ...)
198{
199 va_list arg;
200 va_start(arg, format);
201 pj_log(obj, 3, format, arg);
202 va_end(arg);
203}
204#endif
205
206#if PJ_LOG_MAX_LEVEL >= 4
207PJ_DEF(void) pj_log_4(const char *obj, const char *format, ...)
208{
209 va_list arg;
210 va_start(arg, format);
211 pj_log(obj, 4, format, arg);
212 va_end(arg);
213}
214#endif
215
216#if PJ_LOG_MAX_LEVEL >= 5
217PJ_DEF(void) pj_log_5(const char *obj, const char *format, ...)
218{
219 va_list arg;
220 va_start(arg, format);
221 pj_log(obj, 5, format, arg);
222 va_end(arg);
223}
224#endif
225
226#if PJ_LOG_MAX_LEVEL >= 6
227PJ_DEF(void) pj_log_6(const char *obj, const char *format, ...)
228{
229 va_list arg;
230 va_start(arg, format);
231 pj_log(obj, 6, format, arg);
232 va_end(arg);
233}
234#endif
235