This is the reworked debug stream.

Unless I get objections, this will go into CVS rather soon.

? debug-1.diff
Index: po/POTFILES.in
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/po/POTFILES.in,v
retrieving revision 1.354
diff -u -p -r1.354 POTFILES.in
--- po/POTFILES.in	21 Sep 2003 16:02:52 -0000	1.354
+++ po/POTFILES.in	26 Sep 2003 12:37:01 -0000
@@ -185,6 +185,7 @@ src/mathed/ref_inset.C
 src/paragraph.C
 src/paragraph_funcs.C
 src/rowpainter.C
+src/support/path_defines.C
 src/text.C
 src/text2.C
 src/text3.C
Index: src/debug.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/debug.C,v
retrieving revision 1.37
diff -u -p -r1.37 debug.C
--- src/debug.C	9 Sep 2003 22:13:23 -0000	1.37
+++ src/debug.C	26 Sep 2003 12:37:01 -0000
@@ -16,6 +16,7 @@
 
 #include "support/lstrings.h"
 
+#include <iostream>
 #include <iomanip>
 
 using lyx::support::ascii_lowercase;
@@ -71,16 +72,7 @@ int const numErrorTags = sizeof(errorTag
 } // namespace anon
 
 
-Debug::type const Debug::ANY = Debug::type(
-	Debug::INFO | Debug::INIT | Debug::KEY | Debug::GUI |
-	Debug::PARSER | Debug::LYXRC | Debug::KBMAP | Debug::LATEX |
-	Debug::MATHED | Debug::FONT | Debug::TCLASS | Debug::LYXVC |
-	Debug::LYXSERVER | Debug::ROFF | Debug::ACTION | Debug::LYXLEX |
-	Debug::DEPEND | Debug::INSETS | Debug::FILES | Debug::WORKAREA |
-	Debug::INSETTEXT | Debug::GRAPHICS | Debug::CHANGES | Debug::EXTERNAL);
-
-
-Debug::type Debug::value(string const & val)
+lyx_debug_trait::type lyx_debug_trait::value(string const & val)
 {
 	type l = Debug::NONE;
 	string v(val);
@@ -106,7 +98,7 @@ Debug::type Debug::value(string const & 
 }
 
 
-void Debug::showLevel(ostream & os, Debug::type level)
+void lyx_debug_trait::showLevel(ostream & os, lyx_debug_trait::type level)
 {
 	// Show what features are traced
 	for (int i = 0; i < numErrorTags ; ++i) {
@@ -122,7 +114,7 @@ void Debug::showLevel(ostream & os, Debu
 }
 
 
-void Debug::showTags(ostream & os)
+void lyx_debug_trait::showTags(ostream & os)
 {
 	for (int i = 0; i < numErrorTags ; ++i)
 		os << setw(7) << errorTags[i].level
@@ -130,3 +122,5 @@ void Debug::showTags(ostream & os)
 		   << "  " << _(errorTags[i].desc) << '\n';
 	os.flush();
 }
+
+LyXErr lyxerr(std::cerr.rdbuf());
Index: src/debug.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/debug.h,v
retrieving revision 1.33
diff -u -p -r1.33 debug.h
--- src/debug.h	7 Sep 2003 21:25:33 -0000	1.33
+++ src/debug.h	26 Sep 2003 12:37:01 -0000
@@ -15,12 +15,13 @@
 
 
 #include "support/std_string.h"
+#include "support/debugstream.h"
 
 /** Ideally this should have been a namespace, but since we try to be
     compilable on older C++ compilators too, we use a struct instead.
     This is all the different debug levels that we have.
 */
-struct Debug {
+struct lyx_debug_trait {
 	///
 	enum type {
 		///
@@ -72,15 +73,19 @@ struct Debug {
 		/// change tracking
 		CHANGES    = (1 << 22),
 		///
-		EXTERNAL   = (1 << 23)
+		EXTERNAL   = (1 << 23),
+		///
+		ANY = 0xffffff
 	};
-	///
-	static type const ANY;
+
+	static bool match(type a, type b) {
+		return (a & b);
+	}
 
 	/** A function to convert symbolic string names on debug levels
 	    to their numerical value.
 	*/
-	static Debug::type value(string const & val);
+	static type value(string const & val);
 
 	/** Display the tags and descriptions of the current debug level
 	    of ds
@@ -95,18 +100,17 @@ struct Debug {
 
 
 inline
-void operator|=(Debug::type & d1, Debug::type d2)
+void operator|=(lyx_debug_trait::type & d1, lyx_debug_trait::type d2)
 {
-	d1 = static_cast<Debug::type>(d1 | d2);
+	d1 = static_cast<lyx_debug_trait::type>(d1 | d2);
 }
 
 
-#include "support/DebugStream.h"
-
-
+// std::ostream & operator<<(std::ostream & o, Debug::type t);
 
-std::ostream & operator<<(std::ostream & o, Debug::type t);
+typedef basic_debugstream<lyx_debug_trait> LyXErr;
+typedef LyXErr::debug Debug;
 
-extern DebugStream lyxerr;
+extern LyXErr lyxerr;
 
 #endif
Index: src/lyx_main.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyx_main.C,v
retrieving revision 1.176
diff -u -p -r1.176 lyx_main.C
--- src/lyx_main.C	21 Sep 2003 23:00:44 -0000	1.176
+++ src/lyx_main.C	26 Sep 2003 12:37:01 -0000
@@ -87,8 +87,6 @@ extern void QuitLyX();
 
 extern LyXServer * lyxserver;
 
-DebugStream lyxerr;
-
 boost::scoped_ptr<LastFiles> lastfiles;
 
 // This is the global bufferlist object
Index: src/support/DebugStream.C
===================================================================
RCS file: src/support/DebugStream.C
diff -N src/support/DebugStream.C
--- src/support/DebugStream.C	23 Aug 2003 00:16:56 -0000	1.17
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,299 +0,0 @@
-/**
- * \file DebugStream.C
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-//#define TEST_DEBUGSTREAM
-
-#include <config.h>
-
-//#include "DebugStream.h"
-#include "debug.h"
-
-// Since the current C++ lib in egcs does not have a standard implementation
-// of basic_streambuf and basic_filebuf we don't have to include this
-// header.
-//#define MODERN_STL_STREAMS
-#ifdef MODERN_STL_STREAMS
-#include <fstream>
-#endif
-#include <iostream>
-
-using std::ostream;
-using std::streambuf;
-using std::streamsize;
-using std::filebuf;
-using std::cerr;
-using std::ios;
-
-ostream & operator<<(ostream & o, Debug::type t)
-{
-	return o << int(t);
-}
-
-/** This is a streambuffer that never prints out anything, at least
-    that is the intention. You can call it a no-op streambuffer, and
-    the ostream that uses it will be a no-op stream.
-*/
-class nullbuf : public streambuf {
-protected:
-#ifndef MODERN_STL_STREAMS
-	typedef char char_type;
-	typedef int int_type;
-	///
-	virtual int sync() { return 0; }
-#endif
-	///
-	virtual streamsize xsputn(char_type const *, streamsize n) {
-		// fakes a purge of the buffer by returning n
-		return n;
-	}
-#ifdef MODERN_STL_STREAMS
-	///
-	virtual int_type overflow(int_type c = traits_type::eof()) {
-		// fakes success by returning c
-		return c == traits_type::eof() ? ' ' : c;
-	}
-#else
-	///
-	virtual int_type overflow(int_type c = EOF) {
-		// fakes success by returning c
-		return c == EOF ? ' ' : c;
-	}
-#endif
-};
-
-/** A streambuf that sends the output to two different streambufs. These
-    can be any kind of streambufs.
-*/
-class teebuf : public streambuf {
-public:
-	///
-	teebuf(streambuf * b1, streambuf * b2)
-		: streambuf(), sb1(b1), sb2(b2) {}
-protected:
-#ifdef MODERN_STL_STREAMS
-	///
-	virtual int sync() {
-		sb2->pubsync();
-		return sb1->pubsync();
-	}
-	///
-	virtual streamsize xsputn(char_type const * p, streamsize n) {
-		sb2->sputn(p, n);
-		return sb1->sputn(p, n);
-	}
-	///
-	virtual int_type overflow(int_type c = traits_type::eof()) {
-		sb2->sputc(c);
-		return sb1->sputc(c);
-	}
-#else
-	typedef char char_type;
-	typedef int int_type;
-	///
-	virtual int sync() {
-		sb2->sync();
-		return sb1->sync();
-	}
-	///
-	virtual streamsize xsputn(char_type const * p, streamsize n) {
-		sb2->xsputn(p, n);
-		return sb1->xsputn(p, n);
-	}
-	///
-	virtual int_type overflow(int_type c = EOF) {
-		sb2->overflow(c);
-		return sb1->overflow(c);
-	}
-#endif
-private:
-	///
-	streambuf * sb1;
-	///
-	streambuf * sb2;
-};
-
-///
-class debugbuf : public streambuf {
-public:
-	///
-	debugbuf(streambuf * b)
-		: streambuf(), sb(b) {}
-protected:
-#ifdef MODERN_STL_STREAMS
-	///
-	virtual int sync() {
-		return sb->pubsync();
-	}
-	///
-	virtual streamsize xsputn(char_type const * p, streamsize n) {
-		return sb->sputn(p, n);
-	}
-	///
-	virtual int_type overflow(int_type c = traits_type::eof()) {
-		return sb->sputc(c);
-	}
-#else
-	typedef char char_type;
-	typedef int int_type;
-	///
-	virtual int sync() {
-		return sb->sync();
-	}
-	///
-	virtual streamsize xsputn(char_type const * p, streamsize n) {
-		return sb->xsputn(p, n);
-	}
-	///
-	virtual int_type overflow(int_type c = EOF) {
-		return sb->overflow(c);
-	}
-#endif
-private:
-	///
-	streambuf * sb;
-};
-
-
-/// So that public parts of DebugStream does not need to know about filebuf
-struct DebugStream::debugstream_internal {
-	/// Used when logging to file.
-	filebuf fbuf;
-};
-
-
-/// Constructor, sets the debug level to t.
-DebugStream::DebugStream(Debug::type t)
-	: ostream(new debugbuf(cerr.rdbuf())),
-	  dt(t), nullstream(new nullbuf), internal(0) {}
-
-
-/// Constructor, sets the log file to f, and the debug level to t.
-DebugStream::DebugStream(char const * f, Debug::type t)
-	: ostream(new debugbuf(cerr.rdbuf())),
-	  dt(t), nullstream(new nullbuf),
-	  internal(new debugstream_internal)
-{
-	internal->fbuf.open(f, ios::out|ios::app);
-	delete rdbuf(new teebuf(cerr.rdbuf(),
-				&internal->fbuf));
-}
-
-
-DebugStream::~DebugStream()
-{
-	delete nullstream.rdbuf(0); // Without this we leak
-	delete rdbuf(0);            // Without this we leak
-	delete internal;
-}
-
-
-/// Sets the debugstreams' logfile to f.
-void DebugStream::logFile(char const * f)
-{
-	if (internal) {
-		internal->fbuf.close();
-	} else {
-		internal = new debugstream_internal;
-	}
-	internal->fbuf.open(f, ios::out|ios::app);
-	delete rdbuf(new teebuf(cerr.rdbuf(),
-				&internal->fbuf));
-}
-
-
-#ifdef TEST_DEBUGSTREAM
-
-// Example debug stream
-DebugStream debugstream;
-
-int main(int, char **)
-{
-	/**
-	   I have been running some tests on this to see how much overhead
-	   this kind of permanent debug code has. My conclusion is: not
-	   much. In all, but the most time critical code, this will have
-	   close to no impact at all.
-
-	   In the tests that I have run the use of
-	   if (debugstream.debugging(DebugStream::INFO))
-	   debugstream << "some debug\n";
-	   has close to no overhead when the debug level is not
-	   DebugStream::INFO.
-
-	   The overhead for
-	   debugstream.debug(DebugStream::INFO) << "some debug\n";
-	   is also very small when the debug level is not
-	   DebugStream::INFO. However the overhead for this will increase
-	   if complex debugging information is output.
-
-	   The overhead when the debug level is DebugStream::INFO can be
-	   significant, but since we then are running in debug mode it is
-	   of no concern.
-
-	   Why should we use this instead of the class Error that we already
-	   have? First of all it uses C++ iostream and constructs, secondly
-	   it will be a lot easier to output the debug info that we need
-	   without a lot of manual conversions, thirdly we can now use
-	   iomanipulators and the complete iostream formatting functions.
-	   pluss it will work for all types that have a operator<<
-	   defined, and can be used in functors that take a ostream & as
-	   parameter. And there should be less need for temporary objects.
-	   And one nice bonus is that we get a log file almost for
-	   free.
-
-	   Some of the names are of course open to modifications. I will try
-	   to use the names we already use in LyX.
-	*/
-	// Just a few simple debugs to show how it can work.
-	debugstream << "Debug level set to Debug::NONE\n";
-	if (debugstream.debugging()) {
-		debugstream << "Something must be debugged\n";
-	}
-	debugstream.debug(Debug::WARN) << "more debug(WARN)\n";
-	debugstream.debug(Debug::INFO) << "even more debug(INFO)\n";
-	debugstream.debug(Debug::CRIT) << "even more debug(CRIT)\n";
-	debugstream.level(Debug::value("INFO"));
-	debugstream << "Setting debug level to Debug::INFO\n";
-	if (debugstream.debugging()) {
-		debugstream << "Something must be debugged\n";
-	}
-	debugstream.debug(Debug::WARN) << "more debug(WARN)\n";
-	debugstream.debug(Debug::INFO) << "even more debug(INFO)\n";
-	debugstream.debug(Debug::CRIT) << "even more debug(CRIT)\n";
-	debugstream.addLevel(Debug::type(Debug::CRIT |
-					 Debug::WARN));
-	debugstream << "Adding Debug::CRIT and Debug::WARN\n";
-	debugstream[Debug::WARN] << "more debug(WARN)\n";
-	debugstream[Debug::INFO] << "even more debug(INFO)\n";
-	debugstream[Debug::CRIT] << "even more debug(CRIT)\n";
-	debugstream.delLevel(Debug::INFO);
-	debugstream << "Removing Debug::INFO\n";
-	debugstream[Debug::WARN] << "more debug(WARN)\n";
-	debugstream[Debug::INFO] << "even more debug(INFO)\n";
-	debugstream[Debug::CRIT] << "even more debug(CRIT)\n";
-	debugstream.logFile("logfile");
-	debugstream << "Setting logfile to \"logfile\"\n";
-	debugstream << "Value: " << 123 << " " << "12\n";
-	int i = 0;
-	int * p = new int;
-	// note: the (void*) is needed on g++ 2.7.x since it does not
-	// support partial specialization. In egcs this should not be
-	// needed.
-	debugstream << "automatic " << &i
-		    << ", free store " << p << endl;
-	delete p;
-	/*
-	for (int j = 0; j < 200000; ++j) {
-		DebugStream tmp;
-		tmp << "Test" << endl;
-	}
-	*/
-}
-#endif
Index: src/support/DebugStream.h
===================================================================
RCS file: src/support/DebugStream.h
diff -N src/support/DebugStream.h
--- src/support/DebugStream.h	5 Sep 2003 17:23:10 -0000	1.22
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,145 +0,0 @@
-// -*- C++ -*-
-/**
- * \file DebugStream.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Lars Gullik Bjønnes
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#ifndef DEBUGSTREAM_H
-#define DEBUGSTREAM_H
-
-#include "std_ostream.h"
-
-#ifdef TEST_DEBUGSTREAM
-#include <string>
-struct Debug {
-	enum type {
-		NONE = 0,
-		INFO       = (1 << 0),   // 1
-		WARN       = (1 << 1),   // 2
-		CRIT       = (1 << 2)   // 4
-	};
-	static const type ANY = type(INFO | WARN | CRIT);
-	static Debug::type value(string const & val) {
-		if (val == "NONE") return Debug::NONE;
-		if (val == "INFO") return Debug::INFO;
-		if (val == "WARN") return Debug::WARN;
-		if (val == "CRIT") return Debug::CRIT;
-		return Debug::NONE;
-	}
-};
-#endif
-
-/** DebugStream is a ostream intended for debug output.
-    It has also support for a logfile. Debug output is output to cerr
-    and if the logfile is set, to the logfile.
-
-    Example of Usage:
-    DebugStream debug;
-    debug.level(Debug::INFO);
-    debug.debug(Debug::WARN) << "WARN\n";
-    debug[Debug::INFO] << "INFO\n";
-    debug << "Always\n";
-
-    Will output:
-    INFO
-    Always
-
-    If you want to have debug output from time critical code you should
-    use this construct:
-    if (debug.debugging(Debug::INFO)) {
-	 debug << "...debug output...\n";
-    }
-
-    To give debug info even if no debug (NONE) is requested:
-    debug << "... always output ...\n";
-
-    To give debug output regardless of what debug level is set (!NONE):
-    debug.debug() << "...on debug output...\n";
-    debug[Debug::ANY] << "...on debug output...\n";
-
-    To give debug output when a specific debug level is set (INFO):
-    debug.debug(Debug::INFO) << "...info...\n";
-    debug[Debug::INFO] << "...info...\n";
-
-    To give debug output when either on of debug levels is set (INFO or CRIT):
-    debug.debug(Debug::type(Debug::INFO | Debug::CRIT)) << "...info/crit...\n";
-    debug[Debug::type(Debug::INFO | Debug::CRIT)] << "...info/crit...\n";
-
-*/
-class DebugStream : public std::ostream
-{
-public:
-	/// Constructor, sets the debug level to t.
-	explicit DebugStream(Debug::type t = Debug::NONE);
-
-	/// Constructor, sets the log file to f, and the debug level to t.
-	explicit
-	DebugStream(char const * f, Debug::type t = Debug::NONE);
-
-	///
-	~DebugStream();
-
-	/// Sets the debug level to t.
-	void level(Debug::type t) {
-		dt = Debug::type(t & Debug::ANY);
-	}
-
-	/// Returns the current debug level.
-	Debug::type level() const {
-		return dt;
-	}
-
-	/// Adds t to the current debug level.
-	void addLevel(Debug::type t) {
-		dt = Debug::type(dt | t);
-	}
-
-	/// Deletes t from the current debug level.
-	void delLevel(Debug::type t) {
-		dt = Debug::type(dt & ~t);
-	}
-
-	/// Sets the debugstreams' logfile to f.
-	void logFile(char const * f);
-
-	/// Returns true if t is part of the current debug level.
-	bool debugging(Debug::type t = Debug::ANY) const
-	{
-		if (dt & t) return true;
-		return false;
-	}
-
-
-	/** Returns the no-op stream if t is not part of the
-	    current debug level otherwise the real debug stream
-	    is used.
-	*/
-	std::ostream & debug(Debug::type t = Debug::ANY) {
-		if (dt & t) return *this;
-		return nullstream;
-	}
-
-
-	/** This is an operator to give a more convenient use:
-	    dbgstream[Debug::INFO] << "Info!\n";
-	*/
-	std::ostream & operator[](Debug::type t) {
-		return debug(t);
-	}
-private:
-	/// The current debug level
-	Debug::type dt;
-	/// The no-op stream.
-	std::ostream nullstream;
-	///
-	struct debugstream_internal;
-	///
-	debugstream_internal * internal;
-};
-
-#endif
Index: src/support/Makefile.am
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/Makefile.am,v
retrieving revision 1.67
diff -u -p -r1.67 Makefile.am
--- src/support/Makefile.am	15 Sep 2003 10:59:59 -0000	1.67
+++ src/support/Makefile.am	26 Sep 2003 12:37:01 -0000
@@ -16,8 +16,6 @@ BUILT_SOURCES = path_defines.C
 
 libsupport_la_SOURCES = \
 	BoostFormat.h \
-	DebugStream.C \
-	DebugStream.h \
 	FileInfo.C \
 	FileInfo.h \
 	FileMonitor.h \
@@ -29,6 +27,7 @@ libsupport_la_SOURCES = \
 	copy.C \
 	copied_ptr.h \
 	cow_ptr.h \
+	debugstream,h \
 	filename.C \
 	filename.h \
 	filetools.C \
Index: src/support/debugstream.h
===================================================================
RCS file: src/support/debugstream.h
diff -N src/support/debugstream.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/support/debugstream.h	26 Sep 2003 12:37:02 -0000
@@ -0,0 +1,87 @@
+// -*- C++ -*-
+/**
+ * \file debugStream.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjønnes
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef DEBUG_STREAM_HPP
+#define DEBUG_STREAM_HPP
+
+#include <boost/test/detail/nullstream.hpp>
+
+
+struct debug_trait {
+	enum type {
+		NONE   = 0,
+		EMERG  = 1,
+		ALERT  = 2,
+		CRIT   = 3,
+		ERR    = 4,
+		WARN   = 5,
+		NOTICE = 6,
+		INFO   = 7,
+		DEBUG  = 8,
+		ANY = 0xffffff
+	};
+
+	static bool match(type a, type b) {
+		return (b <= a || (b == ANY && a > NONE));
+	}
+};
+
+
+template <class dtrait,
+	  class charT = char,
+	  class traits = std::char_traits<charT> >
+class basic_debugstream : public std::basic_ostream<charT, traits> {
+public:
+	typedef dtrait debug;
+	typedef typename debug::type Type;
+
+	/// Constructor, sets the debug level to t.
+	explicit basic_debugstream(std::basic_streambuf<charT, traits> * buf)
+		: std::basic_ostream<charT, traits>(buf), dt(debug::NONE)
+	{}
+
+	/// Sets the debug level to t.
+	void level(Type t) {
+		dt = t;
+	}
+
+	/// Returns the current debug level.
+	Type level() const {
+		return dt;
+	}
+
+	/// Returns true if t is part of the current debug level.
+	bool debugging(Type t = debug::ANY) const
+	{
+		if (debug::match(dt, t)) return true;
+		return false;
+	}
+
+	/** Returns the no-op stream if t is not part of the
+	    current debug level otherwise the real debug stream
+	    is used.
+	    Use: dbgstream[Debug::INFO] << "Info!\n";
+	*/
+	std::basic_ostream<charT, traits> & operator[](Type t) {
+		if (debug::match(dt, t))
+			return *this;
+		return nullstream;
+	}
+private:
+	/// The current debug level
+	Type dt;
+	/// The no-op stream.
+	boost::basic_onullstream<charT, traits> nullstream;
+};
+
+typedef basic_debugstream<debug_trait> debugstream;
+
+#endif
Index: src/tex2lyx/tex2lyx.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/tex2lyx/tex2lyx.C,v
retrieving revision 1.49
diff -u -p -r1.49 tex2lyx.C
--- src/tex2lyx/tex2lyx.C	9 Sep 2003 17:25:35 -0000	1.49
+++ src/tex2lyx/tex2lyx.C	26 Sep 2003 12:37:02 -0000
@@ -41,8 +41,7 @@ using std::string;
 using std::vector;
 
 // Hacks to allow the thing to link in the lyxlayout stuff
-Debug::type const Debug::ANY = Debug::type(0);
-DebugStream lyxerr;
+LyXErr lyxerr(std::cerr.rdbuf());
 
 void LyX::emergencyCleanup() {}
 
-- 
        Lgb

Reply via email to