<commit_before>/*
 * File:   cogwheelftpcoreutil.cpp
 *
 * Author: Robert Tizzard
 *
 * Created on August 10, 2017
 *
 * Copyright 2017.
 *
 */

//
// Namespace: CogWheelFTPCoreUtil
//
// Description: CogWheelFTPCore utility functions.
//

// =============
// INCLUDE FILES
// =============

#include "cogwheelftpcoreutil.h"
#include "cogwheellogger.h"

namespace CogWheelFTPCoreUtil {

/**
 * @brief mapPathToLocal
 *
 * Map a FTP root relative path to local filesystem.
 *
 * @param connection   Pointer to control channel instance.
 * @param path         Path to map to local filesystem.
 *
 * @return Local file system path string,
 */
QString mapPathToLocal(CogWheelControlChannel *connection, const QString &path)
{

    QString mappedPath;

    if (path.startsWith('/')) {
        mappedPath = connection->rootDirectory()+path;
    } else {
        mappedPath = connection->rootDirectory()+connection->currentWorkingDirectory();
        if (connection->currentWorkingDirectory()=="/") {
            mappedPath += path;
        } else {
            mappedPath += ("/" + path);
        }
    }

    cogWheelInfo(connection->socketHandle(),"Mapping local "+path+" to "+mappedPath);

    return(mappedPath);
}

/**
 * @brief mapPathFromLocal
 *
 * Map a given local filesystem path to a FTP root path.
 *
 * @param connection   Pointer to control channel instance.
 * @param path         Path to map from local filesystem.
 *
 * @return  FTP root path.
 */
QString mapPathFromLocal(CogWheelControlChannel *connection, const QString &path)
{

    QString mappedPath { QFileInfo(path).absoluteFilePath()};

    cogWheelInfo(connection->socketHandle(),"mapped path : "+mappedPath);

    // Strip off root path

    if (mappedPath.startsWith(connection->rootDirectory())) {
        mappedPath = mappedPath.remove(0,connection->rootDirectory().length());

        // If trying to go above root then reset to root

    } else if (mappedPath.length() < connection->rootDirectory().length()){
        mappedPath = "";
    }

    cogWheelInfo(connection->socketHandle(),"Mapping local from "+path+" to "+mappedPath);

    return(mappedPath);
}

/**
 * @brief buildFilePermissions
 *
 * Build files permissions (for LIST) into QString and return.
 *
 * @param fileInfo  File to produce permissions for.
 *
 * @return Files permissions as a QString.
 */
QString buildFilePermissions(const QFileInfo &fileInfo)
{

    char permissions[10];

    permissions[0] = (fileInfo.permissions() & QFile::ReadUser) ? 'r' : '-';
    permissions[1] = (fileInfo.permissions() & QFile::WriteUser) ? 'w' : '-';
    permissions[2] = (fileInfo.permissions() & QFile::ExeUser) ? 'x' : '-';
    permissions[3] = (fileInfo.permissions() & QFile::ReadGroup) ? 'r' : '-';
    permissions[4] = (fileInfo.permissions() & QFile::WriteGroup) ? 'w' : '-';
    permissions[5] = (fileInfo.permissions() & QFile::ExeGroup) ? 'x' : '-';
    permissions[6] = (fileInfo.permissions() & QFile::ReadOther) ? 'r' : '-';
    permissions[7] = (fileInfo.permissions() & QFile::WriteOther) ? 'w' : '-';
    permissions[8] = (fileInfo.permissions() & QFile::ExeOther) ? 'x' : '-';
    permissions[9] = 0;

    return(permissions);

}

/**
 * @brief buildUnixFilePermissions
 *
 * Build files unix permissions into octal QString and return.
 *
 * @param fileInfo  File to produce permissions for.
 *
 * @return Files permissions as a octal QString.
 */
QString buildUnixFilePermissions(const QFileInfo &fileInfo)
{

    unsigned short permissions=0;

    permissions |= (fileInfo.permissions() & QFile::ReadUser) ? 0400 : 0;
    permissions |= (fileInfo.permissions() & QFile::WriteUser) ? 0200 : 0;
    permissions |= (fileInfo.permissions() & QFile::ExeUser) ? 0100 : 0;
    permissions |= (fileInfo.permissions() & QFile::ReadGroup) ? 0040 : 0;
    permissions |= (fileInfo.permissions() & QFile::WriteGroup) ? 0020 : 0;
    permissions |= (fileInfo.permissions() & QFile::ExeGroup) ? 0010 : 0;
    permissions |= (fileInfo.permissions() & QFile::ReadOther) ? 0004 : 0;
    permissions |= (fileInfo.permissions() & QFile::WriteOther) ? 0002 : 0;
    permissions |= (fileInfo.permissions() & QFile::ExeOther) ? 0001 : 0;

    return("0"+QString::number(permissions,8));

}

/**
 * @brief buildMLSDCommonLine
 *
 * Build common file facts to QString and return.
 *
 * @param fileInfo  File to produce facts for.
 *
 * @return Common file facts as a QString.
 */
QString buildMLSDCommonLine(const QFileInfo &fileInfo)
{
    QString line;

    line.append(static_cast<QString>("Modify=")+fileInfo.lastModified().toString("yyyyMMddhhmmss;"));
    line.append(static_cast<QString>("Create=")+fileInfo.created().toString("yyyyMMddhhmmss;"));
    line.append(static_cast<QString>("UNIX.mode=")+buildUnixFilePermissions(fileInfo)+";");
    line.append(static_cast<QString>("UNIX.owner=")+QString::number(fileInfo.ownerId())+";");
    line.append(static_cast<QString>("UNIX.group=")+QString::number(fileInfo.groupId())+";");

    return line;

}

/**
 * @brief buildLISTLine
 *
 * Build list line for passed in QFileInfo. The format of which
 * is the same as given for the Linux 'ls -l' command.
 *
 * @param fileInfo  File to produce list line for.
 *
 * @return List line QString.
 */
QString buildLISTLine(const QFileInfo &fileInfo)
{

    QChar   fileType= '-';
    QString line;
    QString ownerGroup;

    if (fileInfo.isSymLink()) {
        fileType = 'l';
    } else if (fileInfo.isDir()){
        fileType = 'd';
    }

    line.append(fileType+buildFilePermissions(fileInfo)+" 1 ");

    ownerGroup = fileInfo.owner();
    if(ownerGroup.isEmpty()) {
        ownerGroup = "0";
    }
    line.append(ownerGroup.leftJustified(10,' ',true)+" ");

    ownerGroup = fileInfo.group();
    if(ownerGroup.isEmpty()) {
        ownerGroup = "0";
    }
    line.append(ownerGroup.leftJustified(10,' ',true)+" ");

    line.append(QString::number(fileInfo.size()).rightJustified(10,' ',true)+" ");
    line.append(fileInfo.lastModified().toString("MMM dd hh:mm").rightJustified(12,' ',true)+" ");
    line.append(fileInfo.fileName()+"\r\n");

    return(line);

}

/**
 * @brief buildMLSDPathLine
 *
 * Build list line for requested path in MLSD.
 *
 * @param pathInfo  Directory info to produce MLSD line for.
 * @param path      Directory path.
 *
 * @return MLSD list line QString.
 */
QString buildMLSDPathLine(const QFileInfo &pathInfo, const QString &path)
{
    return (static_cast<QString>("Type=cdir;")+buildMLSDCommonLine(pathInfo)+" "+path+"\r\n");
}

/**
 * @brief buildMLSDLine
 *
 * Build list line for single file in MLSD list.
 *
 * @param fileInfo  File information
 *
 * @return List line for file QString.
 */
QString buildMLSDLine(const QFileInfo &fileInfo)
{

    QString line;

    if(fileInfo.isDir()){
        line.append("Type=dir;");
    }else {
        line.append((static_cast<QString>("Type=file;")+"Size=")+QString::number(fileInfo.size())+";");
    }

    line.append(buildMLSDCommonLine(fileInfo)+" "+fileInfo.fileName()+"\r\n");

    return line;

}

} // namespace CogWheelFTPCoreUtil
<commit_msg>Seperate out FTPCore utility functions into file CogWheelFTPCoreUtil.cpp<commit_after>/*
 * File:   cogwheelftpcoreutil.cpp
 *
 * Author: Robert Tizzard
 *
 * Created on August 10, 2017
 *
 * Copyright 2017.
 *
 */

//
// Namespace: CogWheelFTPCoreUtil
//
// Description: CogWheelFTPCore utility functions. This includes functions
// for mapping to/from the local file system (root relative) and for the creation
// of list information/fact lines for files returned in reponse to the various FTP
// list commands.
//

// =============
// INCLUDE FILES
// =============

#include "cogwheelftpcoreutil.h"
#include "cogwheellogger.h"

