123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- #include "cmConfigure.h" // IWYU pragma: keep
- #include "cmsys/FStream.hxx"
- #include <iostream>
- #include <map>
- #include <stdlib.h>
- #include <string>
- #include <utility>
- #include <vector>
- #include "cmSystemTools.h"
- class CompileCommandParser
- {
- public:
- class CommandType : public std::map<std::string, std::string>
- {
- 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<CommandType> TranslationUnitsType;
- CompileCommandParser(std::istream& input)
- : 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::istream& Input;
- };
- int main()
- {
- cmsys::ifstream file("compile_commands.json");
- CompileCommandParser parser(file);
- parser.Parse();
- for (auto const& tu : parser.GetTranslationUnits()) {
- std::vector<std::string> command;
- cmSystemTools::ParseUnixCommandLine(tu.at("command").c_str(), command);
- if (!cmSystemTools::RunSingleCommand(command, nullptr, nullptr, nullptr,
- tu.at("directory").c_str())) {
- std::cout << "ERROR: Failed to run command \"" << command[0] << "\""
- << std::endl;
- exit(1);
- }
- }
- return 0;
- }
|