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("$\n\\"); 25 if (Pos == StringRef::npos) { 26 OS << Current; 27 Current = ""; 28 continue; 29 } 30 31 OS << Current.substr(0, Pos); 32 Current = Current.substr(Pos); 33 34 if (Current.consume_front("\n")) { 35 OS << "\n" << Indent; 36 continue; 37 } 38 39 if (Current.starts_with("\\$") || Current.starts_with("\\\\")) { 40 OS << Current[1]; 41 Current = Current.drop_front(2); 42 continue; 43 } 44 45 if (Current.consume_front("\\")) 46 continue; 47 48 if (Current.starts_with("${")) { 49 StringRef StartVar = Current; 50 Current = Current.drop_front(2); 51 StringRef Var; 52 std::tie(Var, Current) = Current.split("}"); 53 54 // Warn if we split because no terminator was found. 55 StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size()); 56 if (EndVar.empty()) { 57 PrintWarning(Loc, "Unterminated expansion '${" + Var + "'"); 58 PrintNote("Code: [{" + Code + "}]"); 59 } 60 61 auto ValueI = Expansions.find(Var); 62 if (ValueI == Expansions.end()) { 63 PrintError(Loc, 64 "Attempt to expand an undeclared variable '" + Var + "'"); 65 PrintNote("Code: [{" + Code + "}]"); 66 } 67 if (ShowExpansions) 68 OS << "/*$" << Var << "{*/"; 69 OS << Expansions.lookup(Var); 70 if (ShowExpansions) 71 OS << "/*}*/"; 72 continue; 73 } 74 75 PrintWarning(Loc, "Assuming missing escape character: \\$"); 76 PrintNote("Code: [{" + Code + "}]"); 77 OS << "$"; 78 Current = Current.drop_front(1); 79 } 80 } 81