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