<commit_before>//===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints an PPC MCInst to a .s file.
//
//===----------------------------------------------------------------------===//

#include "PPCInstPrinter.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOpcodes.h"
using namespace llvm;

#define DEBUG_TYPE "asm-printer"

// FIXME: Once the integrated assembler supports full register names, tie this
// to the verbose-asm setting.
static cl::opt<bool>
FullRegNames("ppc-asm-full-reg-names", cl::Hidden, cl::init(false),
             cl::desc("Use full register names when printing assembly"));

#include "PPCGenAsmWriter.inc"

void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
  OS << getRegisterName(RegNo);
}

void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
                               StringRef Annot) {
  // Check for slwi/srwi mnemonics.
  if (MI->getOpcode() == PPC::RLWINM) {
    unsigned char SH = MI->getOperand(2).getImm();
    unsigned char MB = MI->getOperand(3).getImm();
    unsigned char ME = MI->getOperand(4).getImm();
    bool useSubstituteMnemonic = false;
    if (SH <= 31 && MB == 0 && ME == (31-SH)) {
      O << "\tslwi "; useSubstituteMnemonic = true;
    }
    if (SH <= 31 && MB == (32-SH) && ME == 31) {
      O << "\tsrwi "; useSubstituteMnemonic = true;
      SH = 32-SH;
    }
    if (useSubstituteMnemonic) {
      printOperand(MI, 0, O);
      O << ", ";
      printOperand(MI, 1, O);
      O << ", " << (unsigned int)SH;

      printAnnotation(O, Annot);
      return;
    }
  }

  if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) &&
      MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
    O << "\tmr ";
    printOperand(MI, 0, O);
    O << ", ";
    printOperand(MI, 1, O);
    printAnnotation(O, Annot);
    return;
  }

  if (MI->getOpcode() == PPC::RLDICR) {
    unsigned char SH = MI->getOperand(2).getImm();
    unsigned char ME = MI->getOperand(3).getImm();
    // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
    if (63-SH == ME) {
      O << "\tsldi ";
      printOperand(MI, 0, O);
      O << ", ";
      printOperand(MI, 1, O);
      O << ", " << (unsigned int)SH;
      printAnnotation(O, Annot);
      return;
    }
  }

  // For fast-isel, a COPY_TO_REGCLASS may survive this long.  This is
  // used when converting a 32-bit float to a 64-bit float as part of
  // conversion to an integer (see PPCFastISel.cpp:SelectFPToI()),
  // as otherwise we have problems with incorrect register classes
  // in machine instruction verification.  For now, just avoid trying
  // to print it as such an instruction has no effect (a 32-bit float
  // in a register is already in 64-bit form, just with lower
  // precision).  FIXME: Is there a better solution?
  if (MI->getOpcode() == TargetOpcode::COPY_TO_REGCLASS)
    return;

  printInstruction(MI, O);
  printAnnotation(O, Annot);
}

void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
                                           raw_ostream &O,
                                           const char *Modifier) {
  unsigned Code = MI->getOperand(OpNo).getImm();

  if (StringRef(Modifier) == "cc") {
    switch ((PPC::Predicate)Code) {
    case PPC::PRED_LT_MINUS:
    case PPC::PRED_LT_PLUS:
    case PPC::PRED_LT:
      O << "lt";
      return;
    case PPC::PRED_LE_MINUS:
    case PPC::PRED_LE_PLUS:
    case PPC::PRED_LE:
      O << "le";
      return;
    case PPC::PRED_EQ_MINUS:
    case PPC::PRED_EQ_PLUS:
    case PPC::PRED_EQ:
      O << "eq";
      return;
    case PPC::PRED_GE_MINUS:
    case PPC::PRED_GE_PLUS:
    case PPC::PRED_GE:
      O << "ge";
      return;
    case PPC::PRED_GT_MINUS:
    case PPC::PRED_GT_PLUS:
    case PPC::PRED_GT:
      O << "gt";
      return;
    case PPC::PRED_NE_MINUS:
    case PPC::PRED_NE_PLUS:
    case PPC::PRED_NE:
      O << "ne";
      return;
    case PPC::PRED_UN_MINUS:
    case PPC::PRED_UN_PLUS:
    case PPC::PRED_UN:
      O << "un";
      return;
    case PPC::PRED_NU_MINUS:
    case PPC::PRED_NU_PLUS:
    case PPC::PRED_NU:
      O << "nu";
      return;
    case PPC::PRED_BIT_SET:
    case PPC::PRED_BIT_UNSET:
      llvm_unreachable("Invalid use of bit predicate code");
    }
    llvm_unreachable("Invalid predicate code");
  }

  if (StringRef(Modifier) == "pm") {
    switch ((PPC::Predicate)Code) {
    case PPC::PRED_LT:
    case PPC::PRED_LE:
    case PPC::PRED_EQ:
    case PPC::PRED_GE:
    case PPC::PRED_GT:
    case PPC::PRED_NE:
    case PPC::PRED_UN:
    case PPC::PRED_NU:
      return;
    case PPC::PRED_LT_MINUS:
    case PPC::PRED_LE_MINUS:
    case PPC::PRED_EQ_MINUS:
    case PPC::PRED_GE_MINUS:
    case PPC::PRED_GT_MINUS:
    case PPC::PRED_NE_MINUS:
    case PPC::PRED_UN_MINUS:
    case PPC::PRED_NU_MINUS:
      O << "-";
      return;
    case PPC::PRED_LT_PLUS:
    case PPC::PRED_LE_PLUS:
    case PPC::PRED_EQ_PLUS:
    case PPC::PRED_GE_PLUS:
    case PPC::PRED_GT_PLUS:
    case PPC::PRED_NE_PLUS:
    case PPC::PRED_UN_PLUS:
    case PPC::PRED_NU_PLUS:
      O << "+";
      return;
    case PPC::PRED_BIT_SET:
    case PPC::PRED_BIT_UNSET:
      llvm_unreachable("Invalid use of bit predicate code");
    }
    llvm_unreachable("Invalid predicate code");
  }

  assert(StringRef(Modifier) == "reg" &&
         "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
  printOperand(MI, OpNo+1, O);
}

void PPCInstPrinter::printU2ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  unsigned int Value = MI->getOperand(OpNo).getImm();
  assert(Value <= 3 && "Invalid u2imm argument!");
  O << (unsigned int)Value;
}

void PPCInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  unsigned int Value = MI->getOperand(OpNo).getImm();
  assert(Value <= 15 && "Invalid u4imm argument!");
  O << (unsigned int)Value;
}

void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  int Value = MI->getOperand(OpNo).getImm();
  Value = SignExtend32<5>(Value);
  O << (int)Value;
}

void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  unsigned int Value = MI->getOperand(OpNo).getImm();
  assert(Value <= 31 && "Invalid u5imm argument!");
  O << (unsigned int)Value;
}

void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  unsigned int Value = MI->getOperand(OpNo).getImm();
  assert(Value <= 63 && "Invalid u6imm argument!");
  O << (unsigned int)Value;
}

void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
                                        raw_ostream &O) {
  if (MI->getOperand(OpNo).isImm())
    O << (short)MI->getOperand(OpNo).getImm();
  else
    printOperand(MI, OpNo, O);
}

void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
                                        raw_ostream &O) {
  if (MI->getOperand(OpNo).isImm())
    O << (unsigned short)MI->getOperand(OpNo).getImm();
  else
    printOperand(MI, OpNo, O);
}

void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
                                        raw_ostream &O) {
  if (!MI->getOperand(OpNo).isImm())
    return printOperand(MI, OpNo, O);

  // Branches can take an immediate operand.  This is used by the branch
  // selection pass to print .+8, an eight byte displacement from the PC.
  O << ".+";
  printAbsBranchOperand(MI, OpNo, O);
}

void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo,
                                           raw_ostream &O) {
  if (!MI->getOperand(OpNo).isImm())
    return printOperand(MI, OpNo, O);

  O << (int)MI->getOperand(OpNo).getImm()*4;
}

void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
                                 raw_ostream &O) {
  unsigned CCReg = MI->getOperand(OpNo).getReg();
  unsigned RegNo;
  switch (CCReg) {
  default: llvm_unreachable("Unknown CR register");
  case PPC::CR0: RegNo = 0; break;
  case PPC::CR1: RegNo = 1; break;
  case PPC::CR2: RegNo = 2; break;
  case PPC::CR3: RegNo = 3; break;
  case PPC::CR4: RegNo = 4; break;
  case PPC::CR5: RegNo = 5; break;
  case PPC::CR6: RegNo = 6; break;
  case PPC::CR7: RegNo = 7; break;
  }
  O << (0x80 >> RegNo);
}

void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
                                    raw_ostream &O) {
  printS16ImmOperand(MI, OpNo, O);
  O << '(';
  if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
    O << "0";
  else
    printOperand(MI, OpNo+1, O);
  O << ')';
}

void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
                                    raw_ostream &O) {
  // When used as the base register, r0 reads constant zero rather than
  // the value contained in the register.  For this reason, the darwin
  // assembler requires that we print r0 as 0 (no r) when used as the base.
  if (MI->getOperand(OpNo).getReg() == PPC::R0)
    O << "0";
  else
    printOperand(MI, OpNo, O);
  O << ", ";
  printOperand(MI, OpNo+1, O);
}

void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
                                  raw_ostream &O) {
  // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must
  // come at the _end_ of the expression.
  const MCOperand &Op = MI->getOperand(OpNo);
  const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*Op.getExpr());
  O << refExp.getSymbol().getName();
  O << '(';
  printOperand(MI, OpNo+1, O);
  O << ')';
  if (refExp.getKind() != MCSymbolRefExpr::VK_None)
    O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind());
}

/// stripRegisterPrefix - This method strips the character prefix from a
/// register name so that only the number is left.  Used by for linux asm.
static const char *stripRegisterPrefix(const char *RegName) {
  if (FullRegNames)
    return RegName;

  switch (RegName[0]) {
  case 'r':
  case 'f':
  case 'v':
    if (RegName[1] == 's')
      return RegName + 2;
    return RegName + 1;
  case 'c': if (RegName[1] == 'r') return RegName + 2;
  }

  return RegName;
}