namespace CogWheelFTPCoreUtil {

/**
 * @brief mapPathToLocal
 *
 * Map a FTP root relative path to local filesystem.
 *
 * @param connection   Pointer to control channel instance.
 * @param path         Path to map to local filesystem.
 *
 * @return Local file system path string,
 */
QString mapPathToLocal(CogWheelControlChannel *connection, const QString &path)
{

    QString mappedPath;

    if (path.startsWith('/')) {
        mappedPath = connection->rootDirectory()+path;
    } else {
        mappedPath = connection->rootDirectory()+connection->currentWorkingDirectory();
        if (connection->currentWorkingDirectory()=="/") {
            mappedPath += path;
        } else {
            mappedPath += ("/" + path);
        }
    }

    cogWheelInfo(connection->socketHandle(),"Mapping local "+path+" to "+mappedPath);

    return(mappedPath);
}

/**
 * @brief mapPathFromLocal
 *
 * Map a given local filesystem path to a FTP root path.
 *
 * @param connection   Pointer to control channel instance.
 * @param path         Path to map from local filesystem.
 *
 * @return  FTP root path.
 */
QString mapPathFromLocal(CogWheelControlChannel *connection, const QString &path)
{

    QString mappedPath { QFileInfo(path).absoluteFilePath()};

    cogWheelInfo(connection->socketHandle(),"mapped path : "+mappedPath);

    // Strip off root path

    if (mappedPath.startsWith(connection->rootDirectory())) {
        mappedPath = mappedPath.remove(0,connection->rootDirectory().length());

        // If trying to go above root then reset to root

    } else if (mappedPath.length() < connection->rootDirectory().length()){
        mappedPath = "";
    }

    cogWheelInfo(connection->socketHandle(),"Mapping local from "+path+" to "+mappedPath);

    return(mappedPath);
}

/**
 * @brief buildFilePermissions
 *
 * Build files permissions (for LIST) into QString and return.
 *
 * @param fileInfo  File to produce permissions for.
 *
 * @return Files permissions as a QString.
 */
QString buildFilePermissions(const QFileInfo &fileInfo)
{

    char permissions[10];

    permissions[0] = (fileInfo.permissions() & QFile::ReadUser) ? 'r' : '-';
    permissions[1] = (fileInfo.permissions() & QFile::WriteUser) ? 'w' : '-';
    permissions[2] = (fileInfo.permissions() & QFile::ExeUser) ? 'x' : '-';
    permissions[3] = (fileInfo.permissions() & QFile::ReadGroup) ? 'r' : '-';
    permissions[4] = (fileInfo.permissions() & QFile::WriteGroup) ? 'w' : '-';
    permissions[5] = (fileInfo.permissions() & QFile::ExeGroup) ? 'x' : '-';
    permissions[6] = (fileInfo.permissions() & QFile::ReadOther) ? 'r' : '-';
    permissions[7] = (fileInfo.permissions() & QFile::WriteOther) ? 'w' : '-';
    permissions[8] = (fileInfo.permissions() & QFile::ExeOther) ? 'x' : '-';
    permissions[9] = 0;

    return(permissions);

}

/**
 * @brief buildUnixFilePermissions
 *
 * Build files unix permissions into octal QString and return.
 *
 * @param fileInfo  File to produce permissions for.
 *
 * @return Files permissions as a octal QString.
 */
QString buildUnixFilePermissions(const QFileInfo &fileInfo)
{

    unsigned short permissions=0;

    permissions |= (fileInfo.permissions() & QFile::ReadUser) ? 0400 : 0;
    permissions |= (fileInfo.permissions() & QFile::WriteUser) ? 0200 : 0;
    permissions |= (fileInfo.permissions() & QFile::ExeUser) ? 0100 : 0;
    permissions |= (fileInfo.permissions() & QFile::ReadGroup) ? 0040 : 0;
    permissions |= (fileInfo.permissions() & QFile::WriteGroup) ? 0020 : 0;
    permissions |= (fileInfo.permissions() & QFile::ExeGroup) ? 0010 : 0;
    permissions |= (fileInfo.permissions() & QFile::ReadOther) ? 0004 : 0;
    permissions |= (fileInfo.permissions() & QFile::WriteOther) ? 0002 : 0;
    permissions |= (fileInfo.permissions() & QFile::ExeOther) ? 0001 : 0;

    return("0"+QString::number(permissions,8));

}

/**
 * @brief buildMLSDCommonLine
 *
 * Build common file facts to QString and return.
 *
 * @param fileInfo  File to produce facts for.
 *
 * @return Common file facts as a QString.
 */
QString buildMLSDCommonLine(const QFileInfo &fileInfo)
{
    QString line;

    line.append(static_cast<QString>("Modify=")+fileInfo.lastModified().toString("yyyyMMddhhmmss;"));
    line.append(static_cast<QString>("Create=")+fileInfo.created().toString("yyyyMMddhhmmss;"));
    line.append(static_cast<QString>("UNIX.mode=")+buildUnixFilePermissions(fileInfo)+";");
    line.append(static_cast<QString>("UNIX.owner=")+QString::number(fileInfo.ownerId())+";");
    line.append(static_cast<QString>("UNIX.group=")+QString::number(fileInfo.groupId())+";");

    return line;

}

/**
 * @brief buildLISTLine
 *
 * Build list line for passed in QFileInfo. The format of which
 * is the same as given for the Linux 'ls -l' command.
 *
 * @param fileInfo  File to produce list line for.
 *
 * @return List line QString.
 */
QString buildLISTLine(const QFileInfo &fileInfo)
{

    QChar   fileType= '-';
    QString line;
    QString ownerGroup;

    if (fileInfo.isSymLink()) {
        fileType = 'l';
    } else if (fileInfo.isDir()){
        fileType = 'd';
    }

    line.append(fileType+buildFilePermissions(fileInfo)+" 1 ");

    ownerGroup = fileInfo.owner();
    if(ownerGroup.isEmpty()) {
        ownerGroup = "0";
    }
    line.append(ownerGroup.leftJustified(10,' ',true)+" ");

    ownerGroup = fileInfo.group();
    if(ownerGroup.isEmpty()) {
        ownerGroup = "0";
    }
    line.append(ownerGroup.leftJustified(10,' ',true)+" ");

    line.append(QString::number(fileInfo.size()).rightJustified(10,' ',true)+" ");
    line.append(fileInfo.lastModified().toString("MMM dd hh:mm").rightJustified(12,' ',true)+" ");
    line.append(fileInfo.fileName()+"\r\n");

    return(line);

}

/**
 * @brief buildMLSDPathLine
 *
 * Build list line for requested path in MLSD.
 *
 * @param pathInfo  Directory info to produce MLSD line for.
 * @param path      Directory path.
 *
 * @return MLSD list line QString.
 */
QString buildMLSDPathLine(const QFileInfo &pathInfo, const QString &path)
{
    return (static_cast<QString>("Type=cdir;")+buildMLSDCommonLine(pathInfo)+" "+path+"\r\n");
}

/**
 * @brief buildMLSDLine
 *
 * Build list line for single file in MLSD list.
 *
 * @param fileInfo  File information
 *
 * @return List line for file QString.
 */
QString buildMLSDLine(const QFileInfo &fileInfo)
{

    QString line;

    if(fileInfo.isDir()){
        line.append("Type=dir;");
    }else {
        line.append((static_cast<QString>("Type=file;")+"Size=")+QString::number(fileInfo.size())+";");
    }

    line.append(buildMLSDCommonLine(fileInfo)+" "+fileInfo.fileName()+"\r\n");

    return line;

}

} // namespace CogWheelFTPCoreUtil
<|endoftext|>


<commit_before>//===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the writeArchive function.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/ArchiveWriter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"

#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
#include <io.h>
#endif

using namespace llvm;

NewArchiveIterator::NewArchiveIterator() {}

NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I,
                                       StringRef Name)
    : IsNewMember(false), Name(Name), OldI(I) {}

NewArchiveIterator::NewArchiveIterator(StringRef NewFilename, StringRef Name)
    : IsNewMember(true), Name(Name), NewFilename(NewFilename) {}

StringRef NewArchiveIterator::getName() const { return Name; }

bool NewArchiveIterator::isNewMember() const { return IsNewMember; }

object::Archive::child_iterator NewArchiveIterator::getOld() const {
  assert(!IsNewMember);
  return OldI;
}

StringRef NewArchiveIterator::getNew() const {
  assert(IsNewMember);
  return NewFilename;
}

llvm::ErrorOr<int>
NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
  assert(IsNewMember);
  int NewFD;
  if (auto EC = sys::fs::openFileForRead(NewFilename, NewFD))
    return EC;
  assert(NewFD != -1);

  if (auto EC = sys::fs::status(NewFD, NewStatus))
    return EC;

  // Opening a directory doesn't make sense. Let it fail.
  // Linux cannot open directories with open(2), although
  // cygwin and *bsd can.
  if (NewStatus.type() == sys::fs::file_type::directory_file)
    return make_error_code(errc::is_a_directory);

  return NewFD;
}

template <typename T>
static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
				  bool MayTruncate = false) {
  uint64_t OldPos = OS.tell();
  OS << Data;
  unsigned SizeSoFar = OS.tell() - OldPos;
  if (Size > SizeSoFar) {
    unsigned Remaining = Size - SizeSoFar;
    for (unsigned I = 0; I < Remaining; ++I)
      OS << ' ';
  } else if (Size < SizeSoFar) {
    assert(MayTruncate && "Data doesn't fit in Size");
    // Some of the data this is used for (like UID) can be larger than the
    // space available in the archive format. Truncate in that case.
    OS.seek(OldPos + Size);
  }
}

static void print32BE(raw_fd_ostream &Out, unsigned Val) {
  // FIXME: Should use Endian.h here.
  for (int I = 3; I >= 0; --I) {
    char V = (Val >> (8 * I)) & 0xff;
    Out << V;
  }
}

static void printRestOfMemberHeader(raw_fd_ostream &Out,
                                    const sys::TimeValue &ModTime, unsigned UID,
                                    unsigned GID, unsigned Perms,
                                    unsigned Size) {
  printWithSpacePadding(Out, ModTime.toEpochTime(), 12);
  printWithSpacePadding(Out, UID, 6, true);
  printWithSpacePadding(Out, GID, 6, true);
  printWithSpacePadding(Out, format("%o", Perms), 8);
  printWithSpacePadding(Out, Size, 10);
  Out << "`\n";
}

static void printMemberHeader(raw_fd_ostream &Out, StringRef Name,
                              const sys::TimeValue &ModTime, unsigned UID,
                              unsigned GID, unsigned Perms, unsigned Size) {
  printWithSpacePadding(Out, Twine(Name) + "/", 16);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset,
                              const sys::TimeValue &ModTime, unsigned UID,
                              unsigned GID, unsigned Perms, unsigned Size) {
  Out << '/';
  printWithSpacePadding(Out, NameOffset, 15);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void writeStringTable(raw_fd_ostream &Out,
                             ArrayRef<NewArchiveIterator> Members,
                             std::vector<unsigned> &StringMapIndexes) {
  unsigned StartOffset = 0;
  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
                                              E = Members.end();
       I != E; ++I) {
    StringRef Name = I->getName();
    if (Name.size() < 16)
      continue;
    if (StartOffset == 0) {
      printWithSpacePadding(Out, "//", 58);
      Out << "`\n";
      StartOffset = Out.tell();
    }
    StringMapIndexes.push_back(Out.tell() - StartOffset);
    Out << Name << "/\n";
  }
  if (StartOffset == 0)
    return;
  if (Out.tell() % 2)
    Out << '\n';
  int Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(Pos);
}

// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
                 ArrayRef<MemoryBufferRef> Buffers,
                 std::vector<unsigned> &MemberOffsetRefs) {
  unsigned StartOffset = 0;
  unsigned MemberNum = 0;
  std::string NameBuf;
  raw_string_ostream NameOS(NameBuf);
  unsigned NumSyms = 0;
  LLVMContext Context;
  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
                                              E = Members.end();
       I != E; ++I, ++MemberNum) {
    MemoryBufferRef MemberBuffer = Buffers[MemberNum];
    ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
        object::SymbolicFile::createSymbolicFile(
            MemberBuffer, sys::fs::file_magic::unknown, &Context);
    if (!ObjOrErr)
      continue;  // FIXME: check only for "not an object file" errors.
    object::SymbolicFile &Obj = *ObjOrErr.get();

    if (!StartOffset) {
      printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0);
      StartOffset = Out.tell();
      print32BE(Out, 0);
    }

    for (const object::BasicSymbolRef &S : Obj.symbols()) {
      uint32_t Symflags = S.getFlags();
      if (Symflags & object::SymbolRef::SF_FormatSpecific)
        continue;
      if (!(Symflags & object::SymbolRef::SF_Global))
        continue;
      if (Symflags & object::SymbolRef::SF_Undefined)
        continue;
      if (auto EC = S.printName(NameOS))
        return EC;
      NameOS << '\0';
      ++NumSyms;
      MemberOffsetRefs.push_back(MemberNum);
      print32BE(Out, 0);
    }
  }
  Out << NameOS.str();

  if (StartOffset == 0)
    return 0;

  if (Out.tell() % 2)
    Out << '\0';

  unsigned Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(StartOffset);
  print32BE(Out, NumSyms);
  Out.seek(Pos);
  return StartOffset + 4;
}

