summaryrefslogtreecommitdiff
path: root/libopie2/opiecore/odebug.cpp
authormickeyl <mickeyl>2003-03-28 15:11:52 (UTC)
committer mickeyl <mickeyl>2003-03-28 15:11:52 (UTC)
commit11304d02942e9fa493e4e80943a828f9c65f6772 (patch) (side-by-side diff)
treea0223c10c067e1afc70d15c2b82be3f3c15e41ae /libopie2/opiecore/odebug.cpp
parentb271d575fa05cf570a1a829136517761bd47e69b (diff)
downloadopie-11304d02942e9fa493e4e80943a828f9c65f6772.zip
opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.gz
opie-11304d02942e9fa493e4e80943a828f9c65f6772.tar.bz2
skeleton and the start of libopie2, please read README, ROADMAP and STATUS and comment...
Diffstat (limited to 'libopie2/opiecore/odebug.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/odebug.cpp628
1 files changed, 628 insertions, 0 deletions
diff --git a/libopie2/opiecore/odebug.cpp b/libopie2/opiecore/odebug.cpp
new file mode 100644
index 0000000..b4eaf2d
--- a/dev/null
+++ b/libopie2/opiecore/odebug.cpp
@@ -0,0 +1,628 @@
+/*
+ This file is part of the Opie Project
+ (C) 2003 Michael 'Mickey' Lauer (mickey@tm.informatik.uni-frankfurt.de)
+ Inspired by the KDE debug classes, which are
+ (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+ (C) 2002 Holger Freyther (freyther@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>
+
+#ifdef OPIE_NO_DEBUG
+#undef odDebug
+#undef odBacktrace
+#endif
+
+/* OPIE */
+
+#include <opie2/oapplication.h>
+#include <opie2/oglobalsettings.h>
+#include <opie2/oconfig.h>
+
+/* QT */
+
+#include <qbrush.h>
+#include <qdatetime.h>
+#include <qfile.h>
+#include <qhostaddress.h>
+#include <qmessagebox.h>
+#include <qintdict.h>
+#include <qpoint.h>
+#include <qrect.h>
+#include <qregion.h>
+#include <qsize.h>
+#include <qsocketdevice.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextstream.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
+
+
+/*======================================================================================
+ * debug levels
+ *======================================================================================*/
+
+enum DebugLevels {
+ ODEBUG_INFO = 0,
+ ODEBUG_WARN = 1,
+ ODEBUG_ERROR = 2,
+ ODEBUG_FATAL = 3
+};
+
+/*======================================================================================
+ * oDebug private data
+ *======================================================================================*/
+
+/*======================================================================================
+ * the main debug function
+ *======================================================================================*/
+
+static void oDebugBackend( unsigned short level, unsigned int area, const char *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;
+ }
+
+ short output = OGlobalSettings::debugMode();
+ if (!oApp && (output == 1))
+ {
+ qDebug( "oDebugBackend: Warning: no oapplication object - can't use MsgBox" );
+ output = 2; // need an application object to use MsgBox
+ }
+
+ QString areaName = (oApp) ? oApp->appName() : "<unknown>";
+
+ // Output
+ switch( output )
+ {
+ case -1: // ignore
+ {
+ return;
+ }
+ case 0: // File
+ {
+ QString outputFilename = OGlobalSettings::debugOutput();
+
+ const int BUFSIZE = 4096;
+ char buf[BUFSIZE] = "";
+ buf[BUFSIZE-1] = '\0';
+ int nSize;
+
+ nSize = snprintf( buf, BUFSIZE-1, "%s: %s", (const char*) areaName, data);
+
+ QFile outputFile( outputFilename );
+ if ( outputFile.open( IO_WriteOnly | IO_Append ) )
+ {
+ if ( ( nSize == -1 ) || ( nSize >= BUFSIZE ) )
+ {
+ outputFile.writeBlock( buf, BUFSIZE-1 );
+ }
+ else
+ {
+ outputFile.writeBlock( buf, nSize );
+ }
+ }
+ else
+ {
+ qDebug( "ODebug: can't write to file '%s' (%s)", (const char*) outputFilename, strerror(errno) );
+ }
+ break;
+ } // automatic close of file here
+
+ case 1: // Message Box
+ {
+ // Since we are in opiecore here, we cannot use OMsgBox and use
+ // QMessageBox instead
+
+ caption += QString("(") + areaName + ")";
+ QMessageBox::warning( 0L, caption, data, ("&OK") ); // tr?
+ break;
+ }
+
+ case 2: // Shell
+ {
+ FILE *output = stderr;
+ fprintf( output, "%s: ", (const char*) areaName );
+ fputs( data, output);
+ break;
+ }
+
+ case 3: // syslog
+ {
+ syslog( priority, "%s", data);
+ break;
+ }
+
+ case 4: // socket
+ {
+ QString destination = OGlobalSettings::debugOutput();
+ if ( destination && destination.find(":") != -1 )
+ {
+ QString host = destination.left( destination.find(":") );
+ QString port = destination.right( destination.length()-host.length()-1 );
+ QHostAddress addr;
+ addr.setAddress( host );
+ // TODO: sanity check the address
+ QString line;
+ line.sprintf( "%s: %s", (const char*) areaName, (const char*) data );
+ QSocketDevice s( QSocketDevice::Datagram );
+ int result = s.writeBlock( (const char*) line, line.length(), addr, port.toInt() );
+ if ( result == -1 )
+ {
+ qDebug( "ODebug: can't send to address '%s:%d' (%s)", (const char*) host, port.toInt(), strerror(errno) );
+ }
+ }
+ break;
+ }
+ }
+
+ // check if we should abort
+
+ /*
+
+ if( ( nLevel == ODEBUG_FATAL )
+ && ( !oDebug_data->config || oDebug_data->config->readNumEntry( "AbortFatal", 1 ) ) )
+ abort();
+
+ */
+}
+
+/*======================================================================================
+ * odbgstream
+ *======================================================================================*/
+
+odbgstream& perror( odbgstream &s)
+{
+ return s << QString::fromLocal8Bit(strerror(errno));
+}
+
+odbgstream odDebug(int area)
+{
+ return odbgstream(area, ODEBUG_INFO);
+}
+odbgstream odDebug(bool cond, int area)
+{
+ if (cond) return odbgstream(area, ODEBUG_INFO);
+ else return odbgstream(0, 0, false);
+}
+
+odbgstream odError(int area)
+{
+ return odbgstream("ERROR: ", area, ODEBUG_ERROR);
+}
+
+odbgstream odError(bool cond, int area)
+{
+ if (cond) return odbgstream("ERROR: ", area, ODEBUG_ERROR); else return odbgstream(0,0,false);
+}
+
+odbgstream odWarning(int area)
+{
+ return odbgstream("WARNING: ", area, ODEBUG_WARN);
+}
+
+odbgstream odWarning(bool cond, int area)
+{
+ if (cond) return odbgstream("WARNING: ", area, ODEBUG_WARN); else return odbgstream(0,0,false);
+}
+
+odbgstream odFatal(int area)
+{
+ return odbgstream("FATAL: ", area, ODEBUG_FATAL);
+}
+
+odbgstream odFatal(bool cond, int area)
+{
+ if (cond) return odbgstream("FATAL: ", area, 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
+ {
+ oDebugBackend( level, area, output.local8Bit().data() );
+ 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 )
+{
+ /* Qt2 doesn't have a QMemArray... :(
+ *this << "[ ";
+ QMemArray<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