#include "cmSystemTools.h" class CompileCommandParser { public: class CommandType : public std::map { public: std::string const& at(std::string const& k) const { const_iterator i = this->find(k); if (i != this->end()) { return i->second; } static std::string emptyString; return emptyString; } }; typedef std::vector TranslationUnitsType; CompileCommandParser(std::ifstream* input) { this->Input = input; } void Parse() { NextNonWhitespace(); ParseTranslationUnits(); } const TranslationUnitsType& GetTranslationUnits() { return this->TranslationUnits; } private: void ParseTranslationUnits() { this->TranslationUnits = TranslationUnitsType(); ExpectOrDie('[', "at start of compile command file\n"); do { ParseTranslationUnit(); this->TranslationUnits.push_back(this->Command); } while (Expect(',')); ExpectOrDie(']', "at end of array"); } void ParseTranslationUnit() { this->Command = CommandType(); if (!Expect('{')) return; if (Expect('}')) return; do { ParseString(); std::string name = this->String; ExpectOrDie(':', "between name and value"); ParseString(); std::string value = this->String; this->Command[name] = value; } while (Expect(',')); ExpectOrDie('}', "at end of object"); } void ParseString() { this->String = ""; if (!Expect('"')) return; while (!Expect('"')) { Expect('\\'); this->String.append(1, C); Next(); } } bool Expect(char c) { if (this->C == c) { NextNonWhitespace(); return true; } return false; } void ExpectOrDie(char c, const std::string& message) { if (!Expect(c)) ErrorExit(std::string("'") + c + "' expected " + message + "."); } void NextNonWhitespace() { do { Next(); } while (IsWhitespace()); } void Next() { this->C = char(Input->get()); if (this->Input->bad()) ErrorExit("Unexpected end of file."); } void ErrorExit(const std::string& message) { std::cout << "ERROR: " << message; exit(1); } bool IsWhitespace() { return (this->C == ' ' || this->C == '\t' || this->C == '\n' || this->C == '\r'); } char C; TranslationUnitsType TranslationUnits; CommandType Command; std::string String; std::ifstream* Input; }; int main() { std::ifstream file("compile_commands.json"); CompileCommandParser parser(&file); parser.Parse(); for (CompileCommandParser::TranslationUnitsType::const_iterator it = parser.GetTranslationUnits().begin(), end = parser.GetTranslationUnits().end(); it != end; ++it) { std::vector command; cmSystemTools::ParseUnixCommandLine(it->at("command").c_str(), command); if (!cmSystemTools::RunSingleCommand(command, 0, 0, 0, it->at("directory").c_str())) { std::cout << "ERROR: Failed to run command \"" << command[0] << "\"" << std::endl; exit(1); } } return 0; }