forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			120 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
//===---- Implementation of the main header generation class -----*- C++ -*===//
 | 
						|
//
 | 
						|
// 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
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "Generator.h"
 | 
						|
 | 
						|
#include "IncludeFileCommand.h"
 | 
						|
#include "PublicAPICommand.h"
 | 
						|
 | 
						|
#include "llvm/ADT/StringRef.h"
 | 
						|
#include "llvm/Support/MemoryBuffer.h"
 | 
						|
#include "llvm/Support/SourceMgr.h"
 | 
						|
#include "llvm/Support/raw_ostream.h"
 | 
						|
 | 
						|
#include <cstdlib>
 | 
						|
#include <memory>
 | 
						|
 | 
						|
static const char CommandPrefix[] = "%%";
 | 
						|
static const size_t CommandPrefixSize = llvm::StringRef(CommandPrefix).size();
 | 
						|
 | 
						|
static const char CommentPrefix[] = "<!>";
 | 
						|
 | 
						|
static const char ParamNamePrefix[] = "${";
 | 
						|
static const size_t ParamNamePrefixSize =
 | 
						|
    llvm::StringRef(ParamNamePrefix).size();
 | 
						|
static const char ParamNameSuffix[] = "}";
 | 
						|
static const size_t ParamNameSuffixSize =
 | 
						|
    llvm::StringRef(ParamNameSuffix).size();
 | 
						|
 | 
						|
namespace llvm_libc {
 | 
						|
 | 
						|
Command *Generator::getCommandHandler(llvm::StringRef CommandName) {
 | 
						|
  if (CommandName == IncludeFileCommand::Name) {
 | 
						|
    if (!IncludeFileCmd)
 | 
						|
      IncludeFileCmd = std::make_unique<IncludeFileCommand>();
 | 
						|
    return IncludeFileCmd.get();
 | 
						|
  } else if (CommandName == PublicAPICommand::Name) {
 | 
						|
    if (!PublicAPICmd)
 | 
						|
      PublicAPICmd = std::make_unique<PublicAPICommand>();
 | 
						|
    return PublicAPICmd.get();
 | 
						|
  } else {
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void Generator::parseCommandArgs(llvm::StringRef ArgStr, ArgVector &Args) {
 | 
						|
  if (!ArgStr.contains(',') && ArgStr.trim(' ').trim('\t').size() == 0) {
 | 
						|
    // If it is just space between the parenthesis
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  ArgStr.split(Args, ",");
 | 
						|
  for (llvm::StringRef &A : Args) {
 | 
						|
    A = A.trim(' ');
 | 
						|
    if (A.startswith(ParamNamePrefix) && A.endswith(ParamNameSuffix)) {
 | 
						|
      A = A.drop_front(ParamNamePrefixSize).drop_back(ParamNameSuffixSize);
 | 
						|
      A = ArgMap[std::string(A)];
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void Generator::generate(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {
 | 
						|
  auto DefFileBuffer = llvm::MemoryBuffer::getFile(HeaderDefFile);
 | 
						|
  if (!DefFileBuffer) {
 | 
						|
    llvm::errs() << "Unable to open " << HeaderDefFile << ".\n";
 | 
						|
    std::exit(1);
 | 
						|
  }
 | 
						|
  llvm::SourceMgr SrcMgr;
 | 
						|
  unsigned DefFileID = SrcMgr.AddNewSourceBuffer(
 | 
						|
      std::move(DefFileBuffer.get()), llvm::SMLoc::getFromPointer(nullptr));
 | 
						|
 | 
						|
  llvm::StringRef Content = SrcMgr.getMemoryBuffer(DefFileID)->getBuffer();
 | 
						|
  while (true) {
 | 
						|
    std::pair<llvm::StringRef, llvm::StringRef> P = Content.split('\n');
 | 
						|
    Content = P.second;
 | 
						|
 | 
						|
    llvm::StringRef Line = P.first.trim(' ');
 | 
						|
    if (Line.startswith(CommandPrefix)) {
 | 
						|
      Line = Line.drop_front(CommandPrefixSize);
 | 
						|
 | 
						|
      P = Line.split("(");
 | 
						|
      if (P.second.empty() || P.second[P.second.size() - 1] != ')') {
 | 
						|
        SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(P.second.data()),
 | 
						|
                            llvm::SourceMgr::DK_Error,
 | 
						|
                            "Command argument list should begin with '(' "
 | 
						|
                            "and end with ')'.");
 | 
						|
        std::exit(1);
 | 
						|
      }
 | 
						|
      llvm::StringRef CommandName = P.first;
 | 
						|
      Command *Cmd = getCommandHandler(CommandName);
 | 
						|
      if (Cmd == nullptr) {
 | 
						|
        SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(CommandName.data()),
 | 
						|
                            llvm::SourceMgr::DK_Error,
 | 
						|
                            "Unknown command '%%" + CommandName + "'.");
 | 
						|
        std::exit(1);
 | 
						|
      }
 | 
						|
 | 
						|
      llvm::StringRef ArgStr = P.second.drop_back(1);
 | 
						|
      ArgVector Args;
 | 
						|
      parseCommandArgs(ArgStr, Args);
 | 
						|
 | 
						|
      Command::ErrorReporter Reporter(
 | 
						|
          llvm::SMLoc::getFromPointer(CommandName.data()), SrcMgr);
 | 
						|
      Cmd->run(OS, Args, StdHeader, Records, Reporter);
 | 
						|
    } else if (!Line.startswith(CommentPrefix)) {
 | 
						|
      // There is no comment or command on this line so we just write it as is.
 | 
						|
      OS << P.first << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    if (P.second.empty())
 | 
						|
      break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
} // namespace llvm_libc
 |