//===-- ArchiveWriter.cpp - Write LLVM archive files ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Builds up an LLVM archive file (.a) containing LLVM bytecode.
//
//===----------------------------------------------------------------------===//

#include "ArchiveInternals.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Support/Compressor.h"
#include "llvm/System/Signals.h"
#include "llvm/System/Process.h"
#include <fstream>
#include <iostream>
#include <iomanip>

using namespace llvm;

// Write an integer using variable bit rate encoding. This saves a few bytes
// per entry in the symbol table.
inline void writeInteger(unsigned num, std::ofstream& ARFile) {
  while (1) {
    if (num < 0x80) { // done?
      ARFile << (unsigned char)num;
      return;
    }

    // Nope, we are bigger than a character, output the next 7 bits and set the
    // high bit to say that there is more coming...
    ARFile << (unsigned char)(0x80 | ((unsigned char)num & 0x7F));
    num >>= 7;  // Shift out 7 bits now...
  }
}

// Compute how many bytes are taken by a given VBR encoded value. This is needed
// to pre-compute the size of the symbol table.
inline unsigned numVbrBytes(unsigned num) {

  // Note that the following nested ifs are somewhat equivalent to a binary
  // search. We split it in half by comparing against 2^14 first. This allows
  // most reasonable values to be done in 2 comparisons instead of 1 for
  // small ones and four for large ones. We expect this to access file offsets
  // in the 2^10 to 2^24 range and symbol lengths in the 2^0 to 2^8 range,
  // so this approach is reasonable.
  if (num < 1<<14)
    if (num < 1<<7)
      return 1;
    else
      return 2;
  if (num < 1<<21)
    return 3;

  if (num < 1<<28)
    return 4;
  return 5; // anything >= 2^28 takes 5 bytes
}

// Create an empty archive.
Archive*
Archive::CreateEmpty(const sys::Path& FilePath ) {
  Archive* result = new Archive(FilePath,false);
  return result;
}

// Fill the ArchiveMemberHeader with the information from a member. If
// TruncateNames is true, names are flattened to 15 chars or less. The sz field
// is provided here instead of coming from the mbr because the member might be
// stored compressed and the compressed size is not the ArchiveMember's size.
// Furthermore compressed files have negative size fields to identify them as
// compressed.
bool
Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr,
                    int sz, bool TruncateNames) const {

  // Set the permissions mode, uid and gid
  hdr.init();
  char buffer[32];
  sprintf(buffer, "%-8o", mbr.getMode());
  memcpy(hdr.mode,buffer,8);
  sprintf(buffer,  "%-6u", mbr.getUser());
  memcpy(hdr.uid,buffer,6);
  sprintf(buffer,  "%-6u", mbr.getGroup());
  memcpy(hdr.gid,buffer,6);

  // Set the last modification date
  uint64_t secondsSinceEpoch = mbr.getModTime().toEpochTime();
  sprintf(buffer,"%-12u", unsigned(secondsSinceEpoch));
  memcpy(hdr.date,buffer,12);

  // Get rid of trailing blanks in the name
  std::string mbrPath = mbr.getPath().toString();
  size_t mbrLen = mbrPath.length();
  while (mbrLen > 0 && mbrPath[mbrLen-1] == ' ') {
    mbrPath.erase(mbrLen-1,1);
    mbrLen--;
  }

  // Set the name field in one of its various flavors.
  bool writeLongName = false;
  if (mbr.isStringTable()) {
    memcpy(hdr.name,ARFILE_STRTAB_NAME,16);
  } else if (mbr.isSVR4SymbolTable()) {
    memcpy(hdr.name,ARFILE_SVR4_SYMTAB_NAME,16);
  } else if (mbr.isBSD4SymbolTable()) {
    memcpy(hdr.name,ARFILE_BSD4_SYMTAB_NAME,16);
  } else if (mbr.isLLVMSymbolTable()) {
    memcpy(hdr.name,ARFILE_LLVM_SYMTAB_NAME,16);
  } else if (TruncateNames) {
    const char* nm = mbrPath.c_str();
    unsigned len = mbrPath.length();
    size_t slashpos = mbrPath.rfind('/');
    if (slashpos != std::string::npos) {
      nm += slashpos + 1;
      len -= slashpos +1;
    }
    if (len > 15)
      len = 15;
    memcpy(hdr.name,nm,len);
    hdr.name[len] = '/';
  } else if (mbrPath.length() < 16 && mbrPath.find('/') == std::string::npos) {
    memcpy(hdr.name,mbrPath.c_str(),mbrPath.length());
    hdr.name[mbrPath.length()] = '/';
  } else {
    std::string nm = "#1/";
    nm += utostr(mbrPath.length());
    memcpy(hdr.name,nm.data(),nm.length());
    if (sz < 0)
      sz -= mbrPath.length();
    else
      sz += mbrPath.length();
    writeLongName = true;
  }

  // Set the size field
  if (sz < 0) {
    buffer[0] = '-';
    sprintf(&buffer[1],"%-9u",(unsigned)-sz);
  } else {
    sprintf(buffer, "%-10u", (unsigned)sz);
  }
  memcpy(hdr.size,buffer,10);

  return writeLongName;
}

