<commit_before>//===-- DebugInfoProbe.cpp - DebugInfo Probe ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements DebugInfoProbe. This probe can be used by a pass
// manager to analyze how optimizer is treating debugging information.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "debuginfoprobe"
#include "llvm/DebugInfoProbe.h"
#include "llvm/Function.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Metadata.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugLoc.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringRef.h"
#include <set>
#include <string>

using namespace llvm;

static cl::opt<bool>
EnableDebugInfoProbe("enable-debug-info-probe", cl::Hidden,
                     cl::desc("Enable debug info probe"));

// CreateInfoOutputFile - Return a file stream to print our output on.
namespace llvm { extern raw_ostream *CreateInfoOutputFile(); }

//===----------------------------------------------------------------------===//
// DebugInfoProbeImpl - This class implements a interface to monitor
// how an optimization pass is preserving debugging information.

namespace llvm {

  class DebugInfoProbeImpl {
  public:
    DebugInfoProbeImpl() : NumDbgLineLost(0),NumDbgValueLost(0) {}
    void initialize(StringRef PName, Function &F);
    void finalize(Function &F);
    void report();
  private:
    unsigned NumDbgLineLost, NumDbgValueLost;
    std::string PassName;
    Function *TheFn;
    std::set<unsigned> LineNos;
    std::set<MDNode *> DbgVariables;
  };
}

//===----------------------------------------------------------------------===//
// DebugInfoProbeImpl

static void collect(Function &F, std::set<unsigned> &Lines) {
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
         BI != BE; ++BI) {
      const DebugLoc &DL = BI->getDebugLoc();
      unsigned LineNo = 0;
      if (!DL.isUnknown()) {
        if (MDNode *N = DL.getInlinedAt(F.getContext()))
          LineNo = DebugLoc::getFromDILocation(N).getLine();
        else
          LineNo = DL.getLine();

        Lines.insert(LineNo);
      }
    }
}

/// initialize - Collect information before running an optimization pass.
void DebugInfoProbeImpl::initialize(StringRef PName, Function &F) {
  if (!EnableDebugInfoProbe) return;
  PassName = PName;

  LineNos.clear();
  DbgVariables.clear();
  TheFn = &F;
  collect(F, LineNos);

  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
         BI != BE; ++BI) {
      if (!isa<DbgInfoIntrinsic>(BI)) continue;
      Value *Addr = NULL;
      MDNode *Node = NULL;
      if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) {
        Addr = DDI->getAddress();
        Node = DDI->getVariable();
      } else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
        Addr = DVI->getValue();
        Node = DVI->getVariable();
      }
      if (Addr)
        DbgVariables.insert(Node);
    }
}

/// report - Report findings. This should be invoked after finalize.
void DebugInfoProbeImpl::report() {
  if (!EnableDebugInfoProbe) return;
  if (NumDbgLineLost || NumDbgValueLost) {
    raw_ostream *OutStream = CreateInfoOutputFile();
    if (NumDbgLineLost)
      *OutStream << NumDbgLineLost
                 << "\t times line number info lost by "
                 << PassName << "\n";
    if (NumDbgValueLost)
      *OutStream << NumDbgValueLost
                 << "\t times variable info lost by    "
                 << PassName << "\n";
    delete OutStream;
  }
  NumDbgLineLost = 0;
  NumDbgValueLost = 0;
}

/// finalize - Collect information after running an optimization pass. This
/// must be used after initialization.
void DebugInfoProbeImpl::finalize(Function &F) {
  if (!EnableDebugInfoProbe) return;
  std::set<unsigned> LineNos2;
  collect(F, LineNos2);
  assert (TheFn == &F && "Invalid function to measure!");

  for (std::set<unsigned>::iterator I = LineNos.begin(),
         E = LineNos.end(); I != E; ++I) {
    unsigned LineNo = *I;
    if (LineNos2.count(LineNo) == 0) {
      DEBUG(dbgs()
            << "DebugInfoProbe("
            << PassName
            << "): Losing dbg info for source line "
            << LineNo << "\n");
      ++NumDbgLineLost;
    }
  }

  std::set<MDNode *>DbgVariables2;
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
         BI != BE; ++BI) {
      if (!isa<DbgInfoIntrinsic>(BI)) continue;
      Value *Addr = NULL;
      MDNode *Node = NULL;
      if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) {
        Addr = DDI->getAddress();
        Node = DDI->getVariable();
      } else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
        Addr = DVI->getValue();
        Node = DVI->getVariable();
      }
      if (Addr)
        DbgVariables2.insert(Node);
    }

  for (std::set<MDNode *>::iterator I = DbgVariables.begin(),
         E = DbgVariables.end(); I != E; ++I) {
    if (DbgVariables2.count(*I) == 0 && (*I)->getNumOperands() >= 2) {
      DEBUG(dbgs()
            << "DebugInfoProbe("
            << PassName
            << "): Losing dbg info for variable: ");
      if (MDString *MDS = dyn_cast_or_null<MDString>((*I)->getOperand(2)))
        DEBUG(dbgs() << MDS->getString());
      else
        DEBUG(dbgs() << "...");
      DEBUG(dbgs() << "\n");
      ++NumDbgValueLost;
    }
  }
}

//===----------------------------------------------------------------------===//
// DebugInfoProbe

DebugInfoProbe::DebugInfoProbe() {
  pImpl = new DebugInfoProbeImpl();
}

DebugInfoProbe::~DebugInfoProbe() {
  delete pImpl;
}

/// initialize - Collect information before running an optimization pass.
void DebugInfoProbe::initialize(StringRef PName, Function &F) {
  pImpl->initialize(PName, F);
}

/// finalize - Collect information after running an optimization pass. This
/// must be used after initialization.
void DebugInfoProbe::finalize(Function &F) {
  pImpl->finalize(F);
}

/// report - Report findings. This should be invoked after finalize.
void DebugInfoProbe::report() {
  pImpl->report();
}

//===----------------------------------------------------------------------===//
// DebugInfoProbeInfo

/// ~DebugInfoProbeInfo - Report data collected by all probes before deleting
/// them.
DebugInfoProbeInfo::~DebugInfoProbeInfo() {
  if (!EnableDebugInfoProbe) return;
    for (StringMap<DebugInfoProbe*>::iterator I = Probes.begin(),
           E = Probes.end(); I != E; ++I) {
      I->second->report();
      delete I->second;
    }
  }

/// initialize - Collect information before running an optimization pass.
void DebugInfoProbeInfo::initialize(Pass *P, Function &F) {
  if (!EnableDebugInfoProbe) return;
  if (P->getAsPMDataManager())
    return;

  StringMapEntry<DebugInfoProbe *> &Entry =
    Probes.GetOrCreateValue(P->getPassName());
  DebugInfoProbe *&Probe = Entry.getValue();
  if (!Probe)
    Probe = new DebugInfoProbe();
  Probe->initialize(P->getPassName(), F);
}

/// finalize - Collect information after running an optimization pass. This
/// must be used after initialization.
void DebugInfoProbeInfo::finalize(Pass *P, Function &F) {
  if (!EnableDebugInfoProbe) return;
  if (P->getAsPMDataManager())
    return;
  StringMapEntry<DebugInfoProbe *> &Entry =
    Probes.GetOrCreateValue(P->getPassName());
  DebugInfoProbe *&Probe = Entry.getValue();
  assert (Probe && "DebugInfoProbe is not initialized!");
  Probe->finalize(F);
}
<commit_msg>Coalesce some DEBUGs (moving an only-used-in-DEBUG variable's declaration into the DEBUG)<commit_after>//===-- DebugInfoProbe.cpp - DebugInfo Probe ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements DebugInfoProbe. This probe can be used by a pass
// manager to analyze how optimizer is treating debugging information.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "debuginfoprobe"
#include "llvm/DebugInfoProbe.h"
#include "llvm/Function.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Metadata.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugLoc.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringRef.h"
#include <set>
#include <string>

using namespace llvm;

static cl::opt<bool>
EnableDebugInfoProbe("enable-debug-info-probe", cl::Hidden,
                     cl::desc("Enable debug info probe"));

// CreateInfoOutputFile - Return a file stream to print our output on.
namespace llvm { extern raw_ostream *CreateInfoOutputFile(); }

//===----------------------------------------------------------------------===//
// DebugInfoProbeImpl - This class implements a interface to monitor
// how an optimization pass is preserving debugging information.

namespace llvm {

  class DebugInfoProbeImpl {
  public:
    DebugInfoProbeImpl() : NumDbgLineLost(0),NumDbgValueLost(0) {}
    void initialize(StringRef PName, Function &F);
    void finalize(Function &F);
    void report();
  private:
    unsigned NumDbgLineLost, NumDbgValueLost;
    std::string PassName;
    Function *TheFn;
    std::set<unsigned> LineNos;
    std::set<MDNode *> DbgVariables;
  };
}

//===----------------------------------------------------------------------===//
// DebugInfoProbeImpl

static void collect(Function &F, std::set<unsigned> &Lines) {
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
         BI != BE; ++BI) {
      const DebugLoc &DL = BI->getDebugLoc();
      unsigned LineNo = 0;
      if (!DL.isUnknown()) {
        if (MDNode *N = DL.getInlinedAt(F.getContext()))
          LineNo = DebugLoc::getFromDILocation(N).getLine();
        else
          LineNo = DL.getLine();

        Lines.insert(LineNo);
      }
    }
}

