| @@ -5,10 +5,10 @@ SRCS = \ | |||
| HDRS = \ | |||
| src/BXParser.h src/build.h src/compdb.h src/CompileStep.h src/DepNode.h \ | |||
| src/globals.h src/LinkStep.h src/logger.h src/parallel.h src/sys.h \ | |||
| src/toolchain.h | |||
| src/toolchain.h src/bufio.h | |||
| BUILD = build | |||
| OBJS = $(patsubst %,$(BUILD)/%.o,$(SRCS)) | |||
| CFLAGS = -g -O3 -Wall -Wextra -Wno-unused-parameter | |||
| CFLAGS = -O3 -g -Wall -Wextra -Wno-unused-parameter | |||
| LDLIBS = -lpthread | |||
| $(BUILD)/%.cc.o: %.cc $(HDRS) | |||
| @@ -6,37 +6,22 @@ | |||
| #include <errno.h> | |||
| int BXParser::get() { | |||
| if (bufidx_ < buflen_) { | |||
| return buf_[bufidx_++]; | |||
| int c = buf_.get(); | |||
| ch_ += 1; | |||
| if (c == '\n') { | |||
| ch_ = 1; | |||
| line_ += 1; | |||
| } | |||
| bufidx_ = 0; | |||
| stream_.read(buf_, sizeof(buf_)); | |||
| buflen_ = stream_.gcount(); | |||
| if (buflen_ == 0) { | |||
| return EOF; | |||
| } | |||
| return buf_[bufidx_++]; | |||
| return c; | |||
| } | |||
| int BXParser::peek() { | |||
| if (bufidx_ < buflen_) { | |||
| return buf_[bufidx_]; | |||
| } else { | |||
| return stream_.peek(); | |||
| } | |||
| return buf_.peek(); | |||
| } | |||
| int BXParser::peek2() { | |||
| if (bufidx_ + 1 < buflen_) { | |||
| return buf_[bufidx_ + 1]; | |||
| } else { | |||
| stream_.get(); | |||
| int ch = stream_.peek(); | |||
| stream_.unget(); | |||
| return ch; | |||
| } | |||
| return buf_.peek2(); | |||
| } | |||
| BXParser::Operator BXParser::readOperator() { | |||
| @@ -380,65 +365,34 @@ void BXParser::parseList(const BXVariables &vars, std::vector<std::string> &valu | |||
| } | |||
| } | |||
| BXWriter::~BXWriter() { | |||
| if (bufidx_ > 0) { | |||
| stream_.write(buf_, bufidx_); | |||
| } | |||
| } | |||
| void BXWriter::put(char ch) { | |||
| buf_[bufidx_++] = ch; | |||
| if (bufidx_ == sizeof(buf_)) { | |||
| stream_.write(buf_, sizeof(buf_)); | |||
| bufidx_ = 0; | |||
| } | |||
| } | |||
| void BXWriter::put(const std::string &str) { | |||
| size_t w = sizeof(buf_) - bufidx_; | |||
| if (w > str.size()) { | |||
| w = str.size(); | |||
| } | |||
| memcpy(buf_ + bufidx_, str.c_str(), w); | |||
| if (str.size() - w > 0) { | |||
| stream_.write(buf_, bufidx_ + w); | |||
| stream_.write(str.c_str() + w, str.size() - w); | |||
| bufidx_ = 0; | |||
| } else { | |||
| bufidx_ += w; | |||
| } | |||
| } | |||
| void BXWriter::escape(const std::string &str) { | |||
| put('"'); | |||
| buf_.put('"'); | |||
| for (char ch: str) { | |||
| if (ch == '$' || ch == '"' || ch == '\\') { | |||
| put('\\'); | |||
| buf_.put('\\'); | |||
| } | |||
| put(ch); | |||
| buf_.put(ch); | |||
| } | |||
| put('"'); | |||
| buf_.put('"'); | |||
| } | |||
| void BXWriter::write(const BXVariables &vars) { | |||
| for (const auto &pair: vars) { | |||
| size_t chars = 0; | |||
| put(pair.first); | |||
| put(" :="); | |||
| buf_.put(pair.first); | |||
| buf_.put(" :="); | |||
| for (auto &val: pair.second) { | |||
| if (chars >= 80) { | |||
| put('\n'); | |||
| put('\t'); | |||
| buf_.put('\n'); | |||
| buf_.put('\t'); | |||
| chars = 0; | |||
| } else { | |||
| put(' '); | |||
| buf_.put(' '); | |||
| } | |||
| escape(val); | |||
| chars += val.size(); | |||
| } | |||
| put('\n'); | |||
| buf_.put('\n'); | |||
| } | |||
| } | |||
| @@ -6,6 +6,8 @@ | |||
| #include <iostream> | |||
| #include <exception> | |||
| #include "bufio.h" | |||
| struct BXParseError: std::exception { | |||
| BXParseError(std::string msg): message(msg) {} | |||
| std::string message; | |||
| @@ -23,7 +25,7 @@ public: | |||
| static const int FLAG_ONE_LINE = 1 << 0; | |||
| BXParser(std::istream &stream, int flags, int line = 1, int ch = 1): | |||
| flags_(flags), line_(line), ch_(ch), stream_(stream) {} | |||
| flags_(flags), line_(line), ch_(ch), buf_(stream) {} | |||
| void parse(BXVariables &vars); | |||
| void parseList(const BXVariables &vars, std::vector<std::string> &values); | |||
| @@ -62,26 +64,18 @@ private: | |||
| int line_; | |||
| int ch_; | |||
| std::istream &stream_; | |||
| char buf_[1024]; | |||
| size_t bufidx_ = 0; | |||
| size_t buflen_ = 0; | |||
| bufio::IBuf<> buf_; | |||
| }; | |||
| class BXWriter { | |||
| public: | |||
| BXWriter(std::ostream &stream): stream_(stream) {} | |||
| ~BXWriter(); | |||
| BXWriter(std::ostream &stream): buf_(stream) {} | |||
| void write(const BXVariables &vars); | |||
| private: | |||
| void put(char ch); | |||
| void put(const std::string &str); | |||
| void newline(); | |||
| void escape(const std::string &str); | |||
| std::ostream &stream_; | |||
| char buf_[1024]; | |||
| size_t bufidx_ = 0; | |||
| bufio::OBuf<> buf_; | |||
| }; | |||
| @@ -85,7 +85,7 @@ void DepNode::joinBuild() { | |||
| } | |||
| void DepNode::writeCompDB(const std::string &outDir, compdb::Writer &w) { | |||
| std::unique_lock<std::mutex> lock(mut_);\ | |||
| std::unique_lock<std::mutex> lock(mut_); | |||
| doWriteCompDB(outDir, w); | |||
| lock.unlock(); | |||
| @@ -0,0 +1,123 @@ | |||
| #pragma once | |||
| #include <iostream> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| namespace bufio { | |||
| template<size_t bufsiz = 1024> | |||
| class IBuf { | |||
| public: | |||
| IBuf(std::istream &is): is_(is) {} | |||
| char get(); | |||
| int peek(); | |||
| int peek2(); | |||
| private: | |||
| std::istream &is_; | |||
| char buf_[bufsiz]; | |||
| size_t idx_ = 0; | |||
| size_t len_ = 0; | |||
| }; | |||
| template<size_t bufsiz = 1024> | |||
| class OBuf { | |||
| public: | |||
| OBuf(std::ostream &os): os_(os) {} | |||
| ~OBuf(); | |||
| void put(char ch); | |||
| void put(const char *str, size_t len); | |||
| void put(const char *str) { put(str, strlen(str)); } | |||
| void put(const std::string &str) { put(str.c_str(), str.size()); } | |||
| private: | |||
| std::ostream &os_; | |||
| char buf_[bufsiz]; | |||
| size_t idx_ = 0; | |||
| }; | |||
| /* | |||
| * IBuf | |||
| */ | |||
| template<size_t bufsiz> | |||
| inline char IBuf<bufsiz>::get() { | |||
| if (idx_ < len_) { | |||
| return buf_[idx_++]; | |||
| } | |||
| idx_ = 0; | |||
| is_.read(buf_, sizeof(buf_)); | |||
| len_ = is_.gcount(); | |||
| if (len_ == 0) { | |||
| return EOF; | |||
| } | |||
| return buf_[idx_++]; | |||
| } | |||
| template<size_t bufsiz> | |||
| inline int IBuf<bufsiz>::peek() { | |||
| if (idx_ < len_) { | |||
| return buf_[idx_]; | |||
| } else { | |||
| return is_.peek(); | |||
| } | |||
| } | |||
| template<size_t bufsiz> | |||
| inline int IBuf<bufsiz>::peek2() { | |||
| if (idx_ + 1 < len_) { | |||
| return buf_[idx_ + 1]; | |||
| } else if (idx_ < len_) { | |||
| return is_.peek(); | |||
| } else { | |||
| is_.get(); | |||
| int ch = is_.peek(); | |||
| is_.unget(); | |||
| return ch; | |||
| } | |||
| } | |||
| /* | |||
| * OBuf | |||
| */ | |||
| template<size_t bufsiz> | |||
| inline OBuf<bufsiz>::~OBuf() { | |||
| if (idx_ > 0) { | |||
| os_.write(buf_, idx_); | |||
| } | |||
| } | |||
| template<size_t bufsiz> | |||
| inline void OBuf<bufsiz>::put(char ch) { | |||
| buf_[idx_++] = ch; | |||
| if (idx_ == sizeof(buf_)) { | |||
| os_.write(buf_, sizeof(buf_)); | |||
| idx_ = 0; | |||
| } | |||
| } | |||
| template<size_t bufsiz> | |||
| inline void OBuf<bufsiz>::put(const char *str, size_t len) { | |||
| size_t w = sizeof(buf_) - idx_ - 1; | |||
| if (w > len) { | |||
| w = len; | |||
| } | |||
| memcpy(buf_ + idx_, str, w); | |||
| if (len - w > 0) { | |||
| os_.write(buf_, idx_ + w); | |||
| os_.write(str + w, len - w); | |||
| idx_ = 0; | |||
| } else { | |||
| idx_ += w; | |||
| } | |||
| } | |||
| } | |||
| @@ -29,29 +29,34 @@ void Writer::write( | |||
| const std::string &dir, const std::string &file, | |||
| const std::vector<std::string> &cmd) { | |||
| if (first_) { | |||
| stream_ << "[\n\t{\n"; | |||
| buf_.put("[\n\t{\n"); | |||
| first_ = false; | |||
| } else { | |||
| stream_ << ", {\n"; | |||
| buf_.put(", {\n"); | |||
| } | |||
| stream_ | |||
| << "\t\t\"directory\": \"" << escape(dir) << "\",\n" | |||
| << "\t\t\"file\": \"" << escape(file) << "\",\n" | |||
| << "\t\t\"command\": \"" << escape(cmd[0]); | |||
| buf_.put("\t\t\"directory\": \""); | |||
| buf_.put(escape(dir)); | |||
| buf_.put("\",\n"); | |||
| buf_.put("\t\t\"file\": \""); | |||
| buf_.put(escape(file)); | |||
| buf_.put("\",\n"); | |||
| buf_.put("\t\t\"command\": \""); | |||
| buf_.put(escape(cmd[0])); | |||
| for (size_t i = 1; i < cmd.size(); ++i) { | |||
| stream_ << ' ' << escape('"' + escape(cmd[i]) + '"'); | |||
| buf_.put(' '); | |||
| buf_.put(escape('"' + escape(cmd[i]) + '"')); | |||
| } | |||
| stream_ << "\"\n\t}"; | |||
| buf_.put("\"\n\t}"); | |||
| } | |||
| Writer::~Writer() { | |||
| if (first_) { | |||
| stream_ << "[]\n"; | |||
| buf_.put("[]\n"); | |||
| } else { | |||
| stream_ << "\n]\n"; | |||
| buf_.put("\n]\n"); | |||
| } | |||
| } | |||
| @@ -4,11 +4,13 @@ | |||
| #include <vector> | |||
| #include <ostream> | |||
| #include "bufio.h" | |||
| namespace compdb { | |||
| class Writer { | |||
| public: | |||
| Writer(std::ostream &stream): stream_(stream) {} | |||
| Writer(std::ostream &stream): buf_(stream) {} | |||
| ~Writer(); | |||
| void write( | |||
| @@ -16,7 +18,7 @@ public: | |||
| const std::vector<std::string> &cmd); | |||
| private: | |||
| std::ostream &stream_; | |||
| bufio::OBuf<> buf_; | |||
| bool first_ = true; | |||
| }; | |||