void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
                                  raw_ostream &O) {
  const MCOperand &Op = MI->getOperand(OpNo);
  if (Op.isReg()) {
    const char *RegName = getRegisterName(Op.getReg());
    // The linux and AIX assembler does not take register prefixes.
    if (!isDarwinSyntax())
      RegName = stripRegisterPrefix(RegName);

    O << RegName;
    return;
  }

  if (Op.isImm()) {
    O << Op.getImm();
    return;
  }

  assert(Op.isExpr() && "unknown operand kind in printOperand");
  O << *Op.getExpr();
}

<commit_msg>Fix signed integer overflow in PPCInstPrinter.<commit_after>//===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class prints an PPC MCInst to a .s file.
//
//===----------------------------------------------------------------------===//

#include "PPCInstPrinter.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCPredicates.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOpcodes.h"
using namespace llvm;

#define DEBUG_TYPE "asm-printer"

// FIXME: Once the integrated assembler supports full register names, tie this
// to the verbose-asm setting.
static cl::opt<bool>
FullRegNames("ppc-asm-full-reg-names", cl::Hidden, cl::init(false),
             cl::desc("Use full register names when printing assembly"));

#include "PPCGenAsmWriter.inc"

void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
  OS << getRegisterName(RegNo);
}

void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
                               StringRef Annot) {
  // Check for slwi/srwi mnemonics.
  if (MI->getOpcode() == PPC::RLWINM) {
    unsigned char SH = MI->getOperand(2).getImm();
    unsigned char MB = MI->getOperand(3).getImm();
    unsigned char ME = MI->getOperand(4).getImm();
    bool useSubstituteMnemonic = false;
    if (SH <= 31 && MB == 0 && ME == (31-SH)) {
      O << "\tslwi "; useSubstituteMnemonic = true;
    }
    if (SH <= 31 && MB == (32-SH) && ME == 31) {
      O << "\tsrwi "; useSubstituteMnemonic = true;
      SH = 32-SH;
    }
    if (useSubstituteMnemonic) {
      printOperand(MI, 0, O);
      O << ", ";
      printOperand(MI, 1, O);
      O << ", " << (unsigned int)SH;

      printAnnotation(O, Annot);
      return;
    }
  }

  if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) &&
      MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
    O << "\tmr ";
    printOperand(MI, 0, O);
    O << ", ";
    printOperand(MI, 1, O);
    printAnnotation(O, Annot);
    return;
  }

  if (MI->getOpcode() == PPC::RLDICR) {
    unsigned char SH = MI->getOperand(2).getImm();
    unsigned char ME = MI->getOperand(3).getImm();
    // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
    if (63-SH == ME) {
      O << "\tsldi ";
      printOperand(MI, 0, O);
      O << ", ";
      printOperand(MI, 1, O);
      O << ", " << (unsigned int)SH;
      printAnnotation(O, Annot);
      return;
    }
  }

  // For fast-isel, a COPY_TO_REGCLASS may survive this long.  This is
  // used when converting a 32-bit float to a 64-bit float as part of
  // conversion to an integer (see PPCFastISel.cpp:SelectFPToI()),
  // as otherwise we have problems with incorrect register classes
  // in machine instruction verification.  For now, just avoid trying
  // to print it as such an instruction has no effect (a 32-bit float
  // in a register is already in 64-bit form, just with lower
  // precision).  FIXME: Is there a better solution?
  if (MI->getOpcode() == TargetOpcode::COPY_TO_REGCLASS)
    return;

  printInstruction(MI, O);
  printAnnotation(O, Annot);
}

void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
                                           raw_ostream &O,
                                           const char *Modifier) {
  unsigned Code = MI->getOperand(OpNo).getImm();

  if (StringRef(Modifier) == "cc") {
    switch ((PPC::Predicate)Code) {
    case PPC::PRED_LT_MINUS:
    case PPC::PRED_LT_PLUS:
    case PPC::PRED_LT:
      O << "lt";
      return;
    case PPC::PRED_LE_MINUS:
    case PPC::PRED_LE_PLUS:
    case PPC::PRED_LE:
      O << "le";
      return;
    case PPC::PRED_EQ_MINUS:
    case PPC::PRED_EQ_PLUS:
    case PPC::PRED_EQ:
      O << "eq";
      return;
    case PPC::PRED_GE_MINUS:
    case PPC::PRED_GE_PLUS:
    case PPC::PRED_GE:
      O << "ge";
      return;
    case PPC::PRED_GT_MINUS:
    case PPC::PRED_GT_PLUS:
    case PPC::PRED_GT:
      O << "gt";
      return;
    case PPC::PRED_NE_MINUS:
    case PPC::PRED_NE_PLUS:
    case PPC::PRED_NE:
      O << "ne";
      return;
    case PPC::PRED_UN_MINUS:
    case PPC::PRED_UN_PLUS:
    case PPC::PRED_UN:
      O << "un";
      return;
    case PPC::PRED_NU_MINUS:
    case PPC::PRED_NU_PLUS:
    case PPC::PRED_NU:
      O << "nu";
      return;
    case PPC::PRED_BIT_SET:
    case PPC::PRED_BIT_UNSET:
      llvm_unreachable("Invalid use of bit predicate code");
    }
    llvm_unreachable("Invalid predicate code");
  }

  if (StringRef(Modifier) == "pm") {
    switch ((PPC::Predicate)Code) {
    case PPC::PRED_LT:
    case PPC::PRED_LE:
    case PPC::PRED_EQ:
    case PPC::PRED_GE:
    case PPC::PRED_GT:
    case PPC::PRED_NE:
    case PPC::PRED_UN:
    case PPC::PRED_NU:
      return;
    case PPC::PRED_LT_MINUS:
    case PPC::PRED_LE_MINUS:
    case PPC::PRED_EQ_MINUS:
    case PPC::PRED_GE_MINUS:
    case PPC::PRED_GT_MINUS:
    case PPC::PRED_NE_MINUS:
    case PPC::PRED_UN_MINUS:
    case PPC::PRED_NU_MINUS:
      O << "-";
      return;
    case PPC::PRED_LT_PLUS:
    case PPC::PRED_LE_PLUS:
    case PPC::PRED_EQ_PLUS:
    case PPC::PRED_GE_PLUS:
    case PPC::PRED_GT_PLUS:
    case PPC::PRED_NE_PLUS:
    case PPC::PRED_UN_PLUS:
    case PPC::PRED_NU_PLUS:
      O << "+";
      return;
    case PPC::PRED_BIT_SET:
    case PPC::PRED_BIT_UNSET:
      llvm_unreachable("Invalid use of bit predicate code");
    }
    llvm_unreachable("Invalid predicate code");
  }

  assert(StringRef(Modifier) == "reg" &&
         "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
  printOperand(MI, OpNo+1, O);
}

void PPCInstPrinter::printU2ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  unsigned int Value = MI->getOperand(OpNo).getImm();
  assert(Value <= 3 && "Invalid u2imm argument!");
  O << (unsigned int)Value;
}

void PPCInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  unsigned int Value = MI->getOperand(OpNo).getImm();
  assert(Value <= 15 && "Invalid u4imm argument!");
  O << (unsigned int)Value;
}

void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  int Value = MI->getOperand(OpNo).getImm();
  Value = SignExtend32<5>(Value);
  O << (int)Value;
}

void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  unsigned int Value = MI->getOperand(OpNo).getImm();
  assert(Value <= 31 && "Invalid u5imm argument!");
  O << (unsigned int)Value;
}

void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
                                       raw_ostream &O) {
  unsigned int Value = MI->getOperand(OpNo).getImm();
  assert(Value <= 63 && "Invalid u6imm argument!");
  O << (unsigned int)Value;
}

void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
                                        raw_ostream &O) {
  if (MI->getOperand(OpNo).isImm())
    O << (short)MI->getOperand(OpNo).getImm();
  else
    printOperand(MI, OpNo, O);
}

void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
                                        raw_ostream &O) {
  if (MI->getOperand(OpNo).isImm())
    O << (unsigned short)MI->getOperand(OpNo).getImm();
  else
    printOperand(MI, OpNo, O);
}

void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
                                        raw_ostream &O) {
  if (!MI->getOperand(OpNo).isImm())
    return printOperand(MI, OpNo, O);

  // Branches can take an immediate operand.  This is used by the branch
  // selection pass to print .+8, an eight byte displacement from the PC.
  O << ".+";
  printAbsBranchOperand(MI, OpNo, O);
}

void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo,
                                           raw_ostream &O) {
  if (!MI->getOperand(OpNo).isImm())
    return printOperand(MI, OpNo, O);

  O << SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2);
}

void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
                                 raw_ostream &O) {
  unsigned CCReg = MI->getOperand(OpNo).getReg();
  unsigned RegNo;
  switch (CCReg) {
  default: llvm_unreachable("Unknown CR register");
  case PPC::CR0: RegNo = 0; break;
  case PPC::CR1: RegNo = 1; break;
  case PPC::CR2: RegNo = 2; break;
  case PPC::CR3: RegNo = 3; break;
  case PPC::CR4: RegNo = 4; break;
  case PPC::CR5: RegNo = 5; break;
  case PPC::CR6: RegNo = 6; break;
  case PPC::CR7: RegNo = 7; break;
  }
  O << (0x80 >> RegNo);
}

void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
                                    raw_ostream &O) {
  printS16ImmOperand(MI, OpNo, O);
  O << '(';
  if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
    O << "0";
  else
    printOperand(MI, OpNo+1, O);
  O << ')';
}

void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
                                    raw_ostream &O) {
  // When used as the base register, r0 reads constant zero rather than
  // the value contained in the register.  For this reason, the darwin
  // assembler requires that we print r0 as 0 (no r) when used as the base.
  if (MI->getOperand(OpNo).getReg() == PPC::R0)
    O << "0";
  else
    printOperand(MI, OpNo, O);
  O << ", ";
  printOperand(MI, OpNo+1, O);
}

void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
                                  raw_ostream &O) {
  // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must
  // come at the _end_ of the expression.
  const MCOperand &Op = MI->getOperand(OpNo);
  const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*Op.getExpr());
  O << refExp.getSymbol().getName();
  O << '(';
  printOperand(MI, OpNo+1, O);
  O << ')';
  if (refExp.getKind() != MCSymbolRefExpr::VK_None)
    O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind());
}