/// initialize - Collect information before running an optimization pass.
void DebugInfoProbeImpl::initialize(StringRef PName, Function &F) {
  if (!EnableDebugInfoProbe) return;
  PassName = PName;

  LineNos.clear();
  DbgVariables.clear();
  TheFn = &F;
  collect(F, LineNos);

  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
         BI != BE; ++BI) {
      if (!isa<DbgInfoIntrinsic>(BI)) continue;
      Value *Addr = NULL;
      MDNode *Node = NULL;
      if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) {
        Addr = DDI->getAddress();
        Node = DDI->getVariable();
      } else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
        Addr = DVI->getValue();
        Node = DVI->getVariable();
      }
      if (Addr)
        DbgVariables.insert(Node);
    }
}

/// report - Report findings. This should be invoked after finalize.
void DebugInfoProbeImpl::report() {
  if (!EnableDebugInfoProbe) return;
  if (NumDbgLineLost || NumDbgValueLost) {
    raw_ostream *OutStream = CreateInfoOutputFile();
    if (NumDbgLineLost)
      *OutStream << NumDbgLineLost
                 << "\t times line number info lost by "
                 << PassName << "\n";
    if (NumDbgValueLost)
      *OutStream << NumDbgValueLost
                 << "\t times variable info lost by    "
                 << PassName << "\n";
    delete OutStream;
  }
  NumDbgLineLost = 0;
  NumDbgValueLost = 0;
}

/// finalize - Collect information after running an optimization pass. This
/// must be used after initialization.
void DebugInfoProbeImpl::finalize(Function &F) {
  if (!EnableDebugInfoProbe) return;
  std::set<unsigned> LineNos2;
  collect(F, LineNos2);
  assert (TheFn == &F && "Invalid function to measure!");

  for (std::set<unsigned>::iterator I = LineNos.begin(),
         E = LineNos.end(); I != E; ++I) {
    unsigned LineNo = *I;
    if (LineNos2.count(LineNo) == 0) {
      DEBUG(dbgs()
            << "DebugInfoProbe("
            << PassName
            << "): Losing dbg info for source line "
            << LineNo << "\n");
      ++NumDbgLineLost;
    }
  }

  std::set<MDNode *>DbgVariables2;
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();
         BI != BE; ++BI) {
      if (!isa<DbgInfoIntrinsic>(BI)) continue;
      Value *Addr = NULL;
      MDNode *Node = NULL;
      if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) {
        Addr = DDI->getAddress();
        Node = DDI->getVariable();
      } else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
        Addr = DVI->getValue();
        Node = DVI->getVariable();
      }
      if (Addr)
        DbgVariables2.insert(Node);
    }

  for (std::set<MDNode *>::iterator I = DbgVariables.begin(),
         E = DbgVariables.end(); I != E; ++I) {
    if (DbgVariables2.count(*I) == 0 && (*I)->getNumOperands() >= 2) {
      DEBUG(dbgs()
            << "DebugInfoProbe("
            << PassName
            << "): Losing dbg info for variable: ";
            if (MDString *MDS = dyn_cast_or_null<MDString>(
                (*I)->getOperand(2)))
              dbgs() << MDS->getString();
            else
              dbgs() << "...";
            dbgs() << "\n");
      ++NumDbgValueLost;
    }
  }
}

//===----------------------------------------------------------------------===//
// DebugInfoProbe

DebugInfoProbe::DebugInfoProbe() {
  pImpl = new DebugInfoProbeImpl();
}

DebugInfoProbe::~DebugInfoProbe() {
  delete pImpl;
}

/// initialize - Collect information before running an optimization pass.
void DebugInfoProbe::initialize(StringRef PName, Function &F) {
  pImpl->initialize(PName, F);
}

/// finalize - Collect information after running an optimization pass. This
/// must be used after initialization.
void DebugInfoProbe::finalize(Function &F) {
  pImpl->finalize(F);
}

/// report - Report findings. This should be invoked after finalize.
void DebugInfoProbe::report() {
  pImpl->report();
}

//===----------------------------------------------------------------------===//
// DebugInfoProbeInfo

/// ~DebugInfoProbeInfo - Report data collected by all probes before deleting
/// them.
DebugInfoProbeInfo::~DebugInfoProbeInfo() {
  if (!EnableDebugInfoProbe) return;
    for (StringMap<DebugInfoProbe*>::iterator I = Probes.begin(),
           E = Probes.end(); I != E; ++I) {
      I->second->report();
      delete I->second;
    }
  }

/// initialize - Collect information before running an optimization pass.
void DebugInfoProbeInfo::initialize(Pass *P, Function &F) {
  if (!EnableDebugInfoProbe) return;
  if (P->getAsPMDataManager())
    return;

  StringMapEntry<DebugInfoProbe *> &Entry =
    Probes.GetOrCreateValue(P->getPassName());
  DebugInfoProbe *&Probe = Entry.getValue();
  if (!Probe)
    Probe = new DebugInfoProbe();
  Probe->initialize(P->getPassName(), F);
}

/// finalize - Collect information after running an optimization pass. This
/// must be used after initialization.
void DebugInfoProbeInfo::finalize(Pass *P, Function &F) {
  if (!EnableDebugInfoProbe) return;
  if (P->getAsPMDataManager())
    return;
  StringMapEntry<DebugInfoProbe *> &Entry =
    Probes.GetOrCreateValue(P->getPassName());
  DebugInfoProbe *&Probe = Entry.getValue();
  assert (Probe && "DebugInfoProbe is not initialized!");
  Probe->finalize(F);
}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  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
//
//  Current versions can be found at www.libavg.de
//

#include "StringHelper.h"

#include <stdlib.h>
#include <ctype.h>
#include <algorithm>

using namespace std;

namespace avg {

bool isWhitespace(const string& s)
{
    return s.find_first_not_of(" \n\r\t") == s.npos;
}

void skipWhitespace(std::istream& is)
{
    string sWhitespace(" \n\r\t");
    bool bWhitespace;
    do {
        int i = is.peek();
        if (i == EOF) {
            bWhitespace = false;
        } else {
            bWhitespace = (sWhitespace.find(char(i)) != sWhitespace.npos);
        }
        if (bWhitespace) {
            is.ignore();
        }
    } while (bWhitespace);
}

void skipToken(std::istream& is, char token)
{
    skipWhitespace(is);
    int i = is.peek();
    if (i == token) {
        is.ignore();
    } else {
        is.setstate(ios::failbit);
    }
}

int stringToInt(const string& s)
{
    int i;
    fromString(s, i);
    return i;
}

double stringToDouble(const string& s)
{
    double d;
    fromString(s, d);
    return d;
}

bool stringToBool(const string& s)
{
    // avg usually wants xml attributes in lowercase, but python only
    // sees 'True' as true, so we'll accept that too. Also, python 2.3
    // has 1 as true, so that has to be ok too.
    if (s == "True" || s == "true" || s == "1") {
        return true;
    }
    if (s == "False" || s == "false" || s == "0") {
        return false;
    }
    throw (Exception(AVG_ERR_TYPE, string("Could not convert ")+s+" to bool."));
}

DPoint stringToDPoint(const std::string& s)
{
    DPoint pt;
    fromString(s, pt);
    return pt;
}

std::string removeStartEndSpaces(const string& s)
{
    string sResult = s;
    while (sResult[0] == ' ' || sResult[0] == '\n' || sResult[0] == '\r'
            || sResult[0] == '\t')
    {
        sResult.erase(0, 1);
    }
    char c = sResult[sResult.length()-1];
    while (c == ' ' || c == '\n' || c == '\r' || c == '\t') {
        sResult.erase(sResult.length()-1, 1);
        c = sResult[sResult.length()-1];
    }
    return sResult;
}

string tolower(const string& s)
{
    string sResult;
    char lower[2];
    lower[1] = 0;
    for (unsigned i=0; i<s.length(); ++i) {
        sResult.push_back(::tolower(s[i]));
    }
    return sResult;
}

bool equalIgnoreCase(const string& s1, const string& s2)
{
    if (s1.length() != s2.length()) {
        return false;
    }
    string sUpper1;
    string sUpper2;
    transform(s1.begin(), s1.end(), std::back_inserter(sUpper1), (int(*)(int)) toupper);
    transform(s2.begin(), s2.end(), std::back_inserter(sUpper2), (int(*)(int)) toupper);
    return sUpper1 == sUpper2;
}

}

<commit_msg>gcc 4.4 fix.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  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
//
//  Current versions can be found at www.libavg.de
//

#include "StringHelper.h"

#include <stdlib.h>
#include <ctype.h>
#include <algorithm>
#include <cstdio>

using namespace std;

namespace avg {

bool isWhitespace(const string& s)
{
    return s.find_first_not_of(" \n\r\t") == s.npos;
}

void skipWhitespace(std::istream& is)
{
    string sWhitespace(" \n\r\t");
    bool bWhitespace;
    do {
        int i = is.peek();
        if (i == EOF) {
            bWhitespace = false;
        } else {
            bWhitespace = (sWhitespace.find(char(i)) != sWhitespace.npos);
        }
        if (bWhitespace) {
            is.ignore();
        }
    } while (bWhitespace);
}

void skipToken(std::istream& is, char token)
{
    skipWhitespace(is);
    int i = is.peek();
    if (i == token) {
        is.ignore();
    } else {
        is.setstate(ios::failbit);
    }
}

int stringToInt(const string& s)
{
    int i;
    fromString(s, i);
    return i;
}

double stringToDouble(const string& s)
{
    double d;
    fromString(s, d);
    return d;
}

bool stringToBool(const string& s)
{
    // avg usually wants xml attributes in lowercase, but python only
    // sees 'True' as true, so we'll accept that too. Also, python 2.3
    // has 1 as true, so that has to be ok too.
    if (s == "True" || s == "true" || s == "1") {
        return true;
    }
    if (s == "False" || s == "false" || s == "0") {
        return false;
    }
    throw (Exception(AVG_ERR_TYPE, string("Could not convert ")+s+" to bool."));
}

DPoint stringToDPoint(const std::string& s)
{
    DPoint pt;
    fromString(s, pt);
    return pt;
}

std::string removeStartEndSpaces(const string& s)
{
    string sResult = s;
    while (sResult[0] == ' ' || sResult[0] == '\n' || sResult[0] == '\r'
            || sResult[0] == '\t')
    {
        sResult.erase(0, 1);
    }
    char c = sResult[sResult.length()-1];
    while (c == ' ' || c == '\n' || c == '\r' || c == '\t') {
        sResult.erase(sResult.length()-1, 1);
        c = sResult[sResult.length()-1];
    }
    return sResult;
}

string tolower(const string& s)
{
    string sResult;
    char lower[2];
    lower[1] = 0;
    for (unsigned i=0; i<s.length(); ++i) {
        sResult.push_back(::tolower(s[i]));
    }
    return sResult;
}

bool equalIgnoreCase(const string& s1, const string& s2)
{
    if (s1.length() != s2.length()) {
        return false;
    }
    string sUpper1;
    string sUpper2;
    transform(s1.begin(), s1.end(), std::back_inserter(sUpper1), (int(*)(int)) toupper);
    transform(s2.begin(), s2.end(), std::back_inserter(sUpper2), (int(*)(int)) toupper);
    return sUpper1 == sUpper2;
}

}

