1 //===-- Implementation of the main header generation class ----------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "IncludeFileCommand.h"
12 #include "PublicAPICommand.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/raw_ostream.h"
22 static const char CommandPrefix
[] = "%%";
23 static const size_t CommandPrefixSize
= llvm::StringRef(CommandPrefix
).size();
25 static const char CommentPrefix
[] = "<!>";
27 static const char ParamNamePrefix
[] = "${";
28 static const size_t ParamNamePrefixSize
=
29 llvm::StringRef(ParamNamePrefix
).size();
30 static const char ParamNameSuffix
[] = "}";
31 static const size_t ParamNameSuffixSize
=
32 llvm::StringRef(ParamNameSuffix
).size();
36 Command
*Generator::getCommandHandler(llvm::StringRef CommandName
) {
37 if (CommandName
== IncludeFileCommand::Name
) {
39 IncludeFileCmd
= std::make_unique
<IncludeFileCommand
>();
40 return IncludeFileCmd
.get();
41 } else if (CommandName
== PublicAPICommand::Name
) {
43 PublicAPICmd
= std::make_unique
<PublicAPICommand
>(EntrypointNameList
);
44 return PublicAPICmd
.get();
50 void Generator::parseCommandArgs(llvm::StringRef ArgStr
, ArgVector
&Args
) {
51 if (!ArgStr
.contains(',') && ArgStr
.trim(' ').trim('\t').size() == 0) {
52 // If it is just space between the parenthesis
56 ArgStr
.split(Args
, ",");
57 for (llvm::StringRef
&A
: Args
) {
59 if (A
.startswith(ParamNamePrefix
) && A
.endswith(ParamNameSuffix
)) {
60 A
= A
.drop_front(ParamNamePrefixSize
).drop_back(ParamNameSuffixSize
);
61 A
= ArgMap
[std::string(A
)];
66 void Generator::generate(llvm::raw_ostream
&OS
, llvm::RecordKeeper
&Records
) {
67 auto DefFileBuffer
= llvm::MemoryBuffer::getFile(HeaderDefFile
);
69 llvm::errs() << "Unable to open " << HeaderDefFile
<< ".\n";
72 llvm::SourceMgr SrcMgr
;
73 unsigned DefFileID
= SrcMgr
.AddNewSourceBuffer(
74 std::move(DefFileBuffer
.get()), llvm::SMLoc::getFromPointer(nullptr));
76 llvm::StringRef Content
= SrcMgr
.getMemoryBuffer(DefFileID
)->getBuffer();
78 std::pair
<llvm::StringRef
, llvm::StringRef
> P
= Content
.split('\n');
81 llvm::StringRef Line
= P
.first
.trim(' ');
82 if (Line
.startswith(CommandPrefix
)) {
83 Line
= Line
.drop_front(CommandPrefixSize
);
86 if (P
.second
.empty() || P
.second
[P
.second
.size() - 1] != ')') {
87 SrcMgr
.PrintMessage(llvm::SMLoc::getFromPointer(P
.second
.data()),
88 llvm::SourceMgr::DK_Error
,
89 "Command argument list should begin with '(' "
93 llvm::StringRef CommandName
= P
.first
;
94 Command
*Cmd
= getCommandHandler(CommandName
);
96 SrcMgr
.PrintMessage(llvm::SMLoc::getFromPointer(CommandName
.data()),
97 llvm::SourceMgr::DK_Error
,
98 "Unknown command '%%" + CommandName
+ "'.");
102 llvm::StringRef ArgStr
= P
.second
.drop_back(1);
104 parseCommandArgs(ArgStr
, Args
);
106 Command::ErrorReporter
Reporter(
107 llvm::SMLoc::getFromPointer(CommandName
.data()), SrcMgr
);
108 Cmd
->run(OS
, Args
, StdHeader
, Records
, Reporter
);
109 } else if (!Line
.startswith(CommentPrefix
)) {
110 // There is no comment or command on this line so we just write it as is.
111 OS
<< P
.first
<< "\n";
114 if (P
.second
.empty())
119 } // namespace llvm_libc