std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
                   std::vector<NewArchiveIterator> &NewMembers,
                   bool WriteSymtab) {
  SmallString<128> TmpArchive;
  int TmpArchiveFD;
  if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
                                          TmpArchiveFD, TmpArchive))
    return std::make_pair(ArcName, EC);

  tool_output_file Output(TmpArchive, TmpArchiveFD);
  raw_fd_ostream &Out = Output.os();
  Out << "!<arch>\n";

  std::vector<unsigned> MemberOffsetRefs;

  std::vector<std::unique_ptr<MemoryBuffer>> Buffers;
  std::vector<MemoryBufferRef> Members;
  std::vector<sys::fs::file_status> NewMemberStatus;

  for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) {
    NewArchiveIterator &Member = NewMembers[I];
    MemoryBufferRef MemberRef;

    if (Member.isNewMember()) {
      StringRef Filename = Member.getNew();
      NewMemberStatus.resize(NewMemberStatus.size() + 1);
      sys::fs::file_status &Status = NewMemberStatus.back();
      ErrorOr<int> FD = Member.getFD(Status);
      if (auto EC = FD.getError())
        return std::make_pair(Filename, EC);
      ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
          MemoryBuffer::getOpenFile(FD.get(), Filename, Status.getSize(),
                                    false);
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair(Filename, EC);
      if (close(FD.get()) != 0)
        return std::make_pair(Filename,
                              std::error_code(errno, std::generic_category()));
      Buffers.push_back(std::move(MemberBufferOrErr.get()));
      MemberRef = Buffers.back()->getMemBufferRef();
    } else {
      object::Archive::child_iterator OldMember = Member.getOld();
      ErrorOr<MemoryBufferRef> MemberBufferOrErr =
          OldMember->getMemoryBufferRef();
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair("", EC);
      MemberRef = MemberBufferOrErr.get();
    }
    Members.push_back(MemberRef);
  }

  unsigned MemberReferenceOffset = 0;
  if (WriteSymtab) {
    ErrorOr<unsigned> MemberReferenceOffsetOrErr =
        writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs);
    if (auto EC = MemberReferenceOffsetOrErr.getError())
      return std::make_pair(ArcName, EC);
    MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
  }

  std::vector<unsigned> StringMapIndexes;
  writeStringTable(Out, NewMembers, StringMapIndexes);

  unsigned MemberNum = 0;
  unsigned LongNameMemberNum = 0;
  unsigned NewMemberNum = 0;
  std::vector<unsigned> MemberOffset;
  for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(),
                                                 E = NewMembers.end();
       I != E; ++I, ++MemberNum) {

    unsigned Pos = Out.tell();
    MemberOffset.push_back(Pos);

    MemoryBufferRef File = Members[MemberNum];
    if (I->isNewMember()) {
      StringRef FileName = I->getNew();
      const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum];
      NewMemberNum++;

      StringRef Name = sys::path::filename(FileName);
      if (Name.size() < 16)
        printMemberHeader(Out, Name, Status.getLastModificationTime(),
                          Status.getUser(), Status.getGroup(),
                          Status.permissions(), Status.getSize());
      else
        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
                          Status.getLastModificationTime(), Status.getUser(),
                          Status.getGroup(), Status.permissions(),
                          Status.getSize());
    } else {
      object::Archive::child_iterator OldMember = I->getOld();
      StringRef Name = I->getName();

      if (Name.size() < 16)
        printMemberHeader(Out, Name, OldMember->getLastModified(),
                          OldMember->getUID(), OldMember->getGID(),
                          OldMember->getAccessMode(), OldMember->getSize());
      else
        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
                          OldMember->getLastModified(), OldMember->getUID(),
                          OldMember->getGID(), OldMember->getAccessMode(),
                          OldMember->getSize());
    }

    Out << File.getBuffer();

    if (Out.tell() % 2)
      Out << '\n';
  }

  if (MemberReferenceOffset) {
    Out.seek(MemberReferenceOffset);
    for (unsigned MemberNum : MemberOffsetRefs)
      print32BE(Out, MemberOffset[MemberNum]);
  }

  Output.keep();
  Out.close();
  sys::fs::rename(TmpArchive, ArcName);
  return std::make_pair("", std::error_code());
}
<commit_msg>[ArchiveWriter] Use EndianStream. No functional change intended.<commit_after>//===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the writeArchive function.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/ArchiveWriter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"

#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
#include <io.h>
#endif

using namespace llvm;

NewArchiveIterator::NewArchiveIterator() {}

NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I,
                                       StringRef Name)
    : IsNewMember(false), Name(Name), OldI(I) {}

NewArchiveIterator::NewArchiveIterator(StringRef NewFilename, StringRef Name)
    : IsNewMember(true), Name(Name), NewFilename(NewFilename) {}

StringRef NewArchiveIterator::getName() const { return Name; }

bool NewArchiveIterator::isNewMember() const { return IsNewMember; }

object::Archive::child_iterator NewArchiveIterator::getOld() const {
  assert(!IsNewMember);
  return OldI;
}

StringRef NewArchiveIterator::getNew() const {
  assert(IsNewMember);
  return NewFilename;
}

llvm::ErrorOr<int>
NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
  assert(IsNewMember);
  int NewFD;
  if (auto EC = sys::fs::openFileForRead(NewFilename, NewFD))
    return EC;
  assert(NewFD != -1);

  if (auto EC = sys::fs::status(NewFD, NewStatus))
    return EC;

  // Opening a directory doesn't make sense. Let it fail.
  // Linux cannot open directories with open(2), although
  // cygwin and *bsd can.
  if (NewStatus.type() == sys::fs::file_type::directory_file)
    return make_error_code(errc::is_a_directory);

  return NewFD;
}

template <typename T>
static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
				  bool MayTruncate = false) {
  uint64_t OldPos = OS.tell();
  OS << Data;
  unsigned SizeSoFar = OS.tell() - OldPos;
  if (Size > SizeSoFar) {
    OS.indent(Size - SizeSoFar);
  } else if (Size < SizeSoFar) {
    assert(MayTruncate && "Data doesn't fit in Size");
    // Some of the data this is used for (like UID) can be larger than the
    // space available in the archive format. Truncate in that case.
    OS.seek(OldPos + Size);
  }
}

static void print32BE(raw_ostream &Out, uint32_t Val) {
  support::endian::Writer<support::big>(Out).write(Val);
}

static void printRestOfMemberHeader(raw_fd_ostream &Out,
                                    const sys::TimeValue &ModTime, unsigned UID,
                                    unsigned GID, unsigned Perms,
                                    unsigned Size) {
  printWithSpacePadding(Out, ModTime.toEpochTime(), 12);
  printWithSpacePadding(Out, UID, 6, true);
  printWithSpacePadding(Out, GID, 6, true);
  printWithSpacePadding(Out, format("%o", Perms), 8);
  printWithSpacePadding(Out, Size, 10);
  Out << "`\n";
}

static void printMemberHeader(raw_fd_ostream &Out, StringRef Name,
                              const sys::TimeValue &ModTime, unsigned UID,
                              unsigned GID, unsigned Perms, unsigned Size) {
  printWithSpacePadding(Out, Twine(Name) + "/", 16);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset,
                              const sys::TimeValue &ModTime, unsigned UID,
                              unsigned GID, unsigned Perms, unsigned Size) {
  Out << '/';
  printWithSpacePadding(Out, NameOffset, 15);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void writeStringTable(raw_fd_ostream &Out,
                             ArrayRef<NewArchiveIterator> Members,
                             std::vector<unsigned> &StringMapIndexes) {
  unsigned StartOffset = 0;
  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
                                              E = Members.end();
       I != E; ++I) {
    StringRef Name = I->getName();
    if (Name.size() < 16)
      continue;
    if (StartOffset == 0) {
      printWithSpacePadding(Out, "//", 58);
      Out << "`\n";
      StartOffset = Out.tell();
    }
    StringMapIndexes.push_back(Out.tell() - StartOffset);
    Out << Name << "/\n";
  }
  if (StartOffset == 0)
    return;
  if (Out.tell() % 2)
    Out << '\n';
  int Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(Pos);
}

// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
                 ArrayRef<MemoryBufferRef> Buffers,
                 std::vector<unsigned> &MemberOffsetRefs) {
  unsigned StartOffset = 0;
  unsigned MemberNum = 0;
  std::string NameBuf;
  raw_string_ostream NameOS(NameBuf);
  unsigned NumSyms = 0;
  LLVMContext Context;
  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
                                              E = Members.end();
       I != E; ++I, ++MemberNum) {
    MemoryBufferRef MemberBuffer = Buffers[MemberNum];
    ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
        object::SymbolicFile::createSymbolicFile(
            MemberBuffer, sys::fs::file_magic::unknown, &Context);
    if (!ObjOrErr)
      continue;  // FIXME: check only for "not an object file" errors.
    object::SymbolicFile &Obj = *ObjOrErr.get();

    if (!StartOffset) {
      printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0);
      StartOffset = Out.tell();
      print32BE(Out, 0);
    }

    for (const object::BasicSymbolRef &S : Obj.symbols()) {
      uint32_t Symflags = S.getFlags();
      if (Symflags & object::SymbolRef::SF_FormatSpecific)
        continue;
      if (!(Symflags & object::SymbolRef::SF_Global))
        continue;
      if (Symflags & object::SymbolRef::SF_Undefined)
        continue;
      if (auto EC = S.printName(NameOS))
        return EC;
      NameOS << '\0';
      ++NumSyms;
      MemberOffsetRefs.push_back(MemberNum);
      print32BE(Out, 0);
    }
  }
  Out << NameOS.str();

  if (StartOffset == 0)
    return 0;

  if (Out.tell() % 2)
    Out << '\0';

  unsigned Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(StartOffset);
  print32BE(Out, NumSyms);
  Out.seek(Pos);
  return StartOffset + 4;
}

std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
                   std::vector<NewArchiveIterator> &NewMembers,
                   bool WriteSymtab) {
  SmallString<128> TmpArchive;
  int TmpArchiveFD;
  if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
                                          TmpArchiveFD, TmpArchive))
    return std::make_pair(ArcName, EC);

  tool_output_file Output(TmpArchive, TmpArchiveFD);
  raw_fd_ostream &Out = Output.os();
  Out << "!<arch>\n";

  std::vector<unsigned> MemberOffsetRefs;

  std::vector<std::unique_ptr<MemoryBuffer>> Buffers;
  std::vector<MemoryBufferRef> Members;
  std::vector<sys::fs::file_status> NewMemberStatus;

  for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) {
    NewArchiveIterator &Member = NewMembers[I];
    MemoryBufferRef MemberRef;

    if (Member.isNewMember()) {
      StringRef Filename = Member.getNew();
      NewMemberStatus.resize(NewMemberStatus.size() + 1);
      sys::fs::file_status &Status = NewMemberStatus.back();
      ErrorOr<int> FD = Member.getFD(Status);
      if (auto EC = FD.getError())
        return std::make_pair(Filename, EC);
      ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
          MemoryBuffer::getOpenFile(FD.get(), Filename, Status.getSize(),
                                    false);
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair(Filename, EC);
      if (close(FD.get()) != 0)
        return std::make_pair(Filename,
                              std::error_code(errno, std::generic_category()));
      Buffers.push_back(std::move(MemberBufferOrErr.get()));
      MemberRef = Buffers.back()->getMemBufferRef();
    } else {
      object::Archive::child_iterator OldMember = Member.getOld();
      ErrorOr<MemoryBufferRef> MemberBufferOrErr =
          OldMember->getMemoryBufferRef();
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair("", EC);
      MemberRef = MemberBufferOrErr.get();
    }
    Members.push_back(MemberRef);
  }

  unsigned MemberReferenceOffset = 0;
  if (WriteSymtab) {
    ErrorOr<unsigned> MemberReferenceOffsetOrErr =
        writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs);
    if (auto EC = MemberReferenceOffsetOrErr.getError())
      return std::make_pair(ArcName, EC);
    MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
  }

  std::vector<unsigned> StringMapIndexes;
  writeStringTable(Out, NewMembers, StringMapIndexes);

  unsigned MemberNum = 0;
  unsigned LongNameMemberNum = 0;
  unsigned NewMemberNum = 0;
  std::vector<unsigned> MemberOffset;
  for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(),
                                                 E = NewMembers.end();
       I != E; ++I, ++MemberNum) {

    unsigned Pos = Out.tell();
    MemberOffset.push_back(Pos);

    MemoryBufferRef File = Members[MemberNum];
    if (I->isNewMember()) {
      StringRef FileName = I->getNew();
      const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum];
      NewMemberNum++;

      StringRef Name = sys::path::filename(FileName);
      if (Name.size() < 16)
        printMemberHeader(Out, Name, Status.getLastModificationTime(),
                          Status.getUser(), Status.getGroup(),
                          Status.permissions(), Status.getSize());
      else
        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
                          Status.getLastModificationTime(), Status.getUser(),
                          Status.getGroup(), Status.permissions(),
                          Status.getSize());
    } else {
      object::Archive::child_iterator OldMember = I->getOld();
      StringRef Name = I->getName();

      if (Name.size() < 16)
        printMemberHeader(Out, Name, OldMember->getLastModified(),
                          OldMember->getUID(), OldMember->getGID(),
                          OldMember->getAccessMode(), OldMember->getSize());
      else
        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
                          OldMember->getLastModified(), OldMember->getUID(),
                          OldMember->getGID(), OldMember->getAccessMode(),
                          OldMember->getSize());
    }

    Out << File.getBuffer();

    if (Out.tell() % 2)
      Out << '\n';
  }

  if (MemberReferenceOffset) {
    Out.seek(MemberReferenceOffset);
    for (unsigned MemberNum : MemberOffsetRefs)
      print32BE(Out, MemberOffset[MemberNum]);
  }

  Output.keep();
  Out.close();
  sys::fs::rename(TmpArchive, ArcName);
  return std::make_pair("", std::error_code());
}
<|endoftext|>


