1353940Sdim//===- CodeExpander.cpp - Expand variables in a string --------------------===// 2353940Sdim// 3353940Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353940Sdim// See https://llvm.org/LICENSE.txt for license information. 5353940Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353940Sdim// 7353940Sdim//===----------------------------------------------------------------------===// 8353940Sdim// 9353940Sdim/// \file Expand the variables in a string. 10353940Sdim// 11353940Sdim//===----------------------------------------------------------------------===// 12353940Sdim 13353940Sdim#include "CodeExpander.h" 14353940Sdim#include "CodeExpansions.h" 15353940Sdim#include "llvm/Support/CommandLine.h" 16353940Sdim#include "llvm/Support/raw_ostream.h" 17353940Sdim#include "llvm/TableGen/Error.h" 18353940Sdim 19353940Sdimusing namespace llvm; 20353940Sdim 21353940Sdimvoid CodeExpander::emit(raw_ostream &OS) const { 22353940Sdim StringRef Current = Code; 23353940Sdim 24353940Sdim while (!Current.empty()) { 25353940Sdim size_t Pos = Current.find_first_of("$\n\\"); 26353940Sdim if (Pos == StringRef::npos) { 27353940Sdim OS << Current; 28353940Sdim Current = ""; 29353940Sdim continue; 30353940Sdim } 31353940Sdim 32353940Sdim OS << Current.substr(0, Pos); 33353940Sdim Current = Current.substr(Pos); 34353940Sdim 35353940Sdim if (Current.startswith("\n")) { 36353940Sdim OS << "\n" << Indent; 37353940Sdim Current = Current.drop_front(1); 38353940Sdim continue; 39353940Sdim } 40353940Sdim 41353940Sdim if (Current.startswith("\\$") || Current.startswith("\\\\")) { 42353940Sdim OS << Current[1]; 43353940Sdim Current = Current.drop_front(2); 44353940Sdim continue; 45353940Sdim } 46353940Sdim 47353940Sdim if (Current.startswith("\\")) { 48353940Sdim Current = Current.drop_front(1); 49353940Sdim continue; 50353940Sdim } 51353940Sdim 52353940Sdim if (Current.startswith("${")) { 53353940Sdim StringRef StartVar = Current; 54353940Sdim Current = Current.drop_front(2); 55353940Sdim StringRef Var; 56353940Sdim std::tie(Var, Current) = Current.split("}"); 57353940Sdim 58353940Sdim // Warn if we split because no terminator was found. 59353940Sdim StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size()); 60353940Sdim if (EndVar.empty()) { 61353940Sdim size_t LocOffset = StartVar.data() - Code.data(); 62353940Sdim PrintWarning( 63353940Sdim Loc.size() > 0 && Loc[0].isValid() 64353940Sdim ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 65353940Sdim : SMLoc(), 66353940Sdim "Unterminated expansion"); 67353940Sdim } 68353940Sdim 69353940Sdim auto ValueI = Expansions.find(Var); 70353940Sdim if (ValueI == Expansions.end()) { 71353940Sdim size_t LocOffset = StartVar.data() - Code.data(); 72353940Sdim PrintError(Loc.size() > 0 && Loc[0].isValid() 73353940Sdim ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 74353940Sdim : SMLoc(), 75353940Sdim "Attempting to expand an undeclared variable " + Var); 76353940Sdim } 77353940Sdim if (ShowExpansions) 78353940Sdim OS << "/*$" << Var << "{*/"; 79353940Sdim OS << Expansions.lookup(Var); 80353940Sdim if (ShowExpansions) 81353940Sdim OS << "/*}*/"; 82353940Sdim continue; 83353940Sdim } 84353940Sdim 85353940Sdim size_t LocOffset = Current.data() - Code.data(); 86353940Sdim PrintWarning(Loc.size() > 0 && Loc[0].isValid() 87353940Sdim ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset) 88353940Sdim : SMLoc(), 89353940Sdim "Assuming missing escape character"); 90353940Sdim OS << "$"; 91353940Sdim Current = Current.drop_front(1); 92353940Sdim } 93353940Sdim} 94