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
18using namespace llvm;
19
20namespace {
21
22class Filter {
23public:
24 explicit Filter(StringRef Input) : Data(Input), DataLength(Input.size()) {}
25
26 std::string run();
27
28private:
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
42std::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(Chars: "\r\n", From: Pos);
48 Pos = Data.find_first_not_of(Chars: "\r\n", From: Pos);
49 StringRef Line = Data.take_front(N: Pos).drop_front(N: LineStart);
50
51 if (parseLine(Line))
52 Output.push_back(x: Line);
53 }
54
55 return llvm::join(R&: Output, Separator: "");
56}
57
58bool Filter::parseLine(StringRef Line) {
59 Line = Line.ltrim();
60
61 if (!Line.consume_front(Prefix: "#")) {
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(Prefix: "line");
70 if (!Line.starts_with(Prefix: " "))
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(Radix: 10, Result&: N)) // Returns true to signify an error
81 return false;
82
83 Line = Line.ltrim();
84
85 if (!Line.consume_front(Prefix: "\""))
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(Separator: '"').first;
91
92 StringRef Ext = Line.rsplit(Separator: '.').second;
93
94 if (Ext.equals_insensitive(RHS: "h") || Ext.equals_insensitive(RHS: "c")) {
95 Outputting = false;
96 } else {
97 Outputting = true;
98 }
99
100 return false;
101}
102
103bool Filter::streamEof() const { return Pos == DataLength; }
104
105} // anonymous namespace
106
107namespace llvm {
108
109std::string filterCppOutput(StringRef Input) { return Filter(Input).run(); }
110
111} // namespace llvm
112