// Insert a file into the archive before some other member. This also takes care
// of extracting the necessary flags and information from the file.
void
Archive::addFileBefore(const sys::Path& filePath, iterator where) {
  assert(filePath.exists() && "Can't add a non-existent file");

  ArchiveMember* mbr = new ArchiveMember(this);

  mbr->data = 0;
  mbr->path = filePath;
  mbr->path.getStatusInfo(mbr->info);

  unsigned flags = 0;
  bool hasSlash = filePath.toString().find('/') != std::string::npos;
  if (hasSlash)
    flags |= ArchiveMember::HasPathFlag;
  if (hasSlash || filePath.toString().length() > 15)
    flags |= ArchiveMember::HasLongFilenameFlag;
  std::string magic;
  mbr->path.getMagicNumber(magic,4);
  switch (sys::IdentifyFileType(magic.c_str(),4)) {
    case sys::BytecodeFileType:
      flags |= ArchiveMember::BytecodeFlag;
      break;
    case sys::CompressedBytecodeFileType:
      flags |= ArchiveMember::CompressedBytecodeFlag;
      break;
    default:
      break;
  }
  mbr->flags = flags;
  members.insert(where,mbr);
}

// Write one member out to the file.
void
Archive::writeMember(
  const ArchiveMember& member,
  std::ofstream& ARFile,
  bool CreateSymbolTable,
  bool TruncateNames,
  bool ShouldCompress
) {

  unsigned filepos = ARFile.tellp();
  filepos -= 8;

  // Get the data and its size either from the
  // member's in-memory data or directly from the file.
  size_t fSize = member.getSize();
  const char* data = (const char*)member.getData();
  sys::MappedFile* mFile = 0;
  if (!data) {
    mFile = new sys::MappedFile(member.getPath());
    data = (const char*) mFile->map();
    fSize = mFile->size();
  }

  // Now that we have the data in memory, update the
  // symbol table if its a bytecode file.
  if (CreateSymbolTable &&
      (member.isBytecode() || member.isCompressedBytecode())) {
    std::vector<std::string> symbols;
    std::string FullMemberName = archPath.toString() + "(" +
      member.getPath().toString()
      + ")";
    ModuleProvider* MP = GetBytecodeSymbols(
      (const unsigned char*)data,fSize,FullMemberName, symbols);

    // If the bytecode parsed successfully
    if ( MP ) {
      for (std::vector<std::string>::iterator SI = symbols.begin(),
           SE = symbols.end(); SI != SE; ++SI) {

        std::pair<SymTabType::iterator,bool> Res =
          symTab.insert(std::make_pair(*SI,filepos));

        if (Res.second) {
          symTabSize += SI->length() +
                        numVbrBytes(SI->length()) +
                        numVbrBytes(filepos);
        }
      }
      // We don't need this module any more.
      delete MP;
    } else {
      throw std::string("Can't parse bytecode member: ") +
             member.getPath().toString();
    }
  }

  // Determine if we actually should compress this member
  bool willCompress =
      (ShouldCompress &&
      !member.isCompressed() &&
      !member.isCompressedBytecode() &&
      !member.isLLVMSymbolTable() &&
      !member.isSVR4SymbolTable() &&
      !member.isBSD4SymbolTable());

  // Perform the compression. Note that if the file is uncompressed bytecode
  // then we turn the file into compressed bytecode rather than treating it as
  // compressed data. This is necessary since it allows us to determine that the
  // file contains bytecode instead of looking like a regular compressed data
  // member. A compressed bytecode file has its content compressed but has a
  // magic number of "llvc". This acounts for the +/-4 arithmetic in the code
  // below.
  int hdrSize;
  if (willCompress) {
    char* output = 0;
    if (member.isBytecode()) {
      data +=4;
      fSize -= 4;
    }
    fSize = Compressor::compressToNewBuffer(data,fSize,output);
    data = output;
    if (member.isBytecode())
      hdrSize = -fSize-4;
    else
      hdrSize = -fSize;
  } else {
    hdrSize = fSize;
  }

  // Compute the fields of the header
  ArchiveMemberHeader Hdr;
  bool writeLongName = fillHeader(member,Hdr,hdrSize,TruncateNames);

  // Write header to archive file
  ARFile.write((char*)&Hdr, sizeof(Hdr));

  // Write the long filename if its long
  if (writeLongName) {
    ARFile.write(member.getPath().toString().data(),
                 member.getPath().toString().length());
  }

  // Make sure we write the compressed bytecode magic number if we should.
  if (willCompress && member.isBytecode())
    ARFile.write("llvc",4);

  // Write the (possibly compressed) member's content to the file.
  ARFile.write(data,fSize);

  // Make sure the member is an even length
  if ((ARFile.tellp() & 1) == 1)
    ARFile << ARFILE_PAD;

  // Free the compressed data, if necessary
  if (willCompress) {
    free((void*)data);
  }

  // Close the mapped file if it was opened
  if (mFile != 0) {
    mFile->close();
    delete mFile;
  }
}

