18bcb0991SDimitry Andric //===- CodeExpander.cpp - Expand variables in a string --------------------===// 28bcb0991SDimitry Andric // 38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68bcb0991SDimitry Andric // 78bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 88bcb0991SDimitry Andric // 98bcb0991SDimitry Andric /// \file Expand the variables in a string. 108bcb0991SDimitry Andric // 118bcb0991SDimitry Andric //===----------------------------------------------------------------------===// 128bcb0991SDimitry Andric 138bcb0991SDimitry Andric #include "CodeExpander.h" 148bcb0991SDimitry Andric #include "CodeExpansions.h" 158bcb0991SDimitry Andric #include "llvm/Support/raw_ostream.h" 168bcb0991SDimitry Andric #include "llvm/TableGen/Error.h" 178bcb0991SDimitry Andric 188bcb0991SDimitry Andric using namespace llvm; 198bcb0991SDimitry Andric emit(raw_ostream & OS) const208bcb0991SDimitry Andricvoid CodeExpander::emit(raw_ostream &OS) const { 218bcb0991SDimitry Andric StringRef Current = Code; 228bcb0991SDimitry Andric 238bcb0991SDimitry Andric while (!Current.empty()) { 248bcb0991SDimitry Andric size_t Pos = Current.find_first_of("$\n\\"); 258bcb0991SDimitry Andric if (Pos == StringRef::npos) { 268bcb0991SDimitry Andric OS << Current; 278bcb0991SDimitry Andric Current = ""; 288bcb0991SDimitry Andric continue; 298bcb0991SDimitry Andric } 308bcb0991SDimitry Andric 318bcb0991SDimitry Andric OS << Current.substr(0, Pos); 328bcb0991SDimitry Andric Current = Current.substr(Pos); 338bcb0991SDimitry Andric 34*a58f00eaSDimitry Andric if (Current.consume_front("\n")) { 358bcb0991SDimitry Andric OS << "\n" << Indent; 368bcb0991SDimitry Andric continue; 378bcb0991SDimitry Andric } 388bcb0991SDimitry Andric 39c9157d92SDimitry Andric if (Current.starts_with("\\$") || Current.starts_with("\\\\")) { 408bcb0991SDimitry Andric OS << Current[1]; 418bcb0991SDimitry Andric Current = Current.drop_front(2); 428bcb0991SDimitry Andric continue; 438bcb0991SDimitry Andric } 448bcb0991SDimitry Andric 45*a58f00eaSDimitry Andric if (Current.consume_front("\\")) 468bcb0991SDimitry Andric continue; 478bcb0991SDimitry Andric 48c9157d92SDimitry Andric if (Current.starts_with("${")) { 498bcb0991SDimitry Andric StringRef StartVar = Current; 508bcb0991SDimitry Andric Current = Current.drop_front(2); 518bcb0991SDimitry Andric StringRef Var; 528bcb0991SDimitry Andric std::tie(Var, Current) = Current.split("}"); 538bcb0991SDimitry Andric 548bcb0991SDimitry Andric // Warn if we split because no terminator was found. 558bcb0991SDimitry Andric StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size()); 568bcb0991SDimitry Andric if (EndVar.empty()) { 57e8d8bef9SDimitry Andric PrintWarning(Loc, "Unterminated expansion '${" + Var + "'"); 58e8d8bef9SDimitry Andric PrintNote("Code: [{" + Code + "}]"); 598bcb0991SDimitry Andric } 608bcb0991SDimitry Andric 618bcb0991SDimitry Andric auto ValueI = Expansions.find(Var); 628bcb0991SDimitry Andric if (ValueI == Expansions.end()) { 63e8d8bef9SDimitry Andric PrintError(Loc, 64e8d8bef9SDimitry Andric "Attempt to expand an undeclared variable '" + Var + "'"); 65e8d8bef9SDimitry Andric PrintNote("Code: [{" + Code + "}]"); 668bcb0991SDimitry Andric } 678bcb0991SDimitry Andric if (ShowExpansions) 688bcb0991SDimitry Andric OS << "/*$" << Var << "{*/"; 698bcb0991SDimitry Andric OS << Expansions.lookup(Var); 708bcb0991SDimitry Andric if (ShowExpansions) 718bcb0991SDimitry Andric OS << "/*}*/"; 728bcb0991SDimitry Andric continue; 738bcb0991SDimitry Andric } 748bcb0991SDimitry Andric 75e8d8bef9SDimitry Andric PrintWarning(Loc, "Assuming missing escape character: \\$"); 76e8d8bef9SDimitry Andric PrintNote("Code: [{" + Code + "}]"); 778bcb0991SDimitry Andric OS << "$"; 788bcb0991SDimitry Andric Current = Current.drop_front(1); 798bcb0991SDimitry Andric } 808bcb0991SDimitry Andric } 81