<commit_before>//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the MipsMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//
//
#define DEBUG_TYPE "mccodeemitter"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsFixupKinds.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
class MipsMCCodeEmitter : public MCCodeEmitter {
  MipsMCCodeEmitter(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
  void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
  const MCInstrInfo &MCII;
  const MCSubtargetInfo &STI;
  MCContext &Ctx;
  bool IsLittleEndian;

public:
  MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
                    MCContext &ctx, bool IsLittle) :
            MCII(mcii), STI(sti) , Ctx(ctx), IsLittleEndian(IsLittle) {}

  ~MipsMCCodeEmitter() {}

  void EmitByte(unsigned char C, raw_ostream &OS) const {
    OS << (char)C;
  }

  void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const {
    // Output the instruction encoding in little endian byte order.
    for (unsigned i = 0; i < Size; ++i) {
      unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
      EmitByte((Val >> Shift) & 0xff, OS);
    }
  }

  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                         SmallVectorImpl<MCFixup> &Fixups) const;

  // getBinaryCodeForInstr - TableGen'erated function for getting the
  // binary encoding for an instruction.
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
                                 SmallVectorImpl<MCFixup> &Fixups) const;

  // getBranchJumpOpValue - Return binary encoding of the jump
  // target operand. If the machine operand requires relocation,
  // record the relocation and return zero.
   unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
                                 SmallVectorImpl<MCFixup> &Fixups) const;

   // getBranchTargetOpValue - Return binary encoding of the branch
   // target operand. If the machine operand requires relocation,
   // record the relocation and return zero.
  unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                                  SmallVectorImpl<MCFixup> &Fixups) const;

   // getMachineOpValue - Return binary encoding of operand. If the machin
   // operand requires relocation, record the relocation and return zero.
  unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
                             SmallVectorImpl<MCFixup> &Fixups) const;

  unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
                          SmallVectorImpl<MCFixup> &Fixups) const;
  unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups) const;
  unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups) const;

}; // class MipsMCCodeEmitter
}  // namespace

MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
                                               const MCRegisterInfo &MRI,
                                               const MCSubtargetInfo &STI,
                                               MCContext &Ctx)
{
  return new MipsMCCodeEmitter(MCII, STI, Ctx, false);
}

MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
                                               const MCRegisterInfo &MRI,
                                               const MCSubtargetInfo &STI,
                                               MCContext &Ctx)
{
  return new MipsMCCodeEmitter(MCII, STI, Ctx, true);
}

/// EncodeInstruction - Emit the instruction.
/// Size the instruction (currently only 4 bytes
void MipsMCCodeEmitter::
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                  SmallVectorImpl<MCFixup> &Fixups) const
{
  uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);

  // Check for unimplemented opcodes.
  // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0
  // so we have to special check for them.
  unsigned Opcode = MI.getOpcode();
  if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
    llvm_unreachable("unimplemented opcode in EncodeInstruction()");

  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
  uint64_t TSFlags = Desc.TSFlags;

  // Pseudo instructions don't get encoded and shouldn't be here
  // in the first place!
  if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo)
    llvm_unreachable("Pseudo opcode found in EncodeInstruction()");

  // For now all instructions are 4 bytes
  int Size = 4; // FIXME: Have Desc.getSize() return the correct value!

  EmitInstruction(Binary, Size, OS);
}

/// getBranchTargetOpValue - Return binary encoding of the branch
/// target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                       SmallVectorImpl<MCFixup> &Fixups) const {

  const MCOperand &MO = MI.getOperand(OpNo);

  // If the destination is an immediate, we have nothing to do.
  if (MO.isImm()) return MO.getImm();
  assert(MO.isExpr() &&
         "getBranchTargetOpValue expects only expressions or immediates");

  const MCExpr *Expr = MO.getExpr();
  Fixups.push_back(MCFixup::Create(0, Expr,
                                   MCFixupKind(Mips::fixup_Mips_PC16)));
  return 0;
}

/// getJumpTargetOpValue - Return binary encoding of the jump
/// target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
                     SmallVectorImpl<MCFixup> &Fixups) const {

  const MCOperand &MO = MI.getOperand(OpNo);
  // If the destination is an immediate, we have nothing to do.
  if (MO.isImm()) return MO.getImm();
  assert(MO.isExpr() &&
         "getJumpTargetOpValue expects only expressions or an immediate");

  const MCExpr *Expr = MO.getExpr();
  Fixups.push_back(MCFixup::Create(0, Expr,
                                   MCFixupKind(Mips::fixup_Mips_26)));
  return 0;
}

/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                  SmallVectorImpl<MCFixup> &Fixups) const {
  if (MO.isReg()) {
    unsigned Reg = MO.getReg();
    unsigned RegNo = getMipsRegisterNumbering(Reg);
    return RegNo;
  } else if (MO.isImm()) {
    return static_cast<unsigned>(MO.getImm());
  } else if (MO.isFPImm()) {
    return static_cast<unsigned>(APFloat(MO.getFPImm())
        .bitcastToAPInt().getHiBits(32).getLimitedValue());
  }

  // MO must be an Expr.
  assert(MO.isExpr());

  const MCExpr *Expr = MO.getExpr();
  MCExpr::ExprKind Kind = Expr->getKind();

  if (Kind == MCExpr::Binary) {
    Expr = static_cast<const MCBinaryExpr*>(Expr)->getLHS();
    Kind = Expr->getKind();
  }

  assert (Kind == MCExpr::SymbolRef);

  Mips::Fixups FixupKind = Mips::Fixups(0);

  switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
  default: llvm_unreachable("Unknown fixup kind!");
    break;
  case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
    FixupKind = Mips::fixup_Mips_GPOFF_HI;
    break;
  case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
    FixupKind = Mips::fixup_Mips_GPOFF_LO;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
    FixupKind = Mips::fixup_Mips_GOT_PAGE;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT_OFST :
    FixupKind = Mips::fixup_Mips_GOT_OFST;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT_DISP :
    FixupKind = Mips::fixup_Mips_GOT_DISP;
    break;
  case MCSymbolRefExpr::VK_Mips_GPREL:
    FixupKind = Mips::fixup_Mips_GPREL16;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT_CALL:
    FixupKind = Mips::fixup_Mips_CALL16;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT16:
    FixupKind = Mips::fixup_Mips_GOT_Global;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT:
    FixupKind = Mips::fixup_Mips_GOT_Local;
    break;
  case MCSymbolRefExpr::VK_Mips_ABS_HI:
    FixupKind = Mips::fixup_Mips_HI16;
    break;
  case MCSymbolRefExpr::VK_Mips_ABS_LO:
    FixupKind = Mips::fixup_Mips_LO16;
    break;
  case MCSymbolRefExpr::VK_Mips_TLSGD:
    FixupKind = Mips::fixup_Mips_TLSGD;
    break;
  case MCSymbolRefExpr::VK_Mips_TLSLDM:
    FixupKind = Mips::fixup_Mips_TLSLDM;
    break;
  case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
    FixupKind = Mips::fixup_Mips_DTPREL_HI;
    break;
  case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
    FixupKind = Mips::fixup_Mips_DTPREL_LO;
    break;
  case MCSymbolRefExpr::VK_Mips_GOTTPREL:
    FixupKind = Mips::fixup_Mips_GOTTPREL;
    break;
  case MCSymbolRefExpr::VK_Mips_TPREL_HI:
    FixupKind = Mips::fixup_Mips_TPREL_HI;
    break;
  case MCSymbolRefExpr::VK_Mips_TPREL_LO:
    FixupKind = Mips::fixup_Mips_TPREL_LO;
    break;
  case MCSymbolRefExpr::VK_Mips_HIGHER:
    FixupKind = Mips::fixup_Mips_HIGHER;
    break;
  case MCSymbolRefExpr::VK_Mips_HIGHEST:
    FixupKind = Mips::fixup_Mips_HIGHEST;
    break;
  } // switch

  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));

  // All of the information is in the fixup.
  return 0;
}

/// getMemEncoding - Return binary encoding of memory related operand.
/// If the offset operand requires relocation, record the relocation.
unsigned
MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
                                  SmallVectorImpl<MCFixup> &Fixups) const {
  // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
  assert(MI.getOperand(OpNo).isReg());
  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);

  return (OffBits & 0xFFFF) | RegBits;
}

unsigned
MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
                                      SmallVectorImpl<MCFixup> &Fixups) const {
  assert(MI.getOperand(OpNo).isImm());
  unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
  return SizeEncoding - 1;
}

// FIXME: should be called getMSBEncoding
//
unsigned
MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
                                      SmallVectorImpl<MCFixup> &Fixups) const {
  assert(MI.getOperand(OpNo-1).isImm());
  assert(MI.getOperand(OpNo).isImm());
  unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups);
  unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);

  return Position + Size - 1;
}

#include "MipsGenMCCodeEmitter.inc"

<commit_msg>Remove unused private fields to silence -Wunused-private-field.<commit_after>//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the MipsMCCodeEmitter class.
//
//===----------------------------------------------------------------------===//
//
#define DEBUG_TYPE "mccodeemitter"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsFixupKinds.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
class MipsMCCodeEmitter : public MCCodeEmitter {
  MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
  void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
  const MCInstrInfo &MCII;
  bool IsLittleEndian;

public:
  MipsMCCodeEmitter(const MCInstrInfo &mcii, bool IsLittle) :
            MCII(mcii), IsLittleEndian(IsLittle) {}

  ~MipsMCCodeEmitter() {}

  void EmitByte(unsigned char C, raw_ostream &OS) const {
    OS << (char)C;
  }

  void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const {
    // Output the instruction encoding in little endian byte order.
    for (unsigned i = 0; i < Size; ++i) {
      unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
      EmitByte((Val >> Shift) & 0xff, OS);
    }
  }

  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                         SmallVectorImpl<MCFixup> &Fixups) const;

  // getBinaryCodeForInstr - TableGen'erated function for getting the
  // binary encoding for an instruction.
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
                                 SmallVectorImpl<MCFixup> &Fixups) const;

  // getBranchJumpOpValue - Return binary encoding of the jump
  // target operand. If the machine operand requires relocation,
  // record the relocation and return zero.
   unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
                                 SmallVectorImpl<MCFixup> &Fixups) const;

   // getBranchTargetOpValue - Return binary encoding of the branch
   // target operand. If the machine operand requires relocation,
   // record the relocation and return zero.
  unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                                  SmallVectorImpl<MCFixup> &Fixups) const;

   // getMachineOpValue - Return binary encoding of operand. If the machin
   // operand requires relocation, record the relocation and return zero.
  unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
                             SmallVectorImpl<MCFixup> &Fixups) const;

  unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
                          SmallVectorImpl<MCFixup> &Fixups) const;
  unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups) const;
  unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
                              SmallVectorImpl<MCFixup> &Fixups) const;

}; // class MipsMCCodeEmitter
}  // namespace

MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
                                               const MCRegisterInfo &MRI,
                                               const MCSubtargetInfo &STI,
                                               MCContext &Ctx)
{
  return new MipsMCCodeEmitter(MCII, false);
}

MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
                                               const MCRegisterInfo &MRI,
                                               const MCSubtargetInfo &STI,
                                               MCContext &Ctx)
{
  return new MipsMCCodeEmitter(MCII, true);
}

/// EncodeInstruction - Emit the instruction.
/// Size the instruction (currently only 4 bytes
void MipsMCCodeEmitter::
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                  SmallVectorImpl<MCFixup> &Fixups) const
{
  uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);

  // Check for unimplemented opcodes.
  // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0
  // so we have to special check for them.
  unsigned Opcode = MI.getOpcode();
  if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
    llvm_unreachable("unimplemented opcode in EncodeInstruction()");

  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
  uint64_t TSFlags = Desc.TSFlags;

  // Pseudo instructions don't get encoded and shouldn't be here
  // in the first place!
  if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo)
    llvm_unreachable("Pseudo opcode found in EncodeInstruction()");

  // For now all instructions are 4 bytes
  int Size = 4; // FIXME: Have Desc.getSize() return the correct value!

  EmitInstruction(Binary, Size, OS);
}

/// getBranchTargetOpValue - Return binary encoding of the branch
/// target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
                       SmallVectorImpl<MCFixup> &Fixups) const {

  const MCOperand &MO = MI.getOperand(OpNo);

  // If the destination is an immediate, we have nothing to do.
  if (MO.isImm()) return MO.getImm();
  assert(MO.isExpr() &&
         "getBranchTargetOpValue expects only expressions or immediates");

  const MCExpr *Expr = MO.getExpr();
  Fixups.push_back(MCFixup::Create(0, Expr,
                                   MCFixupKind(Mips::fixup_Mips_PC16)));
  return 0;
}

/// getJumpTargetOpValue - Return binary encoding of the jump
/// target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
                     SmallVectorImpl<MCFixup> &Fixups) const {

  const MCOperand &MO = MI.getOperand(OpNo);
  // If the destination is an immediate, we have nothing to do.
  if (MO.isImm()) return MO.getImm();
  assert(MO.isExpr() &&
         "getJumpTargetOpValue expects only expressions or an immediate");

  const MCExpr *Expr = MO.getExpr();
  Fixups.push_back(MCFixup::Create(0, Expr,
                                   MCFixupKind(Mips::fixup_Mips_26)));
  return 0;
}

/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned MipsMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
                  SmallVectorImpl<MCFixup> &Fixups) const {
  if (MO.isReg()) {
    unsigned Reg = MO.getReg();
    unsigned RegNo = getMipsRegisterNumbering(Reg);
    return RegNo;
  } else if (MO.isImm()) {
    return static_cast<unsigned>(MO.getImm());
  } else if (MO.isFPImm()) {
    return static_cast<unsigned>(APFloat(MO.getFPImm())
        .bitcastToAPInt().getHiBits(32).getLimitedValue());
  }

  // MO must be an Expr.
  assert(MO.isExpr());

  const MCExpr *Expr = MO.getExpr();
  MCExpr::ExprKind Kind = Expr->getKind();

  if (Kind == MCExpr::Binary) {
    Expr = static_cast<const MCBinaryExpr*>(Expr)->getLHS();
    Kind = Expr->getKind();
  }

  assert (Kind == MCExpr::SymbolRef);

  Mips::Fixups FixupKind = Mips::Fixups(0);

  switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
  default: llvm_unreachable("Unknown fixup kind!");
    break;
  case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
    FixupKind = Mips::fixup_Mips_GPOFF_HI;
    break;
  case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
    FixupKind = Mips::fixup_Mips_GPOFF_LO;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
    FixupKind = Mips::fixup_Mips_GOT_PAGE;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT_OFST :
    FixupKind = Mips::fixup_Mips_GOT_OFST;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT_DISP :
    FixupKind = Mips::fixup_Mips_GOT_DISP;
    break;
  case MCSymbolRefExpr::VK_Mips_GPREL:
    FixupKind = Mips::fixup_Mips_GPREL16;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT_CALL:
    FixupKind = Mips::fixup_Mips_CALL16;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT16:
    FixupKind = Mips::fixup_Mips_GOT_Global;
    break;
  case MCSymbolRefExpr::VK_Mips_GOT:
    FixupKind = Mips::fixup_Mips_GOT_Local;
    break;
  case MCSymbolRefExpr::VK_Mips_ABS_HI:
    FixupKind = Mips::fixup_Mips_HI16;
    break;
  case MCSymbolRefExpr::VK_Mips_ABS_LO:
    FixupKind = Mips::fixup_Mips_LO16;
    break;
  case MCSymbolRefExpr::VK_Mips_TLSGD:
    FixupKind = Mips::fixup_Mips_TLSGD;
    break;
  case MCSymbolRefExpr::VK_Mips_TLSLDM:
    FixupKind = Mips::fixup_Mips_TLSLDM;
    break;
  case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
    FixupKind = Mips::fixup_Mips_DTPREL_HI;
    break;
  case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
    FixupKind = Mips::fixup_Mips_DTPREL_LO;
    break;
  case MCSymbolRefExpr::VK_Mips_GOTTPREL:
    FixupKind = Mips::fixup_Mips_GOTTPREL;
    break;
  case MCSymbolRefExpr::VK_Mips_TPREL_HI:
    FixupKind = Mips::fixup_Mips_TPREL_HI;
    break;
  case MCSymbolRefExpr::VK_Mips_TPREL_LO:
    FixupKind = Mips::fixup_Mips_TPREL_LO;
    break;
  case MCSymbolRefExpr::VK_Mips_HIGHER:
    FixupKind = Mips::fixup_Mips_HIGHER;
    break;
  case MCSymbolRefExpr::VK_Mips_HIGHEST:
    FixupKind = Mips::fixup_Mips_HIGHEST;
    break;
  } // switch

  Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));

  // All of the information is in the fixup.
  return 0;
}

/// getMemEncoding - Return binary encoding of memory related operand.
/// If the offset operand requires relocation, record the relocation.
unsigned
MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
                                  SmallVectorImpl<MCFixup> &Fixups) const {
  // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
  assert(MI.getOperand(OpNo).isReg());
  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);

  return (OffBits & 0xFFFF) | RegBits;
}

unsigned
MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
                                      SmallVectorImpl<MCFixup> &Fixups) const {
  assert(MI.getOperand(OpNo).isImm());
  unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
  return SizeEncoding - 1;
}

// FIXME: should be called getMSBEncoding
//
unsigned
MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
                                      SmallVectorImpl<MCFixup> &Fixups) const {
  assert(MI.getOperand(OpNo-1).isImm());
  assert(MI.getOperand(OpNo).isImm());
  unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups);
  unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);

  return Position + Size - 1;
}

#include "MipsGenMCCodeEmitter.inc"

<|endoftext|>


<commit_before>#include <dropwhile.hpp>

#include "helpers.hpp"

#include <vector>
#include <string>
#include <iterator>

#include "catch.hpp"

using iter::dropwhile;

using Vec = const std::vector<int>;

TEST_CASE("dropwhile: skips initial elements", "[dropwhile]") {
    Vec ns{1,2,3,4,5,6,7,8};
    auto d = dropwhile([](int i){return i < 5; }, ns);
    Vec v(std::begin(d), std::end(d));
    Vec vc = {5,6,7,8};
    REQUIRE( v == vc );
}

TEST_CASE("dropwhile: doesn't skip anything if it shouldn't", "[dropwhile]") {
    Vec ns {3,4,5,6};
    auto d = dropwhile([](int i){return i < 3; }, ns);
    Vec v(std::begin(d), std::end(d));
    Vec vc = {3,4,5,6};
    REQUIRE( v == vc );
}

TEST_CASE("dropwhile: skips all elements when all are true under predicate",
        "[dropwhile]") {
    Vec ns {3,4,5,6};
    auto d = dropwhile([](int i){return i != 0; }, ns);
    REQUIRE( std::begin(d) == std::end(d) );
}

<commit_msg>adds dropwhile empty test<commit_after>#include <dropwhile.hpp>

#include "helpers.hpp"

#include <vector>
#include <string>
#include <iterator>

#include "catch.hpp"

using iter::dropwhile;

using Vec = const std::vector<int>;

TEST_CASE("dropwhile: skips initial elements", "[dropwhile]") {
    Vec ns{1,2,3,4,5,6,7,8};
    auto d = dropwhile([](int i){return i < 5; }, ns);
    Vec v(std::begin(d), std::end(d));
    Vec vc = {5,6,7,8};
    REQUIRE( v == vc );
}

TEST_CASE("dropwhile: doesn't skip anything if it shouldn't", "[dropwhile]") {
    Vec ns {3,4,5,6};
    auto d = dropwhile([](int i){return i < 3; }, ns);
    Vec v(std::begin(d), std::end(d));
    Vec vc = {3,4,5,6};
    REQUIRE( v == vc );
}

TEST_CASE("dropwhile: skips all elements when all are true under predicate",
        "[dropwhile]") {
    Vec ns {3,4,5,6};
    auto d = dropwhile([](int i){return i != 0; }, ns);
    REQUIRE( std::begin(d) == std::end(d) );
}

TEST_CASE("dropwhile: empty case is empty", "[dropwhile]") {
    Vec ns{};
    auto d = dropwhile([](int i){return i != 0; }, ns);
    REQUIRE( std::begin(d) == std::end(d) );
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "oox/drawingml/textliststyle.hxx"

namespace oox { namespace drawingml {

TextListStyle::TextListStyle()
{
    for ( int i = 0; i < 9; i++ )
    {
        maListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties() ) );
        maAggregationListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties() ) );
    }
}

TextListStyle::~TextListStyle()
{
}

void applyStyleList( const TextParagraphPropertiesVector& rSourceListStyle, TextParagraphPropertiesVector& rDestListStyle )
{
    TextParagraphPropertiesVector::const_iterator aSourceListStyleIter( rSourceListStyle.begin() );
    TextParagraphPropertiesVector::iterator aDestListStyleIter( rDestListStyle.begin() );
    while( aSourceListStyleIter != rSourceListStyle.end() )
    {
        if ( aDestListStyleIter != rDestListStyle.end() )
        {
            (*aDestListStyleIter)->apply( **aSourceListStyleIter );
            aDestListStyleIter++;
        }
        else
            rDestListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties( **aSourceListStyleIter ) ) );
        aSourceListStyleIter++;
    }
}

