diff options
Diffstat (limited to 'kernel/register.cc')
| -rw-r--r-- | kernel/register.cc | 109 |
1 files changed, 102 insertions, 7 deletions
diff --git a/kernel/register.cc b/kernel/register.cc index 26da96b95..4f60338e9 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -25,6 +25,65 @@ #include <stdio.h> #include <errno.h> +#ifdef YOSYS_ENABLE_ZLIB +#include <zlib.h> + +PRIVATE_NAMESPACE_BEGIN +#define GZ_BUFFER_SIZE 8192 +void decompress_gzip(const std::string &filename, std::stringstream &out) +{ + char buffer[GZ_BUFFER_SIZE]; + int bytes_read; + gzFile gzf = gzopen(filename.c_str(), "rb"); + while(!gzeof(gzf)) { + bytes_read = gzread(gzf, reinterpret_cast<void *>(buffer), GZ_BUFFER_SIZE); + out.write(buffer, bytes_read); + } + gzclose(gzf); +} + +/* +An output stream that uses a stringbuf to buffer data internally, +using zlib to write gzip-compressed data every time the stream is flushed. +*/ +class gzip_ostream : public std::ostream { +public: + gzip_ostream() + { + rdbuf(&outbuf); + } + bool open(const std::string &filename) + { + return outbuf.open(filename); + } +private: + class gzip_streambuf : public std::stringbuf { + public: + gzip_streambuf() { }; + bool open(const std::string &filename) + { + gzf = gzopen(filename.c_str(), "wb"); + return gzf != nullptr; + } + virtual int sync() override + { + gzwrite(gzf, reinterpret_cast<const void *>(str().c_str()), unsigned(str().size())); + str(""); + return 0; + } + ~gzip_streambuf() + { + sync(); + gzclose(gzf); + } + private: + gzFile gzf = nullptr; + } outbuf; +}; +PRIVATE_NAMESPACE_END + +#endif + YOSYS_NAMESPACE_BEGIN #define MAX_REG_COUNT 1000 @@ -436,6 +495,28 @@ void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<s delete ff; else f = ff; + if (f != NULL) { + // Check for gzip magic + unsigned char magic[3]; + int n = readsome(*ff, reinterpret_cast<char*>(magic), 3); + if (n == 3 && magic[0] == 0x1f && magic[1] == 0x8b) { + #ifdef YOSYS_ENABLE_ZLIB + log("Found gzip magic in file `%s', decompressing using zlib.\n", filename.c_str()); + if (magic[2] != 8) + log_cmd_error("gzip file `%s' uses unsupported compression type %02x\n", + filename.c_str(), unsigned(magic[2])); + delete ff; + std::stringstream *df = new std::stringstream(); + decompress_gzip(filename, *df); + f = df; + #else + log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename.c_str()); + #endif + } else { + ff->clear(); + ff->seekg(0, std::ios::beg); + } + } } if (f == NULL) log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno)); @@ -546,14 +627,28 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vector<st filename = arg; rewrite_filename(filename); - std::ofstream *ff = new std::ofstream; - ff->open(filename.c_str(), std::ofstream::trunc); - yosys_output_files.insert(filename); - if (ff->fail()) { - delete ff; - log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); + if (filename.size() > 3 && filename.substr(filename.size()-3) == ".gz") { +#ifdef YOSYS_ENABLE_ZLIB + gzip_ostream *gf = new gzip_ostream; + if (!gf->open(filename)) { + delete gf; + log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); + } + yosys_output_files.insert(filename); + f = gf; +#else + log_cmd_error("Yosys is compiled without zlib support, unable to write gzip output.\n"); +#endif + } else { + std::ofstream *ff = new std::ofstream; + ff->open(filename.c_str(), std::ofstream::trunc); + yosys_output_files.insert(filename); + if (ff->fail()) { + delete ff; + log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); + } + f = ff; } - f = ff; } if (called_with_fp) |
