/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corp., 1991 **/ /**********************************************************************/ /* dbgstr.hxx A "stream" protocol for debugging output This lets me use a "stream" style of emitting debugging information, e.g. cdebug << "Couldn't allocate " << _cbFoo << " bytes." << dbgEOL; or cdebug << "Window moved to " << xyFinalRestingPlace << dbgEOL; All client applications have a "cdebug" stream already defined and constructed. Actually, only BLT apps have it already established; console apps must construct an output sink, and init the package like so: main() { OUTPUT_TO_STDERR out; DBGSTREAM::SetCurrent(&out); ... your code here ... DBGSTREAM::SetCurrent(NULL); } The macros DBGOUT and DBGEOL work with this global stream, ensuring that its data disappears from the object image in retail builds. DBGOUT automatically names cdebug as its destination stream; DBGEOL works likewise, but appends an end-of-line to its output. Both take a stream-output-expression, like so: DBGOUT("Number of pels: " << cPels); DBGEOL("; number of lims: " << cLims); or just DBGEOL("Number of pels: " << cPels << "; number of lims: " << cLims); If a client wants its own separate stream, it should first construct an output sink (OUTPUTSINK or derived class) for the stream, then construct the stream, passing the sink as a ctor param. E.g. OUTPUT_TO_WHEREVER out; DBGSTREAM dbgWherever(&out); dbgWherever << mumble; FILE HISTORY: beng 21-May-1991 Created beng 22-May-1991 Added IFTRACE and non-Windows sinks beng 27-Jun-1991 Removed INCL_WINDOWS. How else to use non-Win sinks? beng 06-Jul-1991 Added OUTPUT_TO_STDOUT Johnl 07-Aug-1991 Added some explanatory text beng 25-Oct-1991 Add DBG macros beng 12-Feb-1992 Rename DBG to DBGOUT (conflict w/ NT) beng 28-Feb-1992 New USE_CONSOLE def'n beng 16-Mar-1992 Simplify cdebug setups jonn 08-May-1992 Added TRACEOUT and TRACEEOL beng 10-May-1992 Removed obsolete IFTRACE */ #ifndef _DBGSTR_HXX_ #define _DBGSTR_HXX_ // All the non-Windows versions communicate through stdio. #if !defined(INCL_WINDOWS) || defined(USE_CONSOLE) #include #endif /************************************************************************* NAME: OUTPUTSINK SYNOPSIS: Abstract class describing any destination of debugging output. INTERFACE: Render() - Takes a character string and renders it on the destination. Supplies an optional second argument with the number of characters in the string as a hint for some 'sink implementations. EndOfLine() - Generate a linebreak on the destination. USES: CAVEATS: Client must supply some implementation NOTES: The OUTPUTSINK abstract class will let me extend this package to render output into a file, into a secondary window, etc. HISTORY: beng 21-May-1991 Created **************************************************************************/ DLL_CLASS OUTPUTSINK { public: virtual VOID Render(const TCHAR *psz) = 0; virtual VOID Render(const TCHAR *psz, UINT cch) = 0; virtual VOID EndOfLine() = 0; }; #if defined(INCL_WINDOWS) /************************************************************************* NAME: OUTPUT_TO_AUX SYNOPSIS: Delivers the debugging port for trace messages INTERFACE: Render() - Takes a character string and renders it on the debugging port. EndOfLine() - Generate a linebreak on the destination. PARENT: OUTPUTSINK HISTORY: beng 21-May-1991 Created beng 25-Oct-1991 Implementation outlined **************************************************************************/ DLL_CLASS OUTPUT_TO_AUX: public OUTPUTSINK { public: virtual VOID Render(const TCHAR *psz); virtual VOID Render(const TCHAR *psz, UINT cch); virtual VOID EndOfLine(); }; #endif // WINDOWS #if defined(stderr) /************************************************************************* NAME: OUTPUT_TO_STDERR SYNOPSIS: Delivers the stderr stdio stream for trace messages INTERFACE: Render() - Takes a character string and renders it on handle 2. EndOfLine() - Generate a linebreak on the destination. PARENT: OUTPUTSINK HISTORY: beng 22-May-1991 Created beng 06-Jul-1991 Always assume output is cooked beng 25-Oct-1991 Implementation outlined **************************************************************************/ DLL_CLASS OUTPUT_TO_STDERR: public OUTPUTSINK { public: virtual VOID Render(const TCHAR *psz); virtual VOID Render(const TCHAR *psz, UINT cch); virtual VOID EndOfLine(); }; #endif // STDIO #if defined(stdout) /************************************************************************* NAME: OUTPUT_TO_STDOUT SYNOPSIS: Delivers the stdout stdio stream for trace messages INTERFACE: Render() - Takes a character string and renders it on handle 1. EndOfLine() - Generate a linebreak on the destination. PARENT: OUTPUTSINK HISTORY: beng 06-Jul-1991 Created from OUTPUT_TO_STDERR beng 25-Oct-1991 Implementation outlined **************************************************************************/ DLL_CLASS OUTPUT_TO_STDOUT: public OUTPUTSINK { public: virtual VOID Render(const TCHAR *psz); virtual VOID Render(const TCHAR *psz, UINT cch); virtual VOID EndOfLine(); }; #endif // STDIO /************************************************************************* NAME: OUTPUT_TO_NUL SYNOPSIS: Disables all trace messages. Messages to a DBGSTREAM using this sink will fall into the bitbucket w/o ado. PARENT: OUTPUTSINK NOTES: This class exists so that a stream can shut off messages on itself via SetSink. HISTORY: beng 22-May-1991 Created beng 25-Oct-1991 Implementation outlined **************************************************************************/ DLL_CLASS OUTPUT_TO_NUL: public OUTPUTSINK { virtual VOID Render(const TCHAR *psz); virtual VOID Render(const TCHAR *psz, UINT cch); virtual VOID EndOfLine(); }; #if 0 /************************************************************************* NAME: OUTPUT_TO_WIN SYNOPSIS: Pops up a scrollable window for trace messages. PARENT: OUTPUTSINK CAVEATS: Not yet implemented. NOTES: HISTORY: beng 21-May-1991 Daydreamed. **************************************************************************/ DLL_CLASS OUTPUT_TO_WIN: public OUTPUTSINK { // ... }; #endif // Dropping one of these on a stream results in a special action. // enum DBGSTR_SPECIAL { dbgEOL // End-of-line }; /************************************************************************* NAME: DBGSTREAM SYNOPSIS: Stream-style object for debugging output INTERFACE: DBGSTREAM() - constructor, associating a sink with the stream SetSink() - change the sink on a stream operator<<() - render onto the stream. The class supports most primitive objects; in addition, "dbgEOL" will generate a linebreak. QueryCurrent() - returns a reference to the default global debugging stream, as aliased to "cdebug" in the source and used by the DBGEOL etc. macros. USES: OUTPUTSINK NOTES: Clients may supply their own operators for rendering themselves onto a DBGSTREAM. BUGBUG - the operators should use the "cch" form of Render. HISTORY: beng 21-May-1991 Created beng 25-Oct-1991 Use CCH_x manifests; implementation outlined beng 16-Mar-1992 Added QueryCurrent static etc. beng 29-Jun-1992 Outlined Set/QueryCurrent for dllization **************************************************************************/ DLL_CLASS DBGSTREAM { private: OUTPUTSINK * _pout; // The home of cdebug // static DBGSTREAM * _pdbgCurrentGlobal; public: DBGSTREAM(OUTPUTSINK * pout); ~DBGSTREAM(); static DBGSTREAM& QueryCurrent(); static VOID SetCurrent(DBGSTREAM* pdbg); VOID SetSink(OUTPUTSINK * pout); DBGSTREAM& operator<<(TCHAR c); DBGSTREAM& operator<<(const TCHAR* psz); #if defined(UNICODE) // need these for simple output DBGSTREAM& operator<<(CHAR c); DBGSTREAM& operator<<(const CHAR* psz); #endif DBGSTREAM& operator<<(INT n); DBGSTREAM& operator<<(UINT n); DBGSTREAM& operator<<(SHORT n); #if !defined(UNICODE) // if defined, conflicts with TCHAR def'n DBGSTREAM& operator<<(USHORT n); #endif DBGSTREAM& operator<<(LONG n); DBGSTREAM& operator<<(ULONG n); DBGSTREAM& operator<<(INT64 n); DBGSTREAM& operator<<(UINT64 n); DBGSTREAM& operator<<(DBGSTR_SPECIAL dbgSpecial); }; // For traditional stream-style output, declare an object named // "cdebug" (as in cin, cout, cerr). // // The BLT startup code points this at the AUX debugging console. // Command-line unit tests should hook it to stderr. // #define cdebug (DBGSTREAM::QueryCurrent()) // We have to use the preprocessor to remove completely all trace // messages from the release product, since the compiler will not // optimize away unreferenced message strings. #if defined(DEBUG) #define DBGOUT(x) { cdebug << x ; } #define DBGEOL(x) { cdebug << x << dbgEOL; } #else #define DBGOUT(x) { ; } #define DBGEOL(x) { ; } #endif #if defined(DEBUG) && defined(TRACE) #define TRACEOUT(x) { cdebug << x ; } #define TRACEEOL(x) { cdebug << x << dbgEOL; } // must use semicolons after using these macros #define TRACETIMESTART DWORD dwTraceTime = ::GetTickCount() #define TRACETIMEEND(printthis) TRACEEOL( printthis << ::GetTickCount() - (dwTraceTime) << " msec" ) #define TRACETIMESTART2(name) DWORD dwTraceTime##name = ::GetTickCount() #define TRACETIMEEND2(name,printthis) TRACEEOL( printthis << ::GetTickCount() - (dwTraceTime##name) << " msec" ) #else #define TRACEOUT(x) { ; } #define TRACEEOL(x) { ; } #define TRACETIMESTART { ; } #define TRACETIMEEND(printthis) { ; } #define TRACETIMESTART2(name) { ; } #define TRACETIMEEND2(name,printthis) { ; } #endif #endif // _DBGSTR_HXX_