run_compile_commands.cxx 3.1 KB

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