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; | ||||
}; | }; | ||||