1 //===-- DNBLog.cpp ----------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Created by Greg Clayton on 6/18/07.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "DNBLog.h"
15 
16 static int g_debug = 0;
17 static int g_verbose = 0;
18 
19 #if defined (DNBLOG_ENABLED)
20 
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <sys/time.h>
25 #include <unistd.h>
26 #include <mach/mach.h>
27 #include <pthread.h>
28 #include "PThreadMutex.h"
29 
30 uint32_t g_log_bits = 0;
31 static DNBCallbackLog g_log_callback = NULL;
32 static void *g_log_baton = NULL;
33 
34 
35 int
36 DNBLogGetDebug ()
37 {
38     return g_debug;
39 }
40 
41 
42 void
43 DNBLogSetDebug (int g)
44 {
45     g_debug = g;
46 }
47 
48 int
49 DNBLogGetVerbose ()
50 {
51     return g_verbose;
52 }
53 
54 void
55 DNBLogSetVerbose (int v)
56 {
57     g_verbose = v;
58 }
59 
60 bool
61 DNBLogCheckLogBit (uint32_t bit)
62 {
63     return (g_log_bits & bit) != 0;
64 }
65 
66 uint32_t
67 DNBLogSetLogMask (uint32_t mask)
68 {
69     uint32_t old = g_log_bits;
70     g_log_bits = mask;
71     return old;
72 }
73 
74 uint32_t
75 DNBLogGetLogMask ()
76 {
77     return g_log_bits;
78 }
79 
80 void
81 DNBLogSetLogCallback (DNBCallbackLog callback, void *baton)
82 {
83     g_log_callback = callback;
84     g_log_baton = baton;
85 }
86 
87 bool
88 DNBLogEnabled ()
89 {
90     return g_log_callback != NULL;
91 }
92 
93 static inline void
94 _DNBLogVAPrintf(uint32_t flags, const char *format, va_list args)
95 {
96     if (g_log_callback)
97       g_log_callback(g_log_baton, flags, format, args);
98 }
99 
100 void
101 _DNBLog(uint32_t flags, const char *format, ...)
102 {
103     va_list args;
104     va_start (args, format);
105     _DNBLogVAPrintf(flags, format, args);
106     va_end (args);
107 }
108 
109 //----------------------------------------------------------------------
110 // Print debug strings if and only if the global g_debug is set to
111 // a non-zero value.
112 //----------------------------------------------------------------------
113 void
114 _DNBLogDebug (const char *format, ...)
115 {
116     if (DNBLogEnabled () && g_debug)
117     {
118         va_list args;
119         va_start (args, format);
120         _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);
121         va_end (args);
122     }
123 }
124 
125 
126 //----------------------------------------------------------------------
127 // Print debug strings if and only if the global g_debug is set to
128 // a non-zero value.
129 //----------------------------------------------------------------------
130 void
131 _DNBLogDebugVerbose (const char *format, ...)
132 {
133     if (DNBLogEnabled () && g_debug && g_verbose)
134     {
135         va_list args;
136         va_start (args, format);
137         _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);
138         va_end (args);
139     }
140 }
141 
142 
143 static pthread_mutex_t *
144 GetLogThreadedMutex()
145 {
146     static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
147     return g_LogThreadedMutex.Mutex();
148 }
149 static uint32_t g_message_id = 0;
150 
151 //----------------------------------------------------------------------
152 // Prefix the formatted log string with process and thread IDs and
153 // suffix it with a newline.
154 //----------------------------------------------------------------------
155 void
156 _DNBLogThreaded (const char *format, ...)
157 {
158     if (DNBLogEnabled ())
159     {
160         PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
161 
162         char *arg_msg = NULL;
163         va_list args;
164         va_start (args, format);
165         ::vasprintf (&arg_msg, format, args);
166         va_end (args);
167 
168         if (arg_msg != NULL)
169         {
170             static struct timeval g_timeval = { 0 , 0 };
171             static struct timeval tv;
172             static struct timeval delta;
173             gettimeofday(&tv, NULL);
174             if (g_timeval.tv_sec == 0)
175             {
176                 delta.tv_sec = 0;
177                 delta.tv_usec = 0;
178             }
179             else
180             {
181                 timersub (&tv, &g_timeval, &delta);
182             }
183             g_timeval = tv;
184             _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s",
185                      ++g_message_id,
186                      delta.tv_sec,
187                      delta.tv_usec,
188                      getpid(),
189                      mach_thread_self(),
190                      arg_msg);
191             free (arg_msg);
192         }
193     }
194 }
195 
196 //----------------------------------------------------------------------
197 // Prefix the formatted log string with process and thread IDs and
198 // suffix it with a newline.
199 //----------------------------------------------------------------------
200 void
201 _DNBLogThreadedIf (uint32_t log_bit, const char *format, ...)
202 {
203     if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit)
204     {
205         PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
206 
207         char *arg_msg = NULL;
208         va_list args;
209         va_start (args, format);
210         ::vasprintf (&arg_msg, format, args);
211         va_end (args);
212 
213         if (arg_msg != NULL)
214         {
215             static struct timeval g_timeval = { 0 , 0 };
216             static struct timeval tv;
217             static struct timeval delta;
218             gettimeofday(&tv, NULL);
219             if (g_timeval.tv_sec == 0)
220             {
221                 delta.tv_sec = 0;
222                 delta.tv_usec = 0;
223             }
224             else
225             {
226                 timersub (&tv, &g_timeval, &delta);
227             }
228             g_timeval = tv;
229             _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s",
230                      ++g_message_id,
231                      delta.tv_sec,
232                      delta.tv_usec,
233                      getpid(),
234                      mach_thread_self(),
235                      arg_msg);
236             free (arg_msg);
237         }
238     }
239 }
240 
241 
242 
243 //----------------------------------------------------------------------
244 // Printing of errors that are not fatal.
245 //----------------------------------------------------------------------
246 void
247 _DNBLogError (const char *format, ...)
248 {
249     if (DNBLogEnabled ())
250     {
251         char *arg_msg = NULL;
252         va_list args;
253         va_start (args, format);
254         ::vasprintf (&arg_msg, format, args);
255         va_end (args);
256 
257         if (arg_msg != NULL)
258         {
259             _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg);
260             free (arg_msg);
261         }
262     }
263 }
264 
265 //----------------------------------------------------------------------
266 // Printing of errors that ARE fatal. Exit with ERR exit code
267 // immediately.
268 //----------------------------------------------------------------------
269 void
270 _DNBLogFatalError (int err, const char *format, ...)
271 {
272     if (DNBLogEnabled ())
273     {
274         char *arg_msg = NULL;
275         va_list args;
276         va_start (args, format);
277         ::vasprintf (&arg_msg, format, args);
278         va_end (args);
279 
280         if (arg_msg != NULL)
281         {
282             _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);
283             free (arg_msg);
284         }
285         ::exit (err);
286     }
287 }
288 
289 
290 //----------------------------------------------------------------------
291 // Printing of warnings that are not fatal only if verbose mode is
292 // enabled.
293 //----------------------------------------------------------------------
294 void
295 _DNBLogVerbose (const char *format, ...)
296 {
297     if (DNBLogEnabled () && g_verbose)
298     {
299         va_list args;
300         va_start (args, format);
301         _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);
302         va_end (args);
303     }
304 }
305 
306 //----------------------------------------------------------------------
307 // Printing of warnings that are not fatal only if verbose mode is
308 // enabled.
309 //----------------------------------------------------------------------
310 void
311 _DNBLogWarningVerbose (const char *format, ...)
312 {
313     if (DNBLogEnabled () && g_verbose)
314     {
315         char *arg_msg = NULL;
316         va_list args;
317         va_start (args, format);
318         ::vasprintf (&arg_msg, format, args);
319         va_end (args);
320 
321         if (arg_msg != NULL)
322         {
323             _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg);
324             free (arg_msg);
325         }
326     }
327 }
328 //----------------------------------------------------------------------
329 // Printing of warnings that are not fatal.
330 //----------------------------------------------------------------------
331 void
332 _DNBLogWarning (const char *format, ...)
333 {
334     if (DNBLogEnabled ())
335     {
336         char *arg_msg = NULL;
337         va_list args;
338         va_start (args, format);
339         ::vasprintf (&arg_msg, format, args);
340         va_end (args);
341 
342         if (arg_msg != NULL)
343         {
344             _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);
345             free (arg_msg);
346         }
347     }
348 }
349 
350 #endif
351