1 //===-- ResourceScriptCppFilter.cpp ----------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===---------------------------------------------------------------------===// 9 // 10 // This file implements an interface defined in ResourceScriptCppFilter.h. 11 // 12 //===---------------------------------------------------------------------===// 13 14 #include "ResourceScriptCppFilter.h" 15 #include "llvm/ADT/StringExtras.h" 16 17 #include <vector> 18 19 using namespace llvm; 20 21 namespace { 22 23 class Filter { 24 public: Filter(StringRef Input)25 explicit Filter(StringRef Input) : Data(Input), DataLength(Input.size()) {} 26 27 std::string run(); 28 29 private: 30 // Parse the line, returning whether the line should be included in 31 // the output. 32 bool parseLine(StringRef Line); 33 34 bool streamEof() const; 35 36 StringRef Data; 37 size_t DataLength; 38 39 size_t Pos = 0; 40 bool Outputting = true; 41 }; 42 run()43std::string Filter::run() { 44 std::vector<StringRef> Output; 45 46 while (!streamEof() && Pos != StringRef::npos) { 47 size_t LineStart = Pos; 48 Pos = Data.find_first_of("\r\n", Pos); 49 Pos = Data.find_first_not_of("\r\n", Pos); 50 StringRef Line = Data.take_front(Pos).drop_front(LineStart); 51 52 if (parseLine(Line)) 53 Output.push_back(Line); 54 } 55 56 return llvm::join(Output, ""); 57 } 58 parseLine(StringRef Line)59bool Filter::parseLine(StringRef Line) { 60 Line = Line.ltrim(); 61 62 if (!Line.consume_front("#")) { 63 // A normal content line, filtered according to the current mode. 64 return Outputting; 65 } 66 67 // Found a preprocessing directive line. From here on, we always return 68 // false since the preprocessing directives should be filtered out. 69 70 Line.consume_front("line"); 71 if (!Line.startswith(" ")) 72 return false; // Not a line directive (pragma etc). 73 74 // #line 123 "path/file.h" 75 // # 123 "path/file.h" 1 76 77 Line = 78 Line.ltrim(); // There could be multiple spaces after the #line directive 79 80 size_t N; 81 if (Line.consumeInteger(10, N)) // Returns true to signify an error 82 return false; 83 84 Line = Line.ltrim(); 85 86 if (!Line.consume_front("\"")) 87 return false; // Malformed line, no quote found. 88 89 // Split the string at the last quote (in case the path name had 90 // escaped quotes as well). 91 Line = Line.rsplit('"').first; 92 93 StringRef Ext = Line.rsplit('.').second; 94 95 if (Ext.equals_lower("h") || Ext.equals_lower("c")) { 96 Outputting = false; 97 } else { 98 Outputting = true; 99 } 100 101 return false; 102 } 103 streamEof() const104bool Filter::streamEof() const { return Pos == DataLength; } 105 106 } // anonymous namespace 107 108 namespace llvm { 109 filterCppOutput(StringRef Input)110std::string filterCppOutput(StringRef Input) { return Filter(Input).run(); } 111 112 } // namespace llvm 113