1 // log.cpp: Message logging functions, for gnash.
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 #include <boost/format.hpp>
34 #include <unistd.h> // for getpid
36 #include "GnashAlgorithm.h"
37 #include "ClockTime.h"
43 // TODO: drop this and use boost::this_thread::id instead.
44 inline unsigned long int /* pthread_t */ get_thread_id();
49 // Convert each byte into its hex representation
51 hexify(const unsigned char *p
, size_t length
, bool ascii
)
54 const std::vector
<unsigned char> bytes(p
, p
+ length
);
56 std::ostringstream ss
;
58 // For hex output, fill single-digit numbers with a leading 0.
59 if (!ascii
) ss
<< std::hex
<< std::setfill('0');
61 for (std::vector
<unsigned char>::const_iterator i
= bytes
.begin(),
62 e
= bytes
.end(); i
!= e
; ++i
)
65 if (std::isprint(*i
) || *i
== 0xd) {
72 ss
<< std::setw(2) << static_cast<int>(*i
) << " ";
81 LogFile::getDefaultInstance()
90 LogFile
& dbglogfile
= LogFile::getDefaultInstance();
93 boost::uint64_t startTicks
;
94 std::map
<int, int> threadMap
;
95 Timestamp() : startTicks(clocktime::getTicks()) {}
98 std::ostream
& operator<< (std::ostream
& o
, Timestamp
& t
)
100 int tid
= get_thread_id();
101 int& htid
= t
.threadMap
[tid
];
103 htid
= t
.threadMap
.size();
104 // TODO: notify actual thread id for index
107 boost::uint64_t diff
= clocktime::getTicks() - t
.startTicks
;
108 // should we split in seconds/ms ?
109 o
<< getpid() << ":" << htid
<< "] " << diff
;
119 // boost format functions to process the objects
120 // created by our hundreds of templates
123 processLog_trace(const boost::format
& fmt
)
125 dbglogfile
.log(N_("TRACE"), fmt
.str());
129 processLog_debug(const boost::format
& fmt
)
131 if (dbglogfile
.getVerbosity() < LogFile::LOG_DEBUG
) return;
132 dbglogfile
.log(N_("DEBUG"), fmt
.str());
136 processLog_abc(const boost::format
& fmt
)
138 if (dbglogfile
.getVerbosity() < LogFile::LOG_EXTRA
) return;
139 dbglogfile
.log(N_("ABC"), fmt
.str());
143 processLog_parse(const boost::format
& fmt
)
145 dbglogfile
.log(fmt
.str());
149 processLog_network(const boost::format
& fmt
)
151 dbglogfile
.log(N_("NETWORK"), fmt
.str());
155 processLog_error(const boost::format
& fmt
)
157 dbglogfile
.log(N_("ERROR"), fmt
.str());
161 processLog_unimpl(const boost::format
& fmt
)
163 dbglogfile
.log(N_("UNIMPLEMENTED"), fmt
.str());
167 processLog_security(const boost::format
& fmt
)
169 dbglogfile
.log(N_("SECURITY"), fmt
.str());
173 processLog_swferror(const boost::format
& fmt
)
175 dbglogfile
.log(N_("MALFORMED SWF"), fmt
.str());
179 processLog_aserror(const boost::format
& fmt
)
181 dbglogfile
.log(N_("ACTIONSCRIPT ERROR"), fmt
.str());
185 processLog_action(const boost::format
& fmt
)
187 bool stamp
= dbglogfile
.getStamp();
188 dbglogfile
.setStamp(false);
189 dbglogfile
.log(fmt
.str());
190 dbglogfile
.setStamp(stamp
);
194 LogFile::log(const std::string
& msg
)
197 boost::mutex::scoped_lock
lock(_ioMutex
);
199 if ( !_verbose
) return; // nothing to do if not verbose
201 if (openLogIfNeeded()) {
203 _outstream
<< timestamp
<< ": " << msg
<< "\n";
205 _outstream
<< msg
<< "\n";
211 cout
<< timestamp
<< " " << msg
<< endl
;
223 LogFile::log(const std::string
& label
, const std::string
& msg
)
225 log(label
+ ": " + msg
);
229 LogFile::setLogFilename(const std::string
& fname
)
232 _logFilename
= fname
;
236 LogFile::setWriteDisk(bool use
)
238 if (!use
) closeLog();
242 // Default constructor
257 if (_state
== OPEN
) closeLog();
261 LogFile::openLogIfNeeded()
263 if (_state
!= CLOSED
) return true;
264 if (!_write
) return false;
266 if (_logFilename
.empty()) _logFilename
= DEFAULT_LOGFILE
;
268 // TODO: expand ~ to getenv("HOME") !!
270 return openLog(_logFilename
);
274 LogFile::openLog(const std::string
& filespec
)
278 // don't need to lock the mutex here, as this method
279 // is intended to be called only by openLogIfNeeded,
280 // which in turn is called by operator<< which is called
281 // by the public log_xxx functions that log themselves
283 if (_state
!= CLOSED
) {
284 cout
<< "Closing previously opened stream" << endl
;
289 // Append, don't truncate, the log file
290 _outstream
.open(filespec
.c_str(), std::ios::app
|std::ios::out
); // ios::out
291 if( _outstream
.fail() ) {
292 // Can't use log_error here...
293 cout
<< "ERROR: can't open debug log file " << filespec
<<
294 " for appending." << endl
;
298 _filespec
= filespec
;
307 boost::mutex::scoped_lock
lock(_ioMutex
);
308 if (_state
== OPEN
) {
320 if (_state
== OPEN
) {
324 // Ignore the error, we don't care
325 unlink(_filespec
.c_str());
331 } // end of gnash namespace
338 extern "C" unsigned long int /* DWORD WINAPI */ GetCurrentThreadId();
340 #include <sys/types.h>
347 inline unsigned long int /* pthread_t */ get_thread_id(void)
351 return reinterpret_cast<unsigned long int>(pthread_self());
353 // This isn't a proper style C++ cast, but FreeBSD has a problem with
354 // static_cast for this as pthread_self() returns a pointer. We can
355 // use that too, this ID is only used for the log file to keep output
356 // from seperare threads clear.
358 return GetCurrentThreadId();
360 return (unsigned long int)pthread_self();
365 return GetCurrentThreadId();
367 return static_cast<unsigned long int>(getpid());
373 } // anonymous namespace
377 // indent-tabs-mode: t