/// stripRegisterPrefix - This method strips the character prefix from a
/// register name so that only the number is left.  Used by for linux asm.
static const char *stripRegisterPrefix(const char *RegName) {
  if (FullRegNames)
    return RegName;

  switch (RegName[0]) {
  case 'r':
  case 'f':
  case 'v':
    if (RegName[1] == 's')
      return RegName + 2;
    return RegName + 1;
  case 'c': if (RegName[1] == 'r') return RegName + 2;
  }

  return RegName;
}

void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
                                  raw_ostream &O) {
  const MCOperand &Op = MI->getOperand(OpNo);
  if (Op.isReg()) {
    const char *RegName = getRegisterName(Op.getReg());
    // The linux and AIX assembler does not take register prefixes.
    if (!isDarwinSyntax())
      RegName = stripRegisterPrefix(RegName);

    O << RegName;
    return;
  }

  if (Op.isImm()) {
    O << Op.getImm();
    return;
  }

  assert(Op.isExpr() && "unknown operand kind in printOperand");
  O << *Op.getExpr();
}

<|endoftext|>


<commit_before>#include "alfe/main.h"

class Program : public ProgramBase
{
public:
    void run()
    {
        Array<Byte> observed(0x1000000);
        String dir("M:\\Program Files (x86)\\Apache Software Foundation\\"
            "Apache24\\htdocs\\");
        for (int i = 0; i < 0x100; ++i) {
            File(dir + "VXBaff12_jb2NCDE" + decimal(i) + ".dat", true).
                openRead().read(&observed[i << 16], 0x10000);
        }
        observed[98 + (204 << 8)] = 194;
        observed[(1261 & 0xff) + ((667 - 512) << 8) + (((1261 + 8192) & 0xff00) << 8)] = 196;
        observed[(1263 & 0xff) + ((667 - 512) << 8) + (((1263 + 8192) & 0xff00) << 8)] = 199;
        observed[(1276 & 0xff) + ((667 - 512) << 8) + (((1276 + 8192) & 0xff00) << 8)] = 199;
        observed[(1630 & 0xff) + ((409 - 256) << 8) + (((1630 + 4096) & 0xff00) << 8)] = 199;

        //for (int i = 0; i < 0x100; ++i) {
        //    if (i < 193) {
        //        File(dir + "86-7-WTkKuASmtlj" + decimal(i) + ".dat", true).
        //            openRead().read(&observed[i << 16], 0x10000);
        //    }
        //    else {
        //        File(dir + "5egBqeiqajT-IYHl" + decimal(i - 193) + ".dat",
        //            true).openRead().read(&observed[i << 16], 0x10000);
        //    }
        //}

        Array<Byte> expected(0x1000000);
        for (int dividend = 0; dividend < 0x10000; ++dividend) {
            for (int divisor = 0; divisor < 0x100; ++divisor) {
                int t = 239;
                int remainder = dividend;
                int quotient = 0;
                int qbit = 0x80;
                int x = divisor << 8;
                if (remainder < x) {
                    t = 194;
                    for (int b = 0; b < 8; ++b) {
                        x >>= 1;
                        if (remainder >= x) {
                            remainder -= x;
                            ++t;
                            if (b == 7)
                                t += 2;
                            quotient |= qbit;
                        }
                        qbit >>= 1;
                    }
                }
                int o = ((dividend & 0xff00) << 8) + (divisor << 8) + (dividend & 0xff);
                expected[o] = t;
                observed[o] -= t;
            }
        }
        //for (int dividend1 = 0; dividend1 < 0x10000; ++dividend1) {
        //    for (int divisor1 = 0; divisor1 < 0x100; ++divisor1) {
        //        int dividend = dividend1;
        //        int divisor = divisor1;

        //        int t = 214;
        //        bool negative = false;
        //        bool dividendNegative = false;
        //        if ((dividend & 0x8000) != 0) {
        //            dividend = (~dividend + 1) & 0xffff;
        //            negative = true;
        //            dividendNegative = true;
        //            t += 4;
        //        }
        //        if ((divisor & 0x80) != 0) {
        //            divisor = (~divisor + 1) & 0xff;
        //            negative = !negative;
        //        }
        //        else
        //            t += 1;
        //        int remainder = dividend;
        //        int quotient = 0;
        //        int qbit = 0x80;
        //        int x = divisor << 8;
        //        if (remainder < x) {
        //            for (int b = 0; b < 8; ++b) {
        //                x >>= 1;
        //                if (remainder >= x) {
        //                    remainder -= x;
        //                    ++t;
        //                    if (b == 7)
        //                        t += 2;
        //                    quotient |= qbit;
        //                }
        //                qbit >>= 1;
        //            }
        //            if (/*remainder >= x*/ (quotient & 0x80) != 0)
        //                t += 105;
        //            else {
        //                if (negative)
        //                    quotient = ~quotient + 1;
        //                if (dividendNegative)
        //                    remainder = ~remainder + 1;
        //            }
        //        }
        //        else
        //            t += 34;

        //        int o = ((dividend1 & 0xff00) << 8) + (divisor1 << 8) + (dividend1 & 0xff);
        //        expected[o] = t;
        //    }
        //}

        Array<Byte> rearranged(0x1000000);
        for (int quotient = 0; quotient < 0x100; ++quotient) {
            for (int divisor = 0; divisor < 0x100; ++divisor) {
                for (int remainder = 0; remainder < 0x100; ++remainder) {
                    int dividend = quotient*divisor + remainder;
                    int o = ((dividend & 0xff00) << 8) + (divisor << 8) + (dividend & 0xff);
                    int p = ((quotient & 0xf) << 8) + remainder + ((((quotient & 0xf0) << 4) + divisor) << 12);
                    if (dividend < 0x10000 && remainder < divisor)
                        rearranged[p] = observed[o];
                    else
                        rearranged[p] = 0;
                }
            }
        }
        File("rearranged.raw").save(rearranged);

        Array<Byte> delta(0x1000000);
        Array<int> hist(513);
        for (int i = 0; i < 513; ++i)
            hist[i] = 0;
        for (int y = 0; y < 0x1000; ++y) {
            for (int x = 0; x < 0x1000; ++x) {
                int divisor = y & 0xff;
                int dividend = x + ((y & 0xf00) << 4);
                int o = ((dividend & 0xff00) << 8) + (divisor << 8) + (dividend & 0xff);
                int c = observed[o];
                //int c = expected[o] - observed[o];
                delta[y*0x1000 + x] = c;
                int i = (c - 128) + 256;
                ++hist[i];
                //if (c != 128 && divisor <= 128)
                //    printf("Delta at divisor %i\n",divisor);
            }
        }

        File("diff.raw").save(delta);
        File("hist.raw").save(hist);
    }
};<commit_msg>More division experiments<commit_after>#include "alfe/main.h"

class Program : public ProgramBase
{
public:
    void checkResult(int dividend, int divisor, int quotient, int remainder)
    {
        if (dividend / divisor != quotient || dividend % divisor != remainder)
            throw Exception("Incorrect result.");
    }
    void run()
    {
        Array<Byte> observed(0x1000000);
        String dir("M:\\Program Files (x86)\\Apache Software Foundation\\"
            "Apache24\\htdocs\\");
        for (int i = 0; i < 0x100; ++i) {
            File(dir + "VXBaff12_jb2NCDE" + decimal(i) + ".dat", true).
                openRead().read(&observed[i << 16], 0x10000);
        }
        observed[98 + (204 << 8)] = 194;
        observed[(1261 & 0xff) + ((667 - 512) << 8) + (((1261 + 8192) & 0xff00) << 8)] = 196;
        observed[(1263 & 0xff) + ((667 - 512) << 8) + (((1263 + 8192) & 0xff00) << 8)] = 199;
        observed[(1276 & 0xff) + ((667 - 512) << 8) + (((1276 + 8192) & 0xff00) << 8)] = 199;
        observed[(1630 & 0xff) + ((409 - 256) << 8) + (((1630 + 4096) & 0xff00) << 8)] = 199;

        //for (int i = 0; i < 0x100; ++i) {
        //    if (i < 193) {
        //        File(dir + "86-7-WTkKuASmtlj" + decimal(i) + ".dat", true).
        //            openRead().read(&observed[i << 16], 0x10000);
        //    }
        //    else {
        //        File(dir + "5egBqeiqajT-IYHl" + decimal(i - 193) + ".dat",
        //            true).openRead().read(&observed[i << 16], 0x10000);
        //    }
        //}

        Array<Byte> expected(0x1000000);
        //for (int dividend = 0; dividend < 0x10000; ++dividend) {
        //    for (int divisor = 0; divisor < 0x100; ++divisor) {
        //        int t = 239;
        //        int remainder = dividend;
        //        int quotient = 0;
        //        int qbit = 0x80;
        //        int x = divisor << 8;
        //        if (remainder < x) {
        //            t = 194;
        //            for (int b = 0; b < 8; ++b) {
        //                x >>= 1;
        //                if (remainder >= x) {
        //                    remainder -= x;
        //                    ++t;
        //                    if (b == 7)
        //                        t += 2;
        //                    quotient |= qbit;
        //                }
        //                qbit >>= 1;
        //            }
        //        }
        //        int o = ((dividend & 0xff00) << 8) + (divisor << 8) + (dividend & 0xff);
        //        expected[o] = t;
        //        observed[o] -= t;
        //    }
        //}
        for (int dividend = 0; dividend < 0x10000; ++dividend) {
            for (int divisor = 0; divisor < 0x100; ++divisor) {
                if (dividend == 1 && divisor == 1)
                    printf("Stop");
                int t = 239;
                Byte l = dividend & 0xff;
                Byte h = dividend >> 8;
                if (h < divisor) {
                    t = 194;
                    for (int b = 0; b < 8; ++b) {
                        bool c = false;
                        if (h >= divisor) {
                            h -= divisor;
                            c = true;
                            ++t;
                            if (b == 7)
                                t += 2;
                        }
                        bool nc = (h & 0x80) != 0;
                        h = (h << 1) + ((l & 0x80) != 0 ? 1 : 0);
                        l = (l << 1) + (c ? 1 : 0);

                    }
                    checkResult(dividend, divisor, l, h);
                }
                int o = ((dividend & 0xff00) << 8) + (divisor << 8) + (dividend & 0xff);
                expected[o] = t;
                observed[o] -= t;
            }
        }

        //for (int dividend1 = 0; dividend1 < 0x10000; ++dividend1) {
        //    for (int divisor1 = 0; divisor1 < 0x100; ++divisor1) {
        //        int dividend = dividend1;
        //        int divisor = divisor1;

        //        int t = 214;
        //        bool negative = false;
        //        bool dividendNegative = false;
        //        if ((dividend & 0x8000) != 0) {
        //            dividend = (~dividend + 1) & 0xffff;
        //            negative = true;
        //            dividendNegative = true;
        //            t += 4;
        //        }
        //        if ((divisor & 0x80) != 0) {
        //            divisor = (~divisor + 1) & 0xff;
        //            negative = !negative;
        //        }
        //        else
        //            t += 1;
        //        int remainder = dividend;
        //        int quotient = 0;
        //        int qbit = 0x80;
        //        int x = divisor << 8;
        //        if (remainder < x) {
        //            for (int b = 0; b < 8; ++b) {
        //                x >>= 1;
        //                if (remainder >= x) {
        //                    remainder -= x;
        //                    ++t;
        //                    if (b == 7)
        //                        t += 2;
        //                    quotient |= qbit;
        //                }
        //                qbit >>= 1;
        //            }
        //            if (/*remainder >= x*/ (quotient & 0x80) != 0)
        //                t += 105;
        //            else {
        //                if (negative)
        //                    quotient = ~quotient + 1;
        //                if (dividendNegative)
        //                    remainder = ~remainder + 1;
        //            }
        //        }
        //        else
        //            t += 34;

        //        int o = ((dividend1 & 0xff00) << 8) + (divisor1 << 8) + (dividend1 & 0xff);
        //        expected[o] = t;
        //    }
        //}

        Array<Byte> rearranged(0x1000000);
        for (int quotient = 0; quotient < 0x100; ++quotient) {
            for (int divisor = 0; divisor < 0x100; ++divisor) {
                for (int remainder = 0; remainder < 0x100; ++remainder) {
                    int dividend = quotient*divisor + remainder;
                    int o = ((dividend & 0xff00) << 8) + (divisor << 8) + (dividend & 0xff);
                    int p = ((quotient & 0xf) << 8) + remainder + ((((quotient & 0xf0) << 4) + divisor) << 12);
                    if (dividend < 0x10000 && remainder < divisor)
                        rearranged[p] = observed[o];
                    else
                        rearranged[p] = 0;
                }
            }
        }
        File("rearranged.raw").save(rearranged);

        Array<Byte> delta(0x1000000);
        Array<int> hist(513);
        for (int i = 0; i < 513; ++i)
            hist[i] = 0;
        for (int y = 0; y < 0x1000; ++y) {
            for (int x = 0; x < 0x1000; ++x) {
                int divisor = y & 0xff;
                int dividend = x + ((y & 0xf00) << 4);
                int o = ((dividend & 0xff00) << 8) + (divisor << 8) + (dividend & 0xff);
                int c = observed[o];
                //int c = expected[o] - observed[o];
                delta[y*0x1000 + x] = c;
                int i = (c - 128) + 256;
                ++hist[i];
                //if (c != 128 && divisor <= 128)
                //    printf("Delta at divisor %i\n",divisor);
            }
        }

        File("diff.raw").save(delta);
        File("hist.raw").save(hist);
    }
};<|endoftext|>


