| HDRS = \ | HDRS = \ | ||||
| src/BXParser.h src/build.h src/compdb.h src/CompileStep.h src/DepNode.h \ | 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/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 | BUILD = build | ||||
| OBJS = $(patsubst %,$(BUILD)/%.o,$(SRCS)) | OBJS = $(patsubst %,$(BUILD)/%.o,$(SRCS)) | ||||
| CFLAGS = -g -O3 -Wall -Wextra -Wno-unused-parameter | |||||
| CFLAGS = -O3 -g -Wall -Wextra -Wno-unused-parameter | |||||
| LDLIBS = -lpthread | LDLIBS = -lpthread | ||||
| $(BUILD)/%.cc.o: %.cc $(HDRS) | $(BUILD)/%.cc.o: %.cc $(HDRS) |
| #include <errno.h> | #include <errno.h> | ||||
| int BXParser::get() { | 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() { | int BXParser::peek() { | ||||
| if (bufidx_ < buflen_) { | |||||
| return buf_[bufidx_]; | |||||
| } else { | |||||
| return stream_.peek(); | |||||
| } | |||||
| return buf_.peek(); | |||||
| } | } | ||||
| int BXParser::peek2() { | 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() { | BXParser::Operator BXParser::readOperator() { | ||||
| } | } | ||||
| } | } | ||||
| 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) { | void BXWriter::escape(const std::string &str) { | ||||
| put('"'); | |||||
| buf_.put('"'); | |||||
| for (char ch: str) { | for (char ch: str) { | ||||
| if (ch == '$' || ch == '"' || ch == '\\') { | if (ch == '$' || ch == '"' || ch == '\\') { | ||||
| put('\\'); | |||||
| buf_.put('\\'); | |||||
| } | } | ||||
| put(ch); | |||||
| buf_.put(ch); | |||||
| } | } | ||||
| put('"'); | |||||
| buf_.put('"'); | |||||
| } | } | ||||
| void BXWriter::write(const BXVariables &vars) { | void BXWriter::write(const BXVariables &vars) { | ||||
| for (const auto &pair: vars) { | for (const auto &pair: vars) { | ||||
| size_t chars = 0; | size_t chars = 0; | ||||
| put(pair.first); | |||||
| put(" :="); | |||||
| buf_.put(pair.first); | |||||
| buf_.put(" :="); | |||||
| for (auto &val: pair.second) { | for (auto &val: pair.second) { | ||||
| if (chars >= 80) { | if (chars >= 80) { | ||||
| put('\n'); | |||||
| put('\t'); | |||||
| buf_.put('\n'); | |||||
| buf_.put('\t'); | |||||
| chars = 0; | chars = 0; | ||||
| } else { | } else { | ||||
| put(' '); | |||||
| buf_.put(' '); | |||||
| } | } | ||||
| escape(val); | escape(val); | ||||
| chars += val.size(); | chars += val.size(); | ||||
| } | } | ||||
| put('\n'); | |||||
| buf_.put('\n'); | |||||
| } | } | ||||
| } | } |
| #include <iostream> | #include <iostream> | ||||
| #include <exception> | #include <exception> | ||||
| #include "bufio.h" | |||||
| struct BXParseError: std::exception { | struct BXParseError: std::exception { | ||||
| BXParseError(std::string msg): message(msg) {} | BXParseError(std::string msg): message(msg) {} | ||||
| std::string message; | std::string message; | ||||
| static const int FLAG_ONE_LINE = 1 << 0; | static const int FLAG_ONE_LINE = 1 << 0; | ||||
| BXParser(std::istream &stream, int flags, int line = 1, int ch = 1): | 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 parse(BXVariables &vars); | ||||
| void parseList(const BXVariables &vars, std::vector<std::string> &values); | void parseList(const BXVariables &vars, std::vector<std::string> &values); | ||||
| int line_; | int line_; | ||||
| int ch_; | int ch_; | ||||
| std::istream &stream_; | |||||
| char buf_[1024]; | |||||
| size_t bufidx_ = 0; | |||||
| size_t buflen_ = 0; | |||||
| bufio::IBuf<> buf_; | |||||
| }; | }; | ||||
| class BXWriter { | class BXWriter { | ||||
| public: | public: | ||||
| BXWriter(std::ostream &stream): stream_(stream) {} | |||||
| ~BXWriter(); | |||||
| BXWriter(std::ostream &stream): buf_(stream) {} | |||||
| void write(const BXVariables &vars); | void write(const BXVariables &vars); | ||||
| private: | private: | ||||
| void put(char ch); | |||||
| void put(const std::string &str); | |||||
| void newline(); | void newline(); | ||||
| void escape(const std::string &str); | void escape(const std::string &str); | ||||
| std::ostream &stream_; | |||||
| char buf_[1024]; | |||||
| size_t bufidx_ = 0; | |||||
| bufio::OBuf<> buf_; | |||||
| }; | }; |
| } | } | ||||
| void DepNode::writeCompDB(const std::string &outDir, compdb::Writer &w) { | 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); | doWriteCompDB(outDir, w); | ||||
| lock.unlock(); | lock.unlock(); | ||||
| #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; | |||||
| } | |||||
| } | |||||
| } |
| const std::string &dir, const std::string &file, | const std::string &dir, const std::string &file, | ||||
| const std::vector<std::string> &cmd) { | const std::vector<std::string> &cmd) { | ||||
| if (first_) { | if (first_) { | ||||
| stream_ << "[\n\t{\n"; | |||||
| buf_.put("[\n\t{\n"); | |||||
| first_ = false; | first_ = false; | ||||
| } else { | } 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) { | 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() { | Writer::~Writer() { | ||||
| if (first_) { | if (first_) { | ||||
| stream_ << "[]\n"; | |||||
| buf_.put("[]\n"); | |||||
| } else { | } else { | ||||
| stream_ << "\n]\n"; | |||||
| buf_.put("\n]\n"); | |||||
| } | } | ||||
| } | } | ||||
| #include <vector> | #include <vector> | ||||
| #include <ostream> | #include <ostream> | ||||
| #include "bufio.h" | |||||
| namespace compdb { | namespace compdb { | ||||
| class Writer { | class Writer { | ||||
| public: | public: | ||||
| Writer(std::ostream &stream): stream_(stream) {} | |||||
| Writer(std::ostream &stream): buf_(stream) {} | |||||
| ~Writer(); | ~Writer(); | ||||
| void write( | void write( | ||||
| const std::vector<std::string> &cmd); | const std::vector<std::string> &cmd); | ||||
| private: | private: | ||||
| std::ostream &stream_; | |||||
| bufio::OBuf<> buf_; | |||||
| bool first_ = true; | bool first_ = true; | ||||
| }; | }; | ||||