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 }