<|endoftext|>


<commit_before>/* Copyright 2014 Peter Goodman, all rights reserved. */

#include "clients/lifetime/metadata.h"
#include "clients/lifetime/instrument.h"

using namespace granary;

namespace client {

// A function invoked on every memory read of a watched address `addr`.
void on_read(uintptr_t addr, int num_bytes) {
  auto obj_meta = wp::descriptor_of(addr);
  auto ds_meta = obj_meta->data_structure;
  auto byte_offset_in_struct = addr - obj_meta->base_addr;
  granary::printf(
      "Reading %d bytes from address %lx, %u bytes into struct of size %u\n",
      num_bytes, addr, byte_offset_in_struct, ds_meta->num_bytes);

  // TODO(akshay):
  //    1) Update read counter for the associated bytes.
  //    2) Determine the value being read. This will required using
  //       the `unwatched_addr` function on `addr`, then casting it to an
  //       pointer to an integral type whose size matches `num_bytes`, de-
  //       referencing the pointer (to read the data).
  //    3) Store the value being read into the `ds_meta` somehow.
  //        a) We might want to store some number of values and the number of
  //           times we saw that value. If the number of distinct values seen
  //           exceeds some small threshold, then treat the field as non-
  //           constant.
}

// A function invoked on every memory write to a watched address `addr`.
void on_write(uintptr_t addr, unsigned long num_bytes) {
  auto obj_meta = wp::descriptor_of(addr);
  auto ds_meta = obj_meta->data_structure;
  auto byte_offset_in_struct = addr - obj_meta->base_addr;
  granary::printf(
      "Writing %d bytes to address %lx, %u bytes into struct of size %u\n",
      num_bytes, addr, byte_offset_in_struct, ds_meta->num_bytes);
}

// Versions of the above functions that are safe to call from within
// instrumented code.
app_pc on_read_func = nullptr;
app_pc on_write_func = nullptr;

// Initialize this client / tool. This creates the safe/clean-callable versions
// of the `on_read` and `on_write` callback functions.
void init(void) {
  cpu_state_handle cpu;
  IF_TEST( cpu->in_granary = false; )
  cpu.free_transient_allocators();
  on_read_func = generate_clean_callable_address(on_read);
  cpu.free_transient_allocators();
  on_write_func = generate_clean_callable_address(on_write);
}

DEFINE_READ_VISITOR(lifetime, {
  insert_clean_call_after(ls, label, on_read_func, op, (unsigned long) size);
})

DEFINE_WRITE_VISITOR(lifetime, {
  insert_clean_call_after(ls, label, on_write_func, op, (unsigned long) size);
})

DEFINE_INTERRUPT_VISITOR(lifetime, {})

}  // namespace client
<commit_msg>Minor updates.<commit_after>/* Copyright 2014 Peter Goodman, all rights reserved. */

#include "clients/lifetime/metadata.h"
#include "clients/lifetime/instrument.h"

using namespace granary;

namespace client {

// A function invoked on every memory read of a watched address `addr`.
void on_read(uintptr_t addr, unsigned long num_bytes) {
  auto obj_meta = wp::descriptor_of(addr);
  auto ds_meta = obj_meta->data_structure;
  auto byte_offset_in_struct = addr - obj_meta->base_addr;
  granary::printf(
      "Reading %d bytes from address %lx, %u bytes into struct of size %u\n",
      num_bytes, addr, byte_offset_in_struct, ds_meta->num_bytes);

  // TODO(akshay):
  //    1) Update read counter for the associated bytes.
  //    2) Determine the value being read. This will required using
  //       the `unwatched_addr` function on `addr`, then casting it to an
  //       pointer to an integral type whose size matches `num_bytes`, de-
  //       referencing the pointer (to read the data).
  //    3) Store the value being read into the `ds_meta` somehow.
  //        a) We might want to store some number of values and the number of
  //           times we saw that value. If the number of distinct values seen
  //           exceeds some small threshold, then treat the field as non-
  //           constant.
}

// A function invoked on every memory write to a watched address `addr`.
void on_write(uintptr_t addr, unsigned long num_bytes) {
  auto obj_meta = wp::descriptor_of(addr);
  auto ds_meta = obj_meta->data_structure;
  auto byte_offset_in_struct = addr - obj_meta->base_addr;
  granary::printf(
      "Writing %d bytes to address %lx, %u bytes into struct of size %u\n",
      num_bytes, addr, byte_offset_in_struct, ds_meta->num_bytes);

  // TODO(akshay): Similar to above, but for writes. For writes we don't care
  //               about the value being written, because specializing on writes
  //               is unlikely to lead very far at a large scale.
}

// Versions of the above functions that are safe to call from within
// instrumented code.
app_pc on_read_func = nullptr;
app_pc on_write_func = nullptr;

// Initialize this client / tool. This creates the safe/clean-callable versions
// of the `on_read` and `on_write` callback functions.
void init(void) {
  cpu_state_handle cpu;
  IF_TEST( cpu->in_granary = false; )
  cpu.free_transient_allocators();
  on_read_func = generate_clean_callable_address(on_read);
  cpu.free_transient_allocators();
  on_write_func = generate_clean_callable_address(on_write);
}

// Inject a function call to `on_read` before every memory read of a
// watched address.
DEFINE_READ_VISITOR(lifetime, {
  insert_clean_call_after(ls, label, on_read_func, op, (unsigned long) size);
})

// Inject a function call to `on_write` before every memory write to a
// watched address.
DEFINE_WRITE_VISITOR(lifetime, {
  insert_clean_call_after(ls, label, on_write_func, op, (unsigned long) size);
})

DEFINE_INTERRUPT_VISITOR(lifetime, {})

}  // namespace client
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2012,2015,2017 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ron Dreslinski
 *          Andreas Hansson
 *          William Wang
 */

/**
 * @file
 * Port Object Declaration.
 */

#ifndef __SIM_PORT_HH__
#define __SIM_PORT_HH__

#include <string>

#include "base/types.hh"

/**
 * Ports are used to interface objects to each other.
 */
class Port
{

  private:

    /** Descriptive name (for DPRINTF output) */
    const std::string portName;

  protected:

    /**
     * A numeric identifier to distinguish ports in a vector, and set
     * to InvalidPortID in case this port is not part of a vector.
     */
    const PortID id;

    /**
     * A pointer to this port's peer.
     */
    Port *_peer;

    /**
     * Whether this port is currently connected to a peer port.
     */
    bool _connected;

    /**
     * Abstract base class for ports
     *
     * @param _name Port name including the owners name
     * @param _id A port identifier for vector ports
     */
    Port(const std::string& _name, PortID _id);

    /**
     * Virtual destructor due to inheritance.
     */
    virtual ~Port();

  public:

    /** Return a reference to this port's peer. */
    Port &getPeer() { return *_peer; }

    /** Return port name (for DPRINTF). */
    const std::string name() const { return portName; }

    /** Get the port id. */
    PortID getId() const { return id; }

    /** Attach to a peer port. */
    virtual void
    bind(Port &peer)
    {
        _peer = &peer;
        _connected = true;
    }

    /** Dettach from a peer port. */
    virtual void
    unbind()
    {
        _peer = nullptr;
        _connected = false;
    }

    /** Is this port currently connected to a peer? */
    bool isConnected() const { return _connected; }

    /** A utility function to make it easier to swap out ports. */
    void
    takeOverFrom(Port *old)
    {
        assert(old);
        assert(old->isConnected());
        assert(!isConnected());
        Port &peer = old->getPeer();
        assert(peer.isConnected());

        // Disconnect the original binding.
        old->unbind();
        peer.unbind();

        // Connect the new binding.
        peer.bind(*this);
        bind(peer);
    }
};

static inline std::ostream &
operator << (std::ostream &os, const Port &port)
{
    os << port.name();
    return os;
}

#endif //__SIM_PORT_HH__
<commit_msg>sim: Move destructor of Port to public<commit_after>/*
 * Copyright (c) 2011-2012,2015,2017 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ron Dreslinski
 *          Andreas Hansson
 *          William Wang
 */

/**
 * @file
 * Port Object Declaration.
 */

#ifndef __SIM_PORT_HH__
#define __SIM_PORT_HH__

#include <string>

#include "base/types.hh"

/**
 * Ports are used to interface objects to each other.
 */
class Port
{

  private:

    /** Descriptive name (for DPRINTF output) */
    const std::string portName;

  protected:

    /**
     * A numeric identifier to distinguish ports in a vector, and set
     * to InvalidPortID in case this port is not part of a vector.
     */
    const PortID id;

    /**
     * A pointer to this port's peer.
     */
    Port *_peer;