<commit_before>#pragma once

namespace Headway
{
    constexpr auto VERSION = "4.1";
    constexpr int VERSION_MAJOR = 4;
    constexpr int VERSION_MINOR = 1;

#ifdef Q_OS_MACOS
    constexpr bool GLOBAL_MENUBAR = true;
#else
    constexpr bool GLOBAL_MENUBAR = false;
#endif

#ifdef Q_OS_WINDOWS
    constexpr auto QUICK_CONTROLS_STYLE = "Universal";
#elif Q_OS_MACOS
    constexpr auto QUICK_CONTROLS_STYLE = "macOS";
#else
    constexpr auto QUICK_CONTROLS_STYLE = "Basic";
#endif
}
<commit_msg>fix macro evaluation in config.hpp<commit_after>#pragma once

namespace Headway
{
    constexpr auto VERSION = "4.1";
    constexpr int VERSION_MAJOR = 4;
    constexpr int VERSION_MINOR = 1;

#if defined(Q_OS_MACOS)
    constexpr bool GLOBAL_MENUBAR = true;
#else
    constexpr bool GLOBAL_MENUBAR = false;
#endif

#if defined(Q_OS_WINDOWS)
    constexpr auto QUICK_CONTROLS_STYLE = "Universal";
#elif defined(Q_OS_MACOS)
    constexpr auto QUICK_CONTROLS_STYLE = "macOS";
#else
    constexpr auto QUICK_CONTROLS_STYLE = "Basic";
#endif
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** Copyright (C) 2015 BogDan Vatra <bog_dan_ro@yahoo.com>
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** 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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmakeandroidbuildapkstep.h"
#include "qmakeandroidbuildapkwidget.h"
#include "qmakeandroidrunconfiguration.h"

#include <android/androidconfigurations.h>
#include <android/androidconstants.h>
#include <android/androidmanager.h>
#include <android/androidqtsupport.h>

#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
#include <qmakeprojectmanager/qmakenodes.h>
#include <qmakeprojectmanager/qmakeproject.h>

#include <utils/qtcprocess.h>

#include <QHBoxLayout>

using namespace Android;
using QmakeProjectManager::QmakeProject;
using QmakeProjectManager::QmakeProFileNode;

namespace QmakeAndroidSupport {
namespace Internal {

const Core::Id ANDROID_BUILD_APK_ID("QmakeProjectManager.AndroidBuildApkStep");
const QLatin1String ProFilePathForInputFile("ProFilePathForInputFile");

//////////////////
// QmakeAndroidBuildApkStepFactory
/////////////////

QmakeAndroidBuildApkStepFactory::QmakeAndroidBuildApkStepFactory(QObject *parent)
    : IBuildStepFactory(parent)
{
}

QList<Core::Id> QmakeAndroidBuildApkStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
{
    if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD
            || !canHandle(parent->target())
            || parent->contains(ANDROID_BUILD_APK_ID)) {
        return QList<Core::Id>();
    }

    return QList<Core::Id>() << ANDROID_BUILD_APK_ID;
}

QString QmakeAndroidBuildApkStepFactory::displayNameForId(const Core::Id id) const
{
    if (id == ANDROID_BUILD_APK_ID)
        return tr("Build Android APK");
    return QString();
}

bool QmakeAndroidBuildApkStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const
{
    return availableCreationIds(parent).contains(id);
}

ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id)
{
    Q_ASSERT(canCreate(parent, id));
    Q_UNUSED(id);
    return new QmakeAndroidBuildApkStep(parent);
}

bool QmakeAndroidBuildApkStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
{
    return canCreate(parent, ProjectExplorer::idFromMap(map));
}

ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
{
    Q_ASSERT(canRestore(parent, map));
    QmakeAndroidBuildApkStep * const step = new QmakeAndroidBuildApkStep(parent);
    if (!step->fromMap(map)) {
        delete step;
        return 0;
    }
    return step;
}

bool QmakeAndroidBuildApkStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const
{
    return canCreate(parent, product->id());
}

ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
{
    Q_ASSERT(canClone(parent, product));
    return new QmakeAndroidBuildApkStep(parent, static_cast<QmakeAndroidBuildApkStep *>(product));
}

bool QmakeAndroidBuildApkStepFactory::canHandle(ProjectExplorer::Target *t) const
{
    return t->project()->supportsKit(t->kit())
            && AndroidManager::supportsAndroid(t)
            && qobject_cast<QmakeProject *>(t->project());
}

QmakeAndroidBuildApkStep::QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc)
    :AndroidBuildApkStep(bc, ANDROID_BUILD_APK_ID)
{
    ctor();
}

Utils::FileName QmakeAndroidBuildApkStep::proFilePathForInputFile() const
{
    ProjectExplorer::RunConfiguration *rc = target()->activeRunConfiguration();
    if (auto *arc = qobject_cast<QmakeAndroidRunConfiguration *>(rc))
        return arc->proFilePath();
    return Utils::FileName();
}

QmakeAndroidBuildApkStep::QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc, QmakeAndroidBuildApkStep *other)
    : AndroidBuildApkStep(bc, other)
{
    ctor();
}

Utils::FileName QmakeAndroidBuildApkStep::androidPackageSourceDir() const
{
    QmakeProjectManager::QmakeProject *pro = static_cast<QmakeProjectManager::QmakeProject *>(project());
    const QmakeProjectManager::QmakeProFileNode *node
            = pro->rootQmakeProjectNode()->findProFileFor(proFilePathForInputFile());
    if (!node)
        return Utils::FileName();
    return Utils::FileName::fromString(node->singleVariableValue(QmakeProjectManager::AndroidPackageSourceDir));
}

void QmakeAndroidBuildApkStep::ctor()
{
}

