1518b6c98SMartin Storsjo //===-- ResourceScriptCppFilter.cpp ----------------------------*- C++ -*-===//
2518b6c98SMartin Storsjo //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6518b6c98SMartin Storsjo //
7518b6c98SMartin Storsjo //===---------------------------------------------------------------------===//
8518b6c98SMartin Storsjo //
9518b6c98SMartin Storsjo // This file implements an interface defined in ResourceScriptCppFilter.h.
10518b6c98SMartin Storsjo //
11518b6c98SMartin Storsjo //===---------------------------------------------------------------------===//
12518b6c98SMartin Storsjo
13518b6c98SMartin Storsjo #include "ResourceScriptCppFilter.h"
14518b6c98SMartin Storsjo #include "llvm/ADT/StringExtras.h"
15518b6c98SMartin Storsjo
16518b6c98SMartin Storsjo #include <vector>
17518b6c98SMartin Storsjo
18518b6c98SMartin Storsjo using namespace llvm;
19518b6c98SMartin Storsjo
20518b6c98SMartin Storsjo namespace {
21518b6c98SMartin Storsjo
22518b6c98SMartin Storsjo class Filter {
23518b6c98SMartin Storsjo public:
Filter(StringRef Input)24518b6c98SMartin Storsjo explicit Filter(StringRef Input) : Data(Input), DataLength(Input.size()) {}
25518b6c98SMartin Storsjo
26518b6c98SMartin Storsjo std::string run();
27518b6c98SMartin Storsjo
28518b6c98SMartin Storsjo private:
29518b6c98SMartin Storsjo // Parse the line, returning whether the line should be included in
30518b6c98SMartin Storsjo // the output.
31518b6c98SMartin Storsjo bool parseLine(StringRef Line);
32518b6c98SMartin Storsjo
33518b6c98SMartin Storsjo bool streamEof() const;
34518b6c98SMartin Storsjo
35518b6c98SMartin Storsjo StringRef Data;
36518b6c98SMartin Storsjo size_t DataLength;
37518b6c98SMartin Storsjo
38518b6c98SMartin Storsjo size_t Pos = 0;
39518b6c98SMartin Storsjo bool Outputting = true;
40518b6c98SMartin Storsjo };
41518b6c98SMartin Storsjo
run()42518b6c98SMartin Storsjo std::string Filter::run() {
43518b6c98SMartin Storsjo std::vector<StringRef> Output;
44518b6c98SMartin Storsjo
45518b6c98SMartin Storsjo while (!streamEof() && Pos != StringRef::npos) {
46518b6c98SMartin Storsjo size_t LineStart = Pos;
47518b6c98SMartin Storsjo Pos = Data.find_first_of("\r\n", Pos);
48518b6c98SMartin Storsjo Pos = Data.find_first_not_of("\r\n", Pos);
49518b6c98SMartin Storsjo StringRef Line = Data.take_front(Pos).drop_front(LineStart);
50518b6c98SMartin Storsjo
51518b6c98SMartin Storsjo if (parseLine(Line))
52518b6c98SMartin Storsjo Output.push_back(Line);
53518b6c98SMartin Storsjo }
54518b6c98SMartin Storsjo
55518b6c98SMartin Storsjo return llvm::join(Output, "");
56518b6c98SMartin Storsjo }
57518b6c98SMartin Storsjo
parseLine(StringRef Line)58518b6c98SMartin Storsjo bool Filter::parseLine(StringRef Line) {
59518b6c98SMartin Storsjo Line = Line.ltrim();
60518b6c98SMartin Storsjo
61518b6c98SMartin Storsjo if (!Line.consume_front("#")) {
62518b6c98SMartin Storsjo // A normal content line, filtered according to the current mode.
63518b6c98SMartin Storsjo return Outputting;
64518b6c98SMartin Storsjo }
65518b6c98SMartin Storsjo
66518b6c98SMartin Storsjo // Found a preprocessing directive line. From here on, we always return
67518b6c98SMartin Storsjo // false since the preprocessing directives should be filtered out.
68518b6c98SMartin Storsjo
69518b6c98SMartin Storsjo Line.consume_front("line");
70*586ecdf2SKazu Hirata if (!Line.starts_with(" "))
71518b6c98SMartin Storsjo return false; // Not a line directive (pragma etc).
72518b6c98SMartin Storsjo
73518b6c98SMartin Storsjo // #line 123 "path/file.h"
74518b6c98SMartin Storsjo // # 123 "path/file.h" 1
75518b6c98SMartin Storsjo
76518b6c98SMartin Storsjo Line =
77518b6c98SMartin Storsjo Line.ltrim(); // There could be multiple spaces after the #line directive
78518b6c98SMartin Storsjo
79518b6c98SMartin Storsjo size_t N;
80518b6c98SMartin Storsjo if (Line.consumeInteger(10, N)) // Returns true to signify an error
81518b6c98SMartin Storsjo return false;
82518b6c98SMartin Storsjo
83518b6c98SMartin Storsjo Line = Line.ltrim();
84518b6c98SMartin Storsjo
85518b6c98SMartin Storsjo if (!Line.consume_front("\""))
86518b6c98SMartin Storsjo return false; // Malformed line, no quote found.
87518b6c98SMartin Storsjo
88518b6c98SMartin Storsjo // Split the string at the last quote (in case the path name had
89518b6c98SMartin Storsjo // escaped quotes as well).
90518b6c98SMartin Storsjo Line = Line.rsplit('"').first;
91518b6c98SMartin Storsjo
92518b6c98SMartin Storsjo StringRef Ext = Line.rsplit('.').second;
93518b6c98SMartin Storsjo
9442f74e82SMartin Storsjö if (Ext.equals_insensitive("h") || Ext.equals_insensitive("c")) {
95518b6c98SMartin Storsjo Outputting = false;
96518b6c98SMartin Storsjo } else {
97518b6c98SMartin Storsjo Outputting = true;
98518b6c98SMartin Storsjo }
99518b6c98SMartin Storsjo
100518b6c98SMartin Storsjo return false;
101518b6c98SMartin Storsjo }
102518b6c98SMartin Storsjo
streamEof() const103518b6c98SMartin Storsjo bool Filter::streamEof() const { return Pos == DataLength; }
104518b6c98SMartin Storsjo
105518b6c98SMartin Storsjo } // anonymous namespace
106518b6c98SMartin Storsjo
107518b6c98SMartin Storsjo namespace llvm {
108518b6c98SMartin Storsjo
filterCppOutput(StringRef Input)109518b6c98SMartin Storsjo std::string filterCppOutput(StringRef Input) { return Filter(Input).run(); }
110518b6c98SMartin Storsjo
111518b6c98SMartin Storsjo } // namespace llvm
112