    /**
     * Whether this port is currently connected to a peer port.
     */
    bool _connected;

    /**
     * Abstract base class for ports
     *
     * @param _name Port name including the owners name
     * @param _id A port identifier for vector ports
     */
    Port(const std::string& _name, PortID _id);

  public:

    /**
     * Virtual destructor due to inheritance.
     */
    virtual ~Port();

    /** Return a reference to this port's peer. */
    Port &getPeer() { return *_peer; }

    /** Return port name (for DPRINTF). */
    const std::string name() const { return portName; }

    /** Get the port id. */
    PortID getId() const { return id; }

    /** Attach to a peer port. */
    virtual void
    bind(Port &peer)
    {
        _peer = &peer;
        _connected = true;
    }

    /** Dettach from a peer port. */
    virtual void
    unbind()
    {
        _peer = nullptr;
        _connected = false;
    }

    /** Is this port currently connected to a peer? */
    bool isConnected() const { return _connected; }

    /** A utility function to make it easier to swap out ports. */
    void
    takeOverFrom(Port *old)
    {
        assert(old);
        assert(old->isConnected());
        assert(!isConnected());
        Port &peer = old->getPeer();
        assert(peer.isConnected());

        // Disconnect the original binding.
        old->unbind();
        peer.unbind();

        // Connect the new binding.
        peer.bind(*this);
        bind(peer);
    }
};

static inline std::ostream &
operator << (std::ostream &os, const Port &port)
{
    os << port.name();
    return os;
}

#endif //__SIM_PORT_HH__
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 ScyllaDB
 */

#include "build_id.hh"
#include <fmt/printf.h>
#include <link.h>
#include <seastar/core/align.hh>
#include <sstream>

using namespace seastar;

static const Elf64_Phdr* get_pt_note(dl_phdr_info* info) {
    const auto* h = info->dlpi_phdr;
    auto num_headers = info->dlpi_phnum;
    for (int i = 0; i != num_headers; ++i, ++h) {
        if (h->p_type == PT_NOTE) {
            return h;
        }
    }
    assert(0 && "no PT_NOTE programe header");
}

static const Elf64_Nhdr* get_nt_build_id(dl_phdr_info* info) {
    auto* h = get_pt_note(info);
    auto base = info->dlpi_addr;

    auto* p = reinterpret_cast<const char*>(base) + h->p_vaddr;
    auto* e = p + h->p_memsz;
    while (p != e) {
        const auto* n = reinterpret_cast<const Elf64_Nhdr*>(p);
        if (n->n_type == NT_GNU_BUILD_ID) {
            return n;
        }

        p += sizeof(Elf64_Nhdr);

        p += n->n_namesz;
        p = align_up(p, 4);

        p += n->n_descsz;
        p = align_up(p, 4);
    }
    assert(0 && "no NT_GNU_BUILD_ID note");
}

static int callback(dl_phdr_info* info, size_t size, void* data) {
    std::string& ret = *(std::string*)data;
    std::ostringstream os;

    // The first DSO is always the main program, which has an empty name.
    assert(strlen(info->dlpi_name) == 0);

    auto* n = get_nt_build_id(info);
    auto* p = reinterpret_cast<const char*>(n);

    p += sizeof(Elf64_Nhdr);

    p += n->n_namesz;
    p = align_up(p, 4);

    const char* desc = p;
    for (unsigned i = 0; i < n->n_descsz; ++i) {
        fmt::fprintf(os, "%02x", (unsigned char)*(desc + i));
    }
    ret = os.str();
    return 1;
}

std::string get_build_id() {
    std::string ret;
    int r = dl_iterate_phdr(callback, &ret);
    assert(r == 1);
    return ret;
}
<commit_msg>build-id: Handle the binary having multiple PT_NOTE headers<commit_after>/*
 * Copyright (C) 2019 ScyllaDB
 */

#include "build_id.hh"
#include <fmt/printf.h>
#include <link.h>
#include <seastar/core/align.hh>
#include <sstream>

using namespace seastar;

static const Elf64_Nhdr* get_nt_build_id(dl_phdr_info* info) {
    auto base = info->dlpi_addr;
    const auto* h = info->dlpi_phdr;
    auto num_headers = info->dlpi_phnum;
    for (int i = 0; i != num_headers; ++i, ++h) {
        if (h->p_type != PT_NOTE) {
            continue;
        }

        auto* p = reinterpret_cast<const char*>(base) + h->p_vaddr;
        auto* e = p + h->p_memsz;
        while (p != e) {
            const auto* n = reinterpret_cast<const Elf64_Nhdr*>(p);
            if (n->n_type == NT_GNU_BUILD_ID) {
                return n;
            }

            p += sizeof(Elf64_Nhdr);

            p += n->n_namesz;
            p = align_up(p, 4);

            p += n->n_descsz;
            p = align_up(p, 4);
        }
    }

    assert(0 && "no NT_GNU_BUILD_ID note");
}

static int callback(dl_phdr_info* info, size_t size, void* data) {
    std::string& ret = *(std::string*)data;
    std::ostringstream os;

    // The first DSO is always the main program, which has an empty name.
    assert(strlen(info->dlpi_name) == 0);

    auto* n = get_nt_build_id(info);
    auto* p = reinterpret_cast<const char*>(n);

    p += sizeof(Elf64_Nhdr);

    p += n->n_namesz;
    p = align_up(p, 4);

    const char* desc = p;
    for (unsigned i = 0; i < n->n_descsz; ++i) {
        fmt::fprintf(os, "%02x", (unsigned char)*(desc + i));
    }
    ret = os.str();
    return 1;
}