bool QmakeAndroidBuildApkStep::init()
{
    if (AndroidManager::checkForQt51Files(project()->projectDirectory()))
        emit addOutput(tr("Found old folder \"android\" in source directory. Qt 5.2 does not use that folder by default."), ErrorOutput);

    if (!AndroidBuildApkStep::init())
        return false;

    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
    if (!version)
        return false;

    QString command = version->qmakeProperty("QT_HOST_BINS");
    if (!command.endsWith(QLatin1Char('/')))
        command += QLatin1Char('/');
    command += QLatin1String("androiddeployqt");
    if (Utils::HostOsInfo::isWindowsHost())
        command += QLatin1String(".exe");

    QString deploymentMethod;
    if (m_deployAction == MinistroDeployment)
        deploymentMethod = QLatin1String("ministro");
    else if (m_deployAction == DebugDeployment)
        deploymentMethod = QLatin1String("debug");
    else if (m_deployAction == BundleLibrariesDeployment)
        deploymentMethod = QLatin1String("bundled");

    ProjectExplorer::BuildConfiguration *bc = buildConfiguration();
    QString outputDir = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString();

    const auto *pro = static_cast<QmakeProjectManager::QmakeProject *>(project());
    const QmakeProjectManager::QmakeProFileNode *node = pro->rootQmakeProjectNode()->findProFileFor(proFilePathForInputFile());
    m_skipBuilding = !node;
    if (m_skipBuilding)
        return true;

    QString inputFile = node->singleVariableValue(QmakeProjectManager::AndroidDeploySettingsFile);
    if (inputFile.isEmpty()) { // should never happen
        emit addOutput(tr("Internal Error: Unknown Android deployment JSON file location."), BuildStep::ErrorMessageOutput);
        return false;
    }

    QStringList arguments;
    arguments << QLatin1String("--input")
              << inputFile
              << QLatin1String("--output")
              << outputDir
              << QLatin1String("--deployment")
              << deploymentMethod
              << QLatin1String("--android-platform")
              << AndroidManager::buildTargetSDK(target())
              << QLatin1String("--jdk")
              << AndroidConfigurations::currentConfig().openJDKLocation().toString();

    if (m_verbose)
        arguments << QLatin1String("--verbose");

    if (m_useGradle)
        arguments << QLatin1String("--gradle");
    else
        arguments << QLatin1String("--ant")
                  << AndroidConfigurations::currentConfig().antToolPath().toString();

    QStringList argumentsPasswordConcealed = arguments;

    if (m_signPackage) {
        arguments << QLatin1String("--sign")
                  << m_keystorePath.toString()
                  << m_certificateAlias
                  << QLatin1String("--storepass")
                  << m_keystorePasswd;
        argumentsPasswordConcealed << QLatin1String("--sign") << QLatin1String("******")
                                   << QLatin1String("--storepass") << QLatin1String("******");
        if (!m_certificatePasswd.isEmpty()) {
            arguments << QLatin1String("--keypass")
                      << m_certificatePasswd;
            argumentsPasswordConcealed << QLatin1String("--keypass")
                      << QLatin1String("******");
        }

    }

    ProjectExplorer::ProcessParameters *pp = processParameters();
    setupProcessParameters(pp, bc, arguments, command);

    // Generate arguments with keystore password concealed
    ProjectExplorer::ProcessParameters pp2;
    setupProcessParameters(&pp2, bc, argumentsPasswordConcealed, command);
    m_command = pp2.effectiveCommand();
    m_argumentsPasswordConcealed = pp2.prettyArguments();

    return true;
}

void QmakeAndroidBuildApkStep::run(QFutureInterface<bool> &fi)
{
    if (m_skipBuilding) {
        emit addOutput(tr("No application .pro file found, not building an APK."), BuildStep::ErrorMessageOutput);
        fi.reportResult(true);
        emit finished();
        return;
    }
    AndroidBuildApkStep::run(fi);
}

void QmakeAndroidBuildApkStep::setupProcessParameters(ProjectExplorer::ProcessParameters *pp,
                                                      ProjectExplorer::BuildConfiguration *bc,
                                                      const QStringList &arguments,
                                                      const QString &command)
{
    pp->setMacroExpander(bc->macroExpander());
    pp->setWorkingDirectory(bc->buildDirectory().toString());
    Utils::Environment env = bc->environment();
    pp->setEnvironment(env);
    pp->setCommand(command);
    pp->setArguments(Utils::QtcProcess::joinArgs(arguments));
    pp->resolveAll();
}

void QmakeAndroidBuildApkStep::processStarted()
{
    emit addOutput(tr("Starting: \"%1\" %2")
                   .arg(QDir::toNativeSeparators(m_command),
                        m_argumentsPasswordConcealed),
                   BuildStep::MessageOutput);
}

ProjectExplorer::BuildStepConfigWidget *QmakeAndroidBuildApkStep::createConfigWidget()
{
    return new QmakeAndroidBuildApkWidget(this);
}

bool QmakeAndroidBuildApkStep::fromMap(const QVariantMap &map)
{
    return AndroidBuildApkStep::fromMap(map);
}

