reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
//===- CodeExpander.cpp - Expand variables in a string --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file Expand the variables in a string.
//
//===----------------------------------------------------------------------===//

#include "CodeExpander.h"
#include "CodeExpansions.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"

using namespace llvm;

void CodeExpander::emit(raw_ostream &OS) const {
  StringRef Current = Code;

  while (!Current.empty()) {
    size_t Pos = Current.find_first_of("$\n\\");
    if (Pos == StringRef::npos) {
      OS << Current;
      Current = "";
      continue;
    }

    OS << Current.substr(0, Pos);
    Current = Current.substr(Pos);

    if (Current.startswith("\n")) {
      OS << "\n" << Indent;
      Current = Current.drop_front(1);
      continue;
    }

    if (Current.startswith("\\$") || Current.startswith("\\\\")) {
      OS << Current[1];
      Current = Current.drop_front(2);
      continue;
    }

    if (Current.startswith("\\")) {
      Current = Current.drop_front(1);
      continue;
    }

    if (Current.startswith("${")) {
      StringRef StartVar = Current;
      Current = Current.drop_front(2);
      StringRef Var;
      std::tie(Var, Current) = Current.split("}");

      // Warn if we split because no terminator was found.
      StringRef EndVar = StartVar.drop_front(2 /* ${ */ + Var.size());
      if (EndVar.empty()) {
        size_t LocOffset = StartVar.data() - Code.data();
        PrintWarning(
            Loc.size() > 0 && Loc[0].isValid()
                ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset)
                : SMLoc(),
            "Unterminated expansion");
      }

      auto ValueI = Expansions.find(Var);
      if (ValueI == Expansions.end()) {
        size_t LocOffset = StartVar.data() - Code.data();
        PrintError(Loc.size() > 0 && Loc[0].isValid()
                       ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset)
                       : SMLoc(),
                   "Attempting to expand an undeclared variable " + Var);
      }
      if (ShowExpansions)
        OS << "/*$" << Var << "{*/";
      OS << Expansions.lookup(Var);
      if (ShowExpansions)
        OS << "/*}*/";
      continue;
    }

    size_t LocOffset = Current.data() - Code.data();
    PrintWarning(Loc.size() > 0 && Loc[0].isValid()
                     ? SMLoc::getFromPointer(Loc[0].getPointer() + LocOffset)
                     : SMLoc(),
                 "Assuming missing escape character");
    OS << "$";
    Current = Current.drop_front(1);
  }
}