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 21 void 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 size_t LocOffset = StartVar.data() - Code.data(); 62 PrintWarning( 63 Loc.size() > 0 && Loc[0].isValid() 64 ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 65 : SMLoc(), 66 "Unterminated expansion"); 67 } 68 69 auto ValueI = Expansions.find(Var); 70 if (ValueI == Expansions.end()) { 71 size_t LocOffset = StartVar.data() - Code.data(); 72 PrintError(Loc.size() > 0 && Loc[0].isValid() 73 ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 74 : SMLoc(), 75 "Attempting to expand an undeclared variable " + Var); 76 } 77 if (ShowExpansions) 78 OS << "/*$" << Var << "{*/"; 79 OS << Expansions.lookup(Var); 80 if (ShowExpansions) 81 OS << "/*}*/"; 82 continue; 83 } 84 85 size_t LocOffset = Current.data() - Code.data(); 86 PrintWarning(Loc.size() > 0 && Loc[0].isValid() 87 ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 88 : SMLoc(), 89 "Assuming missing escape character"); 90 OS << "$"; 91 Current = Current.drop_front(1); 92 } 93 } 94