<commit_before>/*
 * Texan
 * 27.05.12
 */

#include <iostream>
#include <sstream>
#include "LoadProfile.hpp"

LoadProfile::LoadProfile(GameManager& game, std::vector<Profile *>& profiles, std::vector<std::string>& names)
  : AMenu("menu/background/backgroundLoadProfile.jpg", "menu/background/backgroundLoadProfile.jpg", 0.0f, -1.0f, 800.0f, game),
    _profiles(profiles),
    _names(names),
    _index(0),
    _timerL(-1.0f),
    _timerR(-1.0f)
{
  this->_tags.push_back(new Tag("menu/LoadNormal.png", "menu/LoadHighlit.png", true, false, TokenMenu::LAST, 700.0f, 0.0f, 1200.0f));
  this->_tags.push_back(new Tag("menu/BlackNormal.png", "menu/BlackHighlit.png", false, false, TokenMenu::LAST, 900.0f, 0.0f, 1200.0f));
  this->_tags.push_back(new Tag("menu/BlackNormal.png", "menu/BlackHighlit.png", false, false, TokenMenu::LAST, 900.0f, 0.0f, 1250.0f));
  this->_tags.push_back(new Tag("menu/DoneNormal.png", "menu/DoneHighlit.png", false, false, TokenMenu::PROFILE, 700.0f, 0.0f, 1300.0f));
  this->_tags.push_back(new Tag("menu/BackNormal.png", "menu/BackHighlit.png", false, false, TokenMenu::MAINMENU, 700.0f, 0.0f, 1350.0f));

}

LoadProfile::~LoadProfile(void)
{
}

double	LoadProfile::getCenterX() const
{
  return (800.0f);
}

double	LoadProfile::getCenterY() const
{
  return (1200.0f);
}

void		LoadProfile::updateText() const
{
  std::stringstream	ss;

  if (this->_profiles.size())
    {
      this->_tags[1]->createText(this->_names[this->_index], 20, 950, 270);
      ss << " Skin : " << this->_profiles[this->_index]->getSkin();
      this->_tags[2]->createText(ss.str(), 20, 950, 310);
    }
  else
    {
      this->_tags[1]->createText("", 20, 950, 270);
      this->_tags[2]->createText("", 20, 950, 310);
    }
}

void		LoadProfile::changeProfile(gdl::GameClock const& clock, gdl::Input& input)
{
  if (clock.getTotalGameTime() >= this->_timerL && input.isKeyDown(gdl::Keys::Left))
    {
      --this->_index;
      if (static_cast<int>(this->_index) < 0)
	this->_index = this->_profiles.size() - 1;
      this->_timerL = clock.getTotalGameTime() + 0.15f;
    }
  else if (clock.getTotalGameTime() >= this->_timerR && input.isKeyDown(gdl::Keys::Right))
    {
      ++this->_index;
      if (this->_index >= this->_profiles.size())
	this->_index = 0;
      this->_timerR = clock.getTotalGameTime() + 0.15f;
    }
}

void	LoadProfile::update(gdl::GameClock const& clock, gdl::Input& input)
{
  std::cout << this->_profiles.size()  << std::endl;
  this->updateText();
  for (size_t i = 0; i < this->_keyEvent.size(); ++i)
    if (input.isKeyDown(this->_keyEvent[i].first))
      (this->*_keyEvent[i].second)(clock);
  if (this->_cursor == 0) //TODO pointer function
    this->changeProfile(clock, input);
  else if (this->_cursor == 1)
    {
      this->_tags[this->_cursor]->setStatus(false);
      this->_cursor = 3;
      this->_tags[this->_cursor]->setStatus(true);

    }
  else if (this->_cursor == 2)
    {
      this->_tags[this->_cursor]->setStatus(false);
      this->_cursor = 0;
      this->_tags[this->_cursor]->setStatus(true);

    }

  if (this->_curToken == TokenMenu::PROFILE)
    if (this->_profiles.size())
      this->_gameManager._mainProfile = this->_profiles[this->_index];
    else
      this->_curToken = TokenMenu::LAST;
}
<commit_msg>Added braces between an if else to avoid warning<commit_after>/*
 * Texan
 * 27.05.12
 */

#include <iostream>
#include <sstream>
#include "LoadProfile.hpp"

LoadProfile::LoadProfile(GameManager& game, std::vector<Profile *>& profiles, std::vector<std::string>& names)
  : AMenu("menu/background/backgroundLoadProfile.jpg", "menu/background/backgroundLoadProfile.jpg", 0.0f, -1.0f, 800.0f, game),
    _profiles(profiles),
    _names(names),
    _index(0),
    _timerL(-1.0f),
    _timerR(-1.0f)
{
  this->_tags.push_back(new Tag("menu/LoadNormal.png", "menu/LoadHighlit.png", true, false, TokenMenu::LAST, 700.0f, 0.0f, 1200.0f));
  this->_tags.push_back(new Tag("menu/BlackNormal.png", "menu/BlackHighlit.png", false, false, TokenMenu::LAST, 900.0f, 0.0f, 1200.0f));
  this->_tags.push_back(new Tag("menu/BlackNormal.png", "menu/BlackHighlit.png", false, false, TokenMenu::LAST, 900.0f, 0.0f, 1250.0f));
  this->_tags.push_back(new Tag("menu/DoneNormal.png", "menu/DoneHighlit.png", false, false, TokenMenu::PROFILE, 700.0f, 0.0f, 1300.0f));
  this->_tags.push_back(new Tag("menu/BackNormal.png", "menu/BackHighlit.png", false, false, TokenMenu::MAINMENU, 700.0f, 0.0f, 1350.0f));

}

LoadProfile::~LoadProfile(void)
{
}

double	LoadProfile::getCenterX() const
{
  return (800.0f);
}

double	LoadProfile::getCenterY() const
{
  return (1200.0f);
}

void		LoadProfile::updateText() const
{
  std::stringstream	ss;

  if (this->_profiles.size())
    {
      this->_tags[1]->createText(this->_names[this->_index], 20, 950, 270);
      ss << " Skin : " << this->_profiles[this->_index]->getSkin();
      this->_tags[2]->createText(ss.str(), 20, 950, 310);
    }
  else
    {
      this->_tags[1]->createText("", 20, 950, 270);
      this->_tags[2]->createText("", 20, 950, 310);
    }
}

void		LoadProfile::changeProfile(gdl::GameClock const& clock, gdl::Input& input)
{
  if (clock.getTotalGameTime() >= this->_timerL && input.isKeyDown(gdl::Keys::Left))
    {
      --this->_index;
      if (static_cast<int>(this->_index) < 0)
	this->_index = this->_profiles.size() - 1;
      this->_timerL = clock.getTotalGameTime() + 0.15f;
    }
  else if (clock.getTotalGameTime() >= this->_timerR && input.isKeyDown(gdl::Keys::Right))
    {
      ++this->_index;
      if (this->_index >= this->_profiles.size())
	this->_index = 0;
      this->_timerR = clock.getTotalGameTime() + 0.15f;
    }
}

void	LoadProfile::update(gdl::GameClock const& clock, gdl::Input& input)
{
  std::cout << this->_profiles.size()  << std::endl;
  this->updateText();
  for (size_t i = 0; i < this->_keyEvent.size(); ++i)
    if (input.isKeyDown(this->_keyEvent[i].first))
      (this->*_keyEvent[i].second)(clock);
  if (this->_cursor == 0) //TODO pointer function
    this->changeProfile(clock, input);
  else if (this->_cursor == 1)
    {
      this->_tags[this->_cursor]->setStatus(false);
      this->_cursor = 3;
      this->_tags[this->_cursor]->setStatus(true);

    }
  else if (this->_cursor == 2)
    {
      this->_tags[this->_cursor]->setStatus(false);
      this->_cursor = 0;
      this->_tags[this->_cursor]->setStatus(true);

    }

  if (this->_curToken == TokenMenu::PROFILE)
    {
      if (this->_profiles.size())
	this->_gameManager._mainProfile = this->_profiles[this->_index];
      else
	this->_curToken = TokenMenu::LAST;
    }
}
<|endoftext|>


<commit_before>#include "LuaGLWidget.h"
#include <QFile>
#include <QVector3D>
#include "util.h"
#include "LuaGlobal.hpp"

#include <cmath>

static float func(const float& x, const float& z)
{
	return cos(x) * log(z);
}

LuaGLWidget::LuaGLWidget(QWidget* const parent) :
	GLWidget(parent),
	timer(this, 1000 / 60)
{
	connect(&timer, SIGNAL(timeout(const float&)), this, SLOT(tick(const float&)));
	connect(&timer, SIGNAL(timeout(const float&)), this, SLOT(updateGL()));
	timer.startOnShow(this);
	update(func);
}

void LuaGLWidget::initializeGL()
{
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
	sceneList = glGenLists(1);
	glNewList(sceneList, GL_COMPILE);
	renderScene();
	glEndList();
}

void LuaGLWidget::tick(const float&)
{
}

void LuaGLWidget::renderScene()
{
	glTranslatef(0, -HALFSIZE/8, 0);
	glBegin(GL_QUADS);
	for (int y = -HALFSIZE; y < HALFSIZE-1; y++) {
		for (int x = -HALFSIZE; x < HALFSIZE-1; x++) {
			// XXX This code is recklessly inefficient; we either don't need
			// QVector3D's or we should reuse objects outside of this loop.
			QVector3D a(x, AMPLITUDE*get(x, y), y);
			QVector3D b(x, AMPLITUDE*get(x, y+1), y+1);
			QVector3D c(x+1, AMPLITUDE*get(x+1, y+1), y+1);
			QVector3D d(x+1, AMPLITUDE*get(x+1, y), y);
			QVector3D norm = normal(x,y);
			// FIXME These normals produce visible edges; I think the average
			// is generated incorrectly.
			QVector3D rnorm = average(norm, normal(x, y+1));
			QVector3D tnorm = average(norm, normal(x+1, y));
			QVector3D lnorm = average(norm, normal(x, y-1));
			QVector3D bnorm = average(norm, normal(x-1, y));
			renderNormal(average(rnorm, bnorm));
			renderVertex(b);
			renderNormal(average(rnorm, tnorm));
			renderVertex(c);
			renderNormal(average(lnorm, tnorm));
			renderVertex(d);
			renderNormal(average(lnorm, bnorm));
			renderVertex(a);
		}
	}
	glEnd();
}

void LuaGLWidget::render()
{
	glClear(GL_DEPTH_BUFFER_BIT);
	glCallList(sceneList);
}

void LuaGLWidget::resizeGL(int width, int height)
{
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	nt::setGLFrustrum(60, (float) width / height, 1, 800);
	glMatrixMode(GL_MODELVIEW);
}