void TextListStyle::apply( const TextListStyle& rTextListStyle )
{
    applyStyleList( rTextListStyle.getAggregationListStyle(), getAggregationListStyle() );
    applyStyleList( rTextListStyle.getListStyle(), getListStyle() );
}

#if OSL_DEBUG_LEVEL > 0
void TextListStyle::dump( int nLevels ) const
{
    for ( int i = 0; i < nLevels; i++ )
    {
    OSL_TRACE("level: %d", i);
        maListStyle[ i ]->dump();
    }
}
#endif

} }

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>cppcheck: prefer prefix variant<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "oox/drawingml/textliststyle.hxx"

namespace oox { namespace drawingml {

TextListStyle::TextListStyle()
{
    for ( int i = 0; i < 9; i++ )
    {
        maListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties() ) );
        maAggregationListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties() ) );
    }
}

TextListStyle::~TextListStyle()
{
}

void applyStyleList( const TextParagraphPropertiesVector& rSourceListStyle, TextParagraphPropertiesVector& rDestListStyle )
{
    TextParagraphPropertiesVector::const_iterator aSourceListStyleIter( rSourceListStyle.begin() );
    TextParagraphPropertiesVector::iterator aDestListStyleIter( rDestListStyle.begin() );
    while( aSourceListStyleIter != rSourceListStyle.end() )
    {
        if ( aDestListStyleIter != rDestListStyle.end() )
        {
            (*aDestListStyleIter)->apply( **aSourceListStyleIter );
            ++aDestListStyleIter;
        }
        else
            rDestListStyle.push_back( TextParagraphPropertiesPtr( new TextParagraphProperties( **aSourceListStyleIter ) ) );
        ++aSourceListStyleIter;
    }
}

void TextListStyle::apply( const TextListStyle& rTextListStyle )
{
    applyStyleList( rTextListStyle.getAggregationListStyle(), getAggregationListStyle() );
    applyStyleList( rTextListStyle.getListStyle(), getListStyle() );
}

#if OSL_DEBUG_LEVEL > 0
void TextListStyle::dump( int nLevels ) const
{
    for ( int i = 0; i < nLevels; i++ )
    {
    OSL_TRACE("level: %d", i);
        maListStyle[ i ]->dump();
    }
}
#endif

} }

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * DefaultPatternMatchCB.cc
 *
 * Copyright (C) 2008,2009,2014 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  February 2008
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/execution/EvaluationLink.h>

#include "DefaultPatternMatchCB.h"
#include "PatternMatchEngine.h"

using namespace opencog;

// #define DEBUG 1
#if DEBUG
   #define dbgprt(f, varargs...) printf(f, ##varargs)
#else
   #define dbgprt(f, varargs...)
#endif

/* ======================================================== */

// Find a good place to start the search.
//
// The handle h points to a clause.  In principle, it is enough to
// simply find a constant in the clause, and just start there. In
// practice, this can be an awful way to do things. So, for example,
// most "typical" clauses will be of the form
//
//    EvaluationLink
//        PredicteNode "blah"
//        ListLink
//            VariableNode $var
//            ConceptNode  "item"
//
// Typically, the incoming set to "blah" will be huge, so starting the
// search there would be a poor choice. Typically, the incoming set to
// "item" will be much smaller, and so makes a better choice.  The code
// below tries to pass over "blah" and pick "item" instead.  It does so
// by comparing the size of the incoming sets of the two constants, and
// picking the one with the smaller ("thinner") incoming set. Note that
// this is a form of "greedy" search.
//
// Note that the algo performs a full-depth search to find this. That's
// OK, because typeical clauses are never deep.
//
// Note that the size of the incoming set really is a better measure,
// and not the depth.  So, for example, if "item" has a huge incoming
// set, but "blah" does not, then "blah" is a much better place to
// start.
//
// size_t& depth will be set to the depth of the thinnest constant found.
// Handle& start will be set to the link containing that constant.
// size_t& width will be set to the incoming-set size of the thinnest
//               constant found.
// The returned value will be the constant at which to start the search.
// If no constant is found, then the returned value is the undefnied
// handle.
//
Handle
DefaultPatternMatchCB::find_starter(Handle h, size_t& depth,
                                    Handle& start, size_t& width)
{

	// If its a node, then we are done. Don't modiy either depth or
	// start.
	Type t = h->getType();
	if (classserver().isNode(t)) {
		if (t != VARIABLE_NODE) {
			width = h->getIncomingSetSize();
			return h;
		}
		return Handle::UNDEFINED;
	}

	size_t deepest = depth;
	start = Handle::UNDEFINED;
	Handle hdeepest(Handle::UNDEFINED);
	size_t thinnest = SIZE_MAX;

	// Iterate over all the handles in the outgoing set.
	// Find the deepest one that contains a constant, and start
	// the search there.  If there are two at the same depth,
	// then start with the skinnier one.
	LinkPtr ll(LinkCast(h));
	const std::vector<Handle> &vh = ll->getOutgoingSet();
	for (size_t i = 0; i < vh.size(); i++) {

		size_t brdepth = depth + 1;
		size_t brwid = SIZE_MAX;
		Handle sbr(h);
		Handle s(find_starter(vh[i], brdepth, sbr, brwid));

		if (s != Handle::UNDEFINED
		    and (brwid < thinnest
		         or (brwid == thinnest and deepest < brdepth)))
		{
			deepest = brdepth;
			hdeepest = s;
			start = sbr;
			thinnest = brwid;
		}

	}
	depth = deepest;
	width = thinnest;
	return hdeepest;
}

/**
 * Search for solutions/groundings over all of the AtomSpace, using
 * some "reasonable" assumptions for what might be searched for. Or,
 * to put it bluntly, this search method *might* miss some possible
 * solutions, for certain "unusual" search types. The trade-off is
 * that this search algo should really be quite fast for "normal"
 * search types.
 *
 * This search algo makes the following (important) assumptions:
 *
 * 1) If there are no variables in the clauses, then this will search
 *    over all links which have the same type as the first clause.
 *    Clearly, this kind of search can fail if link_match() callback
 *    was prepared to accept other link types as well.
 *
 * 2) If there are variables, then the search will begin at the first
 *    non-variable node in the first clause.  The search will proceed
 *    by exploring the entire incoming-set for this node, but no farther.
 *    If the node_match() callback is willing to accept a broader range
 *    of node matches, esp for this initial node, then many possible
 *    solutions will be missed.
 *
 * 3) If the clauses consist entirely of variables, the same search
 *    as described in 1) will be performed.
 *
 * The above describes the limits to the "typical" search that this
 * algo can do well. In particular, if the constraint of 2) can be met,
 * then the search can be quite rapid, since incoming sets are often
 * quite small; and assumption 2) limits the search to "nearby",
 * connected atoms.
 *
 * Note that the default implementation of node_match() and link_match()
 * in this class does satisfy both 1) and 2), so this algo will work
 * correctly if these two methods are not overloaded.
 *
 * If you overload node_match(), and do so in a way that breaks
 * assumption 2), then you will scratch your head, thinking
 * "why did my search fail to find this obvious solution?" The answer
 * will be for you to create a new search algo, in a new class, that
 * overloads this one, and does what you want it to.  This class should
 * probably *not* be modified, since it is quite efficient for the
 * "normal" case.
 */
