#ifndef _LOGSTREAM_H
#define _LOGSTREAM_H
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
#include <simgear/compiler.h>
-// At least Irix needs this
-#ifdef SG_HAVE_NATIVE_SGI_COMPILERS
-#include <char_traits.h>
+#ifdef _MSC_VER
+# include <windows.h>
#endif
#ifdef SG_HAVE_STD_INCLUDES
# include <iostream>
#else
# include <iostream.h>
-# include <simgear/fg_traits.hxx>
+# include <simgear/sg_traits.hxx>
#endif
#include <simgear/debug/debug_types.h>
-#ifndef SG_HAVE_NATIVE_SGI_COMPILERS
SG_USING_STD(streambuf);
SG_USING_STD(ostream);
+SG_USING_STD(cout);
SG_USING_STD(cerr);
SG_USING_STD(endl);
-#else
-SG_USING_STD(char_traits);
-#endif
#ifdef __MWERKS__
SG_USING_STD(iostream);
* messages at runtime. Only messages with priority >= logbuf::logPriority
* and debugClass == logbuf::logClass are output.
*/
+#ifdef SG_NEED_STREAMBUF_HACK
+class logbuf : public __streambuf
+#else
class logbuf : public streambuf
+#endif
{
public:
// logbuf( streambuf* sb ) : sbuf(sb) {}
/** Constructor */
logbuf();
+
/** Destructor */
~logbuf();
- /** Is logging enabled? */
+ /**
+ * Is logging enabled?
+ * @return true or false*/
bool enabled() { return logging_enabled; }
- /** Set the logging level of subsequent messages. */
+ /**
+ * Set the logging level of subsequent messages.
+ * @param c debug class
+ * @param p priority
+ */
void set_log_state( sgDebugClass c, sgDebugPriority p );
- /** Set the global logging level. */
+ /**
+ * Set the global logging level.
+ * @param c debug class
+ * @param p priority
+ */
static void set_log_level( sgDebugClass c, sgDebugPriority p );
- /** Set the stream buffer */
+
+ /**
+ * Set the allowed logging classes.
+ * @param c All enabled logging classes anded together.
+ */
+ static void set_log_classes (sgDebugClass c);
+
+
+ /**
+ * Get the logging classes currently enabled.
+ * @return All enabled debug logging anded together.
+ */
+ static sgDebugClass get_log_classes ();
+
+
+ /**
+ * Set the logging priority.
+ * @param c The priority cutoff for logging messages.
+ */
+ static void set_log_priority (sgDebugPriority p);
+
+
+ /**
+ * Get the current logging priority.
+ * @return The priority cutoff for logging messages.
+ */
+ static sgDebugPriority get_log_priority ();
+
+
+ /**
+ * Set the stream buffer
+ * @param sb stream buffer
+ */
void set_sb( streambuf* sb );
protected:
inline logbuf::int_type
logbuf::overflow( int c )
{
+#ifdef _MSC_VER
+ static has_console = false;
+ if ( logging_enabled ) {
+ if ( !has_console ) {
+ AllocConsole();
+ freopen("conin$", "r", stdin);
+ freopen("conout$", "w", stdout);
+ freopen("conout$", "w", stderr);
+ has_console = true;
+ }
+ sbuf->sputc(c);
+ }
+ else
+ return EOF == 0 ? 1: 0;
+#else
return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
+#endif
}
/**
class logstream : private logstream_base, public ostream
{
public:
- /** The default is to send messages to cerr. */
+ /**
+ * The default is to send messages to cerr.
+ * @param out output stream
+ */
logstream( ostream& out )
// : logstream_base(out.rdbuf()),
: logstream_base(),
ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
- /** Set the output stream */
+ /**
+ * Set the output stream
+ * @param out output stream
+ */
void set_output( ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
- /** Set the global log class and priority level. */
+ /**
+ * Set the global log class and priority level.
+ * @param c debug class
+ * @param p priority
+ */
void setLogLevels( sgDebugClass c, sgDebugPriority p );
- /** Output operator to capture the debug level and priority of a message. */
+ /**
+ * Output operator to capture the debug level and priority of a message.
+ * @param l log level
+ */
inline ostream& operator<< ( const loglevel& l );
};
return *this;
}
+extern logstream *global_logstream;
/**
+ * \relates logstream
* 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.
+ * @return current logstream
*/
inline logstream&
sglog()
{
- static logstream logstrm( cerr );
- return logstrm;
+ if (global_logstream == NULL) {
+
+#ifdef __APPLE__
+ /**
+ * There appears to be a bug in the C++ runtime in Mac OS X that
+ * will crash if certain funtions are called (in this case
+ * cerr.rdbuf()) during static initialization of a class. This
+ * print statement is hack to kick the library in the pants so it
+ * won't crash when cerr.rdbuf() is first called -DW
+ **/
+ cout << "Using Mac OS X hack for initializing C++ stdio..." << endl;
+#endif
+ global_logstream = new logstream (cerr);
+ }
+
+ return *global_logstream;
}
/** \def SG_LOG(C,P,M)
- * Log a message = M of class = C and priority = P
+ * Log a message.
+ * @param C debug class
+ * @param P priority
+ * @param M message
*/
#ifdef FG_NDEBUG
# define SG_LOG(C,P,M)