LuaGLWidget::~LuaGLWidget()
{
	glDeleteLists(sceneList, 1);
}
<commit_msg>Orient Lua's camera towards the action<commit_after>#include "LuaGLWidget.h"
#include <QFile>
#include <QVector3D>
#include "util.h"
#include "LuaGlobal.hpp"

#include <cmath>

static float func(const float& x, const float& z)
{
	return cos(x) * log(z);
}

LuaGLWidget::LuaGLWidget(QWidget* const parent) :
	GLWidget(parent),
	timer(this, 1000 / 60)
{
	connect(&timer, SIGNAL(timeout(const float&)), this, SLOT(tick(const float&)));
	connect(&timer, SIGNAL(timeout(const float&)), this, SLOT(updateGL()));
	timer.startOnShow(this);
	update(func);
}

void LuaGLWidget::initializeGL()
{
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
	sceneList = glGenLists(1);
	glNewList(sceneList, GL_COMPILE);
	renderScene();
	glEndList();
}

void LuaGLWidget::tick(const float&)
{
}

void LuaGLWidget::renderScene()
{
	glTranslatef(0, -HALFSIZE/8, 0);
	glRotatef(-150, 0, 1, 0);
	glRotatef(-10, 1, 0, 0);
	glBegin(GL_QUADS);
	for (int y = -HALFSIZE; y < HALFSIZE-1; y++) {
		for (int x = -HALFSIZE; x < HALFSIZE-1; x++) {
			// XXX This code is recklessly inefficient; we either don't need
			// QVector3D's or we should reuse objects outside of this loop.
			QVector3D a(x, AMPLITUDE*get(x, y), y);
			QVector3D b(x, AMPLITUDE*get(x, y+1), y+1);
			QVector3D c(x+1, AMPLITUDE*get(x+1, y+1), y+1);
			QVector3D d(x+1, AMPLITUDE*get(x+1, y), y);
			QVector3D norm = normal(x,y);
			// FIXME These normals produce visible edges; I think the average
			// is generated incorrectly.
			QVector3D rnorm = average(norm, normal(x, y+1));
			QVector3D tnorm = average(norm, normal(x+1, y));
			QVector3D lnorm = average(norm, normal(x, y-1));
			QVector3D bnorm = average(norm, normal(x-1, y));
			renderNormal(average(rnorm, bnorm));
			renderVertex(b);
			renderNormal(average(rnorm, tnorm));
			renderVertex(c);
			renderNormal(average(lnorm, tnorm));
			renderVertex(d);
			renderNormal(average(lnorm, bnorm));
			renderVertex(a);
		}
	}
	glEnd();
}

void LuaGLWidget::render()
{
	glClear(GL_DEPTH_BUFFER_BIT);
	glCallList(sceneList);
}

void LuaGLWidget::resizeGL(int width, int height)
{
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	nt::setGLFrustrum(60, (float) width / height, 1, 800);
	glMatrixMode(GL_MODELVIEW);
}

LuaGLWidget::~LuaGLWidget()
{
	glDeleteLists(sceneList, 1);
}
<|endoftext|>


<commit_before>/*
 * tcp_epoll.cpp
 *
 *  Created on: Nov 10, 2014
 *      Author: liao
 */
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <cerrno>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/epoll.h>
#include <sys/fcntl.h>
#include <sys/sysinfo.h>
#include <unistd.h>

#include "simple_log.h"
#include "epoll_socket.h"

EpollSocket::EpollSocket() {
    _thread_pool = NULL;
    _use_default_tp = true;
    _status = S_RUN;
    _epollfd = -1;
    _clients = 0;
    pthread_mutex_init(&_client_lock, NULL);
}

EpollSocket::~EpollSocket() {
    if (_thread_pool != NULL && _use_default_tp) {
        delete _thread_pool;
        _thread_pool = NULL;
    }
}

int EpollSocket::set_nonblocking(int fd) {
    int flags;

    if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
        flags = 0;
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
};

int EpollSocket::bind_on(unsigned int ip) {
    /* listen on sock_fd, new connection on new_fd */
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        LOG_ERROR("socket error:%s", strerror(errno));
        return -1;
    }
    int opt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in my_addr; /* my address information */
    memset (&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET; /* host byte order */
    my_addr.sin_port = htons(_port); /* short, network byte order */
    my_addr.sin_addr.s_addr = ip;

    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) {
        LOG_ERROR("bind error:%s", strerror(errno));
        return -1;
    }
    if (listen(sockfd, _backlog) == -1) {
        LOG_ERROR("listen error:%s", strerror(errno));
        return -1;
    }
    _listen_sockets.insert(sockfd);
    return 0;
}

int EpollSocket::listen_on() {
    if (_bind_ips.empty()) {
        int ret = bind_on(INADDR_ANY); /* auto-fill with my IP */
        if (ret != 0) {
            return ret;
        }
        LOG_INFO("bind for all ip (0.0.0.0)!");
    } else {
        for (size_t i = 0; i < _bind_ips.size(); i++) {
            unsigned ip = inet_addr(_bind_ips[i].c_str());
            int ret = bind_on(ip);
            if (ret != 0) {
                return ret;
            }
            LOG_INFO("bind for ip:%s success", _bind_ips[i].c_str());
        }
    }

    LOG_INFO("start Server Socket on port : %d", _port);
    return 0;
}

int EpollSocket::accept_socket(int sockfd, std::string &client_ip) {
    int new_fd;
    struct sockaddr_in their_addr; /* connector's address information */
    socklen_t sin_size = sizeof(struct sockaddr_in);

    if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size)) == -1) {
        LOG_ERROR("accept error:%s", strerror(errno));
        return -1;
    }

    client_ip = inet_ntoa(their_addr.sin_addr);
    LOG_DEBUG("server: got connection from %s\n", client_ip.c_str());
    return new_fd;
}

int EpollSocket::handle_accept_event(int &epollfd, epoll_event &event, EpollSocketWatcher &socket_handler) {
    int sockfd = event.data.fd;

    std::string client_ip;
    int conn_sock = accept_socket(sockfd, client_ip);
    if (conn_sock == -1) {
        return -1;
    }
    set_nonblocking(conn_sock);

    pthread_mutex_lock(&_client_lock);
    _clients++;
    pthread_mutex_unlock(&_client_lock);
    LOG_DEBUG("get accept socket which listen fd:%d, conn_sock_fd:%d", sockfd, conn_sock);

    EpollContext *epoll_context = new EpollContext();
    epoll_context->fd = conn_sock;
    epoll_context->client_ip = client_ip;

    socket_handler.on_accept(*epoll_context);

    struct epoll_event conn_sock_ev;
    conn_sock_ev.events = EPOLLIN | EPOLLONESHOT;
    conn_sock_ev.data.ptr = epoll_context;

    if (epoll_ctl(_epollfd, EPOLL_CTL_ADD, conn_sock, &conn_sock_ev) == -1) {
        LOG_ERROR("epoll_ctl: conn_sock:%s", strerror(errno));
        close_and_release(conn_sock_ev);
        return -1;
    }
    return 0;
}

void read_func(void *data) {
    TaskData *td = (TaskData *) data;
    td->es->handle_readable_event(td->event);
    delete td;
}

int EpollSocket::handle_readable_event(epoll_event &event) {
    EpollContext *epoll_context = (EpollContext *) event.data.ptr;
    int fd = epoll_context->fd;

    int ret = _watcher->on_readable(_epollfd, event);
    if (ret == READ_CLOSE) {
        return close_and_release(event);
    }
    if (ret == READ_CONTINUE) {
        event.events = EPOLLIN | EPOLLONESHOT;
        epoll_ctl(_epollfd, EPOLL_CTL_MOD, fd, &event);
    } else if (ret == READ_OVER) { // READ_OVER
        event.events = EPOLLOUT | EPOLLONESHOT;
        epoll_ctl(_epollfd, EPOLL_CTL_MOD, fd, &event);
    } else {
        LOG_ERROR("unkonw read ret:%d", ret);
    }
    return 0;
}

int EpollSocket::handle_writeable_event(int &epollfd, epoll_event &event, EpollSocketWatcher &socket_handler) {
    EpollContext *epoll_context = (EpollContext *) event.data.ptr;
    int fd = epoll_context->fd;
    LOG_DEBUG("start write data");

    int ret = socket_handler.on_writeable(*epoll_context);
    if(ret == WRITE_CONN_CLOSE) {
        return close_and_release(event);
    }

    if (ret == WRITE_CONN_CONTINUE) {
        event.events = EPOLLOUT | EPOLLONESHOT;
    } else if (ret == WRITE_CONN_ALIVE) {
        if (_status == S_REJECT_CONN) {
            return close_and_release(event);
        }
        // wait for next request
        event.events = EPOLLIN | EPOLLONESHOT;
    } else {
        LOG_ERROR("unkonw write ret:%d", ret);
    }
    epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);

    return 0;
}

void EpollSocket::set_thread_pool(ThreadPool *tp) {
    this->_thread_pool = tp;
    _use_default_tp = false;
}

void EpollSocket::set_port(int port) {
    _port = port;
}

void EpollSocket::set_watcher(EpollSocketWatcher *w) {
    _watcher = w;
}

void EpollSocket::set_backlog(int backlog) {
    _backlog = backlog;
}

void EpollSocket::set_max_events(int me) {
    _max_events = me;
}

int EpollSocket::init_default_tp() {
    int core_size = get_nprocs();
    LOG_INFO("thread pool not set, we will build for core size:%d", core_size);
    _thread_pool = new ThreadPool();
    _thread_pool->set_pool_size(core_size);

    return 0;
}

