118350af1SDaniel Sanders //===- CodeExpander.cpp - Expand variables in a string --------------------===// 218350af1SDaniel Sanders // 318350af1SDaniel Sanders // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 418350af1SDaniel Sanders // See https://llvm.org/LICENSE.txt for license information. 518350af1SDaniel Sanders // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 618350af1SDaniel Sanders // 718350af1SDaniel Sanders //===----------------------------------------------------------------------===// 818350af1SDaniel Sanders // 918350af1SDaniel Sanders /// \file Expand the variables in a string. 1018350af1SDaniel Sanders // 1118350af1SDaniel Sanders //===----------------------------------------------------------------------===// 1218350af1SDaniel Sanders 1318350af1SDaniel Sanders #include "CodeExpander.h" 1418350af1SDaniel Sanders #include "CodeExpansions.h" 1518350af1SDaniel Sanders #include "llvm/Support/raw_ostream.h" 1618350af1SDaniel Sanders #include "llvm/TableGen/Error.h" 1718350af1SDaniel Sanders 1818350af1SDaniel Sanders using namespace llvm; 1918350af1SDaniel Sanders emit(raw_ostream & OS) const2018350af1SDaniel Sandersvoid CodeExpander::emit(raw_ostream &OS) const { 2118350af1SDaniel Sanders StringRef Current = Code; 2218350af1SDaniel Sanders 2318350af1SDaniel Sanders while (!Current.empty()) { 2418350af1SDaniel Sanders size_t Pos = Current.find_first_of("$\n\\"); 2518350af1SDaniel Sanders if (Pos == StringRef::npos) { 2618350af1SDaniel Sanders OS << Current; 2718350af1SDaniel Sanders Current = ""; 2818350af1SDaniel Sanders continue; 2918350af1SDaniel Sanders } 3018350af1SDaniel Sanders 3118350af1SDaniel Sanders OS << Current.substr(0, Pos); 3218350af1SDaniel Sanders Current = Current.substr(Pos); 3318350af1SDaniel Sanders 3418350af1SDaniel Sanders if (Current.startswith("\n")) { 3518350af1SDaniel Sanders OS << "\n" << Indent; 3618350af1SDaniel Sanders Current = Current.drop_front(1); 3718350af1SDaniel Sanders continue; 3818350af1SDaniel Sanders } 3918350af1SDaniel Sanders 4018350af1SDaniel Sanders if (Current.startswith("\\$") || Current.startswith("\\\\")) { 4118350af1SDaniel Sanders OS << Current[1]; 4218350af1SDaniel Sanders Current = Current.drop_front(2); 4318350af1SDaniel Sanders continue; 4418350af1SDaniel Sanders } 4518350af1SDaniel Sanders 4618350af1SDaniel Sanders if (Current.startswith("\\")) { 4718350af1SDaniel Sanders Current = Current.drop_front(1); 4818350af1SDaniel Sanders continue; 4918350af1SDaniel Sanders } 5018350af1SDaniel Sanders 5118350af1SDaniel Sanders if (Current.startswith("${")) { 5218350af1SDaniel Sanders StringRef StartVar = Current; 5318350af1SDaniel Sanders Current = Current.drop_front(2); 5418350af1SDaniel Sanders StringRef Var; 5518350af1SDaniel Sanders std::tie(Var, Current) = Current.split("}"); 5618350af1SDaniel Sanders 5718350af1SDaniel Sanders // Warn if we split because no terminator was found. 5818350af1SDaniel Sanders StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size()); 5918350af1SDaniel Sanders if (EndVar.empty()) { 60*b23e84ffSPaul C. Anagnostopoulos PrintWarning(Loc, "Unterminated expansion '${" + Var + "'"); 61*b23e84ffSPaul C. Anagnostopoulos PrintNote("Code: [{" + Code + "}]"); 6218350af1SDaniel Sanders } 6318350af1SDaniel Sanders 6418350af1SDaniel Sanders auto ValueI = Expansions.find(Var); 6518350af1SDaniel Sanders if (ValueI == Expansions.end()) { 66*b23e84ffSPaul C. Anagnostopoulos PrintError(Loc, 67*b23e84ffSPaul C. Anagnostopoulos "Attempt to expand an undeclared variable '" + Var + "'"); 68*b23e84ffSPaul C. Anagnostopoulos PrintNote("Code: [{" + Code + "}]"); 6918350af1SDaniel Sanders } 7018350af1SDaniel Sanders if (ShowExpansions) 7118350af1SDaniel Sanders OS << "/*$" << Var << "{*/"; 7218350af1SDaniel Sanders OS << Expansions.lookup(Var); 7318350af1SDaniel Sanders if (ShowExpansions) 7418350af1SDaniel Sanders OS << "/*}*/"; 7518350af1SDaniel Sanders continue; 7618350af1SDaniel Sanders } 7718350af1SDaniel Sanders 78*b23e84ffSPaul C. Anagnostopoulos PrintWarning(Loc, "Assuming missing escape character: \\$"); 79*b23e84ffSPaul C. Anagnostopoulos PrintNote("Code: [{" + Code + "}]"); 8018350af1SDaniel Sanders OS << "$"; 8118350af1SDaniel Sanders Current = Current.drop_front(1); 8218350af1SDaniel Sanders } 8318350af1SDaniel Sanders } 84