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     static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
97     PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex);
98 
99     if (g_log_callback)
100       g_log_callback(g_log_baton, flags, format, args);
101 }
102 
103 void
104 _DNBLog(uint32_t flags, const char *format, ...)
105 {
106     va_list args;
107     va_start (args, format);
108     _DNBLogVAPrintf(flags, format, args);
109     va_end (args);
110 }
111 
112 //----------------------------------------------------------------------
113 // Print debug strings if and only if the global g_debug is set to
114 // a non-zero value.
115 //----------------------------------------------------------------------
116 void
117 _DNBLogDebug (const char *format, ...)
118 {
119     if (DNBLogEnabled () && g_debug)
120     {
121         va_list args;
122         va_start (args, format);
123         _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);
124         va_end (args);
125     }
126 }
127 
128 
129 //----------------------------------------------------------------------
130 // Print debug strings if and only if the global g_debug is set to
131 // a non-zero value.
132 //----------------------------------------------------------------------
133 void
134 _DNBLogDebugVerbose (const char *format, ...)
135 {
136     if (DNBLogEnabled () && g_debug && g_verbose)
137     {
138         va_list args;
139         va_start (args, format);
140         _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);
141         va_end (args);
142     }
143 }
144 
145 
146 static uint32_t g_message_id = 0;
147 
148 //----------------------------------------------------------------------
149 // Prefix the formatted log string with process and thread IDs and
150 // suffix it with a newline.
151 //----------------------------------------------------------------------
152 void
153 _DNBLogThreaded (const char *format, ...)
154 {
155     if (DNBLogEnabled ())
156     {
157         //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
158 
159         char *arg_msg = NULL;
160         va_list args;
161         va_start (args, format);
162         ::vasprintf (&arg_msg, format, args);
163         va_end (args);
164 
165         if (arg_msg != NULL)
166         {
167             static struct timeval g_timeval = { 0 , 0 };
168             static struct timeval tv;
169             static struct timeval delta;
170             gettimeofday(&tv, NULL);
171             if (g_timeval.tv_sec == 0)
172             {
173                 delta.tv_sec = 0;
174                 delta.tv_usec = 0;
175             }
176             else
177             {
178                 timersub (&tv, &g_timeval, &delta);
179             }
180             g_timeval = tv;
181             _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s",
182                      ++g_message_id,
183                      delta.tv_sec,
184                      delta.tv_usec,
185                      getpid(),
186                      mach_thread_self(),
187                      arg_msg);
188             free (arg_msg);
189         }
190     }
191 }
192 
193 //----------------------------------------------------------------------
194 // Prefix the formatted log string with process and thread IDs and
195 // suffix it with a newline.
196 //----------------------------------------------------------------------
197 void
198 _DNBLogThreadedIf (uint32_t log_bit, const char *format, ...)
199 {
200     if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit)
201     {
202         //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
203 
204         char *arg_msg = NULL;
205         va_list args;
206         va_start (args, format);
207         ::vasprintf (&arg_msg, format, args);
208         va_end (args);
209 
210         if (arg_msg != NULL)
211         {
212             static struct timeval g_timeval = { 0 , 0 };
213             static struct timeval tv;
214             static struct timeval delta;
215             gettimeofday(&tv, NULL);
216             if (g_timeval.tv_sec == 0)
217             {
218                 delta.tv_sec = 0;
219                 delta.tv_usec = 0;
220             }
221             else
222             {
223                 timersub (&tv, &g_timeval, &delta);
224             }
225             g_timeval = tv;
226             _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s",
227                      ++g_message_id,
228                      delta.tv_sec,
229                      delta.tv_usec,
230                      getpid(),
231                      mach_thread_self(),
232                      arg_msg);
233             free (arg_msg);
234         }
235     }
236 }
237 
238 
239 
240 //----------------------------------------------------------------------
241 // Printing of errors that are not fatal.
242 //----------------------------------------------------------------------
243 void
244 _DNBLogError (const char *format, ...)
245 {
246     if (DNBLogEnabled ())
247     {
248         char *arg_msg = NULL;
249         va_list args;
250         va_start (args, format);
251         ::vasprintf (&arg_msg, format, args);
252         va_end (args);
253 
254         if (arg_msg != NULL)
255         {
256             _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg);
257             free (arg_msg);
258         }
259     }
260 }
261 
262 //----------------------------------------------------------------------
263 // Printing of errors that ARE fatal. Exit with ERR exit code
264 // immediately.
265 //----------------------------------------------------------------------
266 void
267 _DNBLogFatalError (int err, const char *format, ...)
268 {
269     if (DNBLogEnabled ())
270     {
271         char *arg_msg = NULL;
272         va_list args;
273         va_start (args, format);
274         ::vasprintf (&arg_msg, format, args);
275         va_end (args);
276 
277         if (arg_msg != NULL)
278         {
279             _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);
280             free (arg_msg);
281         }
282         ::exit (err);
283     }
284 }
285 
286 
287 //----------------------------------------------------------------------
288 // Printing of warnings that are not fatal only if verbose mode is
289 // enabled.
290 //----------------------------------------------------------------------
291 void
292 _DNBLogVerbose (const char *format, ...)
293 {
294     if (DNBLogEnabled () && g_verbose)
295     {
296         va_list args;
297         va_start (args, format);
298         _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);
299         va_end (args);
300     }
301 }
302 
303 //----------------------------------------------------------------------
304 // Printing of warnings that are not fatal only if verbose mode is
305 // enabled.
306 //----------------------------------------------------------------------
307 void
308 _DNBLogWarningVerbose (const char *format, ...)
309 {
310     if (DNBLogEnabled () && g_verbose)
311     {
312         char *arg_msg = NULL;
313         va_list args;
314         va_start (args, format);
315         ::vasprintf (&arg_msg, format, args);
316         va_end (args);
317 
318         if (arg_msg != NULL)
319         {
320             _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg);
321             free (arg_msg);
322         }
323     }
324 }
325 //----------------------------------------------------------------------
326 // Printing of warnings that are not fatal.
327 //----------------------------------------------------------------------
328 void
329 _DNBLogWarning (const char *format, ...)
330 {
331     if (DNBLogEnabled ())
332     {
333         char *arg_msg = NULL;
334         va_list args;
335         va_start (args, format);
336         ::vasprintf (&arg_msg, format, args);
337         va_end (args);
338 
339         if (arg_msg != NULL)
340         {
341             _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);
342             free (arg_msg);
343         }
344     }
345 }
346 
347 #endif
348