void DefaultPatternMatchCB::perform_search(PatternMatchEngine *pme,
                         std::set<Handle> &vars,
                         std::vector<Handle> &clauses,
                         std::vector<Handle> &negations)
{
	// In principle, we could start our search at some node, any node,
	// that is not a variable. In practice, the search begins by
	// iterating over the incoming set of the node, and so, if it is
	// large, a huge amount of effort might be wasted exploring
	// dead-ends.  Thus, it pays off to start the search on the
	// node with the smallest ("narrowest" or "thinnest") incoming set
	// possible.  Thus, we look at all the clauses, to find the
	// "thinnest" one.
	//
	// Note also: the user is allowed to specify patterns that have
	// no constants in them at all.  In this case, the search is
	// performed by looping over all links of the given types.

	size_t thinnest = SIZE_MAX;
	size_t deepest = 0;
	size_t bestclause = 0;
	Handle best_start(Handle::UNDEFINED);
	_starter_pred = Handle::UNDEFINED;

	size_t nc = clauses.size();
	for (size_t i=0; i < nc; i++) {
		Handle h(clauses[i]);
		size_t depth = 0;
		size_t width = SIZE_MAX;
		Handle pred(Handle::UNDEFINED);
		Handle start(find_starter(h, depth, pred, width));
		if (start != Handle::UNDEFINED
		    and (width < thinnest
		         or (width == thinnest and depth > deepest)))
		{
			thinnest = width;
			deepest = depth;
			bestclause = i;
			best_start = start;
			_starter_pred = pred;
		}
	}

	if ((Handle::UNDEFINED != best_start) && (0 != vars.size()))
	{
		_root = clauses[bestclause];
		dbgprt("Search start node: %s\n", best_start->toShortString().c_str());
		dbgprt("Start pred is: %s\n", _starter_pred->toShortString().c_str());
		IncomingSet iset = get_incoming_set(best_start);
		size_t sz = iset.size();
		for (size_t i = 0; i < sz; i++) {
			Handle h(iset[i]);
			dbgprt("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
			dbgprt("Loop candidate: %s\n", h->toShortString().c_str());
			bool rc = pme->do_candidate(_root, _starter_pred, h);
			if (rc) break;
		}
	}
	else
	{
		_root = clauses[0];
		_starter_pred = _root;

		dbgprt("Start pred is: %s\n", _starter_pred->toShortString().c_str());
		// Get type of the first item in the predicate list.
		Type ptype = _root->getType();

		// Plunge into the deep end - start looking at all viable
		// candidates in the AtomSpace.

		// XXX TODO -- as a performance optimization, we should try all
		// the different clauses, and find the one with the smallest number
		// of atoms of that type, or otherwise try to find a small ("thin")
		// incoming set to search over.
		std::list<Handle> handle_set;
		_atom_space->getHandlesByType(back_inserter(handle_set), ptype);
		std::list<Handle>::iterator i = handle_set.begin();
		std::list<Handle>::iterator iend = handle_set.end();
		for (; i != iend; i++)
		{
			Handle h(*i);
			dbgprt("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
			dbgprt("Loop candidate: %s\n", h->toShortString().c_str());
			bool rc = pme->do_candidate(_root, _starter_pred, h);
			if (rc) break;
		}
	}
}

/* ======================================================== */

bool DefaultPatternMatchCB::virtual_link_match(LinkPtr& lvirt, Handle& gargs)
{
	// At this time, we expect all virutal links to be
	// EvaluationLinks having the structure
	//
	//   EvaluationLink
	//       GroundedPredicateNode "scm:blah"
	//       ListLink
	//           Arg1Atom
	//           Arg2Atom
	//
	// XXX TODO s discussed on the mailing list, we should perhaps first
	// see if the following can be found in the atomspace:
	//
	//   EvaluationLink
	//       PredicateNode "blah"  ; not Grounded any more, and scm: stripped
	//       ListLink
	//           Arg1Atom
	//           Arg2Atom
	//
	// If it does, we should declare a match.  If not, only then run the
	// do_evaluate callback.  Alternately, perhaps the
	// EvaluationLink::do_evaluate() method should do this ??? Its a toss-up.

	Handle schema(lvirt->getOutgoingAtom(0));
	bool relation_holds = EvaluationLink::do_evaluate(_atom_space, schema, gargs);

	// Make a weak effort to clean up bad groundings. gargs is a
	// a grounded ListLink.  We should probably look at it's children;
	// if any of those also do not have any incoming links, they too
	// should be removed. XXX FIXME.
	_atom_space->purgeAtom(gargs, false);

	return not relation_holds;
}

/* ===================== END OF FILE ===================== */
<commit_msg>spell error fix<commit_after>/*
 * DefaultPatternMatchCB.cc
 *
 * Copyright (C) 2008,2009,2014 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  February 2008
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/execution/EvaluationLink.h>

#include "DefaultPatternMatchCB.h"
#include "PatternMatchEngine.h"

using namespace opencog;

// #define DEBUG 1
#if DEBUG
   #define dbgprt(f, varargs...) printf(f, ##varargs)
#else
   #define dbgprt(f, varargs...)
#endif

/* ======================================================== */

// Find a good place to start the search.
//
// The handle h points to a clause.  In principle, it is enough to
// simply find a constant in the clause, and just start there. In
// practice, this can be an awful way to do things. So, for example,
// most "typical" clauses will be of the form
//
//    EvaluationLink
//        PredicateNode "blah"
//        ListLink
//            VariableNode $var
//            ConceptNode  "item"
//
// Typically, the incoming set to "blah" will be huge, so starting the
// search there would be a poor choice. Typically, the incoming set to
// "item" will be much smaller, and so makes a better choice.  The code
// below tries to pass over "blah" and pick "item" instead.  It does so
// by comparing the size of the incoming sets of the two constants, and
// picking the one with the smaller ("thinner") incoming set. Note that
// this is a form of "greedy" search.
//
// Note that the algo performs a full-depth search to find this. That's
// OK, because typeical clauses are never deep.
//
// Note that the size of the incoming set really is a better measure,
// and not the depth.  So, for example, if "item" has a huge incoming
// set, but "blah" does not, then "blah" is a much better place to
// start.
//
// size_t& depth will be set to the depth of the thinnest constant found.
// Handle& start will be set to the link containing that constant.
// size_t& width will be set to the incoming-set size of the thinnest
//               constant found.
// The returned value will be the constant at which to start the search.
// If no constant is found, then the returned value is the undefnied
// handle.
//
Handle
DefaultPatternMatchCB::find_starter(Handle h, size_t& depth,
                                    Handle& start, size_t& width)
{

	// If its a node, then we are done. Don't modiy either depth or
	// start.
	Type t = h->getType();
	if (classserver().isNode(t)) {
		if (t != VARIABLE_NODE) {
			width = h->getIncomingSetSize();
			return h;
		}
		return Handle::UNDEFINED;
	}

	size_t deepest = depth;
	start = Handle::UNDEFINED;
	Handle hdeepest(Handle::UNDEFINED);
	size_t thinnest = SIZE_MAX;

	// Iterate over all the handles in the outgoing set.
	// Find the deepest one that contains a constant, and start
	// the search there.  If there are two at the same depth,
	// then start with the skinnier one.
	LinkPtr ll(LinkCast(h));
	const std::vector<Handle> &vh = ll->getOutgoingSet();
	for (size_t i = 0; i < vh.size(); i++) {

		size_t brdepth = depth + 1;
		size_t brwid = SIZE_MAX;
		Handle sbr(h);
		Handle s(find_starter(vh[i], brdepth, sbr, brwid));

		if (s != Handle::UNDEFINED
		    and (brwid < thinnest
		         or (brwid == thinnest and deepest < brdepth)))
		{
			deepest = brdepth;
			hdeepest = s;
			start = sbr;
			thinnest = brwid;
		}

	}
	depth = deepest;
	width = thinnest;
	return hdeepest;
}

/**
 * Search for solutions/groundings over all of the AtomSpace, using
 * some "reasonable" assumptions for what might be searched for. Or,
 * to put it bluntly, this search method *might* miss some possible
 * solutions, for certain "unusual" search types. The trade-off is
 * that this search algo should really be quite fast for "normal"
 * search types.
 *
 * This search algo makes the following (important) assumptions:
 *
 * 1) If there are no variables in the clauses, then this will search
 *    over all links which have the same type as the first clause.
 *    Clearly, this kind of search can fail if link_match() callback
 *    was prepared to accept other link types as well.
 *
 * 2) If there are variables, then the search will begin at the first
 *    non-variable node in the first clause.  The search will proceed
 *    by exploring the entire incoming-set for this node, but no farther.
 *    If the node_match() callback is willing to accept a broader range
 *    of node matches, esp for this initial node, then many possible
 *    solutions will be missed.
 *
 * 3) If the clauses consist entirely of variables, the same search
 *    as described in 1) will be performed.
 *
 * The above describes the limits to the "typical" search that this
 * algo can do well. In particular, if the constraint of 2) can be met,
 * then the search can be quite rapid, since incoming sets are often
 * quite small; and assumption 2) limits the search to "nearby",
 * connected atoms.
 *
 * Note that the default implementation of node_match() and link_match()
 * in this class does satisfy both 1) and 2), so this algo will work
 * correctly if these two methods are not overloaded.
 *
 * If you overload node_match(), and do so in a way that breaks
 * assumption 2), then you will scratch your head, thinking
 * "why did my search fail to find this obvious solution?" The answer
 * will be for you to create a new search algo, in a new class, that
 * overloads this one, and does what you want it to.  This class should
 * probably *not* be modified, since it is quite efficient for the
 * "normal" case.
 */
void DefaultPatternMatchCB::perform_search(PatternMatchEngine *pme,
                         std::set<Handle> &vars,
                         std::vector<Handle> &clauses,
                         std::vector<Handle> &negations)
{
	// In principle, we could start our search at some node, any node,
	// that is not a variable. In practice, the search begins by
	// iterating over the incoming set of the node, and so, if it is
	// large, a huge amount of effort might be wasted exploring
	// dead-ends.  Thus, it pays off to start the search on the
	// node with the smallest ("narrowest" or "thinnest") incoming set
	// possible.  Thus, we look at all the clauses, to find the
	// "thinnest" one.
	//
	// Note also: the user is allowed to specify patterns that have
	// no constants in them at all.  In this case, the search is
	// performed by looping over all links of the given types.

	size_t thinnest = SIZE_MAX;
	size_t deepest = 0;
	size_t bestclause = 0;
	Handle best_start(Handle::UNDEFINED);
	_starter_pred = Handle::UNDEFINED;

	size_t nc = clauses.size();
	for (size_t i=0; i < nc; i++) {
		Handle h(clauses[i]);
		size_t depth = 0;
		size_t width = SIZE_MAX;
		Handle pred(Handle::UNDEFINED);
		Handle start(find_starter(h, depth, pred, width));
		if (start != Handle::UNDEFINED
		    and (width < thinnest
		         or (width == thinnest and depth > deepest)))
		{
			thinnest = width;
			deepest = depth;
			bestclause = i;
			best_start = start;
			_starter_pred = pred;
		}
	}

	if ((Handle::UNDEFINED != best_start) && (0 != vars.size()))
	{
		_root = clauses[bestclause];
		dbgprt("Search start node: %s\n", best_start->toShortString().c_str());
		dbgprt("Start pred is: %s\n", _starter_pred->toShortString().c_str());
		IncomingSet iset = get_incoming_set(best_start);
		size_t sz = iset.size();
		for (size_t i = 0; i < sz; i++) {
			Handle h(iset[i]);
			dbgprt("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
			dbgprt("Loop candidate: %s\n", h->toShortString().c_str());
			bool rc = pme->do_candidate(_root, _starter_pred, h);
			if (rc) break;
		}
	}
	else
	{
		_root = clauses[0];
		_starter_pred = _root;

		dbgprt("Start pred is: %s\n", _starter_pred->toShortString().c_str());
		// Get type of the first item in the predicate list.
		Type ptype = _root->getType();

		// Plunge into the deep end - start looking at all viable
		// candidates in the AtomSpace.

		// XXX TODO -- as a performance optimization, we should try all
		// the different clauses, and find the one with the smallest number
		// of atoms of that type, or otherwise try to find a small ("thin")
		// incoming set to search over.
		std::list<Handle> handle_set;
		_atom_space->getHandlesByType(back_inserter(handle_set), ptype);
		std::list<Handle>::iterator i = handle_set.begin();
		std::list<Handle>::iterator iend = handle_set.end();
		for (; i != iend; i++)
		{
			Handle h(*i);
			dbgprt("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
			dbgprt("Loop candidate: %s\n", h->toShortString().c_str());
			bool rc = pme->do_candidate(_root, _starter_pred, h);
			if (rc) break;
		}
	}
}

/* ======================================================== */

bool DefaultPatternMatchCB::virtual_link_match(LinkPtr& lvirt, Handle& gargs)
{
	// At this time, we expect all virutal links to be
	// EvaluationLinks having the structure
	//
	//   EvaluationLink
	//       GroundedPredicateNode "scm:blah"
	//       ListLink
	//           Arg1Atom
	//           Arg2Atom
	//
	// XXX TODO s discussed on the mailing list, we should perhaps first
	// see if the following can be found in the atomspace:
	//
	//   EvaluationLink
	//       PredicateNode "blah"  ; not Grounded any more, and scm: stripped
	//       ListLink
	//           Arg1Atom
	//           Arg2Atom
	//
	// If it does, we should declare a match.  If not, only then run the
	// do_evaluate callback.  Alternately, perhaps the
	// EvaluationLink::do_evaluate() method should do this ??? Its a toss-up.

	Handle schema(lvirt->getOutgoingAtom(0));
	bool relation_holds = EvaluationLink::do_evaluate(_atom_space, schema, gargs);

	// Make a weak effort to clean up bad groundings. gargs is a
	// a grounded ListLink.  We should probably look at it's children;
	// if any of those also do not have any incoming links, they too
	// should be removed. XXX FIXME.
	_atom_space->purgeAtom(gargs, false);

	return not relation_holds;
}

/* ===================== END OF FILE ===================== */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AIndexes.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-07-10 14:34:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _CONNECTIVITY_ADO_INDEXES_HXX_
#define _CONNECTIVITY_ADO_INDEXES_HXX_

#ifndef _CONNECTIVITY_SDBCX_COLLECTION_HXX_
#include "connectivity/sdbcx/VCollection.hxx"
#endif
#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
#endif
#ifndef _CONNECTIVITY_ADO_AWRAPADOX_HXX_
#include "ado/Awrapadox.hxx"
#endif

namespace connectivity
{
    namespace ado
    {
        class OConnection;
        class OIndexes : public sdbcx::OCollection
        {
            WpADOIndexes    m_aCollection;
            OConnection*    m_pConnection;
        protected:
            virtual sdbcx::ObjectType createObject(const ::rtl::OUString& _rName);
            virtual void impl_refresh() throw(::com::sun::star::uno::RuntimeException);
            virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createDescriptor();
            virtual sdbcx::ObjectType appendObject( const ::rtl::OUString& _rForName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor );
            virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName);
        public:
            OIndexes(::cppu::OWeakObject& _rParent,
                     ::osl::Mutex& _rMutex,
                     const TStringVector &_rVector,
                     const WpADOIndexes&    _rCollection,
                     sal_Bool _bCase,
                     OConnection* _pConnection)
                    : sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector)
                    , m_aCollection(_rCollection)
                    , m_pConnection(_pConnection)
            {
            }
        };
    }
}

#endif // _CONNECTIVITY_ADO_INDEXES_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.9.262); FILE MERGED 2008/04/01 10:53:20 thb 1.9.262.2: #i85898# Stripping all external header guards 2008/03/28 15:24:11 rt 1.9.262.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: AIndexes.hxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _CONNECTIVITY_ADO_INDEXES_HXX_
#define _CONNECTIVITY_ADO_INDEXES_HXX_

#include "connectivity/sdbcx/VCollection.hxx"
#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
#include "ado/Awrapadox.hxx"

namespace connectivity
{
    namespace ado
    {
        class OConnection;
        class OIndexes : public sdbcx::OCollection
        {
            WpADOIndexes    m_aCollection;
            OConnection*    m_pConnection;
        protected:
            virtual sdbcx::ObjectType createObject(const ::rtl::OUString& _rName);
            virtual void impl_refresh() throw(::com::sun::star::uno::RuntimeException);
            virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > createDescriptor();
            virtual sdbcx::ObjectType appendObject( const ::rtl::OUString& _rForName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor );
            virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName);
        public:
            OIndexes(::cppu::OWeakObject& _rParent,
                     ::osl::Mutex& _rMutex,
                     const TStringVector &_rVector,
                     const WpADOIndexes&    _rCollection,
                     sal_Bool _bCase,
                     OConnection* _pConnection)
                    : sdbcx::OCollection(_rParent,_bCase,_rMutex,_rVector)
                    , m_aCollection(_rCollection)
                    , m_pConnection(_pConnection)
            {
            }
        };
    }
}

#endif // _CONNECTIVITY_ADO_INDEXES_HXX_

<|endoftext|>


<commit_before>#pragma once

//
// Retains no ownership over the object
//
template <class T>
struct Out {
  explicit Out(T& obj) : _obj(obj) {
  }
  T& operator*() {
    return _obj;
  }
  T* operator->() {
    return &_obj;
  }

 private:
  T& _obj;
};

template <class T>
Out<T> out(T& obj) {
  return Out<T>(obj);
}<commit_msg>Add hackish vector-out TODO:TMP<commit_after>#pragma once

#include <type_traits>
#include <vector>

//
// Retains no ownership over the object
//
template <class T>
struct Out {
  explicit Out(T& obj) : _obj(obj) {
  }
  T& operator*() {
    return _obj;
  }
  T* operator->() {
    return &_obj;
  }

 private:
  T& _obj;
};

template <class T>
Out<T> out(T& obj) {
  return Out<T>(obj);
}

//
// Retains no ownership over the object
//
template <typename T>
struct Vout {
  explicit Vout(T& obj) : _obj(obj) {
  }

  T& operator*() {
    return _obj;
  }

  T* operator->() {
    return &_obj;
  }

  const T& operator*() const {
    return _obj;
  }

  typename T::value_type& operator[](int i) {
    return _obj[i];
  }

 private:
  T& _obj;
};

template <typename T>
Vout<T> vout(T& obj) {
  return Vout<T>(obj);
}<|endoftext|>


<commit_before>// Chapter 26, exercise 11: time the sum example from 26.6 with m being square
// matrices with dimensions 100, 10,000, 1,000,000 and 10,000,000. Use random
// elements in the range [-10:10). Rewrite the calculation of v to use a more
// efficient (not O(N^2)) algorithm and compare timings.
//
// Dimensions way too big for stupid methods (takes forever) and memory (matrix
// of doubles with 100,000 elements per dimensions: 80 GB!), hence reduced
// number of elements and allocated on heap

#include<ctime>
#include<iostream>
#include<exception>
#include<vector>
#include<random>

#include "chapter24/Matrix.h"
#include "chapter24/MatrixIO.h"

using namespace std;
using namespace Numeric_lib;

//------------------------------------------------------------------------------

inline int randint(int max) { return rand()%max; }

inline int randint(int min, int max) { return randint(max-min)+min; }

//------------------------------------------------------------------------------

// sum of elements in m[n]
double row_sum(Matrix<double,2>* m, int n)
{
    double sum = 0;
    for (Index i = 0; i<m->dim2(); ++i)
        sum += (*m)(n,i);
    return sum;
}

//------------------------------------------------------------------------------

// sum of elements in m[0:n)
double row_accum(Matrix<double,2>* m, int n)
{
    double s = 0;
    for (Index i = 0; i<n; ++i)
        s += row_sum(m,i);
    return s;
}

//------------------------------------------------------------------------------

// creates random nxn-matrix with elements in range [-10:10)
Matrix<double,2>* random_matrix(int n)
{
    Matrix<double,2>* m = new Matrix<double,2>(n,n);
    for (Index i = 0; i<m->dim1(); ++i)
        for (Index j = 0; j<m->dim2(); ++j)
            (*m)(i,j) = randint(-10,10);
    return m;
}

//------------------------------------------------------------------------------

int main()
try {
    srand(time(0));
    vector<int> dims = {100, 200, 400, 800, 1600, 3200};

    cout << "With the dumb method:\n";
    // scales about with the square of the number of elements
    for (int i = 0; i<dims.size(); ++i) {
        clock_t t1 = clock();
        if (t1 == clock_t(-1))
            throw exception("sorry, no clock");
        Matrix<double,2>* m = random_matrix(dims[i]);
        vector<double> v;
        for (Index idx = 0; idx<m->dim1(); ++idx)
            v.push_back(row_accum(m,idx+1));
        clock_t t2 = clock();
        if (t2 == clock_t(-1))
            throw exception("sorry, clock overflow");
        cout << "Size " << setw(8) << dims[i] << ": "
            << double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";
        delete m;
    }

    dims.push_back(6400);
    dims.push_back(12800);

    cout << "\nWith the smart method:\n";
    // scales linearly with the number of elements
    for (int i = 0; i<dims.size(); ++i) {
        clock_t t1 = clock();
        if (t1 == clock_t(-1))
            throw exception("sorry, no clock");
        Matrix<double,2>* m = random_matrix(dims[i]);
        vector<double> v;
        double sum = 0;
        for (Index idx = 0; idx<m->dim1(); ++idx) {
            sum += row_sum(m,idx);
            v.push_back(sum);
        }
        clock_t t2 = clock();
        if (t2 == clock_t(-1))
            throw exception("sorry, clock overflow");
        cout << "Size " << setw(8) << dims[i] << ": "
            << double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";
        delete m;
    }

}
catch (exception& e) {
    cerr << e.what() << endl;
}
catch (...) {
    cerr << "exception \n";
}

//------------------------------------------------------------------------------
<commit_msg>Allocation doesn't matter, matrix data is anyway on the heap<commit_after>// Chapter 26, exercise 11: time the sum example from 26.6 with m being square
// matrices with dimensions 100, 10,000, 1,000,000 and 10,000,000. Use random
// elements in the range [-10:10). Rewrite the calculation of v to use a more
// efficient (not O(N^2)) algorithm and compare timings.
//
// Dimensions way too big for stupid methods (takes forever) and memory (matrix
// of doubles with 100,000 elements per dimensions: 80 GB!), hence reduced
// number of elements
//
// Also worth to mention: the version in the book passes the matrices by value,
// leading to a lot of copies and unusably slow performance

#include<ctime>
#include<iostream>
#include<exception>
#include<vector>
#include<random>

#include "chapter24/Matrix.h"
#include "chapter24/MatrixIO.h"

using namespace std;
using namespace Numeric_lib;

//------------------------------------------------------------------------------

inline int randint(int max) { return rand()%max; }

inline int randint(int min, int max) { return randint(max-min)+min; }

//------------------------------------------------------------------------------

// sum of elements in m[n]
double row_sum(const Matrix<double,2>& m, int n)
{
    double sum = 0;
    for (Index i = 0; i<m.dim2(); ++i)
        sum += m(n,i);
    return sum;
}

//------------------------------------------------------------------------------

// sum of elements in m[0:n)
double row_accum(const Matrix<double,2>& m, int n)
{
    double s = 0;
    for (Index i = 0; i<n; ++i)
        s += row_sum(m,i);
    return s;
}

//------------------------------------------------------------------------------

// creates random nxn-matrix with elements in range [-10:10)
Matrix<double,2> random_matrix(int n)
{
    Matrix<double,2> m(n,n);
    for (Index i = 0; i<m.dim1(); ++i)
        for (Index j = 0; j<m.dim2(); ++j)
            m(i,j) = randint(-10,10);
    return m;
}

//------------------------------------------------------------------------------

int main()
try {
    srand(time(0));
    vector<int> dims = {100, 200, 400, 800, 1600, 3200};

    cout << "With the dumb method:\n";
    // scales about with the square of the number of elements
    for (int i = 0; i<dims.size(); ++i) {
        clock_t t1 = clock();
        if (t1 == clock_t(-1))
            throw exception("sorry, no clock");
        Matrix<double,2> m = random_matrix(dims[i]);
        vector<double> v;
        for (Index idx = 0; idx<m.dim1(); ++idx)
            v.push_back(row_accum(m,idx+1));
        clock_t t2 = clock();
        if (t2 == clock_t(-1))
            throw exception("sorry, clock overflow");
        cout << "Size " << setw(8) << dims[i] << ": "
            << double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";
    }

    dims.push_back(6400);
    dims.push_back(12800);

    cout << "\nWith the smart method:\n";
    // scales linearly with the number of elements
    for (int i = 0; i<dims.size(); ++i) {
        clock_t t1 = clock();
        if (t1 == clock_t(-1))
            throw exception("sorry, no clock");
        Matrix<double,2> m = random_matrix(dims[i]);
        vector<double> v;
        double sum = 0;
        for (Index idx = 0; idx<m.dim1(); ++idx) {
            sum += row_sum(m,idx);
            v.push_back(sum);
        }
        clock_t t2 = clock();
        if (t2 == clock_t(-1))
            throw exception("sorry, clock overflow");
        cout << "Size " << setw(8) << dims[i] << ": "
            << double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";
    }

}
catch (exception& e) {
    cerr << e.what() << endl;
}
catch (...) {
    cerr << "exception \n";
}

//------------------------------------------------------------------------------
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "maemoruncontrol.h"
#include "maemosshthread.h"
#include "maemorunconfiguration.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <debugger/debuggermanager.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/toolchain.h>
#include <utils/qtcassert.h>

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QFuture>
#include <QtCore/QProcess>
#include <QtCore/QStringBuilder>

#include <QtGui/QMessageBox>

namespace Qt4ProjectManager {
namespace Internal {

using ProjectExplorer::RunConfiguration;
using ProjectExplorer::ToolChain;

AbstractMaemoRunControl::AbstractMaemoRunControl(RunConfiguration *rc)
    : RunControl(rc)
    , m_runConfig(qobject_cast<MaemoRunConfiguration *>(rc))
    , m_devConfig(m_runConfig ? m_runConfig->deviceConfig() : MaemoDeviceConfig())
{
}

AbstractMaemoRunControl::~AbstractMaemoRunControl()
{
}

void AbstractMaemoRunControl::start()
{
    m_stoppedByUser = false;
    emit started();
    startInitialCleanup();
}

void AbstractMaemoRunControl::startInitialCleanup()
{
    emit addToOutputWindow(this, tr("Cleaning up remote leftovers first ..."));
    const QStringList appsToKill
        = QStringList() << executableFileName() << QLatin1String("gdbserver");
    killRemoteProcesses(appsToKill, true);
}

void AbstractMaemoRunControl::stop()
{
    m_stoppedByUser = true;
    if (isCleaning())
        m_initialCleaner->stop();
    else if (isDeploying())
        m_sshDeployer->stop();
    else
        stopInternal();
}

void AbstractMaemoRunControl::handleInitialCleanupFinished()
{
    if (m_stoppedByUser) {
        emit addToOutputWindow(this, tr("Initial cleanup canceled by user."));
        emit finished();
    } else if (m_initialCleaner->hasError()) {
        handleError(tr("Error running initial cleanup: %1.")
                    .arg(m_initialCleaner->error()));
        emit finished();
    } else {
        emit addToOutputWindow(this, tr("Initial cleanup done."));
        startInternal();
    }
}

void AbstractMaemoRunControl::startDeployment(bool forDebugging)
{
    QTC_ASSERT(m_runConfig, return);

    if (!m_devConfig.isValid()) {
        handleError(tr("No device configuration set for run configuration."));
        emit finished();
    } else if (m_stoppedByUser) {
        emit finished();
    } else {
        m_deployables.clear();
        if (m_runConfig->currentlyNeedsDeployment(m_devConfig.host)) {
            m_deployables.append(Deployable(executableFileName(),
                QFileInfo(executableOnHost()).canonicalPath(),
                &MaemoRunConfiguration::wasDeployed));
        }
        if (forDebugging
            && m_runConfig->debuggingHelpersNeedDeployment(m_devConfig.host)) {
            const QFileInfo &info(m_runConfig->dumperLib());
            m_deployables.append(Deployable(info.fileName(), info.canonicalPath(),
                &MaemoRunConfiguration::debuggingHelpersDeployed));
        }

        deploy();
    }
}

void AbstractMaemoRunControl::deploy()
{
    Core::ICore::instance()->progressManager()
        ->addTask(m_progress.future(), tr("Deploying"),
                  QLatin1String("Maemo.Deploy"));
    if (!m_deployables.isEmpty()) {
        QList<SshDeploySpec> deploySpecs;
        QStringList files;
        foreach (const Deployable &deployable, m_deployables) {
            const QString srcFilePath
                = deployable.dir % QDir::separator() % deployable.fileName;
            const QString tgtFilePath
                = remoteDir() % QDir::separator() % deployable.fileName;
            files << srcFilePath;
            deploySpecs << SshDeploySpec(srcFilePath, tgtFilePath);
        }
        emit addToOutputWindow(this, tr("Files to deploy: %1.").arg(files.join(" ")));
        m_sshDeployer.reset(new MaemoSshDeployer(m_devConfig, deploySpecs));
        connect(m_sshDeployer.data(), SIGNAL(finished()),
                this, SLOT(handleDeployThreadFinished()));
        connect(m_sshDeployer.data(), SIGNAL(fileCopied(QString)),
                this, SLOT(handleFileCopied()));
        m_progress.setProgressRange(0, m_deployables.count());
        m_progress.setProgressValue(0);
        m_progress.reportStarted();
        m_sshDeployer->start();
    } else {
        m_progress.reportFinished();
        startExecution();
    }
}

void AbstractMaemoRunControl::handleFileCopied()
{
    Deployable deployable = m_deployables.takeFirst();
    (m_runConfig->*deployable.updateTimestamp)(m_devConfig.host);
    m_progress.setProgressValue(m_progress.progressValue() + 1);
}

bool AbstractMaemoRunControl::isDeploying() const
{
    return m_sshDeployer && m_sshDeployer->isRunning();
}

bool AbstractMaemoRunControl::isCleaning() const
{
    return m_initialCleaner && m_initialCleaner->isRunning();
}

void AbstractMaemoRunControl::startExecution()
{
    m_sshRunner.reset(new MaemoSshRunner(m_devConfig, remoteCall()));
    connect(m_sshRunner.data(), SIGNAL(finished()),
            this, SLOT(handleRunThreadFinished()));
    connect(m_sshRunner.data(), SIGNAL(remoteOutput(QString)),
            this, SLOT(handleRemoteOutput(QString)));
    emit addToOutputWindow(this, tr("Starting remote application."));
    m_sshRunner->start();
}

bool AbstractMaemoRunControl::isRunning() const
{
    return isDeploying() || (m_sshRunner && m_sshRunner->isRunning());
}

void AbstractMaemoRunControl::stopRunning(bool forDebugging)
{
    if (m_sshRunner && m_sshRunner->isRunning()) {
        m_sshRunner->stop();
        QStringList apps(executableFileName());
        if (forDebugging)
            apps << QLatin1String("gdbserver");
        killRemoteProcesses(apps, false);
    }
}

void AbstractMaemoRunControl::killRemoteProcesses(const QStringList &apps,
                                                  bool initialCleanup)
{
    QString niceKill;
    QString brutalKill;
    foreach (const QString &app, apps) {
        niceKill += QString::fromLocal8Bit("pkill -x %1;").arg(app);
        brutalKill += QString::fromLocal8Bit("pkill -x -9 %1;").arg(app);
    }
    const QString remoteCall
        = niceKill + QLatin1String("sleep 1; ") + brutalKill;
    QScopedPointer<MaemoSshRunner> &runner
        = initialCleanup ? m_initialCleaner : m_sshStopper;
    runner.reset(new MaemoSshRunner(m_devConfig, remoteCall));
    if (initialCleanup)
        connect(runner.data(), SIGNAL(finished()),
                this, SLOT(handleInitialCleanupFinished()));
    runner->start();
}

void AbstractMaemoRunControl::handleDeployThreadFinished()
{
    bool cancel;
    if (m_stoppedByUser) {
        emit addToOutputWindow(this, tr("Deployment canceled by user."));
        cancel = true;
    } else if (m_sshDeployer->hasError()) {
        handleError(tr("Deployment failed: %1").arg(m_sshDeployer->error()));
        cancel = true;
    } else {
        emit addToOutputWindow(this, tr("Deployment finished."));
        cancel = false;
    }

    if (cancel) {
        m_progress.reportCanceled();
        m_progress.reportFinished();
        emit finished();
    } else {
        m_progress.reportFinished();
        startExecution();
    }
}

void AbstractMaemoRunControl::handleRunThreadFinished()
{
    if (m_stoppedByUser) {
        emit addToOutputWindow(this,
                 tr("Remote execution canceled due to user request."));
    } else if (m_sshRunner->hasError()) {
        emit addToOutputWindow(this, tr("Remote process exited with error: %1")
                                         .arg(m_sshRunner->error()));
    } else {
        emit addToOutputWindow(this, tr("Remote process finished successfully."));
    }
    emit finished();
}

const QString AbstractMaemoRunControl::executableOnHost() const
{
    qDebug("runconfig->executable: %s", qPrintable(m_runConfig->executable()));
    return m_runConfig->executable();
}

const QString AbstractMaemoRunControl::sshPort() const
{
    return m_devConfig.type == MaemoDeviceConfig::Physical
        ? QString::number(m_devConfig.sshPort)
        : m_runConfig->simulatorSshPort();
}

const QString AbstractMaemoRunControl::executableFileName() const
{
    return QFileInfo(executableOnHost()).fileName();
}

const QString AbstractMaemoRunControl::remoteDir() const
{
    return homeDirOnDevice(m_devConfig.uname);
}

const QStringList AbstractMaemoRunControl::options() const
{
    const bool usePassword
        = m_devConfig.authentication == MaemoDeviceConfig::Password;
    const QLatin1String opt("-o");
    QStringList optionList;
    if (!usePassword)
        optionList << QLatin1String("-i") << m_devConfig.keyFile;
    return optionList << opt
        << QString::fromLatin1("PasswordAuthentication=%1").
            arg(usePassword ? "yes" : "no") << opt
        << QString::fromLatin1("PubkeyAuthentication=%1").
            arg(usePassword ? "no" : "yes") << opt
        << QString::fromLatin1("ConnectTimeout=%1").arg(m_devConfig.timeout)
        << opt << QLatin1String("CheckHostIP=no")
        << opt << QLatin1String("StrictHostKeyChecking=no");
}

const QString AbstractMaemoRunControl::executableOnTarget() const
{
    return QString::fromLocal8Bit("%1/%2").arg(remoteDir()).
        arg(executableFileName());
}

const QString AbstractMaemoRunControl::targetCmdLinePrefix() const
{
    return QString::fromLocal8Bit("chmod u+x %1; source /etc/profile; ").
        arg(executableOnTarget());
}

void AbstractMaemoRunControl::handleError(const QString &errString)
{
    QMessageBox::critical(0, tr("Remote Execution Failure"), errString);
    emit error(this, errString);
}

MaemoRunControl::MaemoRunControl(RunConfiguration *runConfiguration)
    : AbstractMaemoRunControl(runConfiguration)
{
}

MaemoRunControl::~MaemoRunControl()
{
    stop();
}

void MaemoRunControl::startInternal()
{
    startDeployment(false);
}

QString MaemoRunControl::remoteCall() const
{
    return QString::fromLocal8Bit("%1 %2 %3")
        .arg(targetCmdLinePrefix()).arg(executableOnTarget())
        .arg(m_runConfig->arguments().join(" "));
}

void MaemoRunControl::stopInternal()
{
    AbstractMaemoRunControl::stopRunning(false);
}

void MaemoRunControl::handleRemoteOutput(const QString &output)
{
    emit addToOutputWindowInline(this, output);
}

MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration)
    : AbstractMaemoRunControl(runConfiguration)
    , m_debuggerManager(ExtensionSystem::PluginManager::instance()
                      ->getObject<Debugger::DebuggerManager>())
    , m_startParams(new Debugger::DebuggerStartParameters)
{
    QTC_ASSERT(m_debuggerManager != 0, return);
    m_startParams->startMode = Debugger::StartRemote;
    m_startParams->executable = executableOnHost();
    m_startParams->remoteChannel
        = m_devConfig.host % QLatin1Char(':') % gdbServerPort();
    m_startParams->remoteArchitecture = QLatin1String("arm");
    m_startParams->sysRoot = m_runConfig->sysRoot();
    m_startParams->toolChainType = ToolChain::GCC_MAEMO;
    m_startParams->debuggerCommand = m_runConfig->gdbCmd();
    m_startParams->dumperLibrary = m_runConfig->dumperLib();
    m_startParams->remoteDumperLib = QString::fromLocal8Bit("%1/%2")
        .arg(remoteDir()).arg(QFileInfo(m_runConfig->dumperLib()).fileName());

    connect(m_debuggerManager, SIGNAL(debuggingFinished()), this,
        SLOT(debuggingFinished()), Qt::QueuedConnection);
    connect(m_debuggerManager, SIGNAL(applicationOutputAvailable(QString)),
        this, SLOT(debuggerOutput(QString)), Qt::QueuedConnection);
}

MaemoDebugRunControl::~MaemoDebugRunControl()
{
    disconnect(SIGNAL(addToOutputWindow(RunControl*,QString)));
    disconnect(SIGNAL(addToOutputWindowInline(RunControl*,QString)));
    stop();
    debuggingFinished();
}

void MaemoDebugRunControl::startInternal()
{
    m_inferiorPid = -1;
    startDeployment(true);
}

QString MaemoDebugRunControl::remoteCall() const
{
    return QString::fromLocal8Bit("%1 gdbserver :%2 %3 %4")
        .arg(targetCmdLinePrefix()).arg(gdbServerPort())
        .arg(executableOnTarget()).arg(m_runConfig->arguments().join(" "));
}

void MaemoDebugRunControl::handleRemoteOutput(const QString &output)
{
    qDebug("gdbserver's stderr output: %s", output.toLatin1().data());
    if (m_inferiorPid != -1)
        return;
    const QString searchString("pid = ");
    const int searchStringLength = searchString.length();
    int pidStartPos = output.indexOf(searchString);
    const int pidEndPos = output.indexOf("\n", pidStartPos + searchStringLength);
    if (pidStartPos == -1 || pidEndPos == -1)
        return; // gdbserver has not started yet.
    pidStartPos += searchStringLength;
    QString pidString = output.mid(pidStartPos, pidEndPos - pidStartPos);
    qDebug("pidString = %s", pidString.toLatin1().data());
    bool ok;
    const int pid = pidString.toInt(&ok);
    if (!ok) {
        handleError(tr("Debugging failed: Could not parse gdbserver output."));
        m_debuggerManager->exitDebugger();
    } else {
        m_inferiorPid = pid;
        startDebugging();
    }
}

void MaemoDebugRunControl::startDebugging()
{
    m_debuggerManager->startNewDebugger(m_startParams);
}

void MaemoDebugRunControl::stopInternal()
{
    m_debuggerManager->exitDebugger();
}

bool MaemoDebugRunControl::isRunning() const
{
    return AbstractMaemoRunControl::isRunning()
        || m_debuggerManager->state() != Debugger::DebuggerNotReady;
}

void MaemoDebugRunControl::debuggingFinished()
{
    AbstractMaemoRunControl::stopRunning(true);
}

void MaemoDebugRunControl::debuggerOutput(const QString &output)
{
    emit addToOutputWindowInline(this, output);
}

QString MaemoDebugRunControl::gdbServerPort() const
{
    return m_devConfig.type == MaemoDeviceConfig::Physical
        ? QString::number(m_devConfig.gdbServerPort)
        : m_runConfig->simulatorGdbServerPort();
}

} // namespace Internal
} // namespace Qt4ProjectManager
<commit_msg>Maemo: Change misleading status messages.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "maemoruncontrol.h"
#include "maemosshthread.h"
#include "maemorunconfiguration.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <debugger/debuggermanager.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/toolchain.h>
#include <utils/qtcassert.h>

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QFuture>
#include <QtCore/QProcess>
#include <QtCore/QStringBuilder>