int EpollSocket::add_listen_sock_to_epoll() {
    for (std::set<int>::iterator i = _listen_sockets.begin(); i != _listen_sockets.end(); i++) {
        int sockfd = *i;
        struct epoll_event ev;
        ev.events = EPOLLIN;
        ev.data.fd = sockfd;
        if (epoll_ctl(_epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) {
            LOG_ERROR("epoll_ctl: listen_sock:%s", strerror(errno));
            return -1;
        }
    }
    return 0;
}

int EpollSocket::handle_event(epoll_event &e) {
    if (_listen_sockets.count(e.data.fd)) {
        // accept connection
        if (_status == S_RUN) {
            this->handle_accept_event(_epollfd, e, *_watcher);
        } else {
            LOG_INFO("current status:%d, not accept new connect", _status);
            pthread_mutex_lock(&_client_lock);
            if (_clients == 0 && _status == S_REJECT_CONN) {
                _status = S_STOP;
                LOG_INFO("client is empty and ready for stop server!");
            }
            pthread_mutex_unlock(&_client_lock);
        }
    } else if (e.events & EPOLLIN) {
        // handle readable async
        LOG_DEBUG("start handle readable event");
        TaskData *tdata = new TaskData();
        tdata->event = e;
        tdata->es = this;

        Task *task = new Task(read_func, tdata);
        int ret = _thread_pool->add_task(task);
        if (ret != 0) {
            LOG_WARN("add read task fail:%d, we will close connect.", ret);
            close_and_release(e);
            delete tdata;
            delete task;
        }
    } else if (e.events & EPOLLOUT) {
        // writeable
        this->handle_writeable_event(_epollfd, e, *_watcher);
    } else {
        LOG_INFO("unkonw events :%d", e.events);
    }
    return 0;
}

int EpollSocket::create_epoll() {
    // The "size" parameter is a hint specifying the number of file
    // descriptors to be associated with the new instance.
    _epollfd = epoll_create(1024);
    if (_epollfd == -1) {
        LOG_ERROR("epoll_create:%s", strerror(errno));
        return -1;
    }
    return 0;
}

int EpollSocket::init_tp() {
    if (_thread_pool == NULL) {
        init_default_tp();
    }
    int ret = _thread_pool->start_threadpool();
    return ret;
}

int EpollSocket::start_event_loop() {
    epoll_event *events = new epoll_event[_max_events];
    while (_status != S_STOP) {
        int fds_num = epoll_wait(_epollfd, events, _max_events, -1);
        if (fds_num == -1) {
            if (errno == EINTR) { /*The call was interrupted by a signal handler*/
                continue;
            }
            LOG_ERROR("epoll_wait error:%s", strerror(errno));
            break;
        }

        for (int i = 0; i < fds_num; i++) {
            this->handle_event(events[i]);
        }
    }
    LOG_INFO("epoll wait loop stop ...");
    if (events != NULL) {
        delete[] events;
        events = NULL;
    }
    return 0;
}

int EpollSocket::start_epoll() {
    int ret = init_tp();
    CHECK_RET(ret, "thread pool start error:%d", ret);

    ret = this->listen_on();
    CHECK_RET(ret, "listen err:%d", ret);

    ret = this->create_epoll();
    CHECK_RET(ret, "create epoll err:%d", ret);

    ret = this->add_listen_sock_to_epoll();
    CHECK_RET(ret , "add listen sock to epoll fail:%d", ret);

    return start_event_loop();
}

int EpollSocket::stop_epoll() {
    _status = S_REJECT_CONN;
    LOG_INFO("stop epoll , current clients:%u", _clients);
    return 0;
}

int EpollSocket::close_and_release(epoll_event &epoll_event) {
    if (epoll_event.data.ptr == NULL) {
        return 0;
    }
    LOG_DEBUG("connect close");

    EpollContext *hc = (EpollContext *) epoll_event.data.ptr;
    _watcher->on_close(*hc);

    int fd = hc->fd;
    epoll_event.events = EPOLLIN | EPOLLOUT;
    epoll_ctl(_epollfd, EPOLL_CTL_DEL, fd, &epoll_event);

    delete (EpollContext *) epoll_event.data.ptr;
    epoll_event.data.ptr = NULL;

    int ret = close(fd);

    pthread_mutex_lock(&_client_lock);
    _clients--;
    if (_clients == 0 && _status == S_REJECT_CONN) {
        _status = S_STOP;
        LOG_INFO("client is empty and ready for stop server!");
    }
    pthread_mutex_unlock(&_client_lock);

    LOG_DEBUG("connect close complete which fd:%d, ret:%d", fd, ret);
    return ret;
}

void EpollSocket::add_bind_ip(std::string ip) {
    _bind_ips.push_back(ip);
}
<commit_msg>ignore broken pipe signal<commit_after>/*
 * tcp_epoll.cpp
 *
 *  Created on: Nov 10, 2014
 *      Author: liao
 */
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <cerrno>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/epoll.h>
#include <sys/fcntl.h>
#include <sys/sysinfo.h>
#include <unistd.h>

#include "simple_log.h"
#include "epoll_socket.h"

EpollSocket::EpollSocket() {
    _thread_pool = NULL;
    _use_default_tp = true;
    _status = S_RUN;
    _epollfd = -1;
    _clients = 0;
    pthread_mutex_init(&_client_lock, NULL);
}

EpollSocket::~EpollSocket() {
    if (_thread_pool != NULL && _use_default_tp) {
        delete _thread_pool;
        _thread_pool = NULL;
    }
}

int EpollSocket::set_nonblocking(int fd) {
    int flags;

    if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
        flags = 0;
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
};

int EpollSocket::bind_on(unsigned int ip) {
    /* listen on sock_fd, new connection on new_fd */
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        LOG_ERROR("socket error:%s", strerror(errno));
        return -1;
    }
    int opt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in my_addr; /* my address information */
    memset (&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET; /* host byte order */
    my_addr.sin_port = htons(_port); /* short, network byte order */
    my_addr.sin_addr.s_addr = ip;

    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) {
        LOG_ERROR("bind error:%s", strerror(errno));
        return -1;
    }
    if (listen(sockfd, _backlog) == -1) {
        LOG_ERROR("listen error:%s", strerror(errno));
        return -1;
    }
    _listen_sockets.insert(sockfd);
    return 0;
}

int EpollSocket::listen_on() {
    if (_bind_ips.empty()) {
        int ret = bind_on(INADDR_ANY); /* auto-fill with my IP */
        if (ret != 0) {
            return ret;
        }
        LOG_INFO("bind for all ip (0.0.0.0)!");
    } else {
        for (size_t i = 0; i < _bind_ips.size(); i++) {
            unsigned ip = inet_addr(_bind_ips[i].c_str());
            int ret = bind_on(ip);
            if (ret != 0) {
                return ret;
            }
            LOG_INFO("bind for ip:%s success", _bind_ips[i].c_str());
        }
    }

    LOG_INFO("start Server Socket on port : %d", _port);
    return 0;
}

int EpollSocket::accept_socket(int sockfd, std::string &client_ip) {
    int new_fd;
    struct sockaddr_in their_addr; /* connector's address information */
    socklen_t sin_size = sizeof(struct sockaddr_in);

    if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size)) == -1) {
        LOG_ERROR("accept error:%s", strerror(errno));
        return -1;
    }

    client_ip = inet_ntoa(their_addr.sin_addr);
    LOG_DEBUG("server: got connection from %s\n", client_ip.c_str());
    return new_fd;
}

int EpollSocket::handle_accept_event(int &epollfd, epoll_event &event, EpollSocketWatcher &socket_handler) {
    int sockfd = event.data.fd;

    std::string client_ip;
    int conn_sock = accept_socket(sockfd, client_ip);
    if (conn_sock == -1) {
        return -1;
    }
    set_nonblocking(conn_sock);

    pthread_mutex_lock(&_client_lock);
    _clients++;
    pthread_mutex_unlock(&_client_lock);
    LOG_DEBUG("get accept socket which listen fd:%d, conn_sock_fd:%d", sockfd, conn_sock);

    EpollContext *epoll_context = new EpollContext();
    epoll_context->fd = conn_sock;
    epoll_context->client_ip = client_ip;

    socket_handler.on_accept(*epoll_context);

    struct epoll_event conn_sock_ev;
    conn_sock_ev.events = EPOLLIN | EPOLLONESHOT;
    conn_sock_ev.data.ptr = epoll_context;

    if (epoll_ctl(_epollfd, EPOLL_CTL_ADD, conn_sock, &conn_sock_ev) == -1) {
        LOG_ERROR("epoll_ctl: conn_sock:%s", strerror(errno));
        close_and_release(conn_sock_ev);
        return -1;
    }
    return 0;
}

void read_func(void *data) {
    TaskData *td = (TaskData *) data;
    td->es->handle_readable_event(td->event);
    delete td;
}

int EpollSocket::handle_readable_event(epoll_event &event) {
    EpollContext *epoll_context = (EpollContext *) event.data.ptr;
    int fd = epoll_context->fd;

    int ret = _watcher->on_readable(_epollfd, event);
    if (ret == READ_CLOSE) {
        return close_and_release(event);
    }
    if (ret == READ_CONTINUE) {
        event.events = EPOLLIN | EPOLLONESHOT;
        epoll_ctl(_epollfd, EPOLL_CTL_MOD, fd, &event);
    } else if (ret == READ_OVER) { // READ_OVER
        event.events = EPOLLOUT | EPOLLONESHOT;
        epoll_ctl(_epollfd, EPOLL_CTL_MOD, fd, &event);
    } else {
        LOG_ERROR("unkonw read ret:%d", ret);
    }
    return 0;
}

int EpollSocket::handle_writeable_event(int &epollfd, epoll_event &event, EpollSocketWatcher &socket_handler) {
    EpollContext *epoll_context = (EpollContext *) event.data.ptr;
    int fd = epoll_context->fd;
    LOG_DEBUG("start write data");

    int ret = socket_handler.on_writeable(*epoll_context);
    if(ret == WRITE_CONN_CLOSE) {
        return close_and_release(event);
    }

    if (ret == WRITE_CONN_CONTINUE) {
        event.events = EPOLLOUT | EPOLLONESHOT;
    } else if (ret == WRITE_CONN_ALIVE) {
        if (_status == S_REJECT_CONN) {
            return close_and_release(event);
        }
        // wait for next request
        event.events = EPOLLIN | EPOLLONESHOT;
    } else {
        LOG_ERROR("unkonw write ret:%d", ret);
    }
    epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);

    return 0;
}

void EpollSocket::set_thread_pool(ThreadPool *tp) {
    this->_thread_pool = tp;
    _use_default_tp = false;
}

void EpollSocket::set_port(int port) {
    _port = port;
}

void EpollSocket::set_watcher(EpollSocketWatcher *w) {
    _watcher = w;
}

void EpollSocket::set_backlog(int backlog) {
    _backlog = backlog;
}

void EpollSocket::set_max_events(int me) {
    _max_events = me;
}

int EpollSocket::init_default_tp() {
    int core_size = get_nprocs();
    LOG_INFO("thread pool not set, we will build for core size:%d", core_size);
    _thread_pool = new ThreadPool();
    _thread_pool->set_pool_size(core_size);

    return 0;
}

