run_compile_commands.cxx 3.2 KB

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