summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/odebug.cpp4
1 files changed, 4 insertions, 0 deletions
diff --git a/libopie2/opiecore/odebug.cpp b/libopie2/opiecore/odebug.cpp
index d8dfe26..45709dc 100644
--- a/libopie2/opiecore/odebug.cpp
+++ b/libopie2/opiecore/odebug.cpp
@@ -1,645 +1,649 @@
/*
This file is part of the Opie Project
(C) 2003 Michael 'Mickey' Lauer (mickey@tm.informatik.uni-frankfurt.de)
(C) 2002 Holger Freyther (freyther@kde.org)
(C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. This program is distributed in the hope that
     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
    : ..    .:,     . . . without even the implied warranty of
    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
// Include this header without OPIE_NO_DEBUG defined to avoid having the oDebugInfo
// functions inlined to noops (which would then conflict with their definition here).
#include <opie2/odebug.h>
+#if defined(__UCLIBC__)
+#define OPIE_NO_BACKTRACE
+#endif
+
#ifdef OPIE_NO_DEBUG
#undef odDebug
#undef odBacktrace
#endif
/* OPIE */
#include <opie2/oapplication.h>
#include <opie2/oglobalsettings.h>
#include <opie2/oconfig.h>
/* QT */
#include <qfile.h>
#include <qmessagebox.h>
#include <qsocketdevice.h>
/* UNIX */
#include <stdlib.h> // abort
#include <unistd.h> // getpid
#include <stdarg.h> // vararg stuff
#include <ctype.h> // isprint
#include <syslog.h>
#include <errno.h>
#include <string.h>
#ifndef OPIE_NO_BACKTRACE
#include <execinfo.h>
#endif
namespace Opie {
namespace Core {
namespace Internal {
/*======================================================================================
* debug levels
*======================================================================================*/
enum DebugLevels {
ODEBUG_INFO = 0,
ODEBUG_WARN = 1,
ODEBUG_ERROR = 2,
ODEBUG_FATAL = 3
};
/*======================================================================================
* oDebug private data
*======================================================================================*/
/*======================================================================================
* the main debug function
*======================================================================================*/
struct DebugBackend {
DebugBackend() : m_opened( false ), m_file( 0 ) ,m_port( -1 ),m_sock( 0 ) {
m_outp = OGlobalSettings::debugMode();
}
~DebugBackend() {
delete m_file;
delete m_sock;
}
void debug( unsigned short level, unsigned int, const QString& data );
private:
void debugFile( const QString&, const QString& data );
void debugMsgB( const QString&, const QString& data );
void debugShel( const QString&, const QString& data );
void debugSysl( int, const QString& );
void debugSock( const QString&, const QString& data );
QCString line( const QString&, const QString& data );
bool m_opened : 1;
QFile *m_file;
QHostAddress m_addr;
int m_port;
QSocketDevice *m_sock;
short m_outp;
};
void DebugBackend::debug(unsigned short level, unsigned int, const QString& data) {
//qDebug( "oDebugBackend: Level=%d, Area=%d, Data=%s", level, area, data );
// ML: OPIE doesn't use areacodes at the moment. See the KDE debug classes for an
// ML: example use. I think it's not necessary to implement such a strategy here.
// ML: Comments?
int priority = 0;
QString caption;
QString lev;
switch( level )
{
case ODEBUG_INFO: lev = "(Info)"; caption = "Info"; priority = LOG_INFO; break;
case ODEBUG_WARN: lev = "(Warn)"; caption = "Warning"; priority = LOG_WARNING; break;
case ODEBUG_FATAL: lev = "(Fatal)"; caption = "Fatal Error"; priority = LOG_CRIT; break;
default: qDebug( "oDebugBackend: Warning: Unknown debug level! - defaulting to ODEBUG_ERROR." );
case ODEBUG_ERROR: lev = "(Error)"; caption = "Error"; priority = LOG_ERR; break;
}
if (!oApp && (m_outp == 1)) {
qDebug( "oDebugBackend: Warning: no oapplication object - can't use MsgBox" );
m_outp = 2; // need an application object to use MsgBox
}
// gcc 2.9x is dumb and sucks... can you hear it?
//QString areaName = (oApp) ? oApp->appName() : "<unknown>";
QString areaName;
if ( oApp ) areaName = oApp->appName();
else areaName = "<unknown>";
switch( m_outp ) {
case ODEBUG_IGNORE:
return;
case ODEBUG_FILE:
return debugFile( areaName, data );
case ODEBUG_MSGBOX:
return debugMsgB( areaName, data );
case ODEBUG_STDERR:
return debugShel( areaName,data );
case ODEBUG_SYSLOG:
return debugSysl( priority, data );
case ODEBUG_SOCKET:
return debugSock( areaName, data );
}
}
inline void DebugBackend::debugFile(const QString& area, const QString& data) {
/* something went wrong with the file don't bother.. */
if ( m_opened && !m_file )
return;
else if ( !m_opened ) {
m_opened = true;
m_file = new QFile( OGlobalSettings::debugOutput() );
if (!m_file->open( IO_WriteOnly | IO_Append ) ) {
delete m_file; m_file = 0;
qDebug( "ODebug: can't write to file '%s' (%s)", (const char*)OGlobalSettings::debugOutput(),
strerror(errno) );
return;
}
}
/* go to end of file */
m_file->at( m_file->size() );
QCString li = line( area, data );
m_file->writeBlock(li.data(), li.length() );
}
void DebugBackend::debugMsgB( const QString& area, const QString& data ) {
QMessageBox::warning( 0l, "("+area+")", data, ("Ok") );
}
void DebugBackend::debugShel( const QString& are, const QString& data ) {
FILE *output = stderr;
fprintf( output, "%s: %s", are.local8Bit().data(),
data.local8Bit().data() );
}
void DebugBackend::debugSysl( int prio, const QString& data ) {
::syslog( prio, "%s", data.local8Bit().data() );
}
void DebugBackend::debugSock( const QString& are, const QString& data ) {
if ( m_opened && !m_sock )
return;
else if ( !m_opened ){
m_opened = true;
QString destination = OGlobalSettings::debugOutput();
if ( destination && destination.find(":") != -1 ) {
QString host = destination.left( destination.find(":") );
m_port = destination.right( destination.length()-host.length()-1 ).toInt();
m_addr.setAddress( host );
m_sock = new QSocketDevice( QSocketDevice::Datagram );
}else{
m_sock = 0;
return;
}
}
QCString li = line( are, data );
int result = m_sock->writeBlock(li.data(), li.length(), m_addr, m_port );
if ( result == -1 ) {
qDebug( "ODebug: can't send to address '"+ m_addr.toString() +":%d' (%s)",
m_port, strerror(errno) );
}
}
QCString DebugBackend::line( const QString& area, const QString& data ) {
QString str = area +":"+data;
return str.local8Bit();
}
static DebugBackend *backEnd = 0;
}
static void clean_up_routine() {
qWarning( "Clean up Debug" );
delete Internal::backEnd;
Internal::backEnd = 0;
}
/*======================================================================================
* odbgstream
*======================================================================================*/
odbgstream& perror( odbgstream &s)
{
return s << QString::fromLocal8Bit(strerror(errno));
}
odbgstream odDebug(int area)
{
return odbgstream(area, Internal::ODEBUG_INFO);
}
odbgstream odDebug(bool cond, int area)
{
if (cond) return odbgstream(area, Internal::ODEBUG_INFO);
else return odbgstream(0, 0, false);
}
odbgstream odError(int area)
{
return odbgstream("ERROR: ", area, Internal::ODEBUG_ERROR);
}
odbgstream odError(bool cond, int area)
{
if (cond) return odbgstream("ERROR: ", area, Internal::ODEBUG_ERROR); else return odbgstream(0,0,false);
}
odbgstream odWarning(int area)
{
return odbgstream("WARNING: ", area, Internal::ODEBUG_WARN);
}
odbgstream odWarning(bool cond, int area)
{
if (cond) return odbgstream("WARNING: ", area, Internal::ODEBUG_WARN); else return odbgstream(0,0,false);
}
odbgstream odFatal(int area)
{
return odbgstream("FATAL: ", area, Internal::ODEBUG_FATAL);
}
odbgstream odFatal(bool cond, int area)
{
if (cond) return odbgstream("FATAL: ", area, Internal::ODEBUG_FATAL); else return odbgstream(0,0,false);
}
odbgstream::odbgstream(unsigned int _area, unsigned int _level, bool _print)
:area(_area), level(_level), print(_print)
{
}
odbgstream::odbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print)
:output(QString::fromLatin1(initialString)), area(_area), level(_level), print(_print)
{
}
odbgstream::odbgstream(odbgstream &str)
:output(str.output), area(str.area), level(str.level), print(str.print)
{
str.output.truncate(0);
}
odbgstream::odbgstream(const odbgstream &str)
:output(str.output), area(str.area), level(str.level), print(str.print)
{
}
odbgstream& odbgstream::operator<<(bool i)
{
if (!print) return *this;
output += QString::fromLatin1(i ? "true" : "false");
return *this;
}
odbgstream& odbgstream::operator<<(short i)
{
if (!print) return *this;
QString tmp; tmp.setNum(i); output += tmp;
return *this;
}
odbgstream& odbgstream::operator<<(unsigned short i)
{
if (!print) return *this;
QString tmp; tmp.setNum(i); output += tmp;
return *this;
}
odbgstream& odbgstream::operator<<(unsigned char i)
{
return operator<<( static_cast<char>( i ) );
}
odbgstream& odbgstream::operator<<(int i)
{
if (!print) return *this;
QString tmp; tmp.setNum(i); output += tmp;
return *this;
}
odbgstream& odbgstream::operator<<(unsigned int i)
{
if (!print) return *this;
QString tmp; tmp.setNum(i); output += tmp;
return *this;
}
odbgstream& odbgstream::operator<<(long i)
{
if (!print) return *this;
QString tmp; tmp.setNum(i); output += tmp;
return *this;
}
odbgstream& odbgstream::operator<<(unsigned long i)
{
if (!print) return *this;
QString tmp; tmp.setNum(i); output += tmp;
return *this;
}
odbgstream& odbgstream::operator<<(const QString& string)
{
if (!print) return *this;
output += string;
if (output.at(output.length() -1 ) == '\n')
flush();
return *this;
}
odbgstream& odbgstream::operator<<(const char *string)
{
if (!print) return *this;
output += QString::fromUtf8(string);
if (output.at(output.length() - 1) == '\n')
flush();
return *this;
}
odbgstream& odbgstream::operator<<(const QCString& string)
{
*this << string.data();
return *this;
}
odbgstream& odbgstream::operator<<(const void * p)
{
form("%p", p);
return *this;
}
odbgstream& odbgstream::operator<<(double d)
{
QString tmp; tmp.setNum(d); output += tmp;
return *this;
}
/*
odbgstream::odbgstream &form(const char *format, ...)
#ifdef __GNUC__
__attribute__ ( ( format ( printf, 2, 3 ) ) )
#endif
;
*/
void odbgstream::flush()
{
if ( output.isEmpty() || !print )
{
return;
}
else
{
if ( !Internal::backEnd ) {
Internal::backEnd = new Internal::DebugBackend;
qAddPostRoutine( clean_up_routine );
}
Internal::backEnd->debug( level, area, output );
output = QString::null;
}
}
odbgstream& odbgstream::form(const char *format, ...)
{
char buf[4096];
va_list arguments;
va_start( arguments, format );
buf[sizeof(buf)-1] = '\0';
vsnprintf( buf, sizeof(buf)-1, format, arguments );
va_end(arguments);
*this << buf;
return *this;
}
odbgstream::~odbgstream()
{
if (!output.isEmpty())
{
fprintf(stderr, "ASSERT: debug output not ended with \\n\n");
*this << "\n";
}
}
odbgstream& odbgstream::operator<<(char ch)
{
if (!print) return *this;
if (!isprint(ch))
{
output += "\\x" + QString::number( static_cast<uint>( ch ) + 0x100, 16 ).right(2);
}
else
{
output += ch;
if (ch == '\n') flush();
}
return *this;
}
odbgstream& odbgstream::operator<<( QWidget* widget )
{
QString string, temp;
// -----
if(widget==0)
{
string=(QString)"[Null pointer]";
} else
{
temp.setNum((ulong)widget, 16);
string=(QString)"["+widget->className()+" pointer " + "(0x" + temp + ")";
if(widget->name(0)==0)
{
string += " to unnamed widget, ";
} else
{
string += (QString)" to widget " + widget->name() + ", ";
}
string += "geometry="
+ QString().setNum(widget->width())
+ "x"+QString().setNum(widget->height())
+ "+"+QString().setNum(widget->x())
+ "+"+QString().setNum(widget->y())
+ "]";
}
if (!print) return *this;
output += string;
if (output.at(output.length()-1) == '\n')
{
flush();
}
return *this;
}
/*
* either use 'output' directly and do the flush if needed
* or use the QString operator which calls the char* operator
*
*/
odbgstream& odbgstream::operator<<( const QDateTime& time)
{
*this << time.toString();
return *this;
}
odbgstream& odbgstream::operator<<( const QDate& date)
{
*this << date.toString();
return *this;
}
odbgstream& odbgstream::operator<<( const QTime& time )
{
*this << time.toString();
return *this;
}
odbgstream& odbgstream::operator<<( const QPoint& p )
{
*this << "(" << p.x() << ", " << p.y() << ")";
return *this;
}
odbgstream& odbgstream::operator<<( const QSize& s )
{
*this << "[" << s.width() << "x" << s.height() << "]";
return *this;
}
odbgstream& odbgstream::operator<<( const QRect& r )
{
*this << "[" << r.left() << ", " << r.top() << " - " << r.right() << ", " << r.bottom() << "]";
return *this;
}
odbgstream& odbgstream::operator<<( const QRegion& reg )
{
*this << "[ ";
QArray<QRect>rs=reg.rects();
for (uint i=0;i<rs.size();++i)
*this << QString("[%1, %2 - %3, %4] ").arg(rs[i].left()).arg(rs[i].top()).arg(rs[i].right()).arg(rs[i].bottom() ) ;
*this <<"]";
return *this;
}
odbgstream& odbgstream::operator<<( const QStringList& l )
{
*this << "(";
*this << l.join(",");
*this << ")";
return *this;
}
odbgstream& odbgstream::operator<<( const QColor& c )
{
if ( c.isValid() )
*this << c.name();
else
*this << "(invalid/default)";
return *this;
}
odbgstream& odbgstream::operator<<( const QBrush& b)
{
static const char* const s_brushStyles[] = {
"NoBrush", "SolidPattern", "Dense1Pattern", "Dense2Pattern", "Dense3Pattern",
"Dense4Pattern", "Dense5Pattern", "Dense6Pattern", "Dense7Pattern",
"HorPattern", "VerPattern", "CrossPattern", "BDiagPattern", "FDiagPattern",
"DiagCrossPattern" };
*this <<"[ style: ";
*this <<s_brushStyles[ b.style() ];
*this <<" color: ";
// can't use operator<<(str, b.color()) because that terminates a odbgstream (flushes)
if ( b.color().isValid() )
*this <<b.color().name() ;
else
*this <<"(invalid/default)";
if ( b.pixmap() )
*this <<" has a pixmap";
*this <<" ]";
return *this;
}
QString odBacktrace( int levels )
{
QString s;
#ifndef OPIE_NO_BACKTRACE
void* trace[256];
int n = backtrace(trace, 256);
char** strings = backtrace_symbols (trace, n);
if ( levels != -1 )
n = QMIN( n, levels );
s = "[\n";
for (int i = 0; i < n; ++i)
s += QString::number(i) +
QString::fromLatin1(": ") +
QString::fromLatin1(strings[i]) + QString::fromLatin1("\n");
s += "]\n";
free (strings);
#endif
return s;
}
void odClearDebugConfig()
{
/*
delete oDebug_data->config;
oDebug_data->config = 0;
*/
}
#ifdef OPIE_NO_DEBUG
#define odDebug ondDebug
#define odBacktrace ondBacktrace
#endif
}
}