int EpollSocket::add_listen_sock_to_epoll() {
    for (std::set<int>::iterator i = _listen_sockets.begin(); i != _listen_sockets.end(); i++) {
        int sockfd = *i;
        struct epoll_event ev;
        ev.events = EPOLLIN;
        ev.data.fd = sockfd;
        if (epoll_ctl(_epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) {
            LOG_ERROR("epoll_ctl: listen_sock:%s", strerror(errno));
            return -1;
        }
    }
    return 0;
}

int EpollSocket::handle_event(epoll_event &e) {
    if (_listen_sockets.count(e.data.fd)) {
        // accept connection
        if (_status == S_RUN) {
            this->handle_accept_event(_epollfd, e, *_watcher);
        } else {
            LOG_INFO("current status:%d, not accept new connect", _status);
            pthread_mutex_lock(&_client_lock);
            if (_clients == 0 && _status == S_REJECT_CONN) {
                _status = S_STOP;
                LOG_INFO("client is empty and ready for stop server!");
            }
            pthread_mutex_unlock(&_client_lock);
        }
    } else if (e.events & EPOLLIN) {
        // handle readable async
        LOG_DEBUG("start handle readable event");
        TaskData *tdata = new TaskData();
        tdata->event = e;
        tdata->es = this;

        Task *task = new Task(read_func, tdata);
        int ret = _thread_pool->add_task(task);
        if (ret != 0) {
            LOG_WARN("add read task fail:%d, we will close connect.", ret);
            close_and_release(e);
            delete tdata;
            delete task;
        }
    } else if (e.events & EPOLLOUT) {
        // writeable
        this->handle_writeable_event(_epollfd, e, *_watcher);
    } else {
        LOG_INFO("unkonw events :%d", e.events);
    }
    return 0;
}

int EpollSocket::create_epoll() {
    // The "size" parameter is a hint specifying the number of file
    // descriptors to be associated with the new instance.
    _epollfd = epoll_create(1024);
    if (_epollfd == -1) {
        LOG_ERROR("epoll_create:%s", strerror(errno));
        return -1;
    }
    return 0;
}

int EpollSocket::init_tp() {
    if (_thread_pool == NULL) {
        init_default_tp();
    }
    int ret = _thread_pool->start_threadpool();
    return ret;
}

int EpollSocket::start_event_loop() {
    epoll_event *events = new epoll_event[_max_events];
    while (_status != S_STOP) {
        int fds_num = epoll_wait(_epollfd, events, _max_events, -1);
        if (fds_num == -1) {
            if (errno == EINTR) { /*The call was interrupted by a signal handler*/
                continue;
            }
            LOG_ERROR("epoll_wait error:%s", strerror(errno));
            break;
        }

        for (int i = 0; i < fds_num; i++) {
            this->handle_event(events[i]);
        }
    }
    LOG_INFO("epoll wait loop stop ...");
    if (events != NULL) {
        delete[] events;
        events = NULL;
    }
    return 0;
}

int EpollSocket::start_epoll() {
    /* Ignore broken pipe signal. */
    signal(SIGPIPE, SIG_IGN);

    int ret = init_tp();
    CHECK_RET(ret, "thread pool start error:%d", ret);

    ret = this->listen_on();
    CHECK_RET(ret, "listen err:%d", ret);

    ret = this->create_epoll();
    CHECK_RET(ret, "create epoll err:%d", ret);

    ret = this->add_listen_sock_to_epoll();
    CHECK_RET(ret , "add listen sock to epoll fail:%d", ret);

    return start_event_loop();
}

int EpollSocket::stop_epoll() {
    _status = S_REJECT_CONN;
    LOG_INFO("stop epoll , current clients:%u", _clients);
    return 0;
}

int EpollSocket::close_and_release(epoll_event &epoll_event) {
    if (epoll_event.data.ptr == NULL) {
        return 0;
    }
    LOG_DEBUG("connect close");

    EpollContext *hc = (EpollContext *) epoll_event.data.ptr;
    _watcher->on_close(*hc);

    int fd = hc->fd;
    epoll_event.events = EPOLLIN | EPOLLOUT;
    epoll_ctl(_epollfd, EPOLL_CTL_DEL, fd, &epoll_event);

    delete (EpollContext *) epoll_event.data.ptr;
    epoll_event.data.ptr = NULL;

    int ret = close(fd);

    pthread_mutex_lock(&_client_lock);
    _clients--;
    if (_clients == 0 && _status == S_REJECT_CONN) {
        _status = S_STOP;
        LOG_INFO("client is empty and ready for stop server!");
    }
    pthread_mutex_unlock(&_client_lock);

    LOG_DEBUG("connect close complete which fd:%d, ret:%d", fd, ret);
    return ret;
}

void EpollSocket::add_bind_ip(std::string ip) {
    _bind_ips.push_back(ip);
}
<|endoftext|>


<commit_before>//===--- SILMem2Reg.cpp - Promotes AllocStacks to registers ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-mem2reg"
#include "swift/SILPasses/Passes.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/Diagnostics.h"
#include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILPasses/Utils/Local.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/Support/Debug.h"
using namespace swift;

STATISTIC(NumAllocStackRemoved, "Number of AllocStack promoted");
STATISTIC(NumAllocStackFound, "Number of AllocStack found");
STATISTIC(NumAllocStackCaptured, "Number of AllocStack captured");

namespace {

/// Promote memory to registers
class MemoryToRegisters {
  /// Holds all of the AllocStacks in the program.
  SmallVector<AllocStackInst*, 32> Allocations;

  /// The function that we are optimizing.
  SILFunction &F;

public:
  /// C'tor
  MemoryToRegisters(SILFunction &Func) : F(Func) {}

  /// Promote memory to registers.
  void run();

private:
  /// Collect all of the AllocStacks in the program.
  void collectAllocStackInstructions();

  /// Promote a single AllocStack instruction.
  void promoteAllocation(AllocStackInst *ASI);
};

} // end anonymous namespace.

/// Returns true if this AllocStacks is captured.
static bool isCaptured(AllocStackInst *ASI) {
  // For all users of the AllocStack instruction.
  for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI) {
    SILInstruction *II = UI->getUser();

    // Loads are okay.
    if (isa<LoadInst>(II))
      continue;

    // We can store into an AllocStack (but not the pointer).
    if (StoreInst *SI = dyn_cast<StoreInst>(II))
      if (SI->getDest().getDef() == ASI)
        continue;

    // Deallocation is also okay.
    if (isa<DeallocStackInst>(II))
      continue;

    // Other instructions are assumed to capture the AllocStack.
    DEBUG(llvm::errs() << "*** AllocStack is captured by: " << *II << "\n");
    return true;
  }

  // None of the users capture the AllocStack.
  return false;
}

/// Returns true if the AllocStack is only stored into.
static bool isWriteOnlyAllocation(AllocStackInst *ASI) {

  // For all users of the AllocStack:
  for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI) {
    SILInstruction *II = UI->getUser();

    // It is okay to store into this AllocStack.
    if (StoreInst *SI = dyn_cast<StoreInst>(II))
      if (!isa<AllocStackInst>(SI->getSrc()))
        continue;

    // It is also okay to deallocate.
    if (isa<DeallocStackInst>(II))
      continue;

    // Can't do anything else with it.
    DEBUG(llvm::errs() << "*** AllocStack is loaded by: " << *II << "\n");
    return false;
  }

  return true;
}

/// Returns true if this AllocStack is only used within a single basic block.
static bool isSingleBlockUsage(AllocStackInst *ASI) {
  assert(!isCaptured(ASI) && "This AllocStack must not be captured");
  SILBasicBlock *BB = ASI->getParent();

  // All of the users of the AllocStack must be in the same block.
  for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI)
    if (UI->getUser()->getParent() != BB)
      return false;

  return true;
}

void MemoryToRegisters::collectAllocStackInstructions() {
  for (auto &BB : F)
    for (auto &II : BB)
      if (AllocStackInst *ASI = dyn_cast<AllocStackInst>(&II))
        Allocations.push_back(ASI);
  DEBUG(llvm::errs() << "*** Found " << Allocations.size() << " AllocStacks\n");
}

/// Promote all of the AllocStacks in a single basic block in one linear scan.
static void promoteAllocationInBlock(AllocStackInst *ASI) {
  DEBUG(llvm::errs() << "*** Promoting in-block: " << *ASI << "\n");

  SILBasicBlock *BB = ASI->getParent();

  // The default value of the AllocStack is NULL because we don't have
  // unilitialized variables in Swift.
  SILValue RunningVal = SILValue();

  // For all instructions in the block.
  for (auto BBI = BB->begin(), E = BB->end(); BBI != E;) {
    SILInstruction *Inst = BBI++;
    // Remove instructions that we are loading from. Replace the loaded value
    // with our running value.
    if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
      if (LI->getOperand().getDef() == ASI) {
        assert(RunningVal.isValid() &&
               "The AllocStack must be initialized before usage.");
        SILValue(Inst, 0).replaceAllUsesWith(RunningVal);
        Inst->eraseFromParent();
        continue;
      }
    }

    // Remove stores and record the value that we are saving as the running
    // value.
    if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
      if (SI->getDest().getDef() == ASI) {
        RunningVal = SI->getSrc();
        Inst->eraseFromParent();
        continue;
      }
    }

    // Remove deallocation.
    if (DeallocStackInst *DSI = dyn_cast<DeallocStackInst>(Inst)) {
      if (DSI->getOperand() == ASI)
        Inst->eraseFromParent();
    }
  }

  DEBUG(llvm::errs() << "*** Deleting " << *ASI << "\n");
  ASI->eraseFromParent();
  NumAllocStackRemoved++;
}

/// Delete the AllocStack and all of its users. This is used by write-only
/// AllocStacks.
static void deleteAllocation(AllocStackInst *ASI) {
  DEBUG(llvm::errs() << "*** Deleting " << *ASI << "\n");

  eraseUsesOfInstruction(ASI);
  ASI->eraseFromParent();

  NumAllocStackRemoved++;
}

void MemoryToRegisters::promoteAllocation(AllocStackInst *ASI) {
  DEBUG(llvm::errs() << "*** Memory to register looking at: " << *ASI << "\n");
  NumAllocStackFound++;

  // Don't handle captured AllocStacks.
  if (isCaptured(ASI)) {
    NumAllocStackCaptured++;
    return;
  }

  // For AllocStacks that are only used within a single basic blocks, use the
  // linear sweep to remove the AllocStack.
  if (isSingleBlockUsage(ASI))
    return promoteAllocationInBlock(ASI);

  // Remove write-only AllocStacks.
  if (isWriteOnlyAllocation(ASI))
   return deleteAllocation(ASI);

  DEBUG(llvm::errs() << "*** Need to insert PHIs for " << *ASI << "\n");
  // TODO: Replace AllocStacks with PHI-nodes ...
}

void MemoryToRegisters::run() {
  collectAllocStackInstructions();

  for (auto A : Allocations)
    promoteAllocation(A);
}

void promoteAllocasInFunction(SILFunction &F) {
  MemoryToRegisters(F).run();
}

void swift::performSILMem2Reg(SILModule *M) {
  for (auto &F : *M)
    promoteAllocasInFunction(F);

}
<commit_msg>Iterate over the AllocStack instructions in the function instead of collecting them before we optimize them.<commit_after>//===--- SILMem2Reg.cpp - Promotes AllocStacks to registers ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-mem2reg"
#include "swift/SILPasses/Passes.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/Diagnostics.h"
#include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILPasses/Utils/Local.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/Support/Debug.h"
using namespace swift;

STATISTIC(NumAllocStackRemoved, "Number of AllocStack promoted");
STATISTIC(NumAllocStackFound, "Number of AllocStack found");
STATISTIC(NumAllocStackCaptured, "Number of AllocStack captured");

namespace {

/// Promote memory to registers
class MemoryToRegisters {
  /// The function that we are optimizing.
  SILFunction &F;

public:
  /// C'tor
  MemoryToRegisters(SILFunction &Func) : F(Func) {}

  /// Promote memory to registers.
  void run();
};

} // end anonymous namespace.

/// Returns true if this AllocStacks is captured.
static bool isCaptured(AllocStackInst *ASI) {
  // For all users of the AllocStack instruction.
  for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI) {
    SILInstruction *II = UI->getUser();

    // Loads are okay.
    if (isa<LoadInst>(II))
      continue;

    // We can store into an AllocStack (but not the pointer).
    if (StoreInst *SI = dyn_cast<StoreInst>(II))
      if (SI->getDest().getDef() == ASI)
        continue;

    // Deallocation is also okay.
    if (isa<DeallocStackInst>(II))
      continue;

    // Other instructions are assumed to capture the AllocStack.
    DEBUG(llvm::errs() << "*** AllocStack is captured by: " << *II << "\n");
    return true;
  }

  // None of the users capture the AllocStack.
  return false;
}

/// Returns true if the AllocStack is only stored into.
static bool isWriteOnlyAllocation(AllocStackInst *ASI) {
  // For all users of the AllocStack:
  for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI) {
    SILInstruction *II = UI->getUser();

    // It is okay to store into this AllocStack.
    if (StoreInst *SI = dyn_cast<StoreInst>(II))
      if (!isa<AllocStackInst>(SI->getSrc()))
        continue;

    // It is also okay to deallocate.
    if (isa<DeallocStackInst>(II))
      continue;

    // Can't do anything else with it.
    DEBUG(llvm::errs() << "*** AllocStack is loaded by: " << *II << "\n");
    return false;
  }

  return true;
}

/// Returns true if this AllocStack is only used within a single basic block.
static bool isSingleBlockUsage(AllocStackInst *ASI) {
  assert(!isCaptured(ASI) && "This AllocStack must not be captured");
  SILBasicBlock *BB = ASI->getParent();

  // All of the users of the AllocStack must be in the same block.
  for (auto UI = ASI->use_begin(), E = ASI->use_end(); UI != E; ++UI)
    if (UI->getUser()->getParent() != BB)
      return false;

  return true;
}

