1*fa3d789dSPierre van Houtryve //===- CodeExpander.cpp - Expand variables in a string --------------------===// 2*fa3d789dSPierre van Houtryve // 3*fa3d789dSPierre van Houtryve // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*fa3d789dSPierre van Houtryve // See https://llvm.org/LICENSE.txt for license information. 5*fa3d789dSPierre van Houtryve // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*fa3d789dSPierre van Houtryve // 7*fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 8*fa3d789dSPierre van Houtryve // 9*fa3d789dSPierre van Houtryve /// \file Expand the variables in a string. 10*fa3d789dSPierre van Houtryve // 11*fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 12*fa3d789dSPierre van Houtryve 13*fa3d789dSPierre van Houtryve #include "CodeExpander.h" 14*fa3d789dSPierre van Houtryve #include "CodeExpansions.h" 15*fa3d789dSPierre van Houtryve #include "llvm/Support/raw_ostream.h" 16*fa3d789dSPierre van Houtryve #include "llvm/TableGen/Error.h" 17*fa3d789dSPierre van Houtryve 18*fa3d789dSPierre van Houtryve using namespace llvm; 19*fa3d789dSPierre van Houtryve emit(raw_ostream & OS) const20*fa3d789dSPierre van Houtryvevoid CodeExpander::emit(raw_ostream &OS) const { 21*fa3d789dSPierre van Houtryve StringRef Current = Code; 22*fa3d789dSPierre van Houtryve 23*fa3d789dSPierre van Houtryve while (!Current.empty()) { 24*fa3d789dSPierre van Houtryve size_t Pos = Current.find_first_of("$\n\\"); 25*fa3d789dSPierre van Houtryve if (Pos == StringRef::npos) { 26*fa3d789dSPierre van Houtryve OS << Current; 27*fa3d789dSPierre van Houtryve Current = ""; 28*fa3d789dSPierre van Houtryve continue; 29*fa3d789dSPierre van Houtryve } 30*fa3d789dSPierre van Houtryve 31*fa3d789dSPierre van Houtryve OS << Current.substr(0, Pos); 32*fa3d789dSPierre van Houtryve Current = Current.substr(Pos); 33*fa3d789dSPierre van Houtryve 34*fa3d789dSPierre van Houtryve if (Current.consume_front("\n")) { 35*fa3d789dSPierre van Houtryve OS << "\n" << Indent; 36*fa3d789dSPierre van Houtryve continue; 37*fa3d789dSPierre van Houtryve } 38*fa3d789dSPierre van Houtryve 39*fa3d789dSPierre van Houtryve if (Current.starts_with("\\$") || Current.starts_with("\\\\")) { 40*fa3d789dSPierre van Houtryve OS << Current[1]; 41*fa3d789dSPierre van Houtryve Current = Current.drop_front(2); 42*fa3d789dSPierre van Houtryve continue; 43*fa3d789dSPierre van Houtryve } 44*fa3d789dSPierre van Houtryve 45*fa3d789dSPierre van Houtryve if (Current.consume_front("\\")) 46*fa3d789dSPierre van Houtryve continue; 47*fa3d789dSPierre van Houtryve 48*fa3d789dSPierre van Houtryve if (Current.starts_with("${")) { 49*fa3d789dSPierre van Houtryve StringRef StartVar = Current; 50*fa3d789dSPierre van Houtryve Current = Current.drop_front(2); 51*fa3d789dSPierre van Houtryve StringRef Var; 52*fa3d789dSPierre van Houtryve std::tie(Var, Current) = Current.split("}"); 53*fa3d789dSPierre van Houtryve 54*fa3d789dSPierre van Houtryve // Warn if we split because no terminator was found. 55*fa3d789dSPierre van Houtryve StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size()); 56*fa3d789dSPierre van Houtryve if (EndVar.empty()) { 57*fa3d789dSPierre van Houtryve PrintWarning(Loc, "Unterminated expansion '${" + Var + "'"); 58*fa3d789dSPierre van Houtryve PrintNote("Code: [{" + Code + "}]"); 59*fa3d789dSPierre van Houtryve } 60*fa3d789dSPierre van Houtryve 61*fa3d789dSPierre van Houtryve auto ValueI = Expansions.find(Var); 62*fa3d789dSPierre van Houtryve if (ValueI == Expansions.end()) { 63*fa3d789dSPierre van Houtryve PrintError(Loc, 64*fa3d789dSPierre van Houtryve "Attempt to expand an undeclared variable '" + Var + "'"); 65*fa3d789dSPierre van Houtryve PrintNote("Code: [{" + Code + "}]"); 66*fa3d789dSPierre van Houtryve } 67*fa3d789dSPierre van Houtryve if (ShowExpansions) 68*fa3d789dSPierre van Houtryve OS << "/*$" << Var << "{*/"; 69*fa3d789dSPierre van Houtryve OS << Expansions.lookup(Var); 70*fa3d789dSPierre van Houtryve if (ShowExpansions) 71*fa3d789dSPierre van Houtryve OS << "/*}*/"; 72*fa3d789dSPierre van Houtryve continue; 73*fa3d789dSPierre van Houtryve } 74*fa3d789dSPierre van Houtryve 75*fa3d789dSPierre van Houtryve PrintWarning(Loc, "Assuming missing escape character: \\$"); 76*fa3d789dSPierre van Houtryve PrintNote("Code: [{" + Code + "}]"); 77*fa3d789dSPierre van Houtryve OS << "$"; 78*fa3d789dSPierre van Houtryve Current = Current.drop_front(1); 79*fa3d789dSPierre van Houtryve } 80*fa3d789dSPierre van Houtryve } 81