std::string get_build_id() {
    std::string ret;
    int r = dl_iterate_phdr(callback, &ret);
    assert(r == 1);
    return ret;
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Baidu, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Authors: Ge,Jun (gejun@baidu.com)

#include "brpc/retry_policy.h"

namespace brpc {

RetryPolicy::~RetryPolicy() {}

class RpcRetryPolicy : public RetryPolicy {
public:
    bool DoRetry(const Controller* controller) const {
        const int error_code = controller->ErrorCode();
        if (!error_code) {
            return false;
        }
        return (EFAILEDSOCKET == error_code
                || EEOF == error_code
                || EHOSTDOWN == error_code
                || ELOGOFF == error_code
                || ETIMEDOUT == error_code // This is not timeout of RPC.
                || ELIMIT == error_code
                || ENOENT == error_code
                || EPIPE == error_code
                || ECONNREFUSED == error_code
                || ECONNRESET == error_code
                || ENODATA == error_code
                || EOVERCROWDED == error_code);
    }
};

// NOTE(gejun): g_default_policy can't be deleted on process's exit because
// concurrent processing of responses at client-side may trigger retry and
// use the policy.
static pthread_once_t g_default_policy_once = PTHREAD_ONCE_INIT;
static RpcRetryPolicy* g_default_policy = NULL;
static void init_default_policy() {
    g_default_policy = new RpcRetryPolicy;
}
const RetryPolicy* DefaultRetryPolicy() {
    pthread_once(&g_default_policy_once, init_default_policy);
    return g_default_policy;
}

} // namespace brpc
<commit_msg>Retry for EH2RUNOUTSTREAMS<commit_after>// Copyright (c) 2016 Baidu, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Authors: Ge,Jun (gejun@baidu.com)

#include "brpc/retry_policy.h"

namespace brpc {

RetryPolicy::~RetryPolicy() {}

class RpcRetryPolicy : public RetryPolicy {
public:
    bool DoRetry(const Controller* controller) const {
        const int error_code = controller->ErrorCode();
        if (!error_code) {
            return false;
        }
        return (EFAILEDSOCKET == error_code
                || EEOF == error_code
                || EHOSTDOWN == error_code
                || ELOGOFF == error_code
                || ETIMEDOUT == error_code // This is not timeout of RPC.
                || ELIMIT == error_code
                || ENOENT == error_code
                || EPIPE == error_code
                || ECONNREFUSED == error_code
                || ECONNRESET == error_code
                || ENODATA == error_code
                || EOVERCROWDED == error_code
                || EH2RUNOUTSTREAMS == error_code);
    }
};

// NOTE(gejun): g_default_policy can't be deleted on process's exit because
// client-side may still retry and use the policy at exit
static pthread_once_t g_default_policy_once = PTHREAD_ONCE_INIT;
static RpcRetryPolicy* g_default_policy = NULL;
static void init_default_policy() {
    g_default_policy = new RpcRetryPolicy;
}
const RetryPolicy* DefaultRetryPolicy() {
    pthread_once(&g_default_policy_once, init_default_policy);
    return g_default_policy;
}

} // namespace brpc
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "BZAdminClient.h"
#include "BZAdminUI.h"

void BZAdminUI::handleNewPacket(uint16_t) {
  if (client.getLastMessage().first.size() > 0)
    outputMessage(client.getLastMessage().first,
		  client.getLastMessage().second);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>get rid of mangling to long warnings<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifdef _WIN32
#pragma warning(4:4786)
#endif

#include "BZAdminClient.h"
#include "BZAdminUI.h"

void BZAdminUI::handleNewPacket(uint16_t) {
  if (client.getLastMessage().first.size() > 0)
    outputMessage(client.getLastMessage().first,
		  client.getLastMessage().second);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "ServerMenu.h"

/* common implementation headers */
#include "FontManager.h"
#include "StateDatabase.h"

/* local implementation headers */
#include "FontSizer.h"
#include "MainMenu.h"
#include "HUDDialogStack.h"
#include "clientConfig.h"
#include "ConfigFileManager.h"
#include "bzflag.h"
#include "LocalFontFace.h"
#include "playing.h"

bool ServerMenuDefaultKey::keyPress(const BzfKeyEvent& key)
{
  ServerList &serverList = ServerList::instance();

  HUDuiServerList* activeTab( dynamic_cast<HUDuiServerList*>(menu->tabbedControl->getActiveTab()));
  // This may be a bit Draconian, since not all the tests below
  // actually depend on the active tab being of type HUDuiServerList*,
  // but they were all blindly casting before, so assume this is a SNH
  // condition
  if (activeTab == 0) return false;

  // Note that many of the if statments below test for this condition
  // as well and have a different return. Seems like a logic error.
  if (activeTab == static_cast<HUDuiControl*>(menu->customTabControl))
    return MenuDefaultKey::keyPress(key);

  if (key.chr == 'f') {
    if ((activeTab == menu->favoritesList) ||
	(activeTab->hasFocus()) ||
	(menu->tabbedControl->hasFocus()))
      return false;
    if (activeTab != 0) {
      serverList.markAsFavorite(activeTab->getSelectedServer());
      return true;
    }
    return false;
  }

  if (key.chr == 'c') {
    if ((activeTab == static_cast<HUDuiControl*>(menu->customTabControl)) ||
	(activeTab == menu->normalList))
      return false;

    if (activeTab == menu->favoritesList) {
      for (size_t i=0; i<activeTab->getSize(); i++) {
	serverList.unmarkAsFavorite(activeTab->get(i)->getServer());
      }
    }

    if (activeTab == menu->recentList) {
      for (size_t i=0; i<activeTab->getSize(); i++) {
	serverList.unmarkAsRecent(activeTab->get(i)->getServer());
      }
    }

    activeTab->clearList();
    return true;
  }

  if (key.chr == 'v') {
    if ((activeTab == menu->favoritesList) ||
	(activeTab == menu->normalList) ||
	(activeTab == menu->recentList))
      return false;

    std::string tabName = menu->tabbedControl->getActiveTabName();
    HUDuiServerListCache::instance().removeList(activeTab, tabName);
    menu->tabbedControl->removeTab(activeTab, tabName);
  }

  if (key.chr == 'r') {
    ServerList::instance().clear();
    ServerList::instance().startServerPings(getStartupInfo());
    return true;
  }

  if (key.chr == 'h') {
    if ((activeTab == menu->normalList) ||
	(activeTab->hasFocus()) ||
	(menu->tabbedControl->hasFocus()))
      return false;

    if (activeTab == menu->favoritesList)
      serverList.unmarkAsFavorite(activeTab->getSelectedServer());

    if (activeTab == menu->recentList)
      serverList.unmarkAsRecent(activeTab->getSelectedServer());

    activeTab->removeItem(activeTab->getSelectedServer());
    return true;
  }

  return MenuDefaultKey::keyPress(key);
}

bool ServerMenuDefaultKey::keyRelease(const BzfKeyEvent& key)
{
  switch (key.chr) {
  case 27: // escape
  case 13: // return
    return true;
  }

  return false;
}

ServerMenu::PingsMap ServerMenu::activePings;

ServerMenu::ServerMenu()
  : normalList(0)
  , recentList(0)
  , favoritesList(0)
  , tabbedControl(0)
  , serverInfo(new HUDuiServerInfo())
  , customTabControl(new HUDuiServerListCustomTab())
  , listsCache(HUDuiServerListCache::instance())
  , serverList(ServerList::instance())
  , defaultKey(this)
  , title(0)
  , help(0)
{
  // cache font face ID
  const LocalFontFace* fontFace = MainMenu::getFontFace();

  addPlayingCallback(&playingCB, this);

  serverList.updateFromCache();
  serverList.startServerPings(getStartupInfo());
  listsCache.loadCache();

  std::vector<std::pair<HUDuiServerList*, std::string> > cachedLists = listsCache.readCachedLists();

  if (cachedLists.size() > (size_t) 0) {
    normalList = cachedLists[0].first;
    recentList = cachedLists[1].first;
    favoritesList = cachedLists[2].first;
  } else {
    normalList = new HUDuiServerList;
    favoritesList = new HUDuiServerList;
    recentList = new HUDuiServerList;
    listsCache.addNewList(normalList, "");
    listsCache.addNewList(favoritesList, "");
    listsCache.addNewList(recentList, "");
  }

  normalList->setFontFace(fontFace);
  favoritesList->setFontFace(fontFace);
  recentList->setFontFace(fontFace);
  serverInfo->setFontFace(fontFace);
  customTabControl->setFontFace(fontFace);

  title = new HUDuiLabel();
  title->setString("Servers");
  title->setFontFace(fontFace);

  help = new HUDuiLabel();
  help->setString("f - add server to favorites      h - remove server from tab      c - clear tab      v - delete tab      r - refresh server list");
  help->setFontFace(fontFace);

  tabbedControl = new HUDuiTabbedControl;
  tabbedControl->setFontFace(fontFace);
  tabbedControl->addTab(normalList, "All");
  tabbedControl->addTab(recentList, "Recent");
  tabbedControl->addTab(favoritesList, "Favorites");

  for (size_t i=3; i<cachedLists.size(); i++) {
    cachedLists[i].first->setFontFace(fontFace);
    tabbedControl->addTab(cachedLists[i].first, cachedLists[i].second);
  }

  tabbedControl->addTab(customTabControl, "Create New Tab");
  tabbedControl->setActiveTab(0);

  serverList.addServerCallback(newServer, normalList);
  serverList.addFavoriteServerCallback(newServer, favoritesList);
  serverList.addRecentServerCallback(newServer, recentList);

  addControl(title, false);
  addControl(tabbedControl);
  addControl(serverInfo);
  addControl(help, false);

  initNavigation();
}

ServerMenu::~ServerMenu()
{
  serverList.removeServerCallback(newServer, normalList);
  serverList.removeFavoriteServerCallback(newServer, favoritesList);
  serverList.removeRecentServerCallback(newServer, recentList);
}

void ServerMenu::newServer(ServerItem* addedServer, void* data)
{
  HUDuiServerList* serverData( static_cast<HUDuiServerList*>(data) );

  // Server already has a ping
  if (addedServer->ping.pingTime != 0) {
    serverData->addItem(addedServer);
    return;
  }

  // Pinging in process, add on to the list vector
  if (addedServer->ping.pinging) {
    ServerMenu::activePings[addedServer->getServerKey()].second.push_back(serverData);
  }

  ServerPing* newping = new ServerPing(addedServer->ping.serverId.serverHost, ntohs(addedServer->ping.serverId.port));
  newping->start();
  std::vector<HUDuiServerList*> serverListsVector;
  serverListsVector.push_back(serverData);
  ServerMenu::activePings.insert(PingsMap::value_type(addedServer->getServerKey(), std::pair<ServerPing*, std::vector<HUDuiServerList*> >(newping, serverListsVector)));
  addedServer->ping.pinging = true;
}

void ServerMenu::execute()
{
  if ((tabbedControl->getActiveTab() == customTabControl) &&
      (dynamic_cast<HUDuiServerListCustomTab*>(tabbedControl->getActiveTab())->createNew->hasFocus()))
  {
    HUDuiServerList* newServerList = customTabControl->createServerList();
    listsCache.addNewList(newServerList, customTabControl->tabName->getString());
    tabbedControl->addTab(newServerList, customTabControl->tabName->getString(), tabbedControl->getTabCount() - 1);
    for (size_t i=0; i<serverList.size(); i++) {
      newServerList->addItem(serverList.getServerAt(i));
    }
    //newServerList->searchServers(customTabControl->serverName->getString());
    dynamic_cast<HUDuiNestedContainer*>(tabbedControl->getTab(tabbedControl->getTabCount() - 2))->getNav().set(1);
    return;
  }

  if ((tabbedControl->hasFocus())||
      (tabbedControl->getActiveTab()->hasFocus())||
      (tabbedControl->getActiveTabName() == "Create New Tab"))
    return;

  // update startup info
  StartupInfo* info = getStartupInfo();
  ServerItem* selectedServer = dynamic_cast<HUDuiServerList*>(tabbedControl->getActiveTab())->getSelectedServer();
  strncpy(info->serverName, selectedServer->name.c_str(), ServerNameLen-1);
  info->serverPort = ntohs((unsigned short) selectedServer->ping.serverId.port);

  // all done
  HUDDialogStack::get()->pop();
}

void ServerMenu::resize(int _width, int _height)
{
  HUDDialog::resize(_width, _height);
  FontSizer fs = FontSizer(_width, _height);

  FontManager &fm = FontManager::instance();
  const LocalFontFace* fontFace = MainMenu::getFontFace();

  // reposition title
  float x, y;

  // use a big font for title, smaller font for the rest
  fs.setMin(0, (int)(1.0 / BZDB.eval("headerFontSize") / 2.0));
  const float titleFontSize = fs.getFontSize(fontFace->getFMFace(), "headerFontSize");

  title->setFontSize(titleFontSize);
  const float titleWidth = fm.getStringWidth(fontFace->getFMFace(), titleFontSize, title->getString().c_str());
  const float titleHeight = fm.getStringHeight(fontFace->getFMFace(), titleFontSize);
  x = 0.5f * ((float)_width - titleWidth);
  y = (float)_height - titleHeight;
  title->setPosition(x, y);

  fs.setMin(40,10);
  const float fontSize = fs.getFontSize(fontFace->getFMFace(), "alertFontSize");

  float edgeSpacer = fm.getStringWidth(fontFace->getFMFace(), fontSize, "X");
  float bottomSpacer = fm.getStringHeight(fontFace->getFMFace(), fontSize);

  float remainingSpace = y - bottomSpacer*2;
  float listHeight = remainingSpace*0.65f;

  tabbedControl->setSize((_width - (2*edgeSpacer)),listHeight);
  serverInfo->setSize((_width - (2*edgeSpacer)), (remainingSpace - 4*bottomSpacer)*0.35f);

  y = y - (titleHeight/2) - tabbedControl->getHeight();

  float helpLength = fm.getStringWidth(fontFace->getFMFace(), fontSize, help->getString().c_str());

  tabbedControl->setPosition(edgeSpacer, y);
  serverInfo->setPosition(edgeSpacer, bottomSpacer/2 + bottomSpacer);
  help->setPosition((_width - helpLength)/2, bottomSpacer/2);
  tabbedControl->setFontSize(fontSize);
  serverInfo->setFontSize(fontSize);
  help->setFontSize(fontSize);
}

void ServerMenu::updateStatus()
{
  if (tabbedControl->hasFocus() ||
      tabbedControl->getActiveTab()->hasFocus() ||
      tabbedControl->getActiveTabName() == "Create New Tab")
    serverInfo->setServerItem(NULL);
  else
    serverInfo->setServerItem(dynamic_cast<HUDuiServerList*>(tabbedControl->getActiveTab())->getSelectedServer());
}

void ServerMenu::playingCB(void* _self)
{
  ServerList &list = ServerList::instance();
  for (PingsMap::iterator i = ServerMenu::activePings.begin();
       i != ServerMenu::activePings.end();) {
    i->second.first->doPings();
    if (i->second.first->done()) {
      ServerItem* server = list.lookupServer(i->first);
      if (server == NULL)
	break;
      server->ping.pingTime = i->second.first->calcLag();
      server->ping.pinging = false;
      for (size_t j=0; j<(i->second.second.size()); j++) {
	i->second.second[j]->addItem(server);
      }
      delete i->second.first;
      ServerMenu::activePings.erase(i++);
      continue;
    }
    ++i;
  }

  static_cast<ServerMenu*>(_self)->serverList.checkEchos(getStartupInfo());
  static_cast<ServerMenu*>(_self)->updateStatus();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Bug fix for creating new tabs in the server listing. Also adds some comments to the changed code.<commit_after>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "ServerMenu.h"

/* common implementation headers */
#include "FontManager.h"
#include "StateDatabase.h"

/* local implementation headers */
#include "FontSizer.h"
#include "MainMenu.h"
#include "HUDDialogStack.h"
#include "clientConfig.h"
#include "ConfigFileManager.h"
#include "bzflag.h"
#include "LocalFontFace.h"
#include "playing.h"

bool ServerMenuDefaultKey::keyPress(const BzfKeyEvent& key)
{
  ServerList &serverList = ServerList::instance();

  HUDuiControl* activeTabControl = menu->tabbedControl->getActiveTab();
  HUDuiServerList* activeServerList = NULL;

  // The currently active tab is the custom tab creation control. We don't handle
  // any key presses for that here, so pass it on, and return the result we get.
  if (activeTabControl == menu->customTabControl) // Is this the right way to check?
    return MenuDefaultKey::keyPress(key);
  // The currently active tab is NOT the custom tab, so let's try casting it as a
  // HUDuiServerList control. For the server browser we only expect controls of type
  // HUDuiServerListCustomTab, or HUDuiServerList. However, since we are using a
  // HUDuiTabbedControl, we could have any subclass of HUDuiControl, so we have to
  // be careful to check what class we are dealing with when executing key presses.
  else
    activeServerList = dynamic_cast<HUDuiServerList*>(activeTabControl);

  // The active tab is not the custom tab control, and is not a HUDuiServerList
  // Right now we're handling input that affects either custom tab creation, or
  // server list browsing. Since this is neither, return false, we don't handle it.
  if ((activeServerList == 0)||(activeServerList == NULL))
    // dynamic_cast returns 0 if it fails
    return false;

  // These key presses should only be processed when the user has a server selected.
  // As such, we should check to see if the server list, or the tabbed control have
  // focus, and if they do, ignore these key presses for now. Also check that the
  // user has a server selected.
  if ((!activeServerList->hasFocus())&&(!menu->tabbedControl->hasFocus())&&
     (activeServerList->getSelectedServer() != NULL)){
    // The favorite key was pressed
    if (key.chr == 'f') {
	  // Check to see if we're on the favorites list, if we are, ignore keypress
	  if (activeServerList == menu->favoritesList) {
	    return false;
	  }
	  else {
        // Mark it as a favorite server
	    serverList.markAsFavorite(activeServerList->getSelectedServer());
	    return true;
	  }
    }

	// The remove server key was pressed
    if (key.chr == 'h') {
	  // Design decision: Don't let users remove any servers from the normal server
      // list. Let's keep this as a pure representation of all the available servers
      if (activeServerList == menu->normalList)
        return false;

	  // If we're on the favorites list, we need to unmark the server
	  // as a favorite server in order to remove it from the list
      if (activeServerList == menu->favoritesList)
        serverList.unmarkAsFavorite(activeServerList->getSelectedServer());

	  // If we're on the recents list, we need to unmark the server
	  // as a recent server in order to remove it from the list
      if (activeServerList == menu->recentList)
        serverList.unmarkAsRecent(activeServerList->getSelectedServer());

      // Remove the selected server from the active server list
      activeServerList->removeItem(activeServerList->getSelectedServer());
      return true;
    }
  }

  // The clear server list key was pressed
  if (key.chr == 'c') {
	// Design decision: Don't let users remove any servers from the normal server
    // list. Let's keep this as a pure representation of all the available servers
    if (activeServerList == menu->normalList)
      return false;

	// If we're on the favorites list, cycle through all favorite servers and unmark
	// them as favorites. This may be a bad idea, it's fairly easy to accidentally
	// clear your favorites list using this functionality.
    if (activeServerList == menu->favoritesList) {
      for (size_t i=0; i<activeServerList->getSize(); i++) {
        serverList.unmarkAsFavorite(activeServerList->get(i)->getServer());
      }
    }

	// If we're on the recent server list, cycle through all
	// recent servers and unmark them as a recent server.
    if (activeServerList == menu->recentList) {
      for (size_t i=0; i<activeServerList->getSize(); i++) {
        serverList.unmarkAsRecent(activeServerList->get(i)->getServer());
      }
    }

	// Clear the list
    activeServerList->clearList();
    return true;
  }

  // Remove the current tab. This can be pressed at any
  // time, but only works if the user is on a custom tab.
  if (key.chr == 'v') {
    // Do nothing if the user is on any of the standard tabs
    if ((activeServerList == menu->favoritesList) ||
	(activeServerList == menu->normalList) ||
	(activeServerList == menu->recentList))
      return false;

	// Remove the current tab from the tabbed control
    std::string tabName = menu->tabbedControl->getActiveTabName();
    HUDuiServerListCache::instance().removeList(activeServerList, tabName);
    menu->tabbedControl->removeTab(activeServerList, tabName);
	return true;
  }

  // Refresh the server list. This can be done at any time.
  if (key.chr == 'r') {
    ServerList::instance().clear();
    ServerList::instance().startServerPings(getStartupInfo());
    return true;
  }

  return MenuDefaultKey::keyPress(key);
}

bool ServerMenuDefaultKey::keyRelease(const BzfKeyEvent& key)
{
  switch (key.chr) {
  case 27: // escape
  case 13: // return
    return true;
  }

  return false;
}

ServerMenu::PingsMap ServerMenu::activePings;

ServerMenu::ServerMenu()
  : normalList(0)
  , recentList(0)
  , favoritesList(0)
  , tabbedControl(0)
  , serverInfo(new HUDuiServerInfo())
  , customTabControl(new HUDuiServerListCustomTab())
  , listsCache(HUDuiServerListCache::instance())
  , serverList(ServerList::instance())
  , defaultKey(this)
  , title(0)
  , help(0)
{
  // cache font face ID
  const LocalFontFace* fontFace = MainMenu::getFontFace();

  addPlayingCallback(&playingCB, this);

  serverList.updateFromCache();
  serverList.startServerPings(getStartupInfo());
  listsCache.loadCache();

  std::vector<std::pair<HUDuiServerList*, std::string> > cachedLists = listsCache.readCachedLists();

  if (cachedLists.size() > (size_t) 0) {
    normalList = cachedLists[0].first;
    recentList = cachedLists[1].first;
    favoritesList = cachedLists[2].first;
  } else {
    normalList = new HUDuiServerList;
    favoritesList = new HUDuiServerList;
    recentList = new HUDuiServerList;
    listsCache.addNewList(normalList, "");
    listsCache.addNewList(favoritesList, "");
    listsCache.addNewList(recentList, "");
  }

  normalList->setFontFace(fontFace);
  favoritesList->setFontFace(fontFace);
  recentList->setFontFace(fontFace);
  serverInfo->setFontFace(fontFace);
  customTabControl->setFontFace(fontFace);

  title = new HUDuiLabel();
  title->setString("Servers");
  title->setFontFace(fontFace);

  help = new HUDuiLabel();
  help->setString("f - add server to favorites      h - remove server from tab      c - clear tab      v - delete tab      r - refresh server list");
  help->setFontFace(fontFace);

  tabbedControl = new HUDuiTabbedControl;
  tabbedControl->setFontFace(fontFace);
  tabbedControl->addTab(normalList, "All");
  tabbedControl->addTab(recentList, "Recent");
  tabbedControl->addTab(favoritesList, "Favorites");

  for (size_t i=3; i<cachedLists.size(); i++) {
    cachedLists[i].first->setFontFace(fontFace);
    tabbedControl->addTab(cachedLists[i].first, cachedLists[i].second);
  }

  tabbedControl->addTab(customTabControl, "Create New Tab");
  tabbedControl->setActiveTab(0);

  serverList.addServerCallback(newServer, normalList);
  serverList.addFavoriteServerCallback(newServer, favoritesList);
  serverList.addRecentServerCallback(newServer, recentList);

  addControl(title, false);
  addControl(tabbedControl);
  addControl(serverInfo);
  addControl(help, false);

  initNavigation();
}

ServerMenu::~ServerMenu()
{
  serverList.removeServerCallback(newServer, normalList);
  serverList.removeFavoriteServerCallback(newServer, favoritesList);
  serverList.removeRecentServerCallback(newServer, recentList);
}

void ServerMenu::newServer(ServerItem* addedServer, void* data)
{
  HUDuiServerList* serverData( static_cast<HUDuiServerList*>(data) );

  // Server already has a ping
  if (addedServer->ping.pingTime != 0) {
    serverData->addItem(addedServer);
    return;
  }

  // Pinging in process, add on to the list vector
  if (addedServer->ping.pinging) {
    ServerMenu::activePings[addedServer->getServerKey()].second.push_back(serverData);
  }

  ServerPing* newping = new ServerPing(addedServer->ping.serverId.serverHost, ntohs(addedServer->ping.serverId.port));
  newping->start();
  std::vector<HUDuiServerList*> serverListsVector;
  serverListsVector.push_back(serverData);
  ServerMenu::activePings.insert(PingsMap::value_type(addedServer->getServerKey(), std::pair<ServerPing*, std::vector<HUDuiServerList*> >(newping, serverListsVector)));
  addedServer->ping.pinging = true;
}

void ServerMenu::execute()
{
  if ((tabbedControl->getActiveTab() == customTabControl) &&
      (dynamic_cast<HUDuiServerListCustomTab*>(tabbedControl->getActiveTab())->createNew->hasFocus()))
  {
    HUDuiServerList* newServerList = customTabControl->createServerList();
    listsCache.addNewList(newServerList, customTabControl->tabName->getString());
    tabbedControl->addTab(newServerList, customTabControl->tabName->getString(), tabbedControl->getTabCount() - 1);
    for (size_t i=0; i<serverList.size(); i++) {
      newServerList->addItem(serverList.getServerAt(i));
    }
    //newServerList->searchServers(customTabControl->serverName->getString());
    dynamic_cast<HUDuiNestedContainer*>(tabbedControl->getTab(tabbedControl->getTabCount() - 2))->getNav().set(1);
    return;
  }

  if ((tabbedControl->hasFocus())||
      (tabbedControl->getActiveTab()->hasFocus())||
      (tabbedControl->getActiveTabName() == "Create New Tab"))
    return;

  // update startup info
  StartupInfo* info = getStartupInfo();
  ServerItem* selectedServer = dynamic_cast<HUDuiServerList*>(tabbedControl->getActiveTab())->getSelectedServer();
  strncpy(info->serverName, selectedServer->name.c_str(), ServerNameLen-1);
  info->serverPort = ntohs((unsigned short) selectedServer->ping.serverId.port);

  // all done
  HUDDialogStack::get()->pop();
}

void ServerMenu::resize(int _width, int _height)
{
  HUDDialog::resize(_width, _height);
  FontSizer fs = FontSizer(_width, _height);

  FontManager &fm = FontManager::instance();
  const LocalFontFace* fontFace = MainMenu::getFontFace();

  // reposition title
  float x, y;

  // use a big font for title, smaller font for the rest
  fs.setMin(0, (int)(1.0 / BZDB.eval("headerFontSize") / 2.0));
  const float titleFontSize = fs.getFontSize(fontFace->getFMFace(), "headerFontSize");

  title->setFontSize(titleFontSize);
  const float titleWidth = fm.getStringWidth(fontFace->getFMFace(), titleFontSize, title->getString().c_str());
  const float titleHeight = fm.getStringHeight(fontFace->getFMFace(), titleFontSize);
  x = 0.5f * ((float)_width - titleWidth);
  y = (float)_height - titleHeight;
  title->setPosition(x, y);

  fs.setMin(40,10);
  const float fontSize = fs.getFontSize(fontFace->getFMFace(), "alertFontSize");

  float edgeSpacer = fm.getStringWidth(fontFace->getFMFace(), fontSize, "X");
  float bottomSpacer = fm.getStringHeight(fontFace->getFMFace(), fontSize);

  float remainingSpace = y - bottomSpacer*2;
  float listHeight = remainingSpace*0.65f;

  tabbedControl->setSize((_width - (2*edgeSpacer)),listHeight);
  serverInfo->setSize((_width - (2*edgeSpacer)), (remainingSpace - 4*bottomSpacer)*0.35f);

  y = y - (titleHeight/2) - tabbedControl->getHeight();

  float helpLength = fm.getStringWidth(fontFace->getFMFace(), fontSize, help->getString().c_str());

  tabbedControl->setPosition(edgeSpacer, y);
  serverInfo->setPosition(edgeSpacer, bottomSpacer/2 + bottomSpacer);
  help->setPosition((_width - helpLength)/2, bottomSpacer/2);
  tabbedControl->setFontSize(fontSize);
  serverInfo->setFontSize(fontSize);
  help->setFontSize(fontSize);
}

void ServerMenu::updateStatus()
{
  if (tabbedControl->hasFocus() ||
      tabbedControl->getActiveTab()->hasFocus() ||
      tabbedControl->getActiveTabName() == "Create New Tab")
    serverInfo->setServerItem(NULL);
  else
    serverInfo->setServerItem(dynamic_cast<HUDuiServerList*>(tabbedControl->getActiveTab())->getSelectedServer());
}

void ServerMenu::playingCB(void* _self)
{
  ServerList &list = ServerList::instance();
  for (PingsMap::iterator i = ServerMenu::activePings.begin();
       i != ServerMenu::activePings.end();) {
    i->second.first->doPings();
    if (i->second.first->done()) {
      ServerItem* server = list.lookupServer(i->first);
      if (server == NULL)
	break;
      server->ping.pingTime = i->second.first->calcLag();
      server->ping.pinging = false;
      for (size_t j=0; j<(i->second.second.size()); j++) {
	i->second.second[j]->addItem(server);
      }
      delete i->second.first;
      ServerMenu::activePings.erase(i++);
      continue;
    }
    ++i;
  }

  static_cast<ServerMenu*>(_self)->serverList.checkEchos(getStartupInfo());
  static_cast<ServerMenu*>(_self)->updateStatus();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


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

/*
 * Initialize the barrier.
 */
Barrier::Barrier(int threads) :
	num_threads(threads),
	num_waiting(threads)
{
	pthread_cond_init(&waiting_queue, NULL);
	pthread_mutex_init(&lock, NULL);
}

/*
 * Destroy the barrier.
 */
Barrier::~Barrier()
{
	pthread_cond_broadcast(&waiting_queue);
	pthread_mutex_destroy(&lock);
	pthread_cond_destroy(&waiting_queue);
}

/*
 * Synchronize threads.
 */
void Barrier::wait()
{
	pthread_mutex_lock(&lock);
	if (--num_waiting > 0) {
		pthread_cond_wait(&waiting_queue, &lock);
	} else {
		num_waiting = num_threads;
		pthread_cond_broadcast(&waiting_queue);
	}
	pthread_mutex_unlock(&lock);
}
<commit_msg>temporary hack to work around the race conditions for servers<commit_after>#include <pthread.h>
#include <time.h>
#include "barrier.h"

/*
 * Initialize the barrier.
 */
Barrier::Barrier(int threads) :
	num_threads(threads),
	num_waiting(threads)
{
	pthread_cond_init(&waiting_queue, NULL);
	pthread_mutex_init(&lock, NULL);
}

/*
 * Destroy the barrier.
 */
Barrier::~Barrier()
{
	pthread_cond_broadcast(&waiting_queue);
	pthread_mutex_destroy(&lock);
	pthread_cond_destroy(&waiting_queue);
}

/*
 * Synchronize threads.
 */
void Barrier::wait()
{
	pthread_mutex_lock(&lock);
	if (num_threads == 1) {
		// Only one thread, artificially wait for 750 ms
		// FIXME: This is just an ugly hack to prevent the race condition for servers
		timespec timeout = {0, 750000000L};
		pthread_yield();
		nanosleep(&timeout, NULL);
	}

	if (--num_waiting > 0) {
		// Wait until all threads reach this point
		pthread_cond_wait(&waiting_queue, &lock);
	} else {
		// We are the last thread, wake everybody up and continue
		num_waiting = num_threads;
		pthread_cond_broadcast(&waiting_queue);
	}
	pthread_mutex_unlock(&lock);
}
<|endoftext|>


<commit_before>#include "basecpu.h"
#include "errors.h"

BaseCPU::BaseCPU(const System &sys): sys(sys), running(false) {
}

void BaseCPU::stop() {
    running = false;
}

bool BaseCPU::startup() {
    bool started = false;
    if (!running) {
        started = true;
        reset();
        while(running) { tick(); }
    }
    return started;
}

int BaseCPU::readMemory(SizeType offset, SizeType len, void *data) const {
    return sys.readMemory(offset, len, data);
}

int BaseCPU::writeMemory(SizeType offset, SizeType len, const void *data) const {
    return sys.writeMemory(offset, len, data);
}

int BaseCPU::readPort(PortType port, SizeType len, void *data) const {
    return sys.readPort(port, len, data);
}

int BaseCPU::writePort(PortType port, SizeType len, const void *data) const {
    return sys.writePort(port, len, data);
}

void Interruptable::signalInterrupt(Interrupt interrupt) {
    queue.push(interrupt);
}

bool Interruptable::serviceNextInterrupt() {
    bool ret = false;
    if(!queue.empty()) {
        serviceInterrupt(queue.front());
        queue.pop();
        ret = true;
    }
    return ret;
}

GenericCPU::GenericCPU(const System &sys, const InstructionSet &set, Interrupt badInstruction, Interrupt badOperand) :
    BaseCPU(sys), set(set), badInstruction(badInstruction), badOperand(badOperand) {
}

void GenericCPU::tick() {
    if(!(interruptsEnabled() && serviceNextInterrupt())) {
        nextInstruction();
    }
}

bool GenericCPU::loadNextByte(ByteString &buffer, const void * const base) {
    bool ret = false;
    byte next;
    SizeType nextAddr = ((SizeType)base) + buffer.size();

    if(readMemory(nextAddr, 1, &next) != ERR_SUCCESS) {
        ret = false;
    } else {
        buffer.push_back(next);
        ret = true;
    }
    return ret;
}

bool GenericCPU::readBytes(ByteString &buffer, const void * const base, SizeType length) {
    buffer.reserve(length);
    return readMemory((SizeType)base, length, buffer.data()) == ERR_SUCCESS;
}

void GenericCPU::nextInstruction() {
    ByteString opcode;
    int decodeRc = ERR_SUCCESS;
    const void * const instructionBase = instructionPointer();
    // FIXME: Shouldn't HAVE to be const
    const Instruction *inst;

    do {
        if(loadNextByte(opcode, instructionBase))
        {
            signalInterrupt(badOperand);
        } else {
            decodeRc = set.decode(opcode, &inst);
        }
    } while(decodeRc == ERR_CONFLICT || decodeRc == ERR_INCOMPLETE);

    if(decodeRc != ERR_SUCCESS) {
        signalInterrupt(badInstruction);
    } else {
        SizeType operandLength = inst->length;
        SizeType offset = opcode.size();
        ByteString operands;
        if(!readBytes(operands, instructionBase, operandLength)) {
            signalInterrupt(badOperand);
        } else {
            inst->execute(*this, operands);
        }
    }
}<commit_msg>Set running state in startup<commit_after>#include "basecpu.h"
#include "errors.h"

BaseCPU::BaseCPU(const System &sys): sys(sys), running(false) {
}

void BaseCPU::stop() {
    running = false;
}

bool BaseCPU::startup() {
    bool started = false;
    if (!running) {
        running = true;
        started = true;
        reset();
        while(running) { tick(); }
    }
    return started;
}

int BaseCPU::readMemory(SizeType offset, SizeType len, void *data) const {
    return sys.readMemory(offset, len, data);
}

int BaseCPU::writeMemory(SizeType offset, SizeType len, const void *data) const {
    return sys.writeMemory(offset, len, data);
}

int BaseCPU::readPort(PortType port, SizeType len, void *data) const {
    return sys.readPort(port, len, data);
}

int BaseCPU::writePort(PortType port, SizeType len, const void *data) const {
    return sys.writePort(port, len, data);
}

void Interruptable::signalInterrupt(Interrupt interrupt) {
    queue.push(interrupt);
}

bool Interruptable::serviceNextInterrupt() {
    bool ret = false;
    if(!queue.empty()) {
        serviceInterrupt(queue.front());
        queue.pop();
        ret = true;
    }
    return ret;
}

GenericCPU::GenericCPU(const System &sys, const InstructionSet &set, Interrupt badInstruction, Interrupt badOperand) :
    BaseCPU(sys), set(set), badInstruction(badInstruction), badOperand(badOperand) {
}

void GenericCPU::tick() {
    if(!(interruptsEnabled() && serviceNextInterrupt())) {
        nextInstruction();
    }
}

bool GenericCPU::loadNextByte(ByteString &buffer, const void * const base) {
    bool ret = false;
    byte next;
    SizeType nextAddr = ((SizeType)base) + buffer.size();

    if(readMemory(nextAddr, 1, &next) != ERR_SUCCESS) {
        ret = false;
    } else {
        buffer.push_back(next);
        ret = true;
    }
    return ret;
}

bool GenericCPU::readBytes(ByteString &buffer, const void * const base, SizeType length) {
    buffer.reserve(length);
    return readMemory((SizeType)base, length, buffer.data()) == ERR_SUCCESS;
}

void GenericCPU::nextInstruction() {
    ByteString opcode;
    int decodeRc = ERR_SUCCESS;
    const void * const instructionBase = instructionPointer();
    // FIXME: Shouldn't HAVE to be const
    const Instruction *inst;

    do {
        if(loadNextByte(opcode, instructionBase))
        {
            signalInterrupt(badOperand);
        } else {
            decodeRc = set.decode(opcode, &inst);
        }
    } while(decodeRc == ERR_CONFLICT || decodeRc == ERR_INCOMPLETE);

    if(decodeRc != ERR_SUCCESS) {
        signalInterrupt(badInstruction);
    } else {
        SizeType operandLength = inst->length;
        SizeType offset = opcode.size();
        ByteString operands;
        if(!readBytes(operands, instructionBase, operandLength)) {
            signalInterrupt(badOperand);
        } else {
            inst->execute(*this, operands);
        }
    }
}<|endoftext|>


<commit_before>#include "JobHandler/PathPlanningHandler.h"
#include <cmath>
using namespace std;

bool PathPlanningHandler::registered = JobHandler::RegisterJobHandler("path-planning", [](string command) {
	return (ptr<JobHandler>) std::make_shared<PathPlanningHandler>();
});

PathPlanningHandler::PathPlanningHandler()
{
	g = Grid(1000, 1000, 13, 13, 13, 0);
	shortPath = Dijkstra(500, 500);
	path = Path();
	track = 0;
}

PathPlanningHandler::PathPlanningHandler(float w, float h, float scal, float startx, float starty, float startAngle, float goalx, float goaly)
{
	g = Grid(w, h, scal, startx, starty, startAngle);
	shortPath = Dijkstra(goalx, goaly);
	path = Path();
	track = 0;
}

PathPlanningHandler::~PathPlanningHandler()
{
}

void PathPlanningHandler::execute(deque<Job>& jobs, SensorData & data, ControllerData & outputs)
{
	Obstacle newObs;
	auto usInfo = data.find("ULTRASOUNDF");
	if (usInfo != data.end()) {
		//Add obstacle information to grid
		for (int i = 1; i <= 7; i++) {
			float inches = static_pointer_cast<UltrasoundData>(usInfo->second)->distance[i - 1];
			newObs = Obstacle(g.R2Pos.x, g.R2Pos.y, g.r2Angle, 3.14159265/4, inches);
			g.addObstacle(newObs);
		}
		//Recalculate path
		path = shortPath.calcPath(&g);
		track = 0;
	}
	else if(track < path.path.size()){
		//Extract next coordinate from shortest path and calculate motor commands
		Coord moveTo = path.path[track];
		float xdist = moveTo.x - g.R2Pos.x;
		float ydist = moveTo.y - g.R2Pos.y;
		float radius = sqrt(pow(xdist, 2) + pow(ydist, 2));
		float angle = atan2(ydist, xdist) - g.r2Angle;
		int l = (int)(radius * cos(angle));
		int r = (int)(radius * sin(angle));
		track++;
		g.updatePos(moveTo.x, moveTo.y);
		ptr<MotorData> output = std::make_shared<MotorData>();
		output->leftMotor = l;
		output->rightMotor = r;
		outputs["MOTOR"] = output;
	}
	else {
		//Stop motors if no path or goal reached
		ptr<MotorData> output = std::make_shared<MotorData>();
		output->leftMotor = 0;
		output->rightMotor = 0;
		outputs["MOTOR"] = output;
	}

}
<commit_msg>Changed default scale of grid<commit_after>#include "JobHandler/PathPlanningHandler.h"
#include <cmath>
using namespace std;

bool PathPlanningHandler::registered = JobHandler::RegisterJobHandler("path-planning", [](string command) {
	return (ptr<JobHandler>) std::make_shared<PathPlanningHandler>();
});

PathPlanningHandler::PathPlanningHandler()
{
	g = Grid(1000, 1000, 15, 13, 13, 0);
	shortPath = Dijkstra(500, 500);
	path = Path();
	track = 0;
}

PathPlanningHandler::PathPlanningHandler(float w, float h, float scal, float startx, float starty, float startAngle, float goalx, float goaly)
{
	g = Grid(w, h, scal, startx, starty, startAngle);
	shortPath = Dijkstra(goalx, goaly);
	path = Path();
	track = 0;
}

PathPlanningHandler::~PathPlanningHandler()
{
}

void PathPlanningHandler::execute(deque<Job>& jobs, SensorData & data, ControllerData & outputs)
{
	Obstacle newObs;
	auto usInfo = data.find("ULTRASOUNDF");
	if (usInfo != data.end()) {
		//Add obstacle information to grid
		for (int i = 1; i <= 7; i++) {
			float inches = static_pointer_cast<UltrasoundData>(usInfo->second)->distance[i - 1];
			newObs = Obstacle(g.R2Pos.x, g.R2Pos.y, g.r2Angle, 3.14159265/4, inches);
			g.addObstacle(newObs);
		}
		//Recalculate path
		path = shortPath.calcPath(&g);
		track = 0;
	}
	else if(track < path.path.size()){
		//Extract next coordinate from shortest path and calculate motor commands
		Coord moveTo = path.path[track];
		float xdist = moveTo.x - g.R2Pos.x;
		float ydist = moveTo.y - g.R2Pos.y;
		float radius = sqrt(pow(xdist, 2) + pow(ydist, 2));
		float angle = atan2(ydist, xdist) - g.r2Angle;
		int l = (int)(radius * cos(angle));
		int r = (int)(radius * sin(angle));
		track++;
		g.updatePos(moveTo.x, moveTo.y);
		ptr<MotorData> output = std::make_shared<MotorData>();
		output->leftMotor = l;
		output->rightMotor = r;
		outputs["MOTOR"] = output;
	}
	else {
		//Stop motors if no path or goal reached
		ptr<MotorData> output = std::make_shared<MotorData>();
		output->leftMotor = 0;
		output->rightMotor = 0;
		outputs["MOTOR"] = output;
	}

}
<|endoftext|>