/// Promote all of the AllocStacks in a single basic block in one linear scan.
/// Note: This function deletes all of the users of the AllocStackInst,
/// including the DeallocStackInst. However, it does not remove the
// AllocStackInst itself!
static void promoteAllocationInBlock(AllocStackInst *ASI) {
  DEBUG(llvm::errs() << "*** Promoting in-block: " << *ASI << "\n");

  SILBasicBlock *BB = ASI->getParent();

  // The default value of the AllocStack is NULL because we don't have
  // unilitialized variables in Swift.
  SILValue RunningVal = SILValue();

  // For all instructions in the block.
  for (auto BBI = BB->begin(), E = BB->end(); BBI != E;) {
    SILInstruction *Inst = BBI++;
    // Remove instructions that we are loading from. Replace the loaded value
    // with our running value.
    if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
      if (LI->getOperand().getDef() == ASI) {
        assert(RunningVal.isValid() &&
               "The AllocStack must be initialized before usage.");
        SILValue(Inst, 0).replaceAllUsesWith(RunningVal);
        Inst->eraseFromParent();
        continue;
      }
    }

    // Remove stores and record the value that we are saving as the running
    // value.
    if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
      if (SI->getDest().getDef() == ASI) {
        RunningVal = SI->getSrc();
        Inst->eraseFromParent();
        continue;
      }
    }

    // Remove deallocation.
    if (DeallocStackInst *DSI = dyn_cast<DeallocStackInst>(Inst)) {
      if (DSI->getOperand() == ASI)
        Inst->eraseFromParent();
    }
  }
}

void MemoryToRegisters::run() {
  for (auto &BB : F) {
    auto I = BB.begin(), E = BB.end();
    while (I != E) {
      SILInstruction *Inst = I;
      AllocStackInst *ASI = dyn_cast<AllocStackInst>(Inst);
      if (!ASI) {
        ++I;
        continue;
      }

      DEBUG(llvm::errs()<< "*** Memory to register looking at: " << *I << "\n");
      NumAllocStackFound++;

      // Don't handle captured AllocStacks.
      if (isCaptured(ASI)) {
        NumAllocStackCaptured++;
        ++I;
        continue;
      }

      // For AllocStacks that are only used within a single basic blocks, use
      // the linear sweep to remove the AllocStack.
      if (isSingleBlockUsage(ASI)) {
        promoteAllocationInBlock(ASI);

        DEBUG(llvm::errs() << "*** Deleting single block AllocStackInst: " <<
              *ASI << "\n");
        I++;
        ASI->eraseFromParent();
        NumAllocStackRemoved++;
        continue;
      }

      // Remove write-only AllocStacks.
      if (isWriteOnlyAllocation(ASI)) {
        eraseUsesOfInstruction(ASI);

        DEBUG(llvm::errs() << "*** Deleting store-only AllocStackInst: " <<
              *ASI << "\n");
        I++;
        ASI->eraseFromParent();
        NumAllocStackRemoved++;
        continue;
      }

      DEBUG(llvm::errs() << "*** Need to insert PHIs for " << *ASI << "\n");
      // TODO: Replace AllocStacks with PHI-nodes ...

      // Move iterator to avoid invalidation.
      ++I;
    }
  }
}

void promoteAllocasInFunction(SILFunction &F) {
  MemoryToRegisters(F).run();
}

void swift::performSILMem2Reg(SILModule *M) {
  for (auto &F : *M)
    promoteAllocasInFunction(F);

}
<|endoftext|>


<commit_before>// This software is part of OpenMono, see http://developer.openmono.com
// and is available under the MIT license, see LICENSE.txt

#include "application_context.h"
#include "application_controller_interface.h"
#include <display_painter.h>
#include "consoles.h"
#include <mbed_interface.h>

extern "C" {
#include <project.h>
}

using namespace mono;

ApplicationContext ApplicationContext::singleton;
IApplicationContext *IApplicationContext::Instance = NULL; //&(ApplicationContext::singleton);

ApplicationContext::ApplicationContext() : IApplicationContext(
                                                               &pwrMgmt,
                                                               &runLoop,
                                                               &dispController,
                                                               &touchSys,
                                                               &UserButton,
                                                               &at30ts64Sensor,
                                                               &mmaAccelerometer),

                                            dispController(),
                                            UserButton(SW_USER, PullUp)
{
    //enable SWD / JTAG debug, by turning on VTARG/VSYS voltage in expansion connector
//    CyPins_SetPinDriveMode(EXPANSION_PWR_ENABLE, CY_PINS_DM_STRONG);
//    CyPins_SetPin(EXPANSION_PWR_ENABLE);

    // BEEP
    PWM_Start();
    PWM_WriteCompare2(0);
    PWM_WriteCompare1(0);

    for (int i=10; i<100; i+=12) {
        PWM_WriteCompare2(i);
        CyDelay(30);
    }
    PWM_WriteCompare2(0);

    defaultSerial.printf("");

}

int ApplicationContext::exec()
{
    runLoop.exec();

    return 0;
}

void ApplicationContext::setMonoApplication(mono::IApplication *monoApp)
{
    this->application = monoApp;

    CyIntSetSysVector(CY_INT_NMI_IRQN, &mbed_die);
    CyIntSetSysVector(CY_INT_HARD_FAULT_IRQN, &mbed_die);
    CyIntSetSysVector(CY_INT_MEM_MANAGE_IRQN, &mbed_die);
    CyIntSetSysVector(CY_INT_BUS_FAULT_IRQN, &mbed_die);
    CyIntSetSysVector(CY_INT_USAGE_FAULT_IRQN, &mbed_die);

    //PowerSystem->onSystemPowerOnReset();
    pwrMgmt.processResetAwarenessQueue();

    //defaultSerial.printf("Display init deactivated\n\t");
    mono::IApplicationContext::Instance->DisplayController->init();

    touchSys.init();

    //setup default user button handler
    UserButton.DeactivateUntilHandled(); // dont queue up pushes
    UserButton.setDebouncing(true);
    UserButton.fall<ApplicationContext>(this, &ApplicationContext::enterSleepMode);

    monoApp->monoWakeFromReset();

}

void ApplicationContext::sleepForMs(uint32_t ms)
{
    uint8_t ticks = 1;
    while ((1u << ticks) < ms) {
        ticks++;
    }

    defaultSerial.printf("Setting CTW to: %i for ms: %i\n\r",ticks, ms);
    *((reg8*)CYREG_PM_TW_CFG1) = 0x0F & ticks;
    PM_TW_CFG2 = PM_TW_CFG2 | 0x0C; // CTW enable and CTW interrupts
    defaultSerial.printf("CTW CFG Reg: 0x%x\n\r",PM_TW_CFG2);
    enterSleepMode();
}

void ApplicationContext::enterSleepMode()
{
    this->application->monoWillGotoSleep();

    PowerManager->EnterSleep();

    this->application->monoWakeFromSleep();

}

void ApplicationContext::_softwareReset()
{
    Bootloadable_SET_RUN_TYPE(0); // force bootloader to run for 2 secs
    CySoftwareReset();
    while(1); // silence compiler warning
}

void ApplicationContext::_softwareResetToBootloader()
{
    Bootloadable_SET_RUN_TYPE(Bootloadable_START_BTLDR);
    CySoftwareReset();
    while(1); // silence compiler warning
}

void ApplicationContext::_softwareResetToApplication()
{
    Bootloadable_SET_RUN_TYPE(Bootloadable_START_APP);
    CySoftwareReset();
    while(1); // silence compiler warning
}

void ApplicationContext::resetOnUserButton()
{
    debug("Mono will reset on user button!\n\r");
    this->runLoop.setResetOnUserButton(true);
}

<commit_msg>Enabled external power lines<commit_after>// This software is part of OpenMono, see http://developer.openmono.com
// and is available under the MIT license, see LICENSE.txt

#include "application_context.h"
#include "application_controller_interface.h"
#include <display_painter.h>
#include "consoles.h"
#include <mbed_interface.h>

extern "C" {
#include <project.h>
}

using namespace mono;

ApplicationContext ApplicationContext::singleton;
IApplicationContext *IApplicationContext::Instance = NULL; //&(ApplicationContext::singleton);

ApplicationContext::ApplicationContext() : IApplicationContext(
                                                               &pwrMgmt,
                                                               &runLoop,
                                                               &dispController,
                                                               &touchSys,
                                                               &UserButton,
                                                               &at30ts64Sensor,
                                                               &mmaAccelerometer),

                                            dispController(),
                                            UserButton(SW_USER, PullUp)
{
    //enable SWD / JTAG debug, by turning on VTARG/VSYS voltage in expansion connector
    // and set the pwr rail to 3.3V
    CyPins_SetPinDriveMode(EXPANSION_3V3_ENABLE, CY_PINS_DM_STRONG);
    CyPins_SetPin(EXPANSION_3V3_ENABLE);
    CyPins_SetPinDriveMode(EXPANSION_PWR_ENABLE, CY_PINS_DM_STRONG);
    CyPins_SetPin(EXPANSION_PWR_ENABLE);

    // BEEP
    PWM_Start();
    PWM_WriteCompare2(0);
    PWM_WriteCompare1(0);

    for (int i=10; i<100; i+=12) {
        PWM_WriteCompare2(i);
        CyDelay(30);
    }
    PWM_WriteCompare2(0);

    defaultSerial.printf("");

}

int ApplicationContext::exec()
{
    runLoop.exec();

    return 0;
}

void ApplicationContext::setMonoApplication(mono::IApplication *monoApp)
{
    this->application = monoApp;

    CyIntSetSysVector(CY_INT_NMI_IRQN, &mbed_die);
    CyIntSetSysVector(CY_INT_HARD_FAULT_IRQN, &mbed_die);
    CyIntSetSysVector(CY_INT_MEM_MANAGE_IRQN, &mbed_die);
    CyIntSetSysVector(CY_INT_BUS_FAULT_IRQN, &mbed_die);
    CyIntSetSysVector(CY_INT_USAGE_FAULT_IRQN, &mbed_die);

    //PowerSystem->onSystemPowerOnReset();
    pwrMgmt.processResetAwarenessQueue();

    //defaultSerial.printf("Display init deactivated\n\t");
    mono::IApplicationContext::Instance->DisplayController->init();

    touchSys.init();

    //setup default user button handler
    UserButton.DeactivateUntilHandled(); // dont queue up pushes
    UserButton.setDebouncing(true);
    UserButton.fall<ApplicationContext>(this, &ApplicationContext::enterSleepMode);

    monoApp->monoWakeFromReset();

}

void ApplicationContext::sleepForMs(uint32_t ms)
{
    uint8_t ticks = 1;
    while ((1u << ticks) < ms) {
        ticks++;
    }

    defaultSerial.printf("Setting CTW to: %i for ms: %i\n\r",ticks, ms);
    *((reg8*)CYREG_PM_TW_CFG1) = 0x0F & ticks;
    PM_TW_CFG2 = PM_TW_CFG2 | 0x0C; // CTW enable and CTW interrupts
    defaultSerial.printf("CTW CFG Reg: 0x%x\n\r",PM_TW_CFG2);
    enterSleepMode();
}

void ApplicationContext::enterSleepMode()
{
    this->application->monoWillGotoSleep();

    PowerManager->EnterSleep();

    this->application->monoWakeFromSleep();

}

void ApplicationContext::_softwareReset()
{
    Bootloadable_SET_RUN_TYPE(0); // force bootloader to run for 2 secs
    CySoftwareReset();
    while(1); // silence compiler warning
}

void ApplicationContext::_softwareResetToBootloader()
{
    Bootloadable_SET_RUN_TYPE(Bootloadable_START_BTLDR);
    CySoftwareReset();
    while(1); // silence compiler warning
}

void ApplicationContext::_softwareResetToApplication()
{
    Bootloadable_SET_RUN_TYPE(Bootloadable_START_APP);
    CySoftwareReset();
    while(1); // silence compiler warning
}

void ApplicationContext::resetOnUserButton()
{
    debug("Mono will reset on user button!\n\r");
    this->runLoop.setResetOnUserButton(true);
}

<|endoftext|>