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 <unistd.h>
25 #include <mach/mach.h>
26 #include <pthread.h>
27 #include "PThreadMutex.h"
28 
29 uint32_t g_log_bits = 0;
30 static DNBCallbackLog g_log_callback = NULL;
31 static void *g_log_baton = NULL;
32 
33 
34 int
35 DNBLogGetDebug ()
36 {
37     return g_debug;
38 }
39 
40 
41 void
42 DNBLogSetDebug (int g)
43 {
44     g_debug = g;
45 }
46 
47 int
48 DNBLogGetVerbose ()
49 {
50     return g_verbose;
51 }
52 
53 void
54 DNBLogSetVerbose (int v)
55 {
56     g_verbose = v;
57 }
58 
59 bool
60 DNBLogCheckLogBit (uint32_t bit)
61 {
62     return (g_log_bits & bit) != 0;
63 }
64 
65 uint32_t
66 DNBLogSetLogMask (uint32_t mask)
67 {
68     uint32_t old = g_log_bits;
69     g_log_bits = mask;
70     return old;
71 }
72 
73 uint32_t
74 DNBLogGetLogMask ()
75 {
76     return g_log_bits;
77 }
78 
79 void
80 DNBLogSetLogCallback (DNBCallbackLog callback, void *baton)
81 {
82     g_log_callback = callback;
83     g_log_baton = baton;
84 }
85 
86 bool
87 DNBLogEnabled ()
88 {
89     return g_log_callback != NULL;
90 }
91 
92 static inline void
93 _DNBLogVAPrintf(uint32_t flags, const char *format, va_list args)
94 {
95     if (g_log_callback)
96       g_log_callback(g_log_baton, flags, format, args);
97 }
98 
99 void
100 _DNBLog(uint32_t flags, const char *format, ...)
101 {
102     va_list args;
103     va_start (args, format);
104     _DNBLogVAPrintf(flags, format, args);
105     va_end (args);
106 }
107 
108 //----------------------------------------------------------------------
109 // Print debug strings if and only if the global g_debug is set to
110 // a non-zero value.
111 //----------------------------------------------------------------------
112 void
113 _DNBLogDebug (const char *format, ...)
114 {
115     if (DNBLogEnabled () && g_debug)
116     {
117         va_list args;
118         va_start (args, format);
119         _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args);
120         va_end (args);
121     }
122 }
123 
124 
125 //----------------------------------------------------------------------
126 // Print debug strings if and only if the global g_debug is set to
127 // a non-zero value.
128 //----------------------------------------------------------------------
129 void
130 _DNBLogDebugVerbose (const char *format, ...)
131 {
132     if (DNBLogEnabled () && g_debug && g_verbose)
133     {
134         va_list args;
135         va_start (args, format);
136         _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args);
137         va_end (args);
138     }
139 }
140 
141 
142 static pthread_mutex_t *
143 GetLogThreadedMutex()
144 {
145     static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE);
146     return g_LogThreadedMutex.Mutex();
147 }
148 static uint32_t g_message_id = 0;
149 
150 //----------------------------------------------------------------------
151 // Prefix the formatted log string with process and thread IDs and
152 // suffix it with a newline.
153 //----------------------------------------------------------------------
154 void
155 _DNBLogThreaded (const char *format, ...)
156 {
157     if (DNBLogEnabled ())
158     {
159         PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
160 
161         char *arg_msg = NULL;
162         va_list args;
163         va_start (args, format);
164         ::vasprintf (&arg_msg, format, args);
165         va_end (args);
166 
167         if (arg_msg != NULL)
168         {
169             _DNBLog (DNBLOG_FLAG_THREADED, "%u [%4.4x/%4.4x]: %s", ++g_message_id, getpid(), mach_thread_self(), arg_msg);
170             free (arg_msg);
171         }
172     }
173 }
174 
175 //----------------------------------------------------------------------
176 // Prefix the formatted log string with process and thread IDs and
177 // suffix it with a newline.
178 //----------------------------------------------------------------------
179 void
180 _DNBLogThreadedIf (uint32_t log_bit, const char *format, ...)
181 {
182     if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit)
183     {
184         PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex());
185 
186         char *arg_msg = NULL;
187         va_list args;
188         va_start (args, format);
189         ::vasprintf (&arg_msg, format, args);
190         va_end (args);
191 
192         if (arg_msg != NULL)
193         {
194             _DNBLog (DNBLOG_FLAG_THREADED, "%u [%4.4x/%4.4x]: %s", ++g_message_id, getpid(), mach_thread_self(), arg_msg);
195             free (arg_msg);
196         }
197     }
198 }
199 
200 
201 
202 //----------------------------------------------------------------------
203 // Printing of errors that are not fatal.
204 //----------------------------------------------------------------------
205 void
206 _DNBLogError (const char *format, ...)
207 {
208     if (DNBLogEnabled ())
209     {
210         char *arg_msg = NULL;
211         va_list args;
212         va_start (args, format);
213         ::vasprintf (&arg_msg, format, args);
214         va_end (args);
215 
216         if (arg_msg != NULL)
217         {
218             _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg);
219             free (arg_msg);
220         }
221     }
222 }
223 
224 //----------------------------------------------------------------------
225 // Printing of errors that ARE fatal. Exit with ERR exit code
226 // immediately.
227 //----------------------------------------------------------------------
228 void
229 _DNBLogFatalError (int err, const char *format, ...)
230 {
231     if (DNBLogEnabled ())
232     {
233         char *arg_msg = NULL;
234         va_list args;
235         va_start (args, format);
236         ::vasprintf (&arg_msg, format, args);
237         va_end (args);
238 
239         if (arg_msg != NULL)
240         {
241             _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg);
242             free (arg_msg);
243         }
244         ::exit (err);
245     }
246 }
247 
248 
249 //----------------------------------------------------------------------
250 // Printing of warnings that are not fatal only if verbose mode is
251 // enabled.
252 //----------------------------------------------------------------------
253 void
254 _DNBLogVerbose (const char *format, ...)
255 {
256     if (DNBLogEnabled () && g_verbose)
257     {
258         va_list args;
259         va_start (args, format);
260         _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args);
261         va_end (args);
262     }
263 }
264 
265 //----------------------------------------------------------------------
266 // Printing of warnings that are not fatal only if verbose mode is
267 // enabled.
268 //----------------------------------------------------------------------
269 void
270 _DNBLogWarningVerbose (const char *format, ...)
271 {
272     if (DNBLogEnabled () && g_verbose)
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_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg);
283             free (arg_msg);
284         }
285     }
286 }
287 //----------------------------------------------------------------------
288 // Printing of warnings that are not fatal.
289 //----------------------------------------------------------------------
290 void
291 _DNBLogWarning (const char *format, ...)
292 {
293     if (DNBLogEnabled ())
294     {
295         char *arg_msg = NULL;
296         va_list args;
297         va_start (args, format);
298         ::vasprintf (&arg_msg, format, args);
299         va_end (args);
300 
301         if (arg_msg != NULL)
302         {
303             _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg);
304             free (arg_msg);
305         }
306     }
307 }
308 
309 #endif
310