core/vul/vul_redirector.cxx
Go to the documentation of this file.
00001 // This is core/vul/vul_redirector.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 
00008 #include <vcl_compiler.h>
00009 #if defined(VCL_SGI_CC)
00010 // urgh! there is no rdbuf() method for *setting* the stream buffer.
00011 // These headers are in the old style intentionally. We *want* to
00012 // include the old SGI headers as they are, without going through vcl.
00013 // These includes must come *before* vul_redirector.h !
00014 # include <memory.h>         // dont_vxl_filter
00015 # include <stddef.h>         // dont_vxl_filter
00016 # define private public
00017 # define protected public
00018 # include <iostream.h>       // dont_vxl_filter
00019 # undef private
00020 # undef protected
00021 #endif
00022 
00023 #include "vul_redirector.h"
00024 #include <vcl_iostream.h>
00025 #include <vcl_cstdio.h> // for EOF
00026 
00027 //----------------------------------------------------------------------
00028 // This class is used as a stream buffer that can
00029 // redirect output from cout, cerr, clog to a CoutWindow class.
00030 class vul_redirector_streambuf : public vcl_streambuf
00031 {
00032   vul_redirector_data* p;
00033  public:
00034   vul_redirector_streambuf(vul_redirector_data* p_):p(p_) {}
00035   int sync ();
00036   int overflow (int ch);
00037   int underflow(){return 0;}
00038   // The libraries which comes with sgi 7.2.1 and
00039   // SunPro 5.0 take char const *, which is
00040   // non-standard, but we have to live with it. A
00041   // better cpp test would be welcome. fsm.
00042 #if defined(VCL_SGI_CC)
00043 # define xsputn_const const
00044 # define xsputn_sizet int
00045 #elif defined(__INTEL_COMPILER) || defined(VCL_SUNPRO_CC_5) || defined(VCL_KAI) || defined(VCL_BORLAND) || defined(VCL_GCC_3)
00046   // RogueWave or ISO?
00047 # define xsputn_const const
00048 # define xsputn_sizet vcl_streamsize
00049 #else
00050 # define xsputn_const /* */
00051 # define xsputn_sizet vcl_streamsize
00052 #endif
00053   xsputn_sizet xsputn (xsputn_const char* text, xsputn_sizet n);
00054 };
00055 
00056 struct vul_redirector_data
00057 {
00058   vul_redirector* owner;
00059   vcl_streambuf* old_cerrbuf;
00060   vul_redirector_streambuf* buf;
00061   vcl_ostream* s;
00062 };
00063 
00064 /////////////////////////////////////////////////////////////////////////////
00065 // streambuf stuff
00066 
00067 int vul_redirector_streambuf::sync ()
00068 {
00069   vcl_ptrdiff_t n = pptr () - pbase ();
00070   return (n && p->owner->putchunk ( pbase (), n) != n) ? EOF : 0;
00071 }
00072 
00073 int vul_redirector_streambuf::overflow (int ch)
00074 {
00075   int n = static_cast<int>(pptr () - pbase ());
00076   if (n && sync ())
00077     return EOF;
00078   if (ch != EOF)
00079   {
00080     char cbuf[1];
00081     cbuf[0] = (char)ch;
00082     if (p->owner->putchunk ( cbuf, 1) != 1)
00083       return EOF;
00084   }
00085   pbump (-n);  // Reset pptr().
00086   return 0;
00087 }
00088 
00089 xsputn_sizet vul_redirector_streambuf::xsputn (xsputn_const char* text, xsputn_sizet n)
00090 {
00091   return sync () == EOF ? 0 : p->owner->putchunk ( text, n);
00092 }
00093 
00094 //////////////// Data for debugging
00095 
00096 
00097 vul_redirector::vul_redirector(vcl_ostream& s):
00098   p(new vul_redirector_data)
00099 {
00100   p->owner = this;
00101   p->buf = new vul_redirector_streambuf(p);
00102   p->old_cerrbuf = s.rdbuf();
00103 #if defined(VCL_SGI_CC)
00104   s.bp = p->buf;
00105   s.clear();
00106 #else
00107   s.rdbuf(p->buf);
00108 #endif
00109   p->s = &s;
00110 }
00111 
00112 vul_redirector::~vul_redirector()
00113 {
00114 #if defined(VCL_SGI_CC)
00115   // see above
00116   p->s->bp = p->old_cerrbuf;
00117   p->s->clear();
00118 #else
00119   p->s->rdbuf(p->old_cerrbuf);
00120 #endif
00121   delete p->buf;
00122   delete p;
00123 }
00124 
00125 int vul_redirector::sync_passthru()
00126 {
00127 #if defined(VCL_GCC) && !defined(GNU_LIBSTDCXX_V3)
00128   // The default libraries these compilers come with are non-standard
00129   // since they have no pubsync() method. According to standard, though,
00130   // pubsync() just returns sync(), so :
00131   return p->old_cerrbuf->sync();
00132 #elif defined(VCL_SGI_CC)
00133   // ditto
00134   return p->old_cerrbuf->sync();
00135 #else
00136   return p->old_cerrbuf->pubsync();
00137 #endif
00138 }
00139 
00140 vcl_streamsize vul_redirector::put_passthru(char const* buf, vcl_streamsize n)
00141 {
00142   return p->old_cerrbuf->sputn(buf, n);
00143 }
00144 
00145 //: Default action is just to pass text on the old stream.
00146 vcl_streamsize vul_redirector::putchunk(char const* buf, vcl_streamsize n)
00147 {
00148   return put_passthru(buf, n);
00149 }