run_compile_commands.cxx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "cmSystemTools.h"
  2. class CompileCommandParser {
  3. public:
  4. class CommandType: public std::map<cmStdString, cmStdString>
  5. {
  6. public:
  7. cmStdString const& at(cmStdString const& k) const
  8. {
  9. const_iterator i = this->find(k);
  10. if(i != this->end()) { return i->second; }
  11. static cmStdString emptyString;
  12. return emptyString;
  13. }
  14. };
  15. typedef std::vector<CommandType> TranslationUnitsType;
  16. CompileCommandParser(std::ifstream *input)
  17. {
  18. this->Input = input;
  19. }
  20. void Parse()
  21. {
  22. NextNonWhitespace();
  23. ParseTranslationUnits();
  24. }
  25. const TranslationUnitsType& GetTranslationUnits()
  26. {
  27. return this->TranslationUnits;
  28. }
  29. private:
  30. void ParseTranslationUnits()
  31. {
  32. this->TranslationUnits = TranslationUnitsType();
  33. ExpectOrDie('[', "at start of compile command file\n");
  34. do
  35. {
  36. ParseTranslationUnit();
  37. this->TranslationUnits.push_back(this->Command);
  38. } while(Expect(','));
  39. ExpectOrDie(']', "at end of array");
  40. }
  41. void ParseTranslationUnit()
  42. {
  43. this->Command = CommandType();
  44. if(!Expect('{')) return;
  45. if(Expect('}')) return;
  46. do
  47. {
  48. ParseString();
  49. std::string name = this->String;
  50. ExpectOrDie(':', "between name and value");
  51. ParseString();
  52. std::string value = this->String;
  53. this->Command[name] = value;
  54. } while(Expect(','));
  55. ExpectOrDie('}', "at end of object");
  56. }
  57. void ParseString()
  58. {
  59. this->String = "";
  60. if(!Expect('"')) return;
  61. while (!Expect('"'))
  62. {
  63. Expect('\\');
  64. this->String.append(1,C);
  65. Next();
  66. }
  67. }
  68. bool Expect(char c)
  69. {
  70. if(this->C == c)
  71. {
  72. NextNonWhitespace();
  73. return true;
  74. }
  75. return false;
  76. }
  77. void ExpectOrDie(char c, const std::string & message)
  78. {
  79. if (!Expect(c))
  80. ErrorExit(std::string("'") + c + "' expected " + message + ".");
  81. }
  82. void NextNonWhitespace()
  83. {
  84. do { Next(); } while (IsWhitespace());
  85. }
  86. void Next()
  87. {
  88. this->C = char(Input->get());
  89. if (this->Input->bad()) ErrorExit("Unexpected end of file.");
  90. }
  91. void ErrorExit(const std::string &message) {
  92. std::cout << "ERROR: " << message;
  93. exit(1);
  94. }
  95. bool IsWhitespace()
  96. {
  97. return (this->C == ' ' || this->C == '\t' ||
  98. this->C == '\n' || this->C == '\r');
  99. }
  100. char C;
  101. TranslationUnitsType TranslationUnits;
  102. CommandType Command;
  103. std::string String;
  104. std::ifstream *Input;
  105. };
  106. int main ()
  107. {
  108. std::ifstream file("compile_commands.json");
  109. CompileCommandParser parser(&file);
  110. parser.Parse();
  111. for(CompileCommandParser::TranslationUnitsType::const_iterator
  112. it = parser.GetTranslationUnits().begin(),
  113. end = parser.GetTranslationUnits().end(); it != end; ++it)
  114. {
  115. std::vector<cmStdString> command;
  116. cmSystemTools::ParseUnixCommandLine(it->at("command").c_str(), command);
  117. if (!cmSystemTools::RunSingleCommand(
  118. command, 0, 0, it->at("directory").c_str()))
  119. {
  120. std::cout << "ERROR: Failed to run command \""
  121. << command[0] << "\"" << std::endl;
  122. exit(1);
  123. }
  124. }
  125. return 0;
  126. }