summaryrefslogtreecommitdiff
path: root/libopie2/opiecore/odebug.cpp
Unidiff
Diffstat (limited to 'libopie2/opiecore/odebug.cpp') (more/less context) (show 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 @@
1/*
2 This file is part of the Opie Project
3 (C) 2003 Michael 'Mickey' Lauer (mickey@tm.informatik.uni-frankfurt.de)
4 Inspired by the KDE debug classes, which are
5 (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
6 (C) 2002 Holger Freyther (freyther@kde.org)
7 =.
8 .=l.
9           .>+-=
10 _;:,     .>    :=|. This program is free software; you can
11.> <`_,   >  .   <= redistribute it and/or modify it under
12:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
13.="- .-=="i,     .._ License as published by the Free Software
14 - .   .-<_>     .<> Foundation; either version 2 of the License,
15     ._= =}       : or (at your option) any later version.
16    .%`+i>       _;_.
17    .i_,=:_.      -<s. This program is distributed in the hope that
18     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
19    : ..    .:,     . . . without even the implied warranty of
20    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
21  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
22..}^=.=       =       ; Library General Public License for more
23++=   -.     .`     .: details.
24 :     =  ...= . :.=-
25 -.   .:....=;==+<; You should have received a copy of the GNU
26  -_. . .   )=.  = Library General Public License along with
27    --        :-=` this library; see the file COPYING.LIB.
28 If not, write to the Free Software Foundation,
29 Inc., 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA.
31*/
32
33// Include this header without OPIE_NO_DEBUG defined to avoid having the oDebugInfo
34// functions inlined to noops (which would then conflict with their definition here).
35
36#include <opie2/odebug.h>
37
38#ifdef OPIE_NO_DEBUG
39#undef odDebug
40#undef odBacktrace
41#endif
42
43/* OPIE */
44
45#include <opie2/oapplication.h>
46#include <opie2/oglobalsettings.h>
47#include <opie2/oconfig.h>
48
49/* QT */
50
51#include <qbrush.h>
52#include <qdatetime.h>
53#include <qfile.h>
54#include <qhostaddress.h>
55#include <qmessagebox.h>
56#include <qintdict.h>
57#include <qpoint.h>
58#include <qrect.h>
59#include <qregion.h>
60#include <qsize.h>
61#include <qsocketdevice.h>
62#include <qstring.h>
63#include <qstringlist.h>
64#include <qtextstream.h>
65
66/* UNIX */
67
68#include <stdlib.h> // abort
69#include <unistd.h> // getpid
70#include <stdarg.h> // vararg stuff
71#include <ctype.h> // isprint
72#include <syslog.h>
73#include <errno.h>
74#include <string.h>
75
76#ifndef OPIE_NO_BACKTRACE
77#include <execinfo.h>
78#endif
79
80
81/*======================================================================================
82 * debug levels
83 *======================================================================================*/
84
85enum DebugLevels {
86 ODEBUG_INFO = 0,
87 ODEBUG_WARN = 1,
88 ODEBUG_ERROR = 2,
89 ODEBUG_FATAL = 3
90};
91
92/*======================================================================================
93 * oDebug private data
94 *======================================================================================*/
95
96/*======================================================================================
97 * the main debug function
98 *======================================================================================*/
99
100static void oDebugBackend( unsigned short level, unsigned int area, const char *data)
101{
102 //qDebug( "oDebugBackend: Level=%d, Area=%d, Data=%s", level, area, data );
103
104 // ML: OPIE doesn't use areacodes at the moment. See the KDE debug classes for an
105 // ML: example use. I think it's not necessary to implement such a strategy here.
106 // ML: Comments?
107
108 int priority = 0;
109 QString caption;
110 QString lev;
111 switch( level )
112 {
113 case ODEBUG_INFO: lev = "(Info)"; caption = "Info"; priority = LOG_INFO; break;
114 case ODEBUG_WARN: lev = "(Warn)"; caption = "Warning"; priority = LOG_WARNING; break;
115 case ODEBUG_FATAL: lev = "(Fatal)"; caption = "Fatal Error"; priority = LOG_CRIT; break;
116 default: qDebug( "oDebugBackend: Warning: Unknown debug level! - defaulting to ODEBUG_ERROR." );
117 case ODEBUG_ERROR: lev = "(Error)"; caption = "Error"; priority = LOG_ERR; break;
118 }
119
120 short output = OGlobalSettings::debugMode();
121 if (!oApp && (output == 1))
122 {
123 qDebug( "oDebugBackend: Warning: no oapplication object - can't use MsgBox" );
124 output = 2; // need an application object to use MsgBox
125 }
126
127 QString areaName = (oApp) ? oApp->appName() : "<unknown>";
128
129 // Output
130 switch( output )
131 {
132 case -1: // ignore
133 {
134 return;
135 }
136 case 0: // File
137 {
138 QString outputFilename = OGlobalSettings::debugOutput();
139
140 const int BUFSIZE = 4096;
141 char buf[BUFSIZE] = "";
142 buf[BUFSIZE-1] = '\0';
143 int nSize;
144
145 nSize = snprintf( buf, BUFSIZE-1, "%s: %s", (const char*) areaName, data);
146
147 QFile outputFile( outputFilename );
148 if ( outputFile.open( IO_WriteOnly | IO_Append ) )
149 {
150 if ( ( nSize == -1 ) || ( nSize >= BUFSIZE ) )
151 {
152 outputFile.writeBlock( buf, BUFSIZE-1 );
153 }
154 else
155 {
156 outputFile.writeBlock( buf, nSize );
157 }
158 }
159 else
160 {
161 qDebug( "ODebug: can't write to file '%s' (%s)", (const char*) outputFilename, strerror(errno) );
162 }
163 break;
164 } // automatic close of file here
165
166 case 1: // Message Box
167 {
168 // Since we are in opiecore here, we cannot use OMsgBox and use
169 // QMessageBox instead
170
171 caption += QString("(") + areaName + ")";
172 QMessageBox::warning( 0L, caption, data, ("&OK") ); // tr?
173 break;
174 }
175
176 case 2: // Shell
177 {
178 FILE *output = stderr;
179 fprintf( output, "%s: ", (const char*) areaName );
180 fputs( data, output);
181 break;
182 }
183
184 case 3: // syslog
185 {
186 syslog( priority, "%s", data);
187 break;
188 }
189
190 case 4: // socket
191 {
192 QString destination = OGlobalSettings::debugOutput();
193 if ( destination && destination.find(":") != -1 )
194 {
195 QString host = destination.left( destination.find(":") );
196 QString port = destination.right( destination.length()-host.length()-1 );
197 QHostAddress addr;
198 addr.setAddress( host );
199 // TODO: sanity check the address
200 QString line;
201 line.sprintf( "%s: %s", (const char*) areaName, (const char*) data );
202 QSocketDevice s( QSocketDevice::Datagram );
203 int result = s.writeBlock( (const char*) line, line.length(), addr, port.toInt() );
204 if ( result == -1 )
205 {
206 qDebug( "ODebug: can't send to address '%s:%d' (%s)", (const char*) host, port.toInt(), strerror(errno) );
207 }
208 }
209 break;
210 }
211 }
212
213 // check if we should abort
214
215 /*
216
217 if( ( nLevel == ODEBUG_FATAL )
218 && ( !oDebug_data->config || oDebug_data->config->readNumEntry( "AbortFatal", 1 ) ) )
219 abort();
220
221 */
222}
223
224/*======================================================================================
225 * odbgstream
226 *======================================================================================*/
227
228odbgstream& perror( odbgstream &s)
229{
230 return s << QString::fromLocal8Bit(strerror(errno));
231}
232
233odbgstream odDebug(int area)
234{
235 return odbgstream(area, ODEBUG_INFO);
236}
237odbgstream odDebug(bool cond, int area)
238{
239 if (cond) return odbgstream(area, ODEBUG_INFO);
240 else return odbgstream(0, 0, false);
241}
242
243odbgstream odError(int area)
244{
245 return odbgstream("ERROR: ", area, ODEBUG_ERROR);
246}
247
248odbgstream odError(bool cond, int area)
249{
250 if (cond) return odbgstream("ERROR: ", area, ODEBUG_ERROR); else return odbgstream(0,0,false);
251}
252
253odbgstream odWarning(int area)
254{
255 return odbgstream("WARNING: ", area, ODEBUG_WARN);
256}
257
258odbgstream odWarning(bool cond, int area)
259{
260 if (cond) return odbgstream("WARNING: ", area, ODEBUG_WARN); else return odbgstream(0,0,false);
261}
262
263odbgstream odFatal(int area)
264{
265 return odbgstream("FATAL: ", area, ODEBUG_FATAL);
266}
267
268odbgstream odFatal(bool cond, int area)
269{
270 if (cond) return odbgstream("FATAL: ", area, ODEBUG_FATAL); else return odbgstream(0,0,false);
271}
272
273odbgstream::odbgstream(unsigned int _area, unsigned int _level, bool _print)
274 :area(_area), level(_level), print(_print)
275{
276}
277
278
279odbgstream::odbgstream(const char * initialString, unsigned int _area, unsigned int _level, bool _print)
280 :output(QString::fromLatin1(initialString)), area(_area), level(_level), print(_print)
281{
282}
283
284
285odbgstream::odbgstream(odbgstream &str)
286 :output(str.output), area(str.area), level(str.level), print(str.print)
287{
288 str.output.truncate(0);
289}
290
291
292odbgstream::odbgstream(const odbgstream &str)
293 :output(str.output), area(str.area), level(str.level), print(str.print)
294{
295}
296
297odbgstream& odbgstream::operator<<(bool i)
298{
299 if (!print) return *this;
300 output += QString::fromLatin1(i ? "true" : "false");
301 return *this;
302}
303
304
305odbgstream& odbgstream::operator<<(short i)
306{
307 if (!print) return *this;
308 QString tmp; tmp.setNum(i); output += tmp;
309 return *this;
310}
311
312
313odbgstream& odbgstream::operator<<(unsigned short i)
314{
315 if (!print) return *this;
316 QString tmp; tmp.setNum(i); output += tmp;
317 return *this;
318}
319
320
321odbgstream& odbgstream::operator<<(unsigned char i)
322{
323 return operator<<( static_cast<char>( i ) );
324}
325
326
327odbgstream& odbgstream::operator<<(int i)
328{
329 if (!print) return *this;
330 QString tmp; tmp.setNum(i); output += tmp;
331 return *this;
332}
333
334
335odbgstream& odbgstream::operator<<(unsigned int i)
336{
337 if (!print) return *this;
338 QString tmp; tmp.setNum(i); output += tmp;
339 return *this;
340}
341
342
343odbgstream& odbgstream::operator<<(long i)
344{
345 if (!print) return *this;
346 QString tmp; tmp.setNum(i); output += tmp;
347 return *this;
348}
349
350
351odbgstream& odbgstream::operator<<(unsigned long i)
352{
353 if (!print) return *this;
354 QString tmp; tmp.setNum(i); output += tmp;
355 return *this;
356}
357
358
359odbgstream& odbgstream::operator<<(const QString& string)
360{
361 if (!print) return *this;
362 output += string;
363 if (output.at(output.length() -1 ) == '\n')
364 flush();
365 return *this;
366}
367
368
369odbgstream& odbgstream::operator<<(const char *string)
370{
371 if (!print) return *this;
372 output += QString::fromUtf8(string);
373 if (output.at(output.length() - 1) == '\n')
374 flush();
375 return *this;
376}
377
378
379odbgstream& odbgstream::operator<<(const QCString& string)
380{
381 *this << string.data();
382 return *this;
383}
384
385
386odbgstream& odbgstream::operator<<(const void * p)
387{
388 form("%p", p);
389 return *this;
390}
391
392odbgstream& odbgstream::operator<<(double d)
393{
394 QString tmp; tmp.setNum(d); output += tmp;
395 return *this;
396}
397
398/*
399odbgstream::odbgstream &form(const char *format, ...)
400#ifdef __GNUC__
401 __attribute__ ( ( format ( printf, 2, 3 ) ) )
402#endif
403 ;
404*/
405
406void odbgstream::flush()
407{
408 if ( output.isEmpty() || !print )
409 {
410 return;
411 }
412 else
413 {
414 oDebugBackend( level, area, output.local8Bit().data() );
415 output = QString::null;
416 }
417}
418
419odbgstream& odbgstream::form(const char *format, ...)
420{
421 char buf[4096];
422 va_list arguments;
423 va_start( arguments, format );
424 buf[sizeof(buf)-1] = '\0';
425 vsnprintf( buf, sizeof(buf)-1, format, arguments );
426 va_end(arguments);
427 *this << buf;
428 return *this;
429}
430
431odbgstream::~odbgstream()
432{
433 if (!output.isEmpty())
434 {
435 fprintf(stderr, "ASSERT: debug output not ended with \\n\n");
436 *this << "\n";
437 }
438}
439
440odbgstream& odbgstream::operator<<(char ch)
441{
442 if (!print) return *this;
443 if (!isprint(ch))
444 {
445 output += "\\x" + QString::number( static_cast<uint>( ch ) + 0x100, 16 ).right(2);
446 }
447 else
448 {
449 output += ch;
450 if (ch == '\n') flush();
451 }
452 return *this;
453}
454
455odbgstream& odbgstream::operator<<( QWidget* widget )
456{
457 QString string, temp;
458 // -----
459 if(widget==0)
460 {
461 string=(QString)"[Null pointer]";
462 } else
463 {
464 temp.setNum((ulong)widget, 16);
465 string=(QString)"["+widget->className()+" pointer " + "(0x" + temp + ")";
466 if(widget->name(0)==0)
467 {
468 string += " to unnamed widget, ";
469 } else
470 {
471 string += (QString)" to widget " + widget->name() + ", ";
472 }
473 string += "geometry="
474 + QString().setNum(widget->width())
475 + "x"+QString().setNum(widget->height())
476 + "+"+QString().setNum(widget->x())
477 + "+"+QString().setNum(widget->y())
478 + "]";
479 }
480 if (!print) return *this;
481
482 output += string;
483 if (output.at(output.length()-1) == '\n')
484 {
485 flush();
486 }
487 return *this;
488}
489
490/*
491 * either use 'output' directly and do the flush if needed
492 * or use the QString operator which calls the char* operator
493 *
494 */
495odbgstream& odbgstream::operator<<( const QDateTime& time)
496{
497 *this << time.toString();
498 return *this;
499}
500
501
502odbgstream& odbgstream::operator<<( const QDate& date)
503{
504 *this << date.toString();
505
506 return *this;
507}
508
509
510odbgstream& odbgstream::operator<<( const QTime& time )
511{
512 *this << time.toString();
513 return *this;
514}
515
516
517odbgstream& odbgstream::operator<<( const QPoint& p )
518{
519 *this << "(" << p.x() << ", " << p.y() << ")";
520 return *this;
521}
522
523
524odbgstream& odbgstream::operator<<( const QSize& s )
525{
526 *this << "[" << s.width() << "x" << s.height() << "]";
527 return *this;
528}
529
530
531odbgstream& odbgstream::operator<<( const QRect& r )
532{
533 *this << "[" << r.left() << ", " << r.top() << " - " << r.right() << ", " << r.bottom() << "]";
534 return *this;
535}
536
537
538odbgstream& odbgstream::operator<<( const QRegion& reg )
539{
540 /* Qt2 doesn't have a QMemArray... :(
541 *this << "[ ";
542 QMemArray<QRect>rs=reg.rects();
543 for (uint i=0;i<rs.size();++i)
544 *this << QString("[%1, %2 - %3, %4] ").arg(rs[i].left()).arg(rs[i].top()).arg(rs[i].right()).arg(rs[i].bottom() ) ;
545 *this <<"]";
546 */
547 return *this;
548}
549
550
551odbgstream& odbgstream::operator<<( const QStringList& l )
552{
553 *this << "(";
554 *this << l.join(",");
555 *this << ")";
556
557 return *this;
558}
559
560
561odbgstream& odbgstream::operator<<( const QColor& c )
562{
563 if ( c.isValid() )
564 *this << c.name();
565 else
566 *this << "(invalid/default)";
567 return *this;
568}
569
570
571odbgstream& odbgstream::operator<<( const QBrush& b)
572{
573 static const char* const s_brushStyles[] = {
574 "NoBrush", "SolidPattern", "Dense1Pattern", "Dense2Pattern", "Dense3Pattern",
575 "Dense4Pattern", "Dense5Pattern", "Dense6Pattern", "Dense7Pattern",
576 "HorPattern", "VerPattern", "CrossPattern", "BDiagPattern", "FDiagPattern",
577 "DiagCrossPattern" };
578
579 *this <<"[ style: ";
580 *this <<s_brushStyles[ b.style() ];
581 *this <<" color: ";
582 // can't use operator<<(str, b.color()) because that terminates a odbgstream (flushes)
583 if ( b.color().isValid() )
584 *this <<b.color().name() ;
585 else
586 *this <<"(invalid/default)";
587 if ( b.pixmap() )
588 *this <<" has a pixmap";
589 *this <<" ]";
590 return *this;
591}
592
593
594
595QString odBacktrace( int levels )
596{
597 QString s;
598#ifndef OPIE_NO_BACKTRACE
599 void* trace[256];
600 int n = backtrace(trace, 256);
601 char** strings = backtrace_symbols (trace, n);
602
603 if ( levels != -1 )
604 n = QMIN( n, levels );
605 s = "[\n";
606
607 for (int i = 0; i < n; ++i)
608 s += QString::number(i) +
609 QString::fromLatin1(": ") +
610 QString::fromLatin1(strings[i]) + QString::fromLatin1("\n");
611 s += "]\n";
612 free (strings);
613#endif
614 return s;
615}
616
617void odClearDebugConfig()
618{
619 /*
620 delete oDebug_data->config;
621 oDebug_data->config = 0;
622 */
623}
624
625#ifdef OPIE_NO_DEBUG
626#define odDebug ondDebug
627#define odBacktrace ondBacktrace
628#endif