1 | //===- CodeExpander.cpp - Expand variables in a string --------------------===// |
---|---|
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 | /// \file Expand the variables in a string. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "CodeExpander.h" |
14 | #include "CodeExpansions.h" |
15 | #include "llvm/Support/raw_ostream.h" |
16 | #include "llvm/TableGen/Error.h" |
17 | |
18 | using namespace llvm; |
19 | |
20 | void CodeExpander::emit(raw_ostream &OS) const { |
21 | StringRef Current = Code; |
22 | |
23 | while (!Current.empty()) { |
24 | size_t Pos = Current.find_first_of(Chars: "$\n\\"); |
25 | if (Pos == StringRef::npos) { |
26 | OS << Current; |
27 | Current = ""; |
28 | continue; |
29 | } |
30 | |
31 | OS << Current.substr(Start: 0, N: Pos); |
32 | Current = Current.substr(Start: Pos); |
33 | |
34 | if (Current.consume_front(Prefix: "\n")) { |
35 | OS << "\n"<< Indent; |
36 | continue; |
37 | } |
38 | |
39 | if (Current.starts_with(Prefix: "\\$") || Current.starts_with(Prefix: "\\\\")) { |
40 | OS << Current[1]; |
41 | Current = Current.drop_front(N: 2); |
42 | continue; |
43 | } |
44 | |
45 | if (Current.consume_front(Prefix: "\\")) |
46 | continue; |
47 | |
48 | if (Current.starts_with(Prefix: "${")) { |
49 | StringRef StartVar = Current; |
50 | Current = Current.drop_front(N: 2); |
51 | StringRef Var; |
52 | std::tie(args&: Var, args&: Current) = Current.split(Separator: "}"); |
53 | |
54 | // Warn if we split because no terminator was found. |
55 | StringRef EndVar = StartVar.drop_front(N: 2 /* ${ */ + Var.size()); |
56 | if (EndVar.empty()) { |
57 | PrintWarning(WarningLoc: Loc, Msg: "Unterminated expansion '${"+ Var + "'"); |
58 | PrintNote(Msg: "Code: [{"+ Code + "}]"); |
59 | } |
60 | |
61 | auto ValueI = Expansions.find(Variable: Var); |
62 | if (ValueI == Expansions.end()) { |
63 | PrintError(ErrorLoc: Loc, |
64 | Msg: "Attempt to expand an undeclared variable '"+ Var + "'"); |
65 | PrintNote(Msg: "Code: [{"+ Code + "}]"); |
66 | } |
67 | if (ShowExpansions) |
68 | OS << "/*$"<< Var << "{*/"; |
69 | OS << Expansions.lookup(Variable: Var); |
70 | if (ShowExpansions) |
71 | OS << "/*}*/"; |
72 | continue; |
73 | } |
74 | |
75 | PrintWarning(WarningLoc: Loc, Msg: "Assuming missing escape character: \\$"); |
76 | PrintNote(Msg: "Code: [{"+ Code + "}]"); |
77 | OS << "$"; |
78 | Current = Current.drop_front(N: 1); |
79 | } |
80 | } |
81 |