run_compile_commands.cxx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. }
  46. if (Expect('}')) {
  47. return;
  48. }
  49. do {
  50. ParseString();
  51. std::string name = this->String;
  52. ExpectOrDie(':', "between name and value");
  53. ParseString();
  54. std::string value = this->String;
  55. this->Command[name] = value;
  56. } while (Expect(','));
  57. ExpectOrDie('}', "at end of object");
  58. }
  59. void ParseString()
  60. {
  61. this->String = "";
  62. if (!Expect('"')) {
  63. return;
  64. }
  65. while (!Expect('"')) {
  66. Expect('\\');
  67. this->String.append(1, C);
  68. Next();
  69. }
  70. }
  71. bool Expect(char c)
  72. {
  73. if (this->C == c) {
  74. NextNonWhitespace();
  75. return true;
  76. }
  77. return false;
  78. }
  79. void ExpectOrDie(char c, const std::string& message)
  80. {
  81. if (!Expect(c)) {
  82. ErrorExit(std::string("'") + c + "' expected " + message + ".");
  83. }
  84. }
  85. void NextNonWhitespace()
  86. {
  87. do {
  88. Next();
  89. } while (IsWhitespace());
  90. }
  91. void Next()
  92. {
  93. this->C = char(Input->get());
  94. if (this->Input->bad()) {
  95. ErrorExit("Unexpected end of file.");
  96. }
  97. }
  98. void ErrorExit(const std::string& message)
  99. {
  100. std::cout << "ERROR: " << message;
  101. exit(1);
  102. }
  103. bool IsWhitespace()
  104. {
  105. return (this->C == ' ' || this->C == '\t' || this->C == '\n' ||
  106. this->C == '\r');
  107. }
  108. char C;
  109. TranslationUnitsType TranslationUnits;
  110. CommandType Command;
  111. std::string String;
  112. std::ifstream* Input;
  113. };
  114. int main()
  115. {
  116. std::ifstream file("compile_commands.json");
  117. CompileCommandParser parser(&file);
  118. parser.Parse();
  119. for (CompileCommandParser::TranslationUnitsType::const_iterator
  120. it = parser.GetTranslationUnits().begin(),
  121. end = parser.GetTranslationUnits().end();
  122. it != end; ++it) {
  123. std::vector<std::string> command;
  124. cmSystemTools::ParseUnixCommandLine(it->at("command").c_str(), command);
  125. if (!cmSystemTools::RunSingleCommand(command, 0, 0, 0,
  126. it->at("directory").c_str())) {
  127. std::cout << "ERROR: Failed to run command \"" << command[0] << "\""
  128. << std::endl;
  129. exit(1);
  130. }
  131. }
  132. return 0;
  133. }