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/CommandLine.h" 168bcb0991SDimitry Andric #include "llvm/Support/raw_ostream.h" 178bcb0991SDimitry Andric #include "llvm/TableGen/Error.h" 188bcb0991SDimitry Andric 198bcb0991SDimitry Andric using namespace llvm; 208bcb0991SDimitry Andric 218bcb0991SDimitry Andric void CodeExpander::emit(raw_ostream &OS) const { 228bcb0991SDimitry Andric StringRef Current = Code; 238bcb0991SDimitry Andric 248bcb0991SDimitry Andric while (!Current.empty()) { 258bcb0991SDimitry Andric size_t Pos = Current.find_first_of("$\n\\"); 268bcb0991SDimitry Andric if (Pos == StringRef::npos) { 278bcb0991SDimitry Andric OS << Current; 288bcb0991SDimitry Andric Current = ""; 298bcb0991SDimitry Andric continue; 308bcb0991SDimitry Andric } 318bcb0991SDimitry Andric 328bcb0991SDimitry Andric OS << Current.substr(0, Pos); 338bcb0991SDimitry Andric Current = Current.substr(Pos); 348bcb0991SDimitry Andric 358bcb0991SDimitry Andric if (Current.startswith("\n")) { 368bcb0991SDimitry Andric OS << "\n" << Indent; 378bcb0991SDimitry Andric Current = Current.drop_front(1); 388bcb0991SDimitry Andric continue; 398bcb0991SDimitry Andric } 408bcb0991SDimitry Andric 418bcb0991SDimitry Andric if (Current.startswith("\\$") || Current.startswith("\\\\")) { 428bcb0991SDimitry Andric OS << Current[1]; 438bcb0991SDimitry Andric Current = Current.drop_front(2); 448bcb0991SDimitry Andric continue; 458bcb0991SDimitry Andric } 468bcb0991SDimitry Andric 478bcb0991SDimitry Andric if (Current.startswith("\\")) { 488bcb0991SDimitry Andric Current = Current.drop_front(1); 498bcb0991SDimitry Andric continue; 508bcb0991SDimitry Andric } 518bcb0991SDimitry Andric 528bcb0991SDimitry Andric if (Current.startswith("${")) { 538bcb0991SDimitry Andric StringRef StartVar = Current; 548bcb0991SDimitry Andric Current = Current.drop_front(2); 558bcb0991SDimitry Andric StringRef Var; 568bcb0991SDimitry Andric std::tie(Var, Current) = Current.split("}"); 578bcb0991SDimitry Andric 588bcb0991SDimitry Andric // Warn if we split because no terminator was found. 598bcb0991SDimitry Andric StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size()); 608bcb0991SDimitry Andric if (EndVar.empty()) { 618bcb0991SDimitry Andric size_t LocOffset = StartVar.data() - Code.data(); 628bcb0991SDimitry Andric PrintWarning( 638bcb0991SDimitry Andric Loc.size() > 0 && Loc[0].isValid() 648bcb0991SDimitry Andric ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 658bcb0991SDimitry Andric : SMLoc(), 668bcb0991SDimitry Andric "Unterminated expansion"); 678bcb0991SDimitry Andric } 688bcb0991SDimitry Andric 698bcb0991SDimitry Andric auto ValueI = Expansions.find(Var); 708bcb0991SDimitry Andric if (ValueI == Expansions.end()) { 718bcb0991SDimitry Andric size_t LocOffset = StartVar.data() - Code.data(); 728bcb0991SDimitry Andric PrintError(Loc.size() > 0 && Loc[0].isValid() 738bcb0991SDimitry Andric ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 748bcb0991SDimitry Andric : SMLoc(), 758bcb0991SDimitry Andric "Attempting to expand an undeclared variable " + Var); 768bcb0991SDimitry Andric } 778bcb0991SDimitry Andric if (ShowExpansions) 788bcb0991SDimitry Andric OS << "/*$" << Var << "{*/"; 798bcb0991SDimitry Andric OS << Expansions.lookup(Var); 808bcb0991SDimitry Andric if (ShowExpansions) 818bcb0991SDimitry Andric OS << "/*}*/"; 828bcb0991SDimitry Andric continue; 838bcb0991SDimitry Andric } 848bcb0991SDimitry Andric 858bcb0991SDimitry Andric size_t LocOffset = Current.data() - Code.data(); 868bcb0991SDimitry Andric PrintWarning(Loc.size() > 0 && Loc[0].isValid() 878bcb0991SDimitry Andric ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 888bcb0991SDimitry Andric : SMLoc(), 898bcb0991SDimitry Andric "Assuming missing escape character"); 908bcb0991SDimitry Andric OS << "$"; 918bcb0991SDimitry Andric Current = Current.drop_front(1); 928bcb0991SDimitry Andric } 938bcb0991SDimitry Andric } 94