36 #if LOG_ENABLE_CONTEXT
48 static char *log_strip (
char *str);
49 static void log_gettime (
struct timeval *tv);
50 void log_emit_va (
const char *file,
const char *func,
int line,
int lev,
const char *fmt, va_list va);
51 void log_emit_real (
const char *file,
const char *func,
int line,
int lev,
const char *fmt, ...);
52 void log_debugf (
const char *fmt, ...);
57 void log_set_type (
int type);
68 static const char *log_name =
"<unset>";
69 static int log_level = LOG_WARNING;
70 static int log_type = LOG_TO_STDERR;
71 static bool log_lineinfo =
false;
72 static struct timeval log_begtime = { 0, 0 };
78 #if LOG_ENABLE_CONTEXT
79 typedef struct context_entry_t
85 typedef struct context_stack_t
87 context_entry_t stk[256];
92 static int context_count = 0;
93 static __thread context_stack_t *context_stack = 0;
95 static bool log_entry =
false;
96 static bool log_leave =
false;
99 context_write(
int tab,
const char *msg)
102 if( context_stack ) {
103 tag = context_stack->id;
104 if( tab < 0 && context_stack->sp > 0 )
105 tab = context_stack->sp;
107 tab = (tab <= 0) ? 0 : (tab * 4);
109 int len = asprintf(&txt,
"T%d %*s%s\n",
114 if( write(STDERR_FILENO, txt, len) == - 1 ) {
124 for(
int i = 0; i < context_stack->sp; ++i ) {
126 if( context_stack->stk[i].done )
128 context_stack->stk[i].done =
true;
130 snprintf(msg,
sizeof msg,
"%s() { ...",
131 context_stack->stk[i].func);
133 snprintf(msg,
sizeof msg,
"%s()",
134 context_stack->stk[i].func);
135 context_write(i, msg);
140 context_enter(
const char *func)
142 if( !context_stack ) {
143 context_stack = calloc(1,
sizeof *context_stack);
144 context_stack->id = ++context_count;
147 context_stack->stk[context_stack->sp].func = func;
148 context_stack->stk[context_stack->sp].done =
false;
149 context_stack->sp += 1;
158 context_leave(
void *aptr)
160 const char *func = *(
const char **)aptr;
161 assert( context_stack->sp > 0 );
162 context_stack->sp -= 1;
164 if( log_leave && context_stack->stk[context_stack->sp].done ) {
166 snprintf(msg,
sizeof msg,
"} %s()", func);
167 context_write(-1, msg);
169 assert( context_stack->stk[context_stack->sp].func == func );
171 #endif // LOG_ENABLE_CONTEXT
177 static char *log_strip(
char *str)
179 unsigned char *src = (
unsigned char *)str;
180 unsigned char *dst = (
unsigned char *)str;
182 while( *src > 0 && *src <= 32 ) ++src;
186 while( *src > 32 ) *dst++ = *src++;
187 while( *src > 0 && *src <= 32 ) ++src;
188 if( *src == 0 )
break;
195 static void log_gettime(
struct timeval *tv)
198 timersub(tv, &log_begtime, tv);
210 void log_emit_va(
const char *file,
const char *func,
int line,
int lev,
const char *fmt, va_list va)
213 char lineinfo[128] =
"";
214 char timeinfo[32] =
"";
215 char levelinfo[8] =
"";
222 vsyslog(lev, fmt, va);
231 snprintf(lineinfo,
sizeof lineinfo,
232 "%s:%d: %s(): ", file, line, func);
235 snprintf(lineinfo,
sizeof lineinfo,
239 #if LOG_ENABLE_TIMESTAMPS
243 snprintf(timeinfo,
sizeof timeinfo,
246 (
long)tv.tv_usec/1000);
250 #if LOG_ENABLE_LEVELTAGS
252 static const char *tag =
"U:";
255 case LOG_CRIT: tag =
"C:";
break;
256 case LOG_ERR: tag =
"E:";
break;
257 case LOG_WARNING: tag =
"W:";
break;
258 case LOG_NOTICE: tag =
"N:";
break;
259 case LOG_INFO: tag =
"I:";
break;
260 case LOG_DEBUG: tag =
"D:";
break;
262 snprintf(levelinfo,
sizeof levelinfo,
270 vsnprintf(msg,
sizeof msg, fmt, va);
272 #if LOG_ENABLE_CONTEXT
274 snprintf(buf,
sizeof buf,
"%s%s%s%s",
275 lineinfo, timeinfo, levelinfo, msg);
277 context_write(-1, buf);
279 fprintf(stderr,
"%s%s%s%s\n",
280 lineinfo, timeinfo, levelinfo, msg);
303 void log_emit_real(
const char *file,
const char *func,
int line,
int lev,
const char *fmt, ...)
311 void log_debugf(
const char *fmt, ...)
314 if( log_type == LOG_TO_STDERR &&
log_p(LOG_DEBUG) )
318 vfprintf(stderr, fmt, va);
349 return lev <= log_level;
365 void log_set_type(
int type)
394 log_lineinfo = lineinfo;
410 if( !timerisset(&log_begtime) )
411 gettimeofday(&log_begtime, 0);