--- /dev/null
+// NB: To add a dbg_class, add it here, and add it to the structure in
+// fg_debug.c
+
+typedef enum {
+ FG_NONE = 0x00000000,
+
+ FG_TERRAIN = 0x00000001,
+ FG_ASTRO = 0x00000002,
+ FG_FLIGHT = 0x00000004,
+ FG_INPUT = 0x00000008,
+ FG_GL = 0x00000010,
+ FG_VIEW = 0x00000020,
+ FG_COCKPIT = 0x00000040,
+ FG_GENERAL = 0x00000080,
+ FG_MATH = 0x00000100,
+ FG_EVENT = 0x00000200,
+ FG_AIRCRAFT = 0x00000400,
+ FG_AUTOPILOT = 0x00000800,
+ FG_UNDEFD = 0x00001000, // For range checking
+
+ FG_ALL = 0xFFFFFFFF
+} fgDebugClass;
+
+
+// NB: To add a priority, add it here.
+typedef enum {
+ FG_BULK, // For frequent messages
+ FG_DEBUG, // Less frequent debug type messages
+ FG_INFO, // Informatory messages
+ FG_WARN, // Possible impending problem
+ FG_ALERT // Very possible impending problem
+ // FG_EXIT, // Problem (no core)
+ // FG_ABORT // Abandon ship (core)
+} fgDebugPriority;
+
--- /dev/null
+// Stream based logging mechanism.
+//
+// Written by Bernie Bright, 1998
+//
+// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+#include "logstream.hxx"
+
+bool logbuf::logging_enabled = true;
+fgDebugClass logbuf::logClass = FG_NONE;
+fgDebugPriority logbuf::logPriority = FG_INFO;
+streambuf* logbuf::sbuf = NULL;
+
+logbuf::logbuf()
+{
+// if ( sbuf == NULL )
+// sbuf = cerr.rdbuf();
+}
+
+logbuf::~logbuf()
+{
+ if ( sbuf )
+ sbuf->sync();
+}
+
+void
+logbuf::set_sb( streambuf* sb )
+{
+ if ( sbuf )
+ sbuf->sync();
+
+ sbuf = sb;
+}
+
+void
+logbuf::set_log_level( fgDebugClass c, fgDebugPriority p )
+{
+ logClass = c;
+ logPriority = p;
+}
+
+void
+logstream::setLogLevels( fgDebugClass c, fgDebugPriority p )
+{
+ logbuf::set_log_level( c, p );
+}
+
+// $Log$
+// Revision 1.1 1998/11/06 21:20:41 curt
+// Initial revision.
+//
--- /dev/null
+// Stream based logging mechanism.
+//
+// Written by Bernie Bright, 1998
+//
+// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
+
+#ifndef _LOGSTREAM_H
+#define _LOGSTREAM_H
+
+#include "Include/compiler.h"
+
+#ifdef FG_HAVE_STD_INCLUDES
+# include <streambuf>
+# include <ostream>
+#else
+# include <iostream.h>
+# include "Include/fg_traits.hxx"
+#endif
+
+#include "debug_types.h"
+
+//
+// TODO:
+//
+// 1. Change output destination. Done.
+// 2. Make logbuf thread safe.
+// 3. Read environment for default debugClass and debugPriority.
+//
+
+//-----------------------------------------------------------------------------
+//
+// logbuf is an output-only streambuf with the ability to disable sets of
+// messages at runtime. Only messages with priority >= logbuf::logPriority
+// and debugClass == logbuf::logClass are output.
+//
+class logbuf : public streambuf
+{
+public:
+
+#ifndef FG_HAVE_STD_INCLUDES
+ typedef char_traits<char> traits_type;
+ typedef char_traits<char>::int_type int_type;
+ typedef char_traits<char>::pos_type pos_type;
+ typedef char_traits<char>::off_type off_type;
+#endif
+// logbuf( streambuf* sb ) : sbuf(sb) {}
+ logbuf();
+ ~logbuf();
+
+ // Is logging enabled?
+ bool enabled() { return logging_enabled; }
+
+ // Set the logging level of subsequent messages.
+ void set_log_state( fgDebugClass c, fgDebugPriority p );
+
+ // Set the global logging level.
+ static void set_log_level( fgDebugClass c, fgDebugPriority p );
+
+ //
+ void set_sb( streambuf* sb );
+
+protected:
+
+ int sync() { return sbuf->sync(); }
+ int_type overflow( int ch );
+// int xsputn( const char* s, istreamsize n );
+
+private:
+
+ // The streambuf used for actual output. Defaults to cerr.rdbuf().
+ static streambuf* sbuf;
+
+ static bool logging_enabled;
+ static fgDebugClass logClass;
+ static fgDebugPriority logPriority;
+
+private:
+
+ // Not defined.
+ logbuf( const logbuf& );
+ void operator= ( const logbuf& );
+};
+
+inline void
+logbuf::set_log_state( fgDebugClass c, fgDebugPriority p )
+{
+ logging_enabled = ((c & logClass) != 0 && p >= logPriority);
+}
+
+inline logbuf::int_type
+logbuf::overflow( int c )
+{
+ return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
+}
+
+//-----------------------------------------------------------------------------
+//
+// logstream manipulator for setting the log level of a message.
+//
+struct loglevel
+{
+ loglevel( fgDebugClass c, fgDebugPriority p )
+ : logClass(c), logPriority(p) {}
+
+ fgDebugClass logClass;
+ fgDebugPriority logPriority;
+};
+
+//-----------------------------------------------------------------------------
+//
+// A helper class that ensures a streambuf and ostream are constructed and
+// destroyed in the correct order. The streambuf must be created before the
+// ostream but bases are constructed before members. Thus, making this class
+// a private base of logstream, declared to the left of ostream, we ensure the
+// correct order of construction and destruction.
+//
+struct logstream_base
+{
+// logstream_base( streambuf* sb ) : lbuf(sb) {}
+ logstream_base() {}
+
+ logbuf lbuf;
+};
+
+//-----------------------------------------------------------------------------
+//
+//
+//
+class logstream : private logstream_base, public ostream
+{
+public:
+ // The default is to send messages to cerr.
+ logstream( ostream& out )
+// : logstream_base(out.rdbuf()),
+ : logstream_base(),
+ ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
+
+ void set_output( ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
+
+ // Set the global log class and priority level.
+ void setLogLevels( fgDebugClass c, fgDebugPriority p );
+
+ // Output operator to capture the debug level and priority of a message.
+ inline ostream& operator<< ( const loglevel& l );
+};
+
+inline ostream&
+logstream::operator<< ( const loglevel& l )
+{
+ lbuf.set_log_state( l.logClass, l.logPriority );
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+//
+// Return the one and only logstream instance.
+// We use a function instead of a global object so we are assured that cerr
+// has been initialised.
+//
+inline logstream&
+fglog()
+{
+ static logstream logstrm( cerr );
+ return logstrm;
+}
+
+#ifdef FG_NDEBUG
+# define FG_LOG(C,P,M)
+#else
+# define FG_LOG(C,P,M) fglog() << loglevel(C,P) << M << endl
+#endif
+
+#endif // _LOGSTREAM_H
+
+// $Log$
+// Revision 1.1 1998/11/06 21:20:42 curt
+// Initial revision.
+//
--- /dev/null
+#include <string>
+#include "Debug/logstream.hxx"
+
+int
+main( int argc, char* argv[] )
+{
+ fglog().setLogLevels( FG_ALL, FG_INFO );
+
+ FG_LOG( FG_TERRAIN, FG_BULK, "terrain::bulk" ); // shouldnt appear
+ FG_LOG( FG_TERRAIN, FG_DEBUG, "terrain::debug" ); // shouldnt appear
+ FG_LOG( FG_TERRAIN, FG_INFO, "terrain::info" );
+ FG_LOG( FG_TERRAIN, FG_WARN, "terrain::warn" );
+ FG_LOG( FG_TERRAIN, FG_ALERT, "terrain::alert" );
+
+ int i = 12345;
+ long l = 54321L;
+ double d = 3.14159;
+ string s = "Hello world!";
+
+ FG_LOG( FG_EVENT, FG_INFO, "event::info "
+ << "i=" << i
+ << ", l=" << l
+ << ", d=" << d
+ << ", d*l=" << d*l
+ << ", s=\"" << s << "\"" );
+
+ // This shouldn't appear in log output:
+ FG_LOG( FG_EVENT, FG_DEBUG, "event::debug "
+ << "- this should be seen - "
+ << "d=" << d
+ << ", s=\"" << s << "\"" );
+
+ return 0;
+}