#include <QtGui/QMessageBox>

namespace Qt4ProjectManager {
namespace Internal {

using ProjectExplorer::RunConfiguration;
using ProjectExplorer::ToolChain;

AbstractMaemoRunControl::AbstractMaemoRunControl(RunConfiguration *rc)
    : RunControl(rc)
    , m_runConfig(qobject_cast<MaemoRunConfiguration *>(rc))
    , m_devConfig(m_runConfig ? m_runConfig->deviceConfig() : MaemoDeviceConfig())
{
}

AbstractMaemoRunControl::~AbstractMaemoRunControl()
{
}

void AbstractMaemoRunControl::start()
{
    m_stoppedByUser = false;
    emit started();
    startInitialCleanup();
}

void AbstractMaemoRunControl::startInitialCleanup()
{
    emit addToOutputWindow(this, tr("Cleaning up remote leftovers first ..."));
    const QStringList appsToKill
        = QStringList() << executableFileName() << QLatin1String("gdbserver");
    killRemoteProcesses(appsToKill, true);
}

void AbstractMaemoRunControl::stop()
{
    m_stoppedByUser = true;
    if (isCleaning())
        m_initialCleaner->stop();
    else if (isDeploying())
        m_sshDeployer->stop();
    else
        stopInternal();
}

void AbstractMaemoRunControl::handleInitialCleanupFinished()
{
    if (m_stoppedByUser) {
        emit addToOutputWindow(this, tr("Initial cleanup canceled by user."));
        emit finished();
    } else if (m_initialCleaner->hasError()) {
        handleError(tr("Error running initial cleanup: %1.")
                    .arg(m_initialCleaner->error()));
        emit finished();
    } else {
        emit addToOutputWindow(this, tr("Initial cleanup done."));
        startInternal();
    }
}

void AbstractMaemoRunControl::startDeployment(bool forDebugging)
{
    QTC_ASSERT(m_runConfig, return);

    if (!m_devConfig.isValid()) {
        handleError(tr("No device configuration set for run configuration."));
        emit finished();
    } else if (m_stoppedByUser) {
        emit finished();
    } else {
        m_deployables.clear();
        if (m_runConfig->currentlyNeedsDeployment(m_devConfig.host)) {
            m_deployables.append(Deployable(executableFileName(),
                QFileInfo(executableOnHost()).canonicalPath(),
                &MaemoRunConfiguration::wasDeployed));
        }
        if (forDebugging
            && m_runConfig->debuggingHelpersNeedDeployment(m_devConfig.host)) {
            const QFileInfo &info(m_runConfig->dumperLib());
            m_deployables.append(Deployable(info.fileName(), info.canonicalPath(),
                &MaemoRunConfiguration::debuggingHelpersDeployed));
        }

        deploy();
    }
}

void AbstractMaemoRunControl::deploy()
{
    Core::ICore::instance()->progressManager()
        ->addTask(m_progress.future(), tr("Deploying"),
                  QLatin1String("Maemo.Deploy"));
    if (!m_deployables.isEmpty()) {
        QList<SshDeploySpec> deploySpecs;
        QStringList files;
        foreach (const Deployable &deployable, m_deployables) {
            const QString srcFilePath
                = deployable.dir % QDir::separator() % deployable.fileName;
            const QString tgtFilePath
                = remoteDir() % QDir::separator() % deployable.fileName;
            files << srcFilePath;
            deploySpecs << SshDeploySpec(srcFilePath, tgtFilePath);
        }
        emit addToOutputWindow(this, tr("Files to deploy: %1.").arg(files.join(" ")));
        m_sshDeployer.reset(new MaemoSshDeployer(m_devConfig, deploySpecs));
        connect(m_sshDeployer.data(), SIGNAL(finished()),
                this, SLOT(handleDeployThreadFinished()));
        connect(m_sshDeployer.data(), SIGNAL(fileCopied(QString)),
                this, SLOT(handleFileCopied()));
        m_progress.setProgressRange(0, m_deployables.count());
        m_progress.setProgressValue(0);
        m_progress.reportStarted();
        m_sshDeployer->start();
    } else {
        m_progress.reportFinished();
        startExecution();
    }
}

void AbstractMaemoRunControl::handleFileCopied()
{
    Deployable deployable = m_deployables.takeFirst();
    (m_runConfig->*deployable.updateTimestamp)(m_devConfig.host);
    m_progress.setProgressValue(m_progress.progressValue() + 1);
}

bool AbstractMaemoRunControl::isDeploying() const
{
    return m_sshDeployer && m_sshDeployer->isRunning();
}

bool AbstractMaemoRunControl::isCleaning() const
{
    return m_initialCleaner && m_initialCleaner->isRunning();
}

void AbstractMaemoRunControl::startExecution()
{
    m_sshRunner.reset(new MaemoSshRunner(m_devConfig, remoteCall()));
    connect(m_sshRunner.data(), SIGNAL(finished()),
            this, SLOT(handleRunThreadFinished()));
    connect(m_sshRunner.data(), SIGNAL(remoteOutput(QString)),
            this, SLOT(handleRemoteOutput(QString)));
    emit addToOutputWindow(this, tr("Starting remote application."));
    m_sshRunner->start();
}

bool AbstractMaemoRunControl::isRunning() const
{
    return isDeploying() || (m_sshRunner && m_sshRunner->isRunning());
}

void AbstractMaemoRunControl::stopRunning(bool forDebugging)
{
    if (m_sshRunner && m_sshRunner->isRunning()) {
        m_sshRunner->stop();
        QStringList apps(executableFileName());
        if (forDebugging)
            apps << QLatin1String("gdbserver");
        killRemoteProcesses(apps, false);
    }
}

void AbstractMaemoRunControl::killRemoteProcesses(const QStringList &apps,
                                                  bool initialCleanup)
{
    QString niceKill;
    QString brutalKill;
    foreach (const QString &app, apps) {
        niceKill += QString::fromLocal8Bit("pkill -x %1;").arg(app);
        brutalKill += QString::fromLocal8Bit("pkill -x -9 %1;").arg(app);
    }
    const QString remoteCall
        = niceKill + QLatin1String("sleep 1; ") + brutalKill;
    QScopedPointer<MaemoSshRunner> &runner
        = initialCleanup ? m_initialCleaner : m_sshStopper;
    runner.reset(new MaemoSshRunner(m_devConfig, remoteCall));
    if (initialCleanup)
        connect(runner.data(), SIGNAL(finished()),
                this, SLOT(handleInitialCleanupFinished()));
    runner->start();
}

void AbstractMaemoRunControl::handleDeployThreadFinished()
{
    bool cancel;
    if (m_stoppedByUser) {
        emit addToOutputWindow(this, tr("Deployment canceled by user."));
        cancel = true;
    } else if (m_sshDeployer->hasError()) {
        handleError(tr("Deployment failed: %1").arg(m_sshDeployer->error()));
        cancel = true;
    } else {
        emit addToOutputWindow(this, tr("Deployment finished."));
        cancel = false;
    }

    if (cancel) {
        m_progress.reportCanceled();
        m_progress.reportFinished();
        emit finished();
    } else {
        m_progress.reportFinished();
        startExecution();
    }
}

void AbstractMaemoRunControl::handleRunThreadFinished()
{
    if (m_stoppedByUser) {
        emit addToOutputWindow(this,
                 tr("Remote execution canceled due to user request."));
    } else if (m_sshRunner->hasError()) {
        emit addToOutputWindow(this, tr("Error running remote process: %1")
                                         .arg(m_sshRunner->error()));
    } else {
        emit addToOutputWindow(this, tr("Finished running remote process."));
    }
    emit finished();
}

const QString AbstractMaemoRunControl::executableOnHost() const
{
    qDebug("runconfig->executable: %s", qPrintable(m_runConfig->executable()));
    return m_runConfig->executable();
}

const QString AbstractMaemoRunControl::sshPort() const
{
    return m_devConfig.type == MaemoDeviceConfig::Physical
        ? QString::number(m_devConfig.sshPort)
        : m_runConfig->simulatorSshPort();
}

const QString AbstractMaemoRunControl::executableFileName() const
{
    return QFileInfo(executableOnHost()).fileName();
}

const QString AbstractMaemoRunControl::remoteDir() const
{
    return homeDirOnDevice(m_devConfig.uname);
}

const QStringList AbstractMaemoRunControl::options() const
{
    const bool usePassword
        = m_devConfig.authentication == MaemoDeviceConfig::Password;
    const QLatin1String opt("-o");
    QStringList optionList;
    if (!usePassword)
        optionList << QLatin1String("-i") << m_devConfig.keyFile;
    return optionList << opt
        << QString::fromLatin1("PasswordAuthentication=%1").
            arg(usePassword ? "yes" : "no") << opt
        << QString::fromLatin1("PubkeyAuthentication=%1").
            arg(usePassword ? "no" : "yes") << opt
        << QString::fromLatin1("ConnectTimeout=%1").arg(m_devConfig.timeout)
        << opt << QLatin1String("CheckHostIP=no")
        << opt << QLatin1String("StrictHostKeyChecking=no");
}

const QString AbstractMaemoRunControl::executableOnTarget() const
{
    return QString::fromLocal8Bit("%1/%2").arg(remoteDir()).
        arg(executableFileName());
}

const QString AbstractMaemoRunControl::targetCmdLinePrefix() const
{
    return QString::fromLocal8Bit("chmod u+x %1; source /etc/profile; ").
        arg(executableOnTarget());
}

void AbstractMaemoRunControl::handleError(const QString &errString)
{
    QMessageBox::critical(0, tr("Remote Execution Failure"), errString);
    emit error(this, errString);
}

MaemoRunControl::MaemoRunControl(RunConfiguration *runConfiguration)
    : AbstractMaemoRunControl(runConfiguration)
{
}

MaemoRunControl::~MaemoRunControl()
{
    stop();
}

void MaemoRunControl::startInternal()
{
    startDeployment(false);
}

QString MaemoRunControl::remoteCall() const
{
    return QString::fromLocal8Bit("%1 %2 %3")
        .arg(targetCmdLinePrefix()).arg(executableOnTarget())
        .arg(m_runConfig->arguments().join(" "));
}

void MaemoRunControl::stopInternal()
{
    AbstractMaemoRunControl::stopRunning(false);
}

void MaemoRunControl::handleRemoteOutput(const QString &output)
{
    emit addToOutputWindowInline(this, output);
}

MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration)
    : AbstractMaemoRunControl(runConfiguration)
    , m_debuggerManager(ExtensionSystem::PluginManager::instance()
                      ->getObject<Debugger::DebuggerManager>())
    , m_startParams(new Debugger::DebuggerStartParameters)
{
    QTC_ASSERT(m_debuggerManager != 0, return);
    m_startParams->startMode = Debugger::StartRemote;
    m_startParams->executable = executableOnHost();
    m_startParams->remoteChannel
        = m_devConfig.host % QLatin1Char(':') % gdbServerPort();
    m_startParams->remoteArchitecture = QLatin1String("arm");
    m_startParams->sysRoot = m_runConfig->sysRoot();
    m_startParams->toolChainType = ToolChain::GCC_MAEMO;
    m_startParams->debuggerCommand = m_runConfig->gdbCmd();
    m_startParams->dumperLibrary = m_runConfig->dumperLib();
    m_startParams->remoteDumperLib = QString::fromLocal8Bit("%1/%2")
        .arg(remoteDir()).arg(QFileInfo(m_runConfig->dumperLib()).fileName());

    connect(m_debuggerManager, SIGNAL(debuggingFinished()), this,
        SLOT(debuggingFinished()), Qt::QueuedConnection);
    connect(m_debuggerManager, SIGNAL(applicationOutputAvailable(QString)),
        this, SLOT(debuggerOutput(QString)), Qt::QueuedConnection);
}

MaemoDebugRunControl::~MaemoDebugRunControl()
{
    disconnect(SIGNAL(addToOutputWindow(RunControl*,QString)));
    disconnect(SIGNAL(addToOutputWindowInline(RunControl*,QString)));
    stop();
    debuggingFinished();
}

void MaemoDebugRunControl::startInternal()
{
    m_inferiorPid = -1;
    startDeployment(true);
}

QString MaemoDebugRunControl::remoteCall() const
{
    return QString::fromLocal8Bit("%1 gdbserver :%2 %3 %4")
        .arg(targetCmdLinePrefix()).arg(gdbServerPort())
        .arg(executableOnTarget()).arg(m_runConfig->arguments().join(" "));
}

void MaemoDebugRunControl::handleRemoteOutput(const QString &output)
{
    qDebug("gdbserver's stderr output: %s", output.toLatin1().data());
    if (m_inferiorPid != -1)
        return;
    const QString searchString("pid = ");
    const int searchStringLength = searchString.length();
    int pidStartPos = output.indexOf(searchString);
    const int pidEndPos = output.indexOf("\n", pidStartPos + searchStringLength);
    if (pidStartPos == -1 || pidEndPos == -1)
        return; // gdbserver has not started yet.
    pidStartPos += searchStringLength;
    QString pidString = output.mid(pidStartPos, pidEndPos - pidStartPos);
    qDebug("pidString = %s", pidString.toLatin1().data());
    bool ok;
    const int pid = pidString.toInt(&ok);
    if (!ok) {
        handleError(tr("Debugging failed: Could not parse gdbserver output."));
        m_debuggerManager->exitDebugger();
    } else {
        m_inferiorPid = pid;
        startDebugging();
    }
}

void MaemoDebugRunControl::startDebugging()
{
    m_debuggerManager->startNewDebugger(m_startParams);
}

void MaemoDebugRunControl::stopInternal()
{
    m_debuggerManager->exitDebugger();
}

bool MaemoDebugRunControl::isRunning() const
{
    return AbstractMaemoRunControl::isRunning()
        || m_debuggerManager->state() != Debugger::DebuggerNotReady;
}

void MaemoDebugRunControl::debuggingFinished()
{
    AbstractMaemoRunControl::stopRunning(true);
}

void MaemoDebugRunControl::debuggerOutput(const QString &output)
{
    emit addToOutputWindowInline(this, output);
}

QString MaemoDebugRunControl::gdbServerPort() const
{
    return m_devConfig.type == MaemoDeviceConfig::Physical
        ? QString::number(m_devConfig.gdbServerPort)
        : m_runConfig->simulatorGdbServerPort();
}

} // namespace Internal
} // namespace Qt4ProjectManager
<|endoftext|>