QVariantMap QmakeAndroidBuildApkStep::toMap() const
{
    QVariantMap map = AndroidBuildApkStep::toMap();
    return map;
}

} // namespace Internal
} // namespace QmakeAndroidSupport
<commit_msg>Android: Make library projects building skip apk packaging<commit_after>/**************************************************************************
**
** Copyright (C) 2015 BogDan Vatra <bog_dan_ro@yahoo.com>
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** 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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmakeandroidbuildapkstep.h"
#include "qmakeandroidbuildapkwidget.h"
#include "qmakeandroidrunconfiguration.h"

#include <android/androidconfigurations.h>
#include <android/androidconstants.h>
#include <android/androidmanager.h>
#include <android/androidqtsupport.h>

#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
#include <qmakeprojectmanager/qmakenodes.h>
#include <qmakeprojectmanager/qmakeproject.h>

#include <utils/qtcprocess.h>

#include <QHBoxLayout>

using namespace Android;
using QmakeProjectManager::QmakeProject;
using QmakeProjectManager::QmakeProFileNode;

namespace QmakeAndroidSupport {
namespace Internal {

const Core::Id ANDROID_BUILD_APK_ID("QmakeProjectManager.AndroidBuildApkStep");
const QLatin1String ProFilePathForInputFile("ProFilePathForInputFile");

//////////////////
// QmakeAndroidBuildApkStepFactory
/////////////////

QmakeAndroidBuildApkStepFactory::QmakeAndroidBuildApkStepFactory(QObject *parent)
    : IBuildStepFactory(parent)
{
}

QList<Core::Id> QmakeAndroidBuildApkStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
{
    if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD
            || !canHandle(parent->target())
            || parent->contains(ANDROID_BUILD_APK_ID)) {
        return QList<Core::Id>();
    }

    return QList<Core::Id>() << ANDROID_BUILD_APK_ID;
}

QString QmakeAndroidBuildApkStepFactory::displayNameForId(const Core::Id id) const
{
    if (id == ANDROID_BUILD_APK_ID)
        return tr("Build Android APK");
    return QString();
}

bool QmakeAndroidBuildApkStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const
{
    return availableCreationIds(parent).contains(id);
}

ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id)
{
    Q_ASSERT(canCreate(parent, id));
    Q_UNUSED(id);
    return new QmakeAndroidBuildApkStep(parent);
}

bool QmakeAndroidBuildApkStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
{
    return canCreate(parent, ProjectExplorer::idFromMap(map));
}

ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
{
    Q_ASSERT(canRestore(parent, map));
    QmakeAndroidBuildApkStep * const step = new QmakeAndroidBuildApkStep(parent);
    if (!step->fromMap(map)) {
        delete step;
        return 0;
    }
    return step;
}

bool QmakeAndroidBuildApkStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const
{
    return canCreate(parent, product->id());
}

ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
{
    Q_ASSERT(canClone(parent, product));
    return new QmakeAndroidBuildApkStep(parent, static_cast<QmakeAndroidBuildApkStep *>(product));
}

bool QmakeAndroidBuildApkStepFactory::canHandle(ProjectExplorer::Target *t) const
{
    return t->project()->supportsKit(t->kit())
            && AndroidManager::supportsAndroid(t)
            && qobject_cast<QmakeProject *>(t->project());
}

QmakeAndroidBuildApkStep::QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc)
    :AndroidBuildApkStep(bc, ANDROID_BUILD_APK_ID)
{
    ctor();
}

Utils::FileName QmakeAndroidBuildApkStep::proFilePathForInputFile() const
{
    ProjectExplorer::RunConfiguration *rc = target()->activeRunConfiguration();
    if (auto *arc = qobject_cast<QmakeAndroidRunConfiguration *>(rc))
        return arc->proFilePath();
    return Utils::FileName();
}

QmakeAndroidBuildApkStep::QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc, QmakeAndroidBuildApkStep *other)
    : AndroidBuildApkStep(bc, other)
{
    ctor();
}

Utils::FileName QmakeAndroidBuildApkStep::androidPackageSourceDir() const
{
    QmakeProjectManager::QmakeProject *pro = static_cast<QmakeProjectManager::QmakeProject *>(project());
    const QmakeProjectManager::QmakeProFileNode *node
            = pro->rootQmakeProjectNode()->findProFileFor(proFilePathForInputFile());
    if (!node)
        return Utils::FileName();
    return Utils::FileName::fromString(node->singleVariableValue(QmakeProjectManager::AndroidPackageSourceDir));
}

void QmakeAndroidBuildApkStep::ctor()
{
}

bool QmakeAndroidBuildApkStep::init()
{
    if (AndroidManager::checkForQt51Files(project()->projectDirectory()))
        emit addOutput(tr("Found old folder \"android\" in source directory. Qt 5.2 does not use that folder by default."), ErrorOutput);

    if (!AndroidBuildApkStep::init())
        return false;

    QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
    if (!version)
        return false;

    QString command = version->qmakeProperty("QT_HOST_BINS");
    if (!command.endsWith(QLatin1Char('/')))
        command += QLatin1Char('/');
    command += QLatin1String("androiddeployqt");
    if (Utils::HostOsInfo::isWindowsHost())
        command += QLatin1String(".exe");

    QString deploymentMethod;
    if (m_deployAction == MinistroDeployment)
        deploymentMethod = QLatin1String("ministro");
    else if (m_deployAction == DebugDeployment)
        deploymentMethod = QLatin1String("debug");
    else if (m_deployAction == BundleLibrariesDeployment)
        deploymentMethod = QLatin1String("bundled");

    ProjectExplorer::BuildConfiguration *bc = buildConfiguration();
    QString outputDir = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString();

    const auto *pro = static_cast<QmakeProjectManager::QmakeProject *>(project());
    const QmakeProjectManager::QmakeProFileNode *node = pro->rootQmakeProjectNode()->findProFileFor(proFilePathForInputFile());
    m_skipBuilding = !node;
    if (m_skipBuilding)
        return true;

    QString inputFile = node->singleVariableValue(QmakeProjectManager::AndroidDeploySettingsFile);
    if (inputFile.isEmpty()) {
        m_skipBuilding = true;
        return true;
    }

    QStringList arguments;
    arguments << QLatin1String("--input")
              << inputFile
              << QLatin1String("--output")
              << outputDir
              << QLatin1String("--deployment")
              << deploymentMethod
              << QLatin1String("--android-platform")
              << AndroidManager::buildTargetSDK(target())
              << QLatin1String("--jdk")
              << AndroidConfigurations::currentConfig().openJDKLocation().toString();

    if (m_verbose)
        arguments << QLatin1String("--verbose");

    if (m_useGradle)
        arguments << QLatin1String("--gradle");
    else
        arguments << QLatin1String("--ant")
                  << AndroidConfigurations::currentConfig().antToolPath().toString();

    QStringList argumentsPasswordConcealed = arguments;

    if (m_signPackage) {
        arguments << QLatin1String("--sign")
                  << m_keystorePath.toString()
                  << m_certificateAlias
                  << QLatin1String("--storepass")
                  << m_keystorePasswd;
        argumentsPasswordConcealed << QLatin1String("--sign") << QLatin1String("******")
                                   << QLatin1String("--storepass") << QLatin1String("******");
        if (!m_certificatePasswd.isEmpty()) {
            arguments << QLatin1String("--keypass")
                      << m_certificatePasswd;
            argumentsPasswordConcealed << QLatin1String("--keypass")
                      << QLatin1String("******");
        }

    }

    ProjectExplorer::ProcessParameters *pp = processParameters();
    setupProcessParameters(pp, bc, arguments, command);

    // Generate arguments with keystore password concealed
    ProjectExplorer::ProcessParameters pp2;
    setupProcessParameters(&pp2, bc, argumentsPasswordConcealed, command);
    m_command = pp2.effectiveCommand();
    m_argumentsPasswordConcealed = pp2.prettyArguments();

    return true;
}

void QmakeAndroidBuildApkStep::run(QFutureInterface<bool> &fi)
{
    if (m_skipBuilding) {
        emit addOutput(tr("No application .pro file found, not building an APK."), BuildStep::ErrorMessageOutput);
        fi.reportResult(true);
        emit finished();
        return;
    }
    AndroidBuildApkStep::run(fi);
}

void QmakeAndroidBuildApkStep::setupProcessParameters(ProjectExplorer::ProcessParameters *pp,
                                                      ProjectExplorer::BuildConfiguration *bc,
                                                      const QStringList &arguments,
                                                      const QString &command)
{
    pp->setMacroExpander(bc->macroExpander());
    pp->setWorkingDirectory(bc->buildDirectory().toString());
    Utils::Environment env = bc->environment();
    pp->setEnvironment(env);
    pp->setCommand(command);
    pp->setArguments(Utils::QtcProcess::joinArgs(arguments));
    pp->resolveAll();
}

void QmakeAndroidBuildApkStep::processStarted()
{
    emit addOutput(tr("Starting: \"%1\" %2")
                   .arg(QDir::toNativeSeparators(m_command),
                        m_argumentsPasswordConcealed),
                   BuildStep::MessageOutput);
}

ProjectExplorer::BuildStepConfigWidget *QmakeAndroidBuildApkStep::createConfigWidget()
{
    return new QmakeAndroidBuildApkWidget(this);
}

bool QmakeAndroidBuildApkStep::fromMap(const QVariantMap &map)
{
    return AndroidBuildApkStep::fromMap(map);
}

QVariantMap QmakeAndroidBuildApkStep::toMap() const
{
    QVariantMap map = AndroidBuildApkStep::toMap();
    return map;
}

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


<commit_before>
#include "ImguiWindowsFileIO.hpp"

#include <algorithm>
#include <cstdlib>
#include <sstream>

#include <iostream>

#if defined(_WINDOWS)
    #include <windows.h>
    #include <direct.h>
    #define GetCurrentDir _getcwd
#else
    #include <unistd.h>
    #define GetCurrentDir getcwd
 #endif

#define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))

#if defined(ICON_FA_CARET_DOWN)
    #define CARET_DOWN ICON_FA_CARET_DOWN
#else
    #define CARET_DOWN "v"
#endif

using namespace std;
using namespace ImGui;

vector<string> stringSplit(const string &s, char delim)
{
vector<string> elems;
string item;

// use stdlib to tokenize the string
stringstream ss(s);
    while (getline(ss, item, delim))
        if(!item.empty())
        {
            elems.push_back(item);
        }

    return elems;
}

string MiniPath::filePath() const
{
    return path + name;
}

void MiniPath::fromString (const string& file_path, char delim)
{
    int last_delim_pos = file_path.find_last_of (delim);
    name = file_path.substr (last_delim_pos+1);
    path = file_path.substr (0, last_delim_pos+1);
}

MiniPath::MiniPath()
{}

MiniPath::MiniPath( const string& some_path )
{
    string s = some_path;
    if (MiniPath::isAbsoluteFilePath (s))
    {
        if (s.find ("/") != string::npos) // linux style
            fromString (s ,'/');
        else if (s.find ("\\") != string::npos) // windows style
            fromString (s ,'\\');
    }
    else
    {
        string current = MiniPath::getCurrentDir();

        if (current.find ("/") != string::npos)
        {
            std::replace( s.begin(), s.end(), '\\', '/');
            fromString (current + "/" + s ,'/');
        }
        else if (current.find ("\\") != string::npos)
        {
            std::replace( s.begin(), s.end(), '/', '\\');
            fromString (current + "\\" + s ,'\\');
        }
        else
            fromNameInCurrentDir( s );
    }
}

string MiniPath::getDelim() const
{
    if (path.find ("/") != string::npos) // linux style
            return "/";
    else if (path.find ("\\") != string::npos) // windows style
            return "\\";
    else
    {
        return MiniPath::getSystemDelim();
    }
}

std::string MiniPath::getSystemDelim()
{
        string current = MiniPath::getCurrentDir();
        if (current.find ("/") != string::npos) // linux style
            return "/";
        else if (current.find ("\\") != string::npos) // windows style
            return "\\";
        else
            return "/";
}

string MiniPath::prefix() const
{
    return name.substr (0, name.find_last_of ('.'));
}

string MiniPath::extension() const
{
    if (name.find (".") == string::npos)
        return "";

    return name.substr (name.find_last_of ('.')+1);
}

string MiniPath::getCurrentDir()
{
    char cCurrentPath[FILENAME_MAX];
    if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
        return 0;
    cCurrentPath[sizeof(cCurrentPath) - 1] = '\0';
    return string (cCurrentPath);
}

void MiniPath::fromNameInCurrentDir( const string& file_name )
{
    path = getCurrentDir();
    name = file_name;
}

string MiniPath::getName() const
{
    return name;
}

string MiniPath::getPath() const
{
    return path;
}

vector<string> MiniPath::getPathTokens() const
{
    if( !getDelim().empty() )
        return stringSplit( path + getDelim(), getDelim()[0] );

    vector<string> tmp;
    return tmp;
}

void MiniPath::setName( const string& name )
{
    string tmp;
    unsigned last_delim_pos = name.find_last_of ('/');
    if( last_delim_pos != string::npos )
        tmp = name.substr (last_delim_pos+1);
    else
        tmp = name;

    unsigned last_delim_pos2 = tmp.find_last_of ('\\');
    if( last_delim_pos2 != string::npos )
        tmp = tmp.substr (last_delim_pos2+1);

    this->name = tmp;
}

bool MiniPath::setPath( const string& absolut_path )
{
    if (isAbsoluteFilePath( absolut_path ))
    {
        path = absolut_path;
        return true;
    }
    return false;
}

bool MiniPath::isAbsoluteFilePath( const string& s )
{
    if (s.size() > 0)
    {
        if (s.at(0) == '/' || s.at(1) == ':')
            return true;
        else
            return false;
    }
    else
        return false;
}

std::list<string> MiniPath::listDirectories( const string& s )
{
    list<string> directories;

    struct _finddata_t c_file;
    intptr_t hFile;

    string filter = s + MiniPath::getSystemDelim() + "*.*";

    if( (hFile = _findfirst( filter.c_str(), &c_file )) == -1L )
    {}
    else
    {
        do
        {
            char buffer[256];
            if( ( c_file.attrib & _A_SUBDIR ) )
                directories.push_back( string( c_file.name ) );
        } while( _findnext( hFile, &c_file ) == 0 );
    }

    return directories;
}

std::list<string> MiniPath::listFiles( const string& s, string filter )
{
    list<string> files;

    struct _finddata_t c_file;
    intptr_t hFile;

    string find_filter = s + MiniPath::getSystemDelim() + filter;

    if( (hFile = _findfirst( find_filter.c_str(), &c_file )) == -1L )
    {}
    else
    {
        do
        {
            char buffer[256];
            if( !( c_file.attrib & _A_SUBDIR ) )
                files.push_back( string( c_file.name ) );
        } while( _findnext( hFile, &c_file ) == 0 );
    }

    return files;
}

bool fileIOWindow(
    string& file_path,
    std::vector<string>& recently_used_files,
    const string& button_text,
    ImVec2 size )
{
    bool close_it = false;

    std::vector<const char*> extension_cstrings { "*.usr", "*.*" };

    static char current_folder[ 2048 ] = "x";
    if( strcmp( current_folder, "x" ) == 0 )
        strcpy( current_folder, MiniPath::getCurrentDir().c_str() );
    static char current_file[ 256 ] = "Test.usr";
    static int  file_type_selected = 0;
    static int  file_selected = 0;
    static int  directory_selected = 0;
    static bool directory_browsing = false;
    static int  recent_selected = 0;

    string sys_delim = MiniPath::getSystemDelim();

    string tmp = string( current_folder ) + sys_delim;
    MiniPath current_mini_path( tmp );

    list<string> directories = MiniPath::listDirectories( current_mini_path.getPath() );
    std::vector<const char*> dir_list;
    for( const string& s : directories )
        dir_list.push_back( s.c_str() );

    list<string> local_files = MiniPath::listFiles( current_mini_path.getPath(), string( extension_cstrings[file_type_selected] ) );
    std::vector<const char*> file_list;
    for( const string& s : local_files )
        file_list.push_back( s.c_str() );

    if ( directory_browsing )
        size.y += std::min( size_t( 8 ), std::max( dir_list.size(), file_list.size() ) ) *  GetFontSize();

    SetNextWindowSize( size );
    Begin( "FileIO" );

    Text("Directory: "); SameLine();
    PushItemWidth( GetWindowWidth() - 145 );

    InputText( " ", current_folder, IM_ARRAYSIZE( current_folder ) ); SameLine();

    std::vector<const char*> recent {};
    for( const auto& string : recently_used_files )
        recent.push_back(string.c_str());

    if( Button(" " CARET_DOWN " ") )
        ImGui::OpenPopup("RecentFiles");

    if (ImGui::BeginPopup("RecentFiles"))
    {
        if( ListBox( "", &recent_selected, recent.data(), recent.size() ) )
        {
            strcpy(current_file, recent[recent_selected]);
            file_path = current_file;
            CloseCurrentPopup();
        }
        ImGui::EndPopup();
    }

    Text("           "); SameLine();
    vector<string> split_directories = current_mini_path.getPathTokens();
    for( int i = 0; i < split_directories.size(); ++i )
    {
        if( Button( split_directories[i].c_str() ) )
        {
            string chosen_dir;
            for( int j ; j <= i; ++j)
            {
                chosen_dir += split_directories[j];
                if( j != i )
                    chosen_dir += sys_delim;
            }
            strcpy( current_folder, chosen_dir.c_str() );
        }
        if( i != split_directories.size()-1 )
            SameLine();
    }

    if( CollapsingHeader("Browse Directories") )
    {
        directory_browsing = true;
        Text( "           " );
        SameLine();

        PushItemWidth( GetWindowWidth()/2 - 60 );
        if( ListBox( " ", &directory_selected, dir_list.data(), dir_list.size() ) )
        {
            string new_path = string( current_folder ) + sys_delim + dir_list[directory_selected];
            strcpy( current_folder, new_path.c_str() );
        }

        SameLine();
        PushItemWidth( GetWindowWidth()/2 - 60 );
        if( ListBox( "", &file_selected, file_list.data(), file_list.size() ) )
        {
            strcpy( current_file, file_list[file_selected] );
        }
    }
    else
         directory_browsing = false;

    Text(" ");

    Text("File Name: "); SameLine();
    InputText( "  ", current_file, IM_ARRAYSIZE( current_file ) );

    Text( "File Type: " ); SameLine(); Text( extension_cstrings[file_type_selected] ); SameLine();
    if (Button( CARET_DOWN ) )
        ImGui::OpenPopup("FileType");

    if (ImGui::BeginPopup("FileType"))
    {
        if( ListBox( "", &file_type_selected, extension_cstrings.data(), extension_cstrings.size() ) )
        {
            CloseCurrentPopup();
        }
        ImGui::EndPopup();
    }

    ImVec2 pos = GetCursorPos();

    pos.x += GetWindowWidth() - 75 - button_text.size() * ( GetFontSize() * 0.7 );
    pos.y  = GetWindowHeight() - 30;

    SetCursorPos( pos );
    if( Button( button_text.c_str() ) )
    {
        file_path = current_file;
        close_it = true;
    }

    SameLine();
    if( Button( "Cancel" ) )
        close_it = true;
    End();

    return close_it;
}
<commit_msg>add drive list selector for windows<commit_after>
#include "ImguiWindowsFileIO.hpp"

#include <algorithm>
#include <cstdlib>
#include <sstream>

#include <iostream>

#if defined(WIN32)
    #include <windows.h>
    #include <direct.h>
    #include <tchar.h>
    #define GetCurrentDir _getcwd
#else
    #include <unistd.h>
    #define GetCurrentDir getcwd
 #endif

#define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))

#if defined(ICON_FA_CARET_DOWN)
    #define CARET_DOWN ICON_FA_CARET_DOWN
#else
    #define CARET_DOWN "v"
#endif

using namespace std;
using namespace ImGui;

#if defined(WIN32)
vector<string> getWindowsDrives()
{
    vector<string> result;
    TCHAR g_szDrvMsg[] = _T("A:");

    ULONG uDriveMask = _getdrives();

    if (uDriveMask == 0)
    {}
    else
    {
        while (uDriveMask)
        {
            if (uDriveMask & 1)
                result.push_back( g_szDrvMsg );

            ++g_szDrvMsg[0];
            uDriveMask >>= 1;
        }
   }

    return result;
}
#endif

vector<string> stringSplit(const string &s, char delim)
{
vector<string> elems;
string item;

// use stdlib to tokenize the string
stringstream ss(s);
    while (getline(ss, item, delim))
        if(!item.empty())
        {
            elems.push_back(item);
        }

    return elems;
}

string MiniPath::filePath() const
{
    return path + name;
}

void MiniPath::fromString (const string& file_path, char delim)
{
    int last_delim_pos = file_path.find_last_of (delim);
    name = file_path.substr (last_delim_pos+1);
    path = file_path.substr (0, last_delim_pos+1);
}

MiniPath::MiniPath()
{}

MiniPath::MiniPath( const string& some_path )
{
    string s = some_path;
    if (MiniPath::isAbsoluteFilePath (s))
    {
        if (s.find ("/") != string::npos) // linux style
            fromString (s ,'/');
        else if (s.find ("\\") != string::npos) // windows style
            fromString (s ,'\\');
    }
    else
    {
        string current = MiniPath::getCurrentDir();

        if (current.find ("/") != string::npos)
        {
            std::replace( s.begin(), s.end(), '\\', '/');
            fromString (current + "/" + s ,'/');
        }
        else if (current.find ("\\") != string::npos)
        {
            std::replace( s.begin(), s.end(), '/', '\\');
            fromString (current + "\\" + s ,'\\');
        }
        else
            fromNameInCurrentDir( s );
    }
}

string MiniPath::getDelim() const
{
    if (path.find ("/") != string::npos) // linux style
            return "/";
    else if (path.find ("\\") != string::npos) // windows style
            return "\\";
    else
    {
        return MiniPath::getSystemDelim();
    }
}

std::string MiniPath::getSystemDelim()
{
        string current = MiniPath::getCurrentDir();
        if (current.find ("/") != string::npos) // linux style
            return "/";
        else if (current.find ("\\") != string::npos) // windows style
            return "\\";
        else
            return "/";
}

string MiniPath::prefix() const
{
    return name.substr (0, name.find_last_of ('.'));
}

string MiniPath::extension() const
{
    if (name.find (".") == string::npos)
        return "";

    return name.substr (name.find_last_of ('.')+1);
}

string MiniPath::getCurrentDir()
{
    char cCurrentPath[FILENAME_MAX];
    if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
        return 0;
    cCurrentPath[sizeof(cCurrentPath) - 1] = '\0';
    return string (cCurrentPath);
}

void MiniPath::fromNameInCurrentDir( const string& file_name )
{
    path = getCurrentDir();
    name = file_name;
}

string MiniPath::getName() const
{
    return name;
}

string MiniPath::getPath() const
{
    return path;
}

vector<string> MiniPath::getPathTokens() const
{
    if( !getDelim().empty() )
        return stringSplit( path + getDelim(), getDelim()[0] );

    vector<string> tmp;
    return tmp;
}

void MiniPath::setName( const string& name )
{
    string tmp;
    unsigned last_delim_pos = name.find_last_of ('/');
    if( last_delim_pos != string::npos )
        tmp = name.substr (last_delim_pos+1);
    else
        tmp = name;

    unsigned last_delim_pos2 = tmp.find_last_of ('\\');
    if( last_delim_pos2 != string::npos )
        tmp = tmp.substr (last_delim_pos2+1);

    this->name = tmp;
}

bool MiniPath::setPath( const string& absolut_path )
{
    if (isAbsoluteFilePath( absolut_path ))
    {
        path = absolut_path;
        return true;
    }
    return false;
}

bool MiniPath::isAbsoluteFilePath( const string& s )
{
    if (s.size() > 0)
    {
        if (s.at(0) == '/' || s.at(1) == ':')
            return true;
        else
            return false;
    }
    else
        return false;
}

std::list<string> MiniPath::listDirectories( const string& s )
{
    list<string> directories;

    struct _finddata_t c_file;
    intptr_t hFile;

    string filter = s + MiniPath::getSystemDelim() + "*.*";

    if( (hFile = _findfirst( filter.c_str(), &c_file )) == -1L )
    {}
    else
    {
        do
        {
            char buffer[256];
            if( ( c_file.attrib & _A_SUBDIR ) )
                directories.push_back( string( c_file.name ) );
        } while( _findnext( hFile, &c_file ) == 0 );
    }

    return directories;
}

std::list<string> MiniPath::listFiles( const string& s, string filter )
{
    list<string> files;

    struct _finddata_t c_file;
    intptr_t hFile;

    string find_filter = s + MiniPath::getSystemDelim() + filter;

    if( (hFile = _findfirst( find_filter.c_str(), &c_file )) == -1L )
    {}
    else
    {
        do
        {
            char buffer[256];
            if( !( c_file.attrib & _A_SUBDIR ) )
                files.push_back( string( c_file.name ) );
        } while( _findnext( hFile, &c_file ) == 0 );
    }

    return files;
}

bool fileIOWindow(
    string& file_path,
    std::vector<string>& recently_used_files,
    const string& button_text,
    ImVec2 size )
{
    bool close_it = false;

    std::vector<const char*> extension_cstrings { "*.usr", "*.*" };

    static char current_folder[ 2048 ] = "x";
    if( strcmp( current_folder, "x" ) == 0 )
        strcpy( current_folder, MiniPath::getCurrentDir().c_str() );
    static char current_file[ 256 ] = "Test.usr";
    static int  file_type_selected = 0;
    static int  file_selected = 0;
    static int  directory_selected = 0;
    static int  drive_selected = 0;
    static bool directory_browsing = false;
    static int  recent_selected = 0;

    string sys_delim = MiniPath::getSystemDelim();

    string tmp = string( current_folder ) + sys_delim;
    MiniPath current_mini_path( tmp );

    list<string> directories = MiniPath::listDirectories( current_mini_path.getPath() );
    std::vector<const char*> dir_list;
    for( const string& s : directories )
        dir_list.push_back( s.c_str() );

    list<string> local_files = MiniPath::listFiles( current_mini_path.getPath(), string( extension_cstrings[file_type_selected] ) );
    std::vector<const char*> file_list;
    for( const string& s : local_files )
        file_list.push_back( s.c_str() );

    if ( directory_browsing )
        size.y += std::min( size_t( 8 ), std::max( dir_list.size(), file_list.size() ) ) *  GetFontSize();

    SetNextWindowSize( size );
    Begin( "FileIO" );

    Text("Directory: "); SameLine();
    PushItemWidth( GetWindowWidth() - 145 );

    InputText( " ", current_folder, IM_ARRAYSIZE( current_folder ) ); SameLine();

    std::vector<const char*> recent {};
    for( const auto& string : recently_used_files )
        recent.push_back(string.c_str());

    if( Button(" " CARET_DOWN " ") )
        ImGui::OpenPopup("RecentFiles");

    if (ImGui::BeginPopup("RecentFiles"))
    {
        if( ListBox( "", &recent_selected, recent.data(), recent.size() ) )
        {
            strcpy(current_file, recent[recent_selected]);
            file_path = current_file;
            CloseCurrentPopup();
        }
        ImGui::EndPopup();
    }

    Text("           "); SameLine();
    vector<string> split_directories = current_mini_path.getPathTokens();
    for( int i = 0; i < split_directories.size(); ++i )
    {
        if( Button( split_directories[i].c_str() ) )
        {
            string chosen_dir;
            for( int j ; j <= i; ++j)
            {
                chosen_dir += split_directories[j];
                if( j != i )
                    chosen_dir += sys_delim;
            }
            strcpy( current_folder, chosen_dir.c_str() );
        }
        if( i != split_directories.size()-1 )
            SameLine();
    }

    if( CollapsingHeader("Browse Directories") )
    {
        directory_browsing = true;

#if defined(WIN32)
        vector<const char*> drive_list;
        for( const string& s : getWindowsDrives() )
            drive_list.push_back( s.c_str() );

        Text( "  " ); SameLine();
        PushItemWidth( 40 );
        if( ListBox( "  ", &drive_selected, drive_list.data(), drive_list.size() ) )
        {
            string new_path = drive_list[drive_selected];
            strcpy( current_folder, new_path.c_str() );
        }
#else
        Text( "           " );
#endif
        SameLine();

        PushItemWidth( GetWindowWidth()/2 - 60 );
        if( ListBox( " ", &directory_selected, dir_list.data(), dir_list.size() ) )
        {
            string new_path = string( current_folder ) + sys_delim + dir_list[directory_selected];
            strcpy( current_folder, new_path.c_str() );
        }

        SameLine();
        PushItemWidth( GetWindowWidth()/2 - 60 );
        if( ListBox( "", &file_selected, file_list.data(), file_list.size() ) )
        {
            strcpy( current_file, file_list[file_selected] );
        }
    }
    else
         directory_browsing = false;

    Text(" ");

    Text("File Name: "); SameLine();
    InputText( "  ", current_file, IM_ARRAYSIZE( current_file ) );

    Text( "File Type: " ); SameLine(); Text( extension_cstrings[file_type_selected] ); SameLine();
    if (Button( CARET_DOWN ) )
        ImGui::OpenPopup("FileType");

    if (ImGui::BeginPopup("FileType"))
    {
        if( ListBox( "", &file_type_selected, extension_cstrings.data(), extension_cstrings.size() ) )
        {
            CloseCurrentPopup();
        }
        ImGui::EndPopup();
    }

    ImVec2 pos = GetCursorPos();

    pos.x += GetWindowWidth() - 75 - button_text.size() * ( GetFontSize() * 0.7 );
    pos.y  = GetWindowHeight() - 30;

    SetCursorPos( pos );
    if( Button( button_text.c_str() ) )
    {
        file_path = current_file;
        close_it = true;
    }

    SameLine();
    if( Button( "Cancel" ) )
        close_it = true;
    End();

    return close_it;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <ctime>

#include "TestFile.hpp"

using namespace std;
using namespace nix;

void TestFile::setUp() {
    statup_time = time(NULL);
    file_open = File::open("test_file.h5", FileMode::Overwrite);
    file_other = File::open("test_file_other.h5", FileMode::Overwrite);
    file_null = NULL;
}

void TestFile::tearDown() {
    file_open = NULL;      // TODO fix this as soon as there is a nicer method for closing files
    file_other = NULL;
}

void TestFile::testFormat() {
    CPPUNIT_ASSERT(file_open.format() == "pandora");
}

void TestFile::testVersion() {
    CPPUNIT_ASSERT(file_open.version() == "1.0");
}

void TestFile::testCreatedAt() {
    CPPUNIT_ASSERT(file_open.createdAt() >= statup_time);
    time_t past_time = time(NULL) - 10000000;
    file_open.forceCreatedAt(past_time);
    CPPUNIT_ASSERT(file_open.createdAt() == past_time);
}

void TestFile::testUpdatedAt() {
    CPPUNIT_ASSERT(file_open.updatedAt() >= statup_time);
}

void TestFile::testBlockAccess() {
    vector<string> names = { "block_a", "block_b", "block_c", "block_d", "block_e" };

    CPPUNIT_ASSERT(file_open.blockCount() == 0);
    CPPUNIT_ASSERT(file_open.blocks().size() == 0);

    vector<string> ids;
    for (auto it = names.begin(); it != names.end(); it++) {
        Block bl = file_open.createBlock(*it, "dataset");
        CPPUNIT_ASSERT(bl.name() == *it);

        ids.push_back(bl.id());
    }

    CPPUNIT_ASSERT(file_open.blockCount() == names.size());
    CPPUNIT_ASSERT(file_open.blocks().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); it++) {
        Block bl = file_open.getBlock(*it);
        CPPUNIT_ASSERT(file_open.hasBlock(*it) == true);
        CPPUNIT_ASSERT(bl.id() == *it);

        file_open.removeBlock(*it);
    }

    CPPUNIT_ASSERT(file_open.blockCount() == 0);
    CPPUNIT_ASSERT(file_open.blocks().size() == 0);
}

void TestFile::testSectionAccess() {
    vector<string> names = {"section_a", "section_b", "section_c", "section_d", "section_e" };

    CPPUNIT_ASSERT(file_open.sectionCount() == 0);
    CPPUNIT_ASSERT(file_open.sections().size() == 0);

    vector<string> ids;
    for (auto it = names.begin(); it != names.end(); it++) {
        Section sec = file_open.createSection(*it, "root section");
        CPPUNIT_ASSERT(sec.name() == *it);

        ids.push_back(sec.id());
    }

    CPPUNIT_ASSERT(file_open.sectionCount() == names.size());
    CPPUNIT_ASSERT(file_open.sections().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); it++) {
        Section sec = file_open.getSection(*it);
        CPPUNIT_ASSERT(file_open.hasSection(*it) == true);
        CPPUNIT_ASSERT(sec.id() == *it);

        file_open.removeSection(*it);
    }

    CPPUNIT_ASSERT(file_open.sectionCount() == 0);
    CPPUNIT_ASSERT(file_open.sections().size() == 0);
}

void TestFile::testOperators(){
    CPPUNIT_ASSERT(file_null == NULL);
    CPPUNIT_ASSERT(file_null == nullptr);

    CPPUNIT_ASSERT(file_open != NULL);
    CPPUNIT_ASSERT(file_open != nullptr);

    CPPUNIT_ASSERT(file_open == file_open);
    CPPUNIT_ASSERT(file_open != file_other);

    file_other = file_open;
    CPPUNIT_ASSERT(file_other == file_open);

    file_other = nullptr;
    CPPUNIT_ASSERT(file_null == NULL);
    CPPUNIT_ASSERT(file_null == nullptr);
}

<commit_msg>Use the new close method in TestFile<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <ctime>

#include "TestFile.hpp"

using namespace std;
using namespace nix;

void TestFile::setUp() {
    statup_time = time(NULL);
    file_open = File::open("test_file.h5", FileMode::Overwrite);
    file_other = File::open("test_file_other.h5", FileMode::Overwrite);
    file_null = NULL;
}

void TestFile::tearDown() {
    file_open.close();
    file_other.close();
}

void TestFile::testFormat() {
    CPPUNIT_ASSERT(file_open.format() == "pandora");
}

void TestFile::testVersion() {
    CPPUNIT_ASSERT(file_open.version() == "1.0");
}

void TestFile::testCreatedAt() {
    CPPUNIT_ASSERT(file_open.createdAt() >= statup_time);
    time_t past_time = time(NULL) - 10000000;
    file_open.forceCreatedAt(past_time);
    CPPUNIT_ASSERT(file_open.createdAt() == past_time);
}

void TestFile::testUpdatedAt() {
    CPPUNIT_ASSERT(file_open.updatedAt() >= statup_time);
}

void TestFile::testBlockAccess() {
    vector<string> names = { "block_a", "block_b", "block_c", "block_d", "block_e" };

    CPPUNIT_ASSERT(file_open.blockCount() == 0);
    CPPUNIT_ASSERT(file_open.blocks().size() == 0);

    vector<string> ids;
    for (auto it = names.begin(); it != names.end(); it++) {
        Block bl = file_open.createBlock(*it, "dataset");
        CPPUNIT_ASSERT(bl.name() == *it);

        ids.push_back(bl.id());
    }

    CPPUNIT_ASSERT(file_open.blockCount() == names.size());
    CPPUNIT_ASSERT(file_open.blocks().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); it++) {
        Block bl = file_open.getBlock(*it);
        CPPUNIT_ASSERT(file_open.hasBlock(*it) == true);
        CPPUNIT_ASSERT(bl.id() == *it);

        file_open.removeBlock(*it);
    }

    CPPUNIT_ASSERT(file_open.blockCount() == 0);
    CPPUNIT_ASSERT(file_open.blocks().size() == 0);
}

void TestFile::testSectionAccess() {
    vector<string> names = {"section_a", "section_b", "section_c", "section_d", "section_e" };

    CPPUNIT_ASSERT(file_open.sectionCount() == 0);
    CPPUNIT_ASSERT(file_open.sections().size() == 0);

    vector<string> ids;
    for (auto it = names.begin(); it != names.end(); it++) {
        Section sec = file_open.createSection(*it, "root section");
        CPPUNIT_ASSERT(sec.name() == *it);

        ids.push_back(sec.id());
    }

    CPPUNIT_ASSERT(file_open.sectionCount() == names.size());
    CPPUNIT_ASSERT(file_open.sections().size() == names.size());

    for (auto it = ids.begin(); it != ids.end(); it++) {
        Section sec = file_open.getSection(*it);
        CPPUNIT_ASSERT(file_open.hasSection(*it) == true);
        CPPUNIT_ASSERT(sec.id() == *it);

        file_open.removeSection(*it);
    }

    CPPUNIT_ASSERT(file_open.sectionCount() == 0);
    CPPUNIT_ASSERT(file_open.sections().size() == 0);
}

void TestFile::testOperators(){
    CPPUNIT_ASSERT(file_null == NULL);
    CPPUNIT_ASSERT(file_null == nullptr);

    CPPUNIT_ASSERT(file_open != NULL);
    CPPUNIT_ASSERT(file_open != nullptr);

    CPPUNIT_ASSERT(file_open == file_open);
    CPPUNIT_ASSERT(file_open != file_other);

    file_other = file_open;
    CPPUNIT_ASSERT(file_other == file_open);

    file_other = nullptr;
    CPPUNIT_ASSERT(file_null == NULL);
    CPPUNIT_ASSERT(file_null == nullptr);
}

<|endoftext|>