// Write out the LLVM symbol table as an archive member to the file.
void
Archive::writeSymbolTable(std::ofstream& ARFile) {

  // Construct the symbol table's header
  ArchiveMemberHeader Hdr;
  Hdr.init();
  memcpy(Hdr.name,ARFILE_LLVM_SYMTAB_NAME,16);
  uint64_t secondsSinceEpoch = sys::TimeValue::now().toEpochTime();
  char buffer[32];
  sprintf(buffer, "%-8o", 0644);
  memcpy(Hdr.mode,buffer,8);
  sprintf(buffer, "%-6u", sys::Process::GetCurrentUserId());
  memcpy(Hdr.uid,buffer,6);
  sprintf(buffer, "%-6u", sys::Process::GetCurrentGroupId());
  memcpy(Hdr.gid,buffer,6);
  sprintf(buffer,"%-12u", unsigned(secondsSinceEpoch));
  memcpy(Hdr.date,buffer,12);
  sprintf(buffer,"%-10u",symTabSize);
  memcpy(Hdr.size,buffer,10);

  // Write the header
  ARFile.write((char*)&Hdr, sizeof(Hdr));

  // Save the starting position of the symbol tables data content.
  unsigned startpos = ARFile.tellp();

  // Write out the symbols sequentially
  for ( Archive::SymTabType::iterator I = symTab.begin(), E = symTab.end();
        I != E; ++I)
  {
    // Write out the file index
    writeInteger(I->second, ARFile);
    // Write out the length of the symbol
    writeInteger(I->first.length(), ARFile);
    // Write out the symbol
    ARFile.write(I->first.data(), I->first.length());
  }

  // Now that we're done with the symbol table, get the ending file position
  unsigned endpos = ARFile.tellp();

  // Make sure that the amount we wrote is what we pre-computed. This is
  // critical for file integrity purposes.
  assert(endpos - startpos == symTabSize && "Invalid symTabSize computation");

  // Make sure the symbol table is even sized
  if (symTabSize % 2 != 0 )
    ARFile << ARFILE_PAD;
}

// Write the entire archive to the file specified when the archive was created.
// This writes to a temporary file first. Options are for creating a symbol
// table, flattening the file names (no directories, 15 chars max) and
// compressing each archive member.
void
Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress){

  // Make sure they haven't opened up the file, not loaded it,
  // but are now trying to write it which would wipe out the file.
  assert(!(members.empty() && mapfile->size() > 8) &&
         "Can't write an archive not opened for writing");

  // Create a temporary file to store the archive in
  sys::Path TmpArchive = archPath;
  TmpArchive.createTemporaryFileOnDisk();

  // Make sure the temporary gets removed if we crash
  sys::RemoveFileOnSignal(TmpArchive);

  // Ensure we can remove the temporary even in the face of an exception
  try {
    // Create archive file for output.
    std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
                                 std::ios::binary;
    std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode);

    // Check for errors opening or creating archive file.
    if ( !ArchiveFile.is_open() || ArchiveFile.bad() ) {
      throw std::string("Error opening archive file: ") + archPath.toString();
    }

    // If we're creating a symbol table, reset it now
    if (CreateSymbolTable) {
      symTabSize = 0;
      symTab.clear();
    }

    // Write magic string to archive.
    ArchiveFile << ARFILE_MAGIC;

    // Loop over all member files, and write them out. Note that this also
    // builds the symbol table, symTab.
    for ( MembersList::iterator I = begin(), E = end(); I != E; ++I) {
      writeMember(*I,ArchiveFile,CreateSymbolTable,TruncateNames,Compress);
    }

    // Close archive file.
    ArchiveFile.close();

    // Write the symbol table
    if (CreateSymbolTable) {
      // At this point we have written a file that is a legal archive but it
      // doesn't have a symbol table in it. To aid in faster reading and to
      // ensure compatibility with other archivers we need to put the symbol
      // table first in the file. Unfortunately, this means mapping the file
      // we just wrote back in and copying it to the destination file.

      // Map in the archive we just wrote.
      sys::MappedFile arch(TmpArchive);
      const char* base = (const char*) arch.map();

      // Open the final file to write and check it.
      std::ofstream FinalFile(archPath.c_str(), io_mode);
      if ( !FinalFile.is_open() || FinalFile.bad() ) {
        throw std::string("Error opening archive file: ") + archPath.toString();
      }

      // Write the file magic number
      FinalFile << ARFILE_MAGIC;

      // If there is a foreign symbol table, put it into the file now. Most
      // ar(1) implementations require the symbol table to be first but llvm-ar
      // can deal with it being after a foreign symbol table. This ensures
      // compatibility with other ar(1) implementations as well as allowing the
      // archive to store both native .o and LLVM .bc files, both indexed.
      if (foreignST) {
        writeMember(*foreignST, FinalFile, false, false, false);
      }

      // Put out the LLVM symbol table now.
      writeSymbolTable(FinalFile);

      // Copy the temporary file contents being sure to skip the file's magic
      // number.
      FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
        arch.size()-sizeof(ARFILE_MAGIC)+1);

      // Close up shop
      FinalFile.close();
      arch.close();
      TmpArchive.eraseFromDisk();

    } else {
      // We don't have to insert the symbol table, so just renaming the temp
      // file to the correct name will suffice.
      TmpArchive.renamePathOnDisk(archPath);
    }
  } catch (...) {
    // Make sure we clean up.
    if (TmpArchive.exists())
      TmpArchive.eraseFromDisk();
    throw;
  }
}