<commit_before>#include "VTCriticalSection.h"
#include <pthread.h>

struct VT::CriticalSection::critical_section_data
{
    pthread_mutex_t _criticalSection;
};

VT::CriticalSection::CriticalSection() : data( new critical_section_data() )
{
    pthread_mutex_init( &data->_criticalSection, NULL );
}

VT::CriticalSection::~CriticalSection()
{
    pthread_mutex_destroy( &data->_criticalSection );
    delete data;
}

void VT::CriticalSection::enter()
{
    pthread_mutex_lock( &data->_criticalSection );
}

bool VT::CriticalSection::try_enter()
{
    //static_assert(0, "Not implemented");
}

void VT::CriticalSection::leave()
{
    pthread_mutex_unlock( &data->_criticalSection );
}
<commit_msg>Linux mutex try lock<commit_after>#include "VTCriticalSection.h"
#include <pthread.h>

struct VT::CriticalSection::critical_section_data
{
    pthread_mutex_t _criticalSection;
};

VT::CriticalSection::CriticalSection() : data( new critical_section_data() )
{
    pthread_mutex_init( &data->_criticalSection, NULL );
}

VT::CriticalSection::~CriticalSection()
{
    pthread_mutex_destroy( &data->_criticalSection );
    delete data;
}

void VT::CriticalSection::enter()
{
    pthread_mutex_lock( &data->_criticalSection );
}

bool VT::CriticalSection::try_enter()
{
    return pthread_mutex_trylock( &data->_criticalSection ) == 0;
}

void VT::CriticalSection::leave()
{
    pthread_mutex_unlock( &data->_criticalSection );
}
<|endoftext|>