blob: 863d868d8383412f755e7e2e3661a45079adb253 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijono32177c02008-06-20 22:44:47 +00003 * Copyright (C)2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00004 *
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
Benny Prijono8ab968f2007-07-20 08:08:30 +000027#if 0
28PJ_DEF_DATA(int) pj_log_max_level = PJ_LOG_MAX_LEVEL;
29#else
30static int pj_log_max_level = PJ_LOG_MAX_LEVEL;
31#endif
Benny Prijono9033e312005-11-21 02:08:39 +000032static pj_log_func *log_writer = &pj_log_write;
33static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
Benny Prijonod6e362a2008-07-19 17:53:47 +000034 PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE |
35 PJ_LOG_HAS_SPACE
36#if defined(PJ_WIN32) && PJ_WIN32!=0
37 | PJ_LOG_HAS_COLOR
38#endif
39 ;
40
41static pj_color_t PJ_LOG_COLOR_0 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
42static pj_color_t PJ_LOG_COLOR_1 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
43static pj_color_t PJ_LOG_COLOR_2 = PJ_TERM_COLOR_BRIGHT |
44 PJ_TERM_COLOR_R |
45 PJ_TERM_COLOR_G;
46static pj_color_t PJ_LOG_COLOR_3 = PJ_TERM_COLOR_BRIGHT |
47 PJ_TERM_COLOR_R |
48 PJ_TERM_COLOR_G |
49 PJ_TERM_COLOR_B;
50static pj_color_t PJ_LOG_COLOR_4 = PJ_TERM_COLOR_R |
51 PJ_TERM_COLOR_G |
52 PJ_TERM_COLOR_B;
53static pj_color_t PJ_LOG_COLOR_5 = PJ_TERM_COLOR_R |
54 PJ_TERM_COLOR_G |
55 PJ_TERM_COLOR_B;
56static pj_color_t PJ_LOG_COLOR_6 = PJ_TERM_COLOR_R |
57 PJ_TERM_COLOR_G |
58 PJ_TERM_COLOR_B;
59/* Default terminal color */
60static pj_color_t PJ_LOG_COLOR_77 = PJ_TERM_COLOR_R |
61 PJ_TERM_COLOR_G |
62 PJ_TERM_COLOR_B;
Benny Prijono9033e312005-11-21 02:08:39 +000063
64#if PJ_LOG_USE_STACK_BUFFER==0
65static char log_buffer[PJ_LOG_MAX_SIZE];
66#endif
67
68PJ_DEF(void) pj_log_set_decor(unsigned decor)
69{
70 log_decor = decor;
71}
72
73PJ_DEF(unsigned) pj_log_get_decor(void)
74{
75 return log_decor;
76}
77
Benny Prijonod6e362a2008-07-19 17:53:47 +000078PJ_DEF(void) pj_log_set_color(int level, pj_color_t color)
79{
80 switch (level)
81 {
82 case 0: PJ_LOG_COLOR_0 = color;
83 break;
84 case 1: PJ_LOG_COLOR_1 = color;
85 break;
86 case 2: PJ_LOG_COLOR_2 = color;
87 break;
88 case 3: PJ_LOG_COLOR_3 = color;
89 break;
90 case 4: PJ_LOG_COLOR_4 = color;
91 break;
92 case 5: PJ_LOG_COLOR_5 = color;
93 break;
94 case 6: PJ_LOG_COLOR_6 = color;
95 break;
96 /* Default terminal color */
97 case 77: PJ_LOG_COLOR_77 = color;
98 break;
99 default:
100 /* Do nothing */
101 break;
102 }
103}
104
105PJ_DEF(pj_color_t) pj_log_get_color(int level)
106{
107 switch (level) {
108 case 0:
109 return PJ_LOG_COLOR_0;
110 case 1:
111 return PJ_LOG_COLOR_1;
112 case 2:
113 return PJ_LOG_COLOR_2;
114 case 3:
115 return PJ_LOG_COLOR_3;
116 case 4:
117 return PJ_LOG_COLOR_4;
118 case 5:
119 return PJ_LOG_COLOR_5;
120 case 6:
121 return PJ_LOG_COLOR_6;
122 default:
123 /* Return default terminal color */
124 return PJ_LOG_COLOR_77;
125 }
126}
127
Benny Prijono9033e312005-11-21 02:08:39 +0000128PJ_DEF(void) pj_log_set_level(int level)
129{
Benny Prijono505e82e2007-03-05 21:08:01 +0000130 pj_log_max_level = level;
Benny Prijono9033e312005-11-21 02:08:39 +0000131}
132
Benny Prijono8ab968f2007-07-20 08:08:30 +0000133#if 1
Benny Prijono9033e312005-11-21 02:08:39 +0000134PJ_DEF(int) pj_log_get_level(void)
135{
Benny Prijono505e82e2007-03-05 21:08:01 +0000136 return pj_log_max_level;
Benny Prijono9033e312005-11-21 02:08:39 +0000137}
Benny Prijono505e82e2007-03-05 21:08:01 +0000138#endif
Benny Prijono9033e312005-11-21 02:08:39 +0000139
140PJ_DEF(void) pj_log_set_log_func( pj_log_func *func )
141{
142 log_writer = func;
143}
144
145PJ_DEF(pj_log_func*) pj_log_get_log_func(void)
146{
147 return log_writer;
148}
149
150PJ_DEF(void) pj_log( const char *sender, int level,
151 const char *format, va_list marker)
152{
153 pj_time_val now;
154 pj_parsed_time ptime;
155 char *pre;
156#if PJ_LOG_USE_STACK_BUFFER
157 char log_buffer[PJ_LOG_MAX_SIZE];
158#endif
Benny Prijonoccf95622006-02-07 18:48:01 +0000159 int len, print_len;
Benny Prijono9033e312005-11-21 02:08:39 +0000160
161 PJ_CHECK_STACK();
162
Benny Prijono505e82e2007-03-05 21:08:01 +0000163 if (level > pj_log_max_level)
Benny Prijono9033e312005-11-21 02:08:39 +0000164 return;
165
166 /* Get current date/time. */
167 pj_gettimeofday(&now);
168 pj_time_decode(&now, &ptime);
169
170 pre = log_buffer;
171 if (log_decor & PJ_LOG_HAS_DAY_NAME) {
172 static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed",
173 "Thu", "Fri", "Sat"};
Benny Prijonoed811d72006-03-10 12:57:12 +0000174 pj_ansi_strcpy(pre, wdays[ptime.wday]);
Benny Prijono9033e312005-11-21 02:08:39 +0000175 pre += 3;
176 }
177 if (log_decor & PJ_LOG_HAS_YEAR) {
178 *pre++ = ' ';
179 pre += pj_utoa(ptime.year, pre);
180 }
181 if (log_decor & PJ_LOG_HAS_MONTH) {
182 *pre++ = '-';
Benny Prijono9cb09a22007-08-30 09:35:10 +0000183 pre += pj_utoa_pad(ptime.mon+1, pre, 2, '0');
Benny Prijono9033e312005-11-21 02:08:39 +0000184 }
185 if (log_decor & PJ_LOG_HAS_DAY_OF_MON) {
Benny Prijonod6e362a2008-07-19 17:53:47 +0000186 *pre++ = '-';
Benny Prijono9033e312005-11-21 02:08:39 +0000187 pre += pj_utoa_pad(ptime.day, pre, 2, '0');
188 }
189 if (log_decor & PJ_LOG_HAS_TIME) {
190 *pre++ = ' ';
191 pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
192 *pre++ = ':';
193 pre += pj_utoa_pad(ptime.min, pre, 2, '0');
194 *pre++ = ':';
195 pre += pj_utoa_pad(ptime.sec, pre, 2, '0');
196 }
197 if (log_decor & PJ_LOG_HAS_MICRO_SEC) {
198 *pre++ = '.';
199 pre += pj_utoa_pad(ptime.msec, pre, 3, '0');
200 }
201 if (log_decor & PJ_LOG_HAS_SENDER) {
Benny Prijono0016d0c2006-08-11 12:42:06 +0000202 enum { SENDER_WIDTH = 14 };
Benny Prijono9033e312005-11-21 02:08:39 +0000203 int sender_len = strlen(sender);
204 *pre++ = ' ';
205 if (sender_len <= SENDER_WIDTH) {
206 while (sender_len < SENDER_WIDTH)
207 *pre++ = ' ', ++sender_len;
208 while (*sender)
209 *pre++ = *sender++;
210 } else {
211 int i;
212 for (i=0; i<SENDER_WIDTH; ++i)
213 *pre++ = *sender++;
214 }
215 }
216
217 if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE)
218 *pre++ = ' ';
219
Benny Prijonod6e362a2008-07-19 17:53:47 +0000220 if (log_decor & PJ_LOG_HAS_SPACE) {
221 *pre++ = ' ';
222 }
223
Benny Prijono9033e312005-11-21 02:08:39 +0000224 len = pre - log_buffer;
225
226 /* Print the whole message to the string log_buffer. */
Benny Prijonoed811d72006-03-10 12:57:12 +0000227 print_len = pj_ansi_vsnprintf(pre, sizeof(log_buffer)-len, format,
228 marker);
Benny Prijonoccf95622006-02-07 18:48:01 +0000229 if (print_len < 0) {
Benny Prijono6e996dd2006-06-19 12:08:27 +0000230 level = 1;
Benny Prijonoed811d72006-03-10 12:57:12 +0000231 print_len = pj_ansi_snprintf(pre, sizeof(log_buffer)-len,
232 "<logging error: msg too long>");
Benny Prijonoccf95622006-02-07 18:48:01 +0000233 }
234 len = len + print_len;
Benny Prijonoa1e69682007-05-11 15:14:34 +0000235 if (len > 0 && len < (int)sizeof(log_buffer)-2) {
Benny Prijono9cf138e2006-01-19 03:58:29 +0000236 if (log_decor & PJ_LOG_HAS_CR) {
237 log_buffer[len++] = '\r';
238 }
Benny Prijono9033e312005-11-21 02:08:39 +0000239 if (log_decor & PJ_LOG_HAS_NEWLINE) {
240 log_buffer[len++] = '\n';
241 }
Benny Prijono0f3173d2006-10-13 13:48:56 +0000242 log_buffer[len] = '\0';
Benny Prijono9033e312005-11-21 02:08:39 +0000243 } else {
244 len = sizeof(log_buffer)-1;
Benny Prijono9cf138e2006-01-19 03:58:29 +0000245 if (log_decor & PJ_LOG_HAS_CR) {
246 log_buffer[sizeof(log_buffer)-3] = '\r';
247 }
Benny Prijono9033e312005-11-21 02:08:39 +0000248 if (log_decor & PJ_LOG_HAS_NEWLINE) {
249 log_buffer[sizeof(log_buffer)-2] = '\n';
250 }
251 log_buffer[sizeof(log_buffer)-1] = '\0';
252 }
253
254 if (log_writer)
255 (*log_writer)(level, log_buffer, len);
256}
257
Benny Prijono8ab968f2007-07-20 08:08:30 +0000258/*
Benny Prijono9033e312005-11-21 02:08:39 +0000259PJ_DEF(void) pj_log_0(const char *obj, const char *format, ...)
260{
261 va_list arg;
262 va_start(arg, format);
263 pj_log(obj, 0, format, arg);
264 va_end(arg);
265}
Benny Prijono8ab968f2007-07-20 08:08:30 +0000266*/
Benny Prijono9033e312005-11-21 02:08:39 +0000267
268PJ_DEF(void) pj_log_1(const char *obj, const char *format, ...)
269{
270 va_list arg;
271 va_start(arg, format);
272 pj_log(obj, 1, format, arg);
273 va_end(arg);
274}
275#endif /* PJ_LOG_MAX_LEVEL >= 1 */
276
277#if PJ_LOG_MAX_LEVEL >= 2
278PJ_DEF(void) pj_log_2(const char *obj, const char *format, ...)
279{
280 va_list arg;
281 va_start(arg, format);
282 pj_log(obj, 2, format, arg);
283 va_end(arg);
284}
285#endif
286
287#if PJ_LOG_MAX_LEVEL >= 3
288PJ_DEF(void) pj_log_3(const char *obj, const char *format, ...)
289{
290 va_list arg;
291 va_start(arg, format);
292 pj_log(obj, 3, format, arg);
293 va_end(arg);
294}
295#endif
296
297#if PJ_LOG_MAX_LEVEL >= 4
298PJ_DEF(void) pj_log_4(const char *obj, const char *format, ...)
299{
300 va_list arg;
301 va_start(arg, format);
302 pj_log(obj, 4, format, arg);
303 va_end(arg);
304}
305#endif
306
307#if PJ_LOG_MAX_LEVEL >= 5
308PJ_DEF(void) pj_log_5(const char *obj, const char *format, ...)
309{
310 va_list arg;
311 va_start(arg, format);
312 pj_log(obj, 5, format, arg);
313 va_end(arg);
314}
315#endif
316
317#if PJ_LOG_MAX_LEVEL >= 6
318PJ_DEF(void) pj_log_6(const char *obj, const char *format, ...)
319{
320 va_list arg;
321 va_start(arg, format);
322 pj_log(obj, 6, format, arg);
323 va_end(arg);
324}
325#endif
326