xref: /llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp (revision 586ecdf205aa8b3d162da6f955170a6736656615)
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