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