Move "loop" related tests in their own dir. This is just to break the ice... ideally...
[gnash.git] / libbase / log.h
blob188b76a5a98a9edf7083ba338faa1e87e9bf535b
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // Foundation, Inc
4 //
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 3 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef GNASH_LOG_H
20 #define GNASH_LOG_H
22 #ifdef HAVE_CONFIG_H
23 #include "gnashconfig.h"
24 #endif
26 #include "rc.h" // for IF_VERBOSE_* implementation
27 #include "dsodefs.h" // for DSOEXPORT
29 #include <fstream>
30 #include <boost/thread/thread.hpp>
31 #include <boost/thread/mutex.hpp>
32 #include <boost/format.hpp>
34 // the default name for the debug log
35 #define DEFAULT_LOGFILE "gnash-dbg.log"
37 // Support compilation with (or without) native language support
38 #include "gettext.h"
39 #define _(String) gettext (String)
40 #define N_(String) gettext_noop (String)
42 // Macro to prevent repeated logging calls for the same
43 // event
44 #define LOG_ONCE(x) { \
45 static bool warned = false; \
46 if (!warned) { warned = true; x; } \
49 # include <boost/preprocessor/arithmetic/inc.hpp>
50 # include <boost/preprocessor/repetition/enum_params.hpp>
51 # include <boost/preprocessor/repetition/repeat.hpp>
52 # include <boost/preprocessor/repetition/repeat_from_to.hpp>
53 # include <boost/preprocessor/seq/for_each.hpp>
55 // Mingw32 (win32 console) doesn't use the standard GCC defines that
56 // Gnash used for debug messages, so make it so...
57 #ifndef __FUNCDNAME__
58 #define __FUNCDNAME__ __FUNCTION__
59 #endif
61 namespace gnash {
63 // This is a basic file logging class
64 class DSOEXPORT LogFile
66 public:
68 static LogFile& getDefaultInstance();
70 ~LogFile();
72 enum LogLevel {
73 LOG_SILENT,
74 LOG_NORMAL,
75 LOG_DEBUG,
76 LOG_EXTRA
79 enum FileState {
80 CLOSED,
81 OPEN,
82 INPROGRESS,
83 IDLE
86 /// Intended for use by log_*(). Thread-safe (locks _ioMutex)
88 /// @param label
89 /// The label string ie: "ERROR" for "ERROR: <msg>"
90 ///
91 /// @param msg
92 /// The message string ie: "bah" for "ERROR: bah"
93 ///
94 void log(const std::string& label, const std::string& msg);
96 /// Intended for use by log_*(). Thread-safe (locks _ioMutex)
98 /// @param msg
99 /// The message to print
101 void log(const std::string& msg);
103 /// Remove the log file
105 /// Does NOT lock _ioMutex (should it?)
107 bool removeLog();
109 /// Close the log file
111 /// Locks _ioMutex to prevent race conditions accessing _outstream
113 bool closeLog();
115 /// Set log filename
117 /// If a log file is opened already, it will be closed
118 /// by this call, and will be reopened on next use
119 /// if needed.
121 void setLogFilename(const std::string& fname);
123 // accessors for the verbose level
124 void setVerbosity() {
125 ++_verbose;
128 void setVerbosity(int x) {
129 _verbose = x;
132 int getVerbosity() const {
133 return _verbose;
136 void setActionDump(int x) {
137 _actiondump = x;
140 void setNetwork(int x) {
141 _network = x;
144 int getActionDump() const {
145 return _actiondump;
148 int getNetwork() const {
149 return _network;
152 void setParserDump (int x) {
153 _parserdump = x;
156 int getParserDump() const {
157 return _parserdump;
160 void setStamp (bool b) {
161 _stamp = b;
164 bool getStamp() const {
165 return _stamp;
168 /// Set whether to write logs to file
169 void setWriteDisk(bool b);
171 bool getWriteDisk() const {
172 return _write;
175 typedef void (*logListener)(const std::string& s);
177 void registerLogCallback(logListener l) { _listener = l; }
179 private:
181 /// Open the specified file to write logs on disk
183 /// Locks _ioMutex to prevent race conditions accessing _outstream
185 /// @return true on success, false on failure
187 bool openLog(const std::string& filespec);
189 /// \brief
190 /// Open the RcInitFile-specified log file if log write
191 /// is requested.
193 /// This method is called before any attempt to write is made.
194 /// It will return true if the file was opened, false if wasn't
195 /// (either not requested or error).
197 /// On error, will print a message on stderr
199 bool openLogIfNeeded();
201 // Use getDefaultInstance for getting the singleton
202 LogFile ();
204 /// Mutex for locking I/O during logfile access.
205 boost::mutex _ioMutex;
207 /// Stream to write to stdout.
208 std::ofstream _outstream;
210 /// How much output is required: 2 or more gives debug output.
211 int _verbose;
213 /// Whether to dump all SWF actions
214 bool _actiondump;
216 /// Whether to dump all networking actions
217 bool _network;
219 /// Whether to dump parser output
220 bool _parserdump;
222 /// The state of the log file.
223 FileState _state;
225 bool _stamp;
227 /// Whether to write the log file to disk.
228 bool _write;
230 std::string _filespec;
232 std::string _logFilename;
234 logListener _listener;
238 DSOEXPORT void processLog_network(const boost::format& fmt);
239 DSOEXPORT void processLog_error(const boost::format& fmt);
240 DSOEXPORT void processLog_unimpl(const boost::format& fmt);
241 DSOEXPORT void processLog_trace(const boost::format& fmt);
242 DSOEXPORT void processLog_debug(const boost::format& fmt);
243 DSOEXPORT void processLog_action(const boost::format& fmt);
244 DSOEXPORT void processLog_parse(const boost::format& fmt);
245 DSOEXPORT void processLog_security(const boost::format& fmt);
246 DSOEXPORT void processLog_swferror(const boost::format& fmt);
247 DSOEXPORT void processLog_amferror(const boost::format& fmt);
248 DSOEXPORT void processLog_aserror(const boost::format& fmt);
249 DSOEXPORT void processLog_abc(const boost::format& fmt);
251 /// This heap of steaming preprocessor code magically converts
252 /// printf-style statements into boost::format messages using templates.
254 /// Macro to feed boost::format strings to the boost::format object,
255 /// producing code like this: "% t1 % t2 % t3 ..."
256 #define TOKENIZE_FORMAT(z, n, t) % t##n
258 /// Macro to add a number of arguments to the templated function
259 /// corresponding to the number of template arguments. Produces code
260 /// like this: "const T0& t0, const T1& t1, const T2& t2 ..."
261 #define TOKENIZE_ARGS(z, n, t) BOOST_PP_COMMA_IF(n) const T##n& t##n
263 /// This is a sequence of different log message types to be used in
264 /// the code. Append the name to log_ to call the function, e.g.
265 /// log_error, log_unimpl.
266 #define LOG_TYPES (error) (debug) (unimpl) (aserror) (swferror) \
267 (amferror) (security) (action) (parse) (trace) (abc) (network)
269 /// This actually creates the template functions using the TOKENIZE
270 /// functions above. The templates look like this:
272 /// template<typename T0 , typename T1 , typename T2>
273 /// void log_error(const T0& t0 , const T1& t1 , const T2& t2)
274 /// {
275 /// if (LogFile::getDefaultInstance().getVerbosity() == 0) return;
276 /// boost::format f(t0);
277 /// using namespace boost::io;
278 /// f.exceptions(all_error_bits ^ (too_many_args_bit |
279 /// too_few_args_bit |
280 /// bad_format_string_bit));
281 /// processLog_error(f % t1 % t2);
282 /// }
284 /// Only not as nicely indented.
286 /// Use "g++ -E log.h" or "cpp log.h" to check.
287 #define LOG_TEMPLATES(z, n, data)\
288 template<BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), typename T)>\
289 inline void log_##data(BOOST_PP_REPEAT(BOOST_PP_INC(n), TOKENIZE_ARGS, t)) \
291 if (LogFile::getDefaultInstance().getVerbosity() == 0) return; \
292 boost::format f(t0); \
293 using namespace boost::io; \
294 f.exceptions(all_error_bits ^ (too_many_args_bit | \
295 too_few_args_bit | \
296 bad_format_string_bit)); \
297 processLog_##data(f BOOST_PP_REPEAT_FROM_TO(1, \
298 BOOST_PP_INC(n), \
299 TOKENIZE_FORMAT, t));\
302 /// Defines the maximum number of template arguments
304 /// The preprocessor generates templates with 1..ARG_NUMBER
305 /// arguments.
306 #define ARG_NUMBER 10
308 /// Calls the macro LOG_TEMPLATES an ARG_NUMBER number
309 /// of times, each time adding an extra typename argument to the
310 /// template.
311 #define GENERATE_LOG_TYPES(r, _, t) \
312 BOOST_PP_REPEAT(ARG_NUMBER, LOG_TEMPLATES, t)
314 /// Calls the template generator for each log type in the
315 /// sequence LOG_TYPES.
316 BOOST_PP_SEQ_FOR_EACH(GENERATE_LOG_TYPES, _, LOG_TYPES)
318 #undef TOKENIZE_ARGS
319 #undef TOKENIZE_FORMAT
320 #undef GENERATE_LOG_TYPES
321 #undef LOG_TEMPLATES
322 #undef ARG_NUMBER
324 /// Convert a sequence of bytes to hex or ascii format.
326 /// @param bytes the array of bytes to process
327 /// @param length the number of bytes to read. Callers are responsible
328 /// for checking that length does not exceed the array size.
329 /// @param ascii whether to return in ascii or space-separated hex format.
330 /// @return a string representation of the byte sequence.
331 DSOEXPORT std::string hexify(const unsigned char *bytes, size_t length,
332 bool ascii);
334 // Define to 0 to completely remove parse debugging at compile-time
335 #ifndef VERBOSE_PARSE
336 #define VERBOSE_PARSE 1
337 #endif
339 // Define to 0 to completely remove action debugging at compile-time
340 #ifndef VERBOSE_ACTION
341 #define VERBOSE_ACTION 1
342 #endif
344 // Define to 0 to remove ActionScript errors verbosity at compile-time
345 #ifndef VERBOSE_ASCODING_ERRORS
346 #define VERBOSE_ASCODING_ERRORS 1
347 #endif
349 // Define to 0 this to remove invalid SWF verbosity at compile-time
350 #ifndef VERBOSE_MALFORMED_SWF
351 #define VERBOSE_MALFORMED_SWF 1
352 #endif
354 // Define to 0 this to remove invalid AMF verbosity at compile-time
355 #ifndef VERBOSE_MALFORMED_AMF
356 #define VERBOSE_MALFORMED_AMF 1
357 #endif
359 // Define to 0 this to remove Networking verbosity at compile-time
360 #ifndef VERBOSE_NETWORKING
361 #define VERBOSE_NETWORKING 1
362 #endif
364 #if VERBOSE_PARSE
365 #define IF_VERBOSE_PARSE(x) do { if ( LogFile::getDefaultInstance().getParserDump() ) { x; } } while (0);
366 #else
367 #define IF_VERBOSE_PARSE(x)
368 #endif
370 #if VERBOSE_ACTION
371 #define IF_VERBOSE_ACTION(x) do { if ( LogFile::getDefaultInstance().getActionDump() ) { x; } } while (0);
372 #else
373 #define IF_VERBOSE_ACTION(x)
374 #endif
376 #if VERBOSE_ACTION
377 #define IF_VERBOSE_NETWORK(x) do { if ( LogFile::getDefaultInstance().getNetwork() ) { x; } } while (0);
378 #else
379 #define IF_VERBOSE_NETWORK(x)
380 #endif
382 #if VERBOSE_ASCODING_ERRORS
383 // TODO: check if it's worth to check verbosity level too...
384 #define IF_VERBOSE_ASCODING_ERRORS(x) { if ( gnash::RcInitFile::getDefaultInstance().showASCodingErrors() ) { x; } }
385 #else
386 #define IF_VERBOSE_ASCODING_ERRORS(x)
387 #endif
389 #if VERBOSE_MALFORMED_SWF
390 // TODO: check if it's worth to check verbosity level too...
391 #define IF_VERBOSE_MALFORMED_SWF(x) { if ( gnash::RcInitFile::getDefaultInstance().showMalformedSWFErrors() ) { x; } }
392 #else
393 #define IF_VERBOSE_MALFORMED_SWF(x)
394 #endif
396 #if VERBOSE_MALFORMED_AMF
397 // TODO: check if it's worth to check verbosity level too...
398 #define IF_VERBOSE_MALFORMED_AMF(x) { if ( gnash::RcInitFile::getDefaultInstance().showMalformedAMFErrors() ) { x; } }
399 #else
400 #define IF_VERBOSE_MALFORMED_AMF(x)
401 #endif
403 class DSOEXPORT __Host_Function_Report__
405 public:
406 const char *func;
408 // Only print function tracing messages when multiple -v
409 // options have been supplied.
410 __Host_Function_Report__(void) {
411 log_debug("entering");
414 __Host_Function_Report__(char *_func) {
415 func = _func;
416 log_debug("%s enter", func);
419 __Host_Function_Report__(const char *_func) {
420 func = _func;
421 if (func) {
422 log_debug("%s enter", func);
424 else {
425 log_debug("No Function Name! enter");
429 ~__Host_Function_Report__(void) {
430 log_debug("%s returning", func);
434 #ifndef HAVE_FUNCTION
435 #ifndef HAVE_func
436 #define dummystr(x) # x
437 #define dummyestr(x) dummystr(x)
438 #define __FUNCTION__ __FILE__":"dummyestr(__LINE__)
439 #else
440 #define __FUNCTION__ __func__
441 #endif
442 #endif
444 #ifndef HAVE_PRETTY_FUNCTION
445 #define __PRETTY_FUNCTION__ __FUNCTION__
446 #endif
448 #if defined(__cplusplus) && defined(__GNUC__)
449 #define GNASH_REPORT_FUNCTION \
450 gnash::__Host_Function_Report__ __host_function_report__( __PRETTY_FUNCTION__)
451 #define GNASH_REPORT_RETURN
452 #else
453 #define GNASH_REPORT_FUNCTION \
454 gnash::log_debug("entering")
456 #define GNASH_REPORT_RETURN \
457 gnash::log_debug("returning")
458 #endif
463 #endif // GNASH_LOG_H
466 // Local Variables:
467 // mode: C++
468 // indent-tabs-mode: nil
469 // End: