here we go

This commit is contained in:
Cary Sandvig 2000-12-13 02:02:48 +00:00
parent e2bfd4c7ed
commit e7660fd47c
4 changed files with 123 additions and 89 deletions

View File

@ -8,11 +8,12 @@
executionEnvironment.h filename.I filename.cxx filename.h \ executionEnvironment.h filename.I filename.cxx filename.h \
load_dso.cxx load_dso.h dSearchPath.I dSearchPath.cxx \ load_dso.cxx load_dso.h dSearchPath.I dSearchPath.cxx \
dSearchPath.h pfstream.h vector_string.cxx vector_string.h \ dSearchPath.h pfstream.h vector_string.cxx vector_string.h \
gnu_getopt.c gnu_getopt.h gnu_getopt1.c gnu_getopt.c gnu_getopt.h gnu_getopt1.c pfstreamBuf.h pfstreamBuf.cxx
#define INSTALL_HEADERS \ #define INSTALL_HEADERS \
executionEnvironment.I executionEnvironment.h filename.I \ executionEnvironment.I executionEnvironment.h filename.I \
filename.h load_dso.h dSearchPath.I dSearchPath.h \ filename.h load_dso.h dSearchPath.I dSearchPath.h \
pfstream.h vector_string.h gnu_getopt.h pfstream.h pfstream.I vector_string.h gnu_getopt.h \
pfstreamBuf.h
#end lib_target #end lib_target

View File

@ -6,87 +6,28 @@
#ifndef __PFSTREAM_H__ #ifndef __PFSTREAM_H__
#define __PFSTREAM_H__ #define __PFSTREAM_H__
#include <dtoolbase.h> #include "pfstreambuf.h"
#include <string> class EXPCL_DTOOL ipfstream : public istream {
#include <stdio.h> PUBLISHED:
INLINE ipfstream(const string);
#ifdef WIN32_VC INLINE void flush(void);
#define popen _popen private:
#define pclose _pclose PipeStreamBuf _psb;
#endif
class EXPCL_DTOOL ipfstream { INLINE ipfstream(void);
private:
ifstream *ifs;
FILE *fd;
bool ok;
ipfstream() {}
ipfstream(const ipfstream&) {}
public:
ipfstream(std::string cmd, int mode = ios::in, int = 0664) : ok(false) {
#ifndef PENV_PS2
fd = popen(cmd.c_str(), (mode & ios::in)?"r":"w");
if (fd != (FILE *)0l) {
// this can't work under windows until this is re-written
#ifdef WIN32_VC
cerr << "ipfstream: this class needs to be rewritten for windows!"
<< endl;
#else
ifs = new ifstream(fileno(fd));
#endif // WIN32_VC
ok = true;
}
#endif // PENV_PS2
}
~ipfstream() {
#ifndef PENV_PS2
if (ok) {
pclose(fd);
delete ifs;
}
#endif // PENV_PS2
}
INLINE operator istream&() {
return *ifs;
}
}; };
class EXPCL_DTOOL opfstream { class EXPCL_DTOOL opfstream : public ostream {
private: PUBLISHED:
ofstream *ofs; INLINE opfstream(const string);
FILE *fd;
bool ok;
opfstream() {} INLINE void flush(void);
opfstream(const opfstream&) {} private:
public: PipeStreamBuf _psb;
opfstream(std::string cmd, int mode = ios::out, int = 0664) : ok(false) {
#ifndef PENV_PS2
fd = popen(cmd.c_str(), (mode & ios::out)?"w":"r");
if (fd != (FILE *)0L) {
#ifndef WIN32_VC
ofs = new ofstream(fileno(fd));
#endif
ok = true;
}
#endif // PENV_PS2
}
~opfstream() {
#ifndef PENV_PS2
if (ok) {
pclose(fd);
delete ofs;
}
#endif
}
INLINE operator ostream&() { INLINE opfstream(void);
return *ofs;
}
}; };
#endif /* __PFSTREAM_H__ */ #endif /* __PFSTREAM_H__ */

View File

@ -4,32 +4,55 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#include "pfstreamBuf.h" #include "pfstreamBuf.h"
#include <assert.h>
#ifndef HAVE_STREAMSIZE #ifndef HAVE_STREAMSIZE
// Some compilers (notably SGI) don't define this for us // Some compilers (notably SGI) don't define this for us
typedef int streamsize; typedef int streamsize;
#endif /* HAVE_STREAMSIZE */ #endif /* HAVE_STREAMSIZE */
PipeStreamBuf::PipeStreamBuf(void) { PipeStreamBuf::PipeStreamBuf(PipeStreamBuf::Direction dir) : _dir(dir),
_pipe((FILE*)0L) {
#ifndef WIN32_VC #ifndef WIN32_VC
// taken from Dr. Ose. // taken from Dr. Ose.
// These lines, which are essential on Irix and Linux, seem to be // These lines, which are essential on Irix and Linux, seem to be
// unnecessary and not understood on Windows. // unnecessary and not understood on Windows.
allocate(); allocate();
assert((dir == Input) || (dir == Output));
if (dir == Input) {
cerr << "allocated reserve is " << blen() << " bytes long" << endl;
setg(base(), ebuf(), ebuf());
} else {
setp(base(), ebuf()); setp(base(), ebuf());
}
#endif /* WIN32_VC */ #endif /* WIN32_VC */
} }
PipeStreamBuf::~PipeStreamBuf(void) { PipeStreamBuf::~PipeStreamBuf(void) {
if (_pipe != (FILE*)0L) {
sync(); sync();
flush();
// any other cleanup needed (pclose, etc) // any other cleanup needed (pclose, etc)
pclose(_pipe);
}
} }
void PipeStreamBuf::flush(void) { void PipeStreamBuf::flush(void) {
// if there's anything to do here assert(_pipe != (FILE*)0L);
if (_dir == Output) {
write_chars("", 0, true);
}
}
void PipeStreamBuf::command(const string cmd) {
assert(_pipe == (FILE*)0L);
const char *typ = (_dir == Output)?"w":"r";
_pipe = popen(cmd.c_str(), typ);
} }
int PipeStreamBuf::overflow(int c) { int PipeStreamBuf::overflow(int c) {
assert(_pipe != (FILE*)0L);
assert(_dir == Output);
streamsize n = pptr() - pbase(); streamsize n = pptr() - pbase();
if (n != 0) { if (n != 0) {
write_chars(pbase(), n, false); write_chars(pbase(), n, false);
@ -44,11 +67,65 @@ int PipeStreamBuf::overflow(int c) {
} }
int PipeStreamBuf::sync(void) { int PipeStreamBuf::sync(void) {
assert(_pipe != (FILE*)0L);
if (_dir == Output) {
streamsize n = pptr() - pbase(); streamsize n = pptr() - pbase();
write_chars(pbase(), n, false); write_chars(pbase(), n, false);
pbump(-n); pbump(-n);
} else {
streamsize n = egptr() - gptr();
gbump(n); // flush all our stored input away
cerr << "pfstream tossed out " << n << " bytes" << endl;
}
return 0; return 0;
} }
int PipeStreamBuf::underflow(void) { int PipeStreamBuf::underflow(void) {
assert(_pipe != (FILE*)0L);
assert(_dir == Input);
if (gptr() < egptr()) {
char c = *(gptr());
return c;
}
if (feof(_pipe) != 0)
return EOF;
char* buf = new char[blen()];
size_t n = fread(buf, 1, blen(), _pipe);
int ret = buf[0];
if (n == 0)
ret = EOF;
else {
memcpy(base()+(blen() - n), buf, n);
gbump(-n);
}
delete buf;
return ret;
}
void PipeStreamBuf::write_chars(const char* start, int length, bool flush) {
assert(_dir == Output);
size_t orig = _line_buffer.length();
string latest(start, length);
string line;
if (flush) {
// if we're going to flush the stream now, we dump the whole thing
// reguardless of whether we have reached end-of-line.
line = _line_buffer + latest;
_line_buffer = "";
} else {
// Otherwise, we check for the end-of-line character.
_line_buffer += latest;
size_t eol = _line_buffer.rfind('\n', orig);
if (eol != string::npos) {
line = _line_buffer.substr(0, eol+1);
_line_buffer = _line_buffer.substr(eol+1);
}
}
// now output 'line'
size_t wrote = fwrite(line.c_str(), 1, line.length(), _pipe);
if (wrote != line.length())
cerr << "wrote only " << wrote << " of " << line.length()
<< " bytes to pipe" << endl;
fflush(_pipe);
} }

View File

@ -8,18 +8,33 @@
#include <dtoolbase.h> #include <dtoolbase.h>
#include <iostream> #include <iostream>
#include <string>
#include <stdio.h>
class EXPCL_PANDA PipeStreamBuf : public streambuf { #ifdef WIN32_VC
#define popen _popen
#define pclose _pclose
#endif
class EXPCL_DTOOL PipeStreamBuf : public streambuf {
public: public:
PipeStreamBuf(void); enum Direction { Input, Output };
PipeStreamBuf(Direction);
virtual ~PipeStreamBuf(void); virtual ~PipeStreamBuf(void);
void flush(); void flush();
void command(const string);
protected: protected:
virtual int overflow(int c); virtual int overflow(int c);
virtual int sync(); virtual int sync(void);
virtual int underflow(); virtual int underflow(void);
private: private:
Direction _dir;
string _line_buffer;
FILE* _pipe;
void write_chars(const char*, int, bool);
}; };
#endif /* __PFSTREAMBUF_H__ */ #endif /* __PFSTREAMBUF_H__ */