<commit_before>// @(#)root/gui:$Name:  $:$Id: TRootEmbeddedCanvas.cxx,v 1.3 2001/02/14 15:39:35 rdm Exp $
// Author: Fons Rademakers   15/07/98

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootEmbeddedCanvas                                                  //
//                                                                      //
// This class creates a TGCanvas in which a TCanvas is created. Use     //
// GetCanvas() to get a pointer to the TCanvas.                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TRootEmbeddedCanvas.h"
#include "TCanvas.h"
#include "TROOT.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootEmbeddedContainer                                               //
//                                                                      //
// Utility class used by TRootEmbeddedCanvas. The TRootEmbeddedContainer//
// is the frame embedded in the TGCanvas widget. The ROOT graphics goes //
// into this frame. This class is used to enable input events on this   //
// graphics frame and forward the events to the TRootEmbeddedCanvas     //
// handlers.                                                            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TRootEmbeddedContainer : public TGCompositeFrame {
private:
   TRootEmbeddedCanvas  *fCanvas;    // pointer back to embedded canvas
public:
   TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t id, const TGWindow *parent);

   Bool_t  HandleButton(Event_t *ev)
                { return fCanvas->HandleContainerButton(ev); }
   Bool_t  HandleDoubleClick(Event_t *ev)
                { return fCanvas->HandleContainerDoubleClick(ev); }
   Bool_t  HandleConfigureNotify(Event_t *ev)
                { TGFrame::HandleConfigureNotify(ev);
                  return fCanvas->HandleContainerConfigure(ev); }
   Bool_t  HandleKey(Event_t *ev)
                { return fCanvas->HandleContainerKey(ev); }
   Bool_t  HandleMotion(Event_t *ev)
                { return fCanvas->HandleContainerMotion(ev); }
   Bool_t  HandleExpose(Event_t *ev)
                { return fCanvas->HandleContainerExpose(ev); }
   Bool_t  HandleCrossing(Event_t *ev)
                { return fCanvas->HandleContainerCrossing(ev); }
};

//______________________________________________________________________________
TRootEmbeddedContainer::TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t id,
   const TGWindow *p) : TGCompositeFrame(gClient, id, p)
{
   // Create a canvas container.

   fCanvas = c;

   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
                    kButtonPressMask | kButtonReleaseMask,
                    kNone, kNone);

   AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask |
            kExposureMask | kStructureNotifyMask | kLeaveWindowMask);
}

ClassImp(TRootEmbeddedCanvas)

//______________________________________________________________________________
TRootEmbeddedCanvas::TRootEmbeddedCanvas(const char *name, const TGWindow *p,
            UInt_t w, UInt_t h, UInt_t options, ULong_t back)
   : TGCanvas(p, w, h, options, back)
{
   // Create an TCanvas embedded in a TGFrame. A pointer to the TCanvas can
   // be obtained via the GetCanvas() member function. To embed a canvas
   // derived from a TCanvas do the following:
   // TRootEmbeddedCanvas *embedded = new TRootEmbeddedCanvas(0, p, w, h);
   //      [note name must be 0, not null string ""]
   // Int_t wid = embedded->GetCanvasWindowId();
   // TMyCanvas *myc = new TMyCanvas("myname", 10, 10, wid);
   // embedded->AdoptCanvas(myc);
   //      [ the MyCanvas is adopted by the embedded canvas and will be
   //        destroyed by it ]

   fButton  = 0;
   fAutoFit = kTRUE;

   fCWinId = gVirtualX->InitWindow((ULong_t)GetViewPort()->GetId());
   Window_t win = gVirtualX->GetWindowID(fCWinId);
   fCanvasContainer = new TRootEmbeddedContainer(this, win, GetViewPort());
   SetContainer(fCanvasContainer);

   if (name)
      fCanvas = new TCanvas(name, 10, 10, fCWinId);
}

//______________________________________________________________________________
TRootEmbeddedCanvas::~TRootEmbeddedCanvas()
{
   // Delete embedded ROOT canvas.

   delete fCanvas;
   delete fCanvasContainer;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerButton(Event_t *event)
{
   // Handle mouse button events in the canvas container.

   Int_t button = event->fCode;
   Int_t x = event->fX;
   Int_t y = event->fY;

   if (event->fType == kButtonPress) {
      fButton = button;
      if (button == kButton1)
         fCanvas->HandleInput(kButton1Down, x, y);
      if (button == kButton2)
         fCanvas->HandleInput(kButton2Down, x, y);
      if (button == kButton3) {
         fCanvas->HandleInput(kButton3Down, x, y);
         fButton = 0;  // button up is consumed by TContextMenu
      }

   } else if (event->fType == kButtonRelease) {
      if (button == kButton1)
         fCanvas->HandleInput(kButton1Up, x, y);
      if (button == kButton2)
         fCanvas->HandleInput(kButton2Up, x, y);
      if (button == kButton3)
         fCanvas->HandleInput(kButton3Up, x, y);

      fButton = 0;
   }

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerDoubleClick(Event_t *event)
{
   // Handle mouse button double click events in the canvas container.

   Int_t button = event->fCode;
   Int_t x = event->fX;
   Int_t y = event->fY;

   if (button == kButton1)
      fCanvas->HandleInput(kButton1Double, x, y);
   if (button == kButton2)
      fCanvas->HandleInput(kButton2Double, x, y);
   if (button == kButton3)
      fCanvas->HandleInput(kButton3Double, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerConfigure(Event_t *)
{
   // Handle configure (i.e. resize) event.

   if (fAutoFit) {
      fCanvas->Resize();
      fCanvas->Update();
   }
   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerKey(Event_t *event)
{
   // Handle keyboard events in the canvas container.

   if (event->fType == kGKeyPress) {
      fButton = event->fCode;
      UInt_t keysym;
      char str[2];
      gVirtualX->LookupString(event, str, sizeof(str), keysym);
      if (str[0] == 3)   // ctrl-c sets the interrupt flag
         gROOT->SetInterrupt();
      fCanvas->HandleInput(kKeyPress, str[0], keysym);
   } else if (event->fType == kKeyRelease)
      fButton = 0;

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerMotion(Event_t *event)
{
   // Handle mouse motion event in the canvas container.

   Int_t x = event->fX;
   Int_t y = event->fY;

   if (fButton == 0)
      fCanvas->HandleInput(kMouseMotion, x, y);
   if (fButton == kButton1)
      fCanvas->HandleInput(kButton1Motion, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerExpose(Event_t *event)
{
   // Handle expose events.

   if (event->fCount == 0)
      fCanvas->Flush();

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerCrossing(Event_t *event)
{
   // Handle enter/leave events. Only leave is activated at the moment.

   if (event->fType == kLeaveNotify)
      fCanvas->HandleInput(kMouseLeave, 0, 0);

   return kTRUE;
}
<commit_msg>fCanvas was not initialzed to 0 and add protection in methods against fCanvas possibly being 0.<commit_after>// @(#)root/gui:$Name:  $:$Id: TRootEmbeddedCanvas.cxx,v 1.4 2001/04/04 13:38:38 rdm Exp $
// Author: Fons Rademakers   15/07/98

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootEmbeddedCanvas                                                  //
//                                                                      //
// This class creates a TGCanvas in which a TCanvas is created. Use     //
// GetCanvas() to get a pointer to the TCanvas.                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TRootEmbeddedCanvas.h"
#include "TCanvas.h"
#include "TROOT.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootEmbeddedContainer                                               //
//                                                                      //
// Utility class used by TRootEmbeddedCanvas. The TRootEmbeddedContainer//
// is the frame embedded in the TGCanvas widget. The ROOT graphics goes //
// into this frame. This class is used to enable input events on this   //
// graphics frame and forward the events to the TRootEmbeddedCanvas     //
// handlers.                                                            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TRootEmbeddedContainer : public TGCompositeFrame {
private:
   TRootEmbeddedCanvas  *fCanvas;    // pointer back to embedded canvas
public:
   TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t id, const TGWindow *parent);

   Bool_t  HandleButton(Event_t *ev)
                { return fCanvas->HandleContainerButton(ev); }
   Bool_t  HandleDoubleClick(Event_t *ev)
                { return fCanvas->HandleContainerDoubleClick(ev); }
   Bool_t  HandleConfigureNotify(Event_t *ev)
                { TGFrame::HandleConfigureNotify(ev);
                  return fCanvas->HandleContainerConfigure(ev); }
   Bool_t  HandleKey(Event_t *ev)
                { return fCanvas->HandleContainerKey(ev); }
   Bool_t  HandleMotion(Event_t *ev)
                { return fCanvas->HandleContainerMotion(ev); }
   Bool_t  HandleExpose(Event_t *ev)
                { return fCanvas->HandleContainerExpose(ev); }
   Bool_t  HandleCrossing(Event_t *ev)
                { return fCanvas->HandleContainerCrossing(ev); }
};

//______________________________________________________________________________
TRootEmbeddedContainer::TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t id,
   const TGWindow *p) : TGCompositeFrame(gClient, id, p)
{
   // Create a canvas container.

   fCanvas = c;

   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
                    kButtonPressMask | kButtonReleaseMask,
                    kNone, kNone);

   AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask |
            kExposureMask | kStructureNotifyMask | kLeaveWindowMask);
}

ClassImp(TRootEmbeddedCanvas)

//______________________________________________________________________________
TRootEmbeddedCanvas::TRootEmbeddedCanvas(const char *name, const TGWindow *p,
            UInt_t w, UInt_t h, UInt_t options, ULong_t back)
   : TGCanvas(p, w, h, options, back)
{
   // Create an TCanvas embedded in a TGFrame. A pointer to the TCanvas can
   // be obtained via the GetCanvas() member function. To embed a canvas
   // derived from a TCanvas do the following:
   // TRootEmbeddedCanvas *embedded = new TRootEmbeddedCanvas(0, p, w, h);
   //      [note name must be 0, not null string ""]
   // Int_t wid = embedded->GetCanvasWindowId();
   // TMyCanvas *myc = new TMyCanvas("myname", 10, 10, wid);
   // embedded->AdoptCanvas(myc);
   //      [ the MyCanvas is adopted by the embedded canvas and will be
   //        destroyed by it ]

   fCanvas  = 0;
   fButton  = 0;
   fAutoFit = kTRUE;

   fCWinId = gVirtualX->InitWindow((ULong_t)GetViewPort()->GetId());
   Window_t win = gVirtualX->GetWindowID(fCWinId);
   fCanvasContainer = new TRootEmbeddedContainer(this, win, GetViewPort());
   SetContainer(fCanvasContainer);

   if (name)
      fCanvas = new TCanvas(name, 10, 10, fCWinId);
}

//______________________________________________________________________________
TRootEmbeddedCanvas::~TRootEmbeddedCanvas()
{
   // Delete embedded ROOT canvas.

   delete fCanvas;
   delete fCanvasContainer;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerButton(Event_t *event)
{
   // Handle mouse button events in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t button = event->fCode;
   Int_t x = event->fX;
   Int_t y = event->fY;

   if (event->fType == kButtonPress) {
      fButton = button;
      if (button == kButton1)
         fCanvas->HandleInput(kButton1Down, x, y);
      if (button == kButton2)
         fCanvas->HandleInput(kButton2Down, x, y);
      if (button == kButton3) {
         fCanvas->HandleInput(kButton3Down, x, y);
         fButton = 0;  // button up is consumed by TContextMenu
      }

   } else if (event->fType == kButtonRelease) {
      if (button == kButton1)
         fCanvas->HandleInput(kButton1Up, x, y);
      if (button == kButton2)
         fCanvas->HandleInput(kButton2Up, x, y);
      if (button == kButton3)
         fCanvas->HandleInput(kButton3Up, x, y);

      fButton = 0;
   }

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerDoubleClick(Event_t *event)
{
   // Handle mouse button double click events in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t button = event->fCode;
   Int_t x = event->fX;
   Int_t y = event->fY;

   if (button == kButton1)
      fCanvas->HandleInput(kButton1Double, x, y);
   if (button == kButton2)
      fCanvas->HandleInput(kButton2Double, x, y);
   if (button == kButton3)
      fCanvas->HandleInput(kButton3Double, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerConfigure(Event_t *)
{
   // Handle configure (i.e. resize) event.

   if (fAutoFit && fCanvas) {
      fCanvas->Resize();
      fCanvas->Update();
   }
   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerKey(Event_t *event)
{
   // Handle keyboard events in the canvas container.

   if (!fCanvas) return kTRUE;

   if (event->fType == kGKeyPress) {
      fButton = event->fCode;
      UInt_t keysym;
      char str[2];
      gVirtualX->LookupString(event, str, sizeof(str), keysym);
      if (str[0] == 3)   // ctrl-c sets the interrupt flag
         gROOT->SetInterrupt();
      fCanvas->HandleInput(kKeyPress, str[0], keysym);
   } else if (event->fType == kKeyRelease)
      fButton = 0;

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerMotion(Event_t *event)
{
   // Handle mouse motion event in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t x = event->fX;
   Int_t y = event->fY;

   if (fButton == 0)
      fCanvas->HandleInput(kMouseMotion, x, y);
   if (fButton == kButton1)
      fCanvas->HandleInput(kButton1Motion, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerExpose(Event_t *event)
{
   // Handle expose events.

   if (!fCanvas) return kTRUE;

   if (event->fCount == 0)
      fCanvas->Flush();

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerCrossing(Event_t *event)
{
   // Handle enter/leave events. Only leave is activated at the moment.

   if (!fCanvas) return kTRUE;

   if (event->fType == kLeaveNotify)
      fCanvas->HandleInput(kMouseLeave, 0, 0);

   return kTRUE;
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "build/build_config.h"
#include "base/debug_util.h"

#if defined(OS_LINUX)
#include <unistd.h>
#include <execinfo.h>
#endif

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <unistd.h>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/string_piece.h"

// static
bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) {
  NOTIMPLEMENTED();
  return false;
}

#if defined(OS_MACOSX)

// Based on Apple's recommended method as described in
// http://developer.apple.com/qa/qa2004/qa1361.html
// static
bool DebugUtil::BeingDebugged() {
  // Initialize mib, which tells sysctl what info we want.  In this case,
  // we're looking for information about a specific process ID.
  int mib[] = {
    CTL_KERN,
    KERN_PROC,
    KERN_PROC_PID,
    getpid()
  };

  // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE.  The source and
  // binary interfaces may change.
  struct kinfo_proc info;
  size_t info_size = sizeof(info);

  int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
  DCHECK(sysctl_result == 0);
  if (sysctl_result != 0)
    return false;

  // This process is being debugged if the P_TRACED flag is set.
  return (info.kp_proc.p_flag & P_TRACED) != 0;
}

#elif defined(OS_LINUX)

// We can look in /proc/self/status for TracerPid.  We are likely used in crash
// handling, so we are careful not to use the heap or have side effects.
// Another option that is common is to try to ptrace yourself, but then we
// can't detach without forking(), and that's not so great.
// static
bool DebugUtil::BeingDebugged() {
  int status_fd = open("/proc/self/status", O_RDONLY);
  if (status_fd == -1)
    return false;

  // We assume our line will be in the first 1024 characters and that we can
  // read this much all at once.  In practice this will generally be true.
  // This simplifies and speeds up things considerably.
  char buf[1024];

  ssize_t num_read = read(status_fd, buf, sizeof(buf));
  close(status_fd);

  if (num_read <= 0)
    return false;

  StringPiece status(buf, num_read);
  StringPiece tracer("TracerPid:\t");

  StringPiece::size_type pid_index = status.find(tracer);
  if (pid_index == StringPiece::npos)
    return false;

  // Our pid is 0 without a debugger, assume this for any pid starting with 0.
  pid_index += tracer.size();
  return pid_index < status.size() && status[pid_index] != '0';
}

#endif  // OS_LINUX

// static
void DebugUtil::BreakDebugger() {
  asm ("int3");
}

#if defined(OS_LINUX)

StackTrace::StackTrace() {
  static const unsigned kMaxCallers = 256;

  void* callers[kMaxCallers];
  int count = backtrace(callers, kMaxCallers);
  trace_.resize(count);
  memcpy(&trace_[0], callers, sizeof(void*) * count);
}

void StackTrace::PrintBacktrace() {
  fflush(stderr);
  backtrace_symbols_fd(&trace_[0], trace_.size(), STDERR_FILENO);
}

#elif defined(OS_MACOSX)

// TODO(port): complete this code
StackTrace::StackTrace() { }

StackTrace::PrintBacktrace() {
  NOTIMPLEMENTED();
}

#endif  // defined(OS_MACOSX)

const void *const *StackTrace::Addresses(size_t* count) {
  *count = trace_.size();
  if (trace_.size())
    return &trace_[0];
  return NULL;
}
<commit_msg>Mac build fix<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "build/build_config.h"
#include "base/debug_util.h"

#if defined(OS_LINUX)
#include <unistd.h>
#include <execinfo.h>
#endif

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <unistd.h>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/string_piece.h"

// static
bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) {
  NOTIMPLEMENTED();
  return false;
}

#if defined(OS_MACOSX)

// Based on Apple's recommended method as described in
// http://developer.apple.com/qa/qa2004/qa1361.html
// static
bool DebugUtil::BeingDebugged() {
  // Initialize mib, which tells sysctl what info we want.  In this case,
  // we're looking for information about a specific process ID.
  int mib[] = {
    CTL_KERN,
    KERN_PROC,
    KERN_PROC_PID,
    getpid()
  };

  // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE.  The source and
  // binary interfaces may change.
  struct kinfo_proc info;
  size_t info_size = sizeof(info);

  int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
  DCHECK(sysctl_result == 0);
  if (sysctl_result != 0)
    return false;

  // This process is being debugged if the P_TRACED flag is set.
  return (info.kp_proc.p_flag & P_TRACED) != 0;
}

#elif defined(OS_LINUX)

// We can look in /proc/self/status for TracerPid.  We are likely used in crash
// handling, so we are careful not to use the heap or have side effects.
// Another option that is common is to try to ptrace yourself, but then we
// can't detach without forking(), and that's not so great.
// static
bool DebugUtil::BeingDebugged() {
  int status_fd = open("/proc/self/status", O_RDONLY);
  if (status_fd == -1)
    return false;

  // We assume our line will be in the first 1024 characters and that we can
  // read this much all at once.  In practice this will generally be true.
  // This simplifies and speeds up things considerably.
  char buf[1024];

  ssize_t num_read = read(status_fd, buf, sizeof(buf));
  close(status_fd);

  if (num_read <= 0)
    return false;

  StringPiece status(buf, num_read);
  StringPiece tracer("TracerPid:\t");

  StringPiece::size_type pid_index = status.find(tracer);
  if (pid_index == StringPiece::npos)
    return false;

  // Our pid is 0 without a debugger, assume this for any pid starting with 0.
  pid_index += tracer.size();
  return pid_index < status.size() && status[pid_index] != '0';
}

#endif  // OS_LINUX

// static
void DebugUtil::BreakDebugger() {
  asm ("int3");
}

#if defined(OS_LINUX)

StackTrace::StackTrace() {
  static const unsigned kMaxCallers = 256;

  void* callers[kMaxCallers];
  int count = backtrace(callers, kMaxCallers);
  trace_.resize(count);
  memcpy(&trace_[0], callers, sizeof(void*) * count);
}

void StackTrace::PrintBacktrace() {
  fflush(stderr);
  backtrace_symbols_fd(&trace_[0], trace_.size(), STDERR_FILENO);
}

#elif defined(OS_MACOSX)

// TODO(port): complete this code
StackTrace::StackTrace() { }

void StackTrace::PrintBacktrace() {
  NOTIMPLEMENTED();
}

#endif  // defined(OS_MACOSX)

const void *const *StackTrace::Addresses(size_t* count) {
  *count = trace_.size();
  if (trace_.size())
    return &trace_[0];
  return NULL;
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "build/build_config.h"
#include "base/debug_util.h"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <unistd.h>

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#endif

#include "base/basictypes.h"
#include "base/compat_execinfo.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/string_piece.h"

// static
bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) {
  NOTIMPLEMENTED();
  return false;
}

#if defined(OS_MACOSX)

// Based on Apple's recommended method as described in
// http://developer.apple.com/qa/qa2004/qa1361.html
// static
bool DebugUtil::BeingDebugged() {
  // If the process is sandboxed then we can't use the sysctl, so cache the
  // value.
  static bool is_set = false;
  static bool being_debugged = false;

  if (is_set) {
    return being_debugged;
  }

  // Initialize mib, which tells sysctl what info we want.  In this case,
  // we're looking for information about a specific process ID.
  int mib[] = {
    CTL_KERN,
    KERN_PROC,
    KERN_PROC_PID,
    getpid()
  };

  // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE.  The source and
  // binary interfaces may change.
  struct kinfo_proc info;
  size_t info_size = sizeof(info);

  int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
  DCHECK(sysctl_result == 0);
  if (sysctl_result != 0) {
    is_set = true;
    being_debugged = false;
    return being_debugged;
  }

  // This process is being debugged if the P_TRACED flag is set.
  is_set = true;
  being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
  return being_debugged;
}

#elif defined(OS_LINUX)

// We can look in /proc/self/status for TracerPid.  We are likely used in crash
// handling, so we are careful not to use the heap or have side effects.
// Another option that is common is to try to ptrace yourself, but then we
// can't detach without forking(), and that's not so great.
// static
bool DebugUtil::BeingDebugged() {
  int status_fd = open("/proc/self/status", O_RDONLY);
  if (status_fd == -1)
    return false;

  // We assume our line will be in the first 1024 characters and that we can
  // read this much all at once.  In practice this will generally be true.
  // This simplifies and speeds up things considerably.
  char buf[1024];

  ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf)));
  HANDLE_EINTR(close(status_fd));

  if (num_read <= 0)
    return false;

  base::StringPiece status(buf, num_read);
  base::StringPiece tracer("TracerPid:\t");

  base::StringPiece::size_type pid_index = status.find(tracer);
  if (pid_index == base::StringPiece::npos)
    return false;

  // Our pid is 0 without a debugger, assume this for any pid starting with 0.
  pid_index += tracer.size();
  return pid_index < status.size() && status[pid_index] != '0';
}

#endif  // OS_LINUX

// static
void DebugUtil::BreakDebugger() {
#if defined(ARCH_CPU_ARM_FAMILY)
  asm("bkpt 0");
#else
  asm("int3");
#endif
}

StackTrace::StackTrace() {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (!backtrace) {
    count_ = 0;
    return;
  }
#endif
  // Though the backtrace API man page does not list any possible negative
  // return values, we take no chance.
  count_ = std::max(backtrace(trace_, arraysize(trace_)), 0);
}

void StackTrace::PrintBacktrace() {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (!backtrace_symbols_fd)
    return;
#endif
  fflush(stderr);
  backtrace_symbols_fd(trace_, count_, STDERR_FILENO);
}

void StackTrace::OutputToStream(std::ostream* os) {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (!backtrace_symbols)
    return;
#endif
  scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace_, count_));

  // If we can't retrieve the symbols, print an error and just dump the raw
  // addresses.
  if (trace_symbols.get() == NULL) {
    (*os) << "Unable get symbols for backtrace (" << strerror(errno)
          << "). Dumping raw addresses in trace:\n";
    for (int i = 0; i < count_; ++i) {
      (*os) << "\t" << trace_[i] << "\n";
    }
  } else {
    (*os) << "Backtrace:\n";
    for (int i = 0; i < count_; ++i) {
      (*os) << "\t" << trace_symbols.get()[i] << "\n";
    }
  }
}
<commit_msg>Explicitly compare to NULL when looking for weak_import symbols.<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "build/build_config.h"
#include "base/debug_util.h"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <unistd.h>

#if defined(OS_MACOSX)
#include <AvailabilityMacros.h>
#endif

#include "base/basictypes.h"
#include "base/compat_execinfo.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/string_piece.h"

// static
bool DebugUtil::SpawnDebuggerOnProcess(unsigned /* process_id */) {
  NOTIMPLEMENTED();
  return false;
}

#if defined(OS_MACOSX)

// Based on Apple's recommended method as described in
// http://developer.apple.com/qa/qa2004/qa1361.html
// static
bool DebugUtil::BeingDebugged() {
  // If the process is sandboxed then we can't use the sysctl, so cache the
  // value.
  static bool is_set = false;
  static bool being_debugged = false;

  if (is_set) {
    return being_debugged;
  }

  // Initialize mib, which tells sysctl what info we want.  In this case,
  // we're looking for information about a specific process ID.
  int mib[] = {
    CTL_KERN,
    KERN_PROC,
    KERN_PROC_PID,
    getpid()
  };

  // Caution: struct kinfo_proc is marked __APPLE_API_UNSTABLE.  The source and
  // binary interfaces may change.
  struct kinfo_proc info;
  size_t info_size = sizeof(info);

  int sysctl_result = sysctl(mib, arraysize(mib), &info, &info_size, NULL, 0);
  DCHECK(sysctl_result == 0);
  if (sysctl_result != 0) {
    is_set = true;
    being_debugged = false;
    return being_debugged;
  }

  // This process is being debugged if the P_TRACED flag is set.
  is_set = true;
  being_debugged = (info.kp_proc.p_flag & P_TRACED) != 0;
  return being_debugged;
}

#elif defined(OS_LINUX)

// We can look in /proc/self/status for TracerPid.  We are likely used in crash
// handling, so we are careful not to use the heap or have side effects.
// Another option that is common is to try to ptrace yourself, but then we
// can't detach without forking(), and that's not so great.
// static
bool DebugUtil::BeingDebugged() {
  int status_fd = open("/proc/self/status", O_RDONLY);
  if (status_fd == -1)
    return false;

  // We assume our line will be in the first 1024 characters and that we can
  // read this much all at once.  In practice this will generally be true.
  // This simplifies and speeds up things considerably.
  char buf[1024];

  ssize_t num_read = HANDLE_EINTR(read(status_fd, buf, sizeof(buf)));
  HANDLE_EINTR(close(status_fd));

  if (num_read <= 0)
    return false;

  base::StringPiece status(buf, num_read);
  base::StringPiece tracer("TracerPid:\t");

  base::StringPiece::size_type pid_index = status.find(tracer);
  if (pid_index == base::StringPiece::npos)
    return false;

  // Our pid is 0 without a debugger, assume this for any pid starting with 0.
  pid_index += tracer.size();
  return pid_index < status.size() && status[pid_index] != '0';
}

#endif  // OS_LINUX

// static
void DebugUtil::BreakDebugger() {
#if defined(ARCH_CPU_ARM_FAMILY)
  asm("bkpt 0");
#else
  asm("int3");
#endif
}

StackTrace::StackTrace() {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace == NULL) {
    count_ = 0;
    return;
  }
#endif
  // Though the backtrace API man page does not list any possible negative
  // return values, we take no chance.
  count_ = std::max(backtrace(trace_, arraysize(trace_)), 0);
}

void StackTrace::PrintBacktrace() {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace_symbols_fd == NULL)
    return;
#endif
  fflush(stderr);
  backtrace_symbols_fd(trace_, count_, STDERR_FILENO);
}

void StackTrace::OutputToStream(std::ostream* os) {
#if defined(OS_MACOSX) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
  if (backtrace_symbols == NULL)
    return;
#endif
  scoped_ptr_malloc<char*> trace_symbols(backtrace_symbols(trace_, count_));

  // If we can't retrieve the symbols, print an error and just dump the raw
  // addresses.
  if (trace_symbols.get() == NULL) {
    (*os) << "Unable get symbols for backtrace (" << strerror(errno)
          << "). Dumping raw addresses in trace:\n";
    for (int i = 0; i < count_; ++i) {
      (*os) << "\t" << trace_[i] << "\n";
    }
  } else {
    (*os) << "Backtrace:\n";
    for (int i = 0; i < count_; ++i) {
      (*os) << "\t" << trace_symbols.get()[i] << "\n";
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Facebook, 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.
 */

// This is heavily inspired by the signal handler from google-glog

#include <folly/experimental/symbolizer/SignalHandler.h>

#include <sys/types.h>
#include <sys/syscall.h>
#include <atomic>
#include <ctime>
#include <mutex>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <vector>

#include <glog/logging.h>

#include <folly/Conv.h>
#include <folly/FileUtil.h>
#include <folly/Portability.h>
#include <folly/ScopeGuard.h>
#include <folly/experimental/symbolizer/Symbolizer.h>

namespace folly { namespace symbolizer {

namespace {

/**
 * Fatal signal handler registry.
 */
class FatalSignalCallbackRegistry {
 public:
  FatalSignalCallbackRegistry();

  void add(SignalCallback func);
  void markInstalled();
  void run();

 private:
  std::atomic<bool> installed_;
  std::mutex mutex_;
  std::vector<SignalCallback> handlers_;
};

FatalSignalCallbackRegistry::FatalSignalCallbackRegistry()
  : installed_(false) {
}

void FatalSignalCallbackRegistry::add(SignalCallback func) {
  std::lock_guard<std::mutex> lock(mutex_);
  CHECK(!installed_)
    << "FatalSignalCallbackRegistry::add may not be used "
       "after installing the signal handlers.";
  handlers_.push_back(func);
}

void FatalSignalCallbackRegistry::markInstalled() {
  std::lock_guard<std::mutex> lock(mutex_);
  CHECK(!installed_.exchange(true))
    << "FatalSignalCallbackRegistry::markInstalled must be called "
    << "at most once";
}

void FatalSignalCallbackRegistry::run() {
  if (!installed_) {
    return;
  }

  for (auto& fn : handlers_) {
    fn();
  }
}

// Leak it so we don't have to worry about destruction order
FatalSignalCallbackRegistry* gFatalSignalCallbackRegistry =
  new FatalSignalCallbackRegistry;

struct {
  int number;
  const char* name;
  struct sigaction oldAction;
} kFatalSignals[] = {
  { SIGSEGV, "SIGSEGV" },
  { SIGILL,  "SIGILL"  },
  { SIGFPE,  "SIGFPE"  },
  { SIGABRT, "SIGABRT" },
  { SIGBUS,  "SIGBUS"  },
  { SIGTERM, "SIGTERM" },
  { 0,       nullptr   }
};

void callPreviousSignalHandler(int signum) {
  // Restore disposition to old disposition, then kill ourselves with the same
  // signal. The signal will be blocked until we return from our handler,
  // then it will invoke the default handler and abort.
  for (auto p = kFatalSignals; p->name; ++p) {
    if (p->number == signum) {
      sigaction(signum, &p->oldAction, nullptr);
      raise(signum);
      return;
    }
  }

  // Not one of the signals we know about. Oh well. Reset to default.
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SIG_DFL;
  sigaction(signum, &sa, nullptr);
  raise(signum);
}

constexpr size_t kDefaultCapacity = 500;

// Note: not thread-safe, but that's okay, as we only let one thread
// in our signal handler at a time.
//
// Leak it so we don't have to worry about destruction order
auto gSignalSafeElfCache = new SignalSafeElfCache(kDefaultCapacity);

// Buffered writer (using a fixed-size buffer). We try to write only once
// to prevent interleaving with messages written from other threads.
//
// Leak it so we don't have to worry about destruction order.
auto gPrinter = new FDSymbolizePrinter(STDERR_FILENO,
                                       SymbolizePrinter::COLOR_IF_TTY,
                                       size_t(64) << 10);  // 64KiB

// Flush gPrinter, also fsync, in case we're about to crash again...
void flush() {
  gPrinter->flush();
  fsyncNoInt(STDERR_FILENO);
}

void printDec(uint64_t val) {
  char buf[20];
  uint32_t n = uint64ToBufferUnsafe(val, buf);
  gPrinter->print(StringPiece(buf, n));
}

const char kHexChars[] = "0123456789abcdef";
void printHex(uint64_t val) {
  // TODO(tudorb): Add this to folly/Conv.h
  char buf[2 + 2 * sizeof(uint64_t)];  // "0x" prefix, 2 digits for each byte

  char* end = buf + sizeof(buf);
  char* p = end;
  do {
    *--p = kHexChars[val & 0x0f];
    val >>= 4;
  } while (val != 0);
  *--p = 'x';
  *--p = '0';

  gPrinter->print(StringPiece(p, end));
}

void print(StringPiece sp) {
  gPrinter->print(sp);
}

void dumpTimeInfo() {
  SCOPE_EXIT { flush(); };
  time_t now = time(nullptr);
  print("*** Aborted at ");
  printDec(now);
  print(" (Unix time, try 'date -d @");
  printDec(now);
  print("') ***\n");
}

void dumpSignalInfo(int signum, siginfo_t* siginfo) {
  SCOPE_EXIT { flush(); };
  // Get the signal name, if possible.
  const char* name = nullptr;
  for (auto p = kFatalSignals; p->name; ++p) {
    if (p->number == signum) {
      name = p->name;
      break;
    }
  }

  print("*** Signal ");
  printDec(signum);
  if (name) {
    print(" (");
    print(name);
    print(")");
  }

  print(" (");
  printHex(reinterpret_cast<uint64_t>(siginfo->si_addr));
  print(") received by PID ");
  printDec(getpid());
  print(" (pthread TID ");
  printHex((uint64_t)pthread_self());
  print(") (linux TID ");
  printDec(syscall(__NR_gettid));
  print("), stack trace: ***\n");
}

FOLLY_NOINLINE void dumpStackTrace(bool symbolize);

void dumpStackTrace(bool symbolize) {
  SCOPE_EXIT { flush(); };
  // Get and symbolize stack trace
  constexpr size_t kMaxStackTraceDepth = 100;
  FrameArray<kMaxStackTraceDepth> addresses;

  // Skip the getStackTrace frame
  if (!getStackTraceSafe(addresses)) {
    print("(error retrieving stack trace)\n");
  } else if (symbolize) {
    Symbolizer symbolizer(gSignalSafeElfCache);
    symbolizer.symbolize(addresses);

    // Skip the top 2 frames:
    // getStackTraceSafe
    // dumpStackTrace (here)
    //
    // Leaving signalHandler on the stack for clarity, I think.
    gPrinter->println(addresses, 2);
  } else {
    print("(safe mode, symbolizer not available)\n");
    AddressFormatter formatter;
    for (size_t i = 0; i < addresses.frameCount; ++i) {
      print(formatter.format(addresses.addresses[i]));
      print("\n");
    }
  }
}

// On Linux, pthread_t is a pointer, so 0 is an invalid value, which we
// take to indicate "no thread in the signal handler".
//
// POSIX defines PTHREAD_NULL for this purpose, but that's not available.
constexpr pthread_t kInvalidThreadId = 0;

std::atomic<pthread_t> gSignalThread(kInvalidThreadId);
std::atomic<bool> gInRecursiveSignalHandler(false);

// Here be dragons.
void innerSignalHandler(int signum, siginfo_t* info, void* uctx) {
  // First, let's only let one thread in here at a time.
  pthread_t myId = pthread_self();

  pthread_t prevSignalThread = kInvalidThreadId;
  while (!gSignalThread.compare_exchange_strong(prevSignalThread, myId)) {
    if (pthread_equal(prevSignalThread, myId)) {
      // First time here. Try to dump the stack trace without symbolization.
      // If we still fail, well, we're mightily screwed, so we do nothing the
      // next time around.
      if (!gInRecursiveSignalHandler.exchange(true)) {
        print("Entered fatal signal handler recursively. We're in trouble.\n");
        dumpStackTrace(false);  // no symbolization
      }
      return;
    }

    // Wait a while, try again.
    timespec ts;
    ts.tv_sec = 0;
    ts.tv_nsec = 100L * 1000 * 1000;  // 100ms
    nanosleep(&ts, nullptr);

    prevSignalThread = kInvalidThreadId;
  }

  dumpTimeInfo();
  dumpSignalInfo(signum, info);
  dumpStackTrace(true);  // with symbolization

  // Run user callbacks
  gFatalSignalCallbackRegistry->run();
}

void signalHandler(int signum, siginfo_t* info, void* uctx) {
  SCOPE_EXIT { flush(); };
  innerSignalHandler(signum, info, uctx);

  gSignalThread = kInvalidThreadId;
  // Kill ourselves with the previous handler.
  callPreviousSignalHandler(signum);
}

}  // namespace

void addFatalSignalCallback(SignalCallback cb) {
  gFatalSignalCallbackRegistry->add(cb);
}

void installFatalSignalCallbacks() {
  gFatalSignalCallbackRegistry->markInstalled();
}

namespace {

std::atomic<bool> gAlreadyInstalled;

}  // namespace

void installFatalSignalHandler() {
  if (gAlreadyInstalled.exchange(true)) {
    // Already done.
    return;
  }

  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sigemptyset(&sa.sa_mask);
  // By default signal handlers are run on the signaled thread's stack.
  // In case of stack overflow running the SIGSEGV signal handler on
  // the same stack leads to another SIGSEGV and crashes the program.
  // Use SA_ONSTACK, so alternate stack is used (only if configured via
  // sigaltstack).
  sa.sa_flags |= SA_SIGINFO | SA_ONSTACK;
  sa.sa_sigaction = &signalHandler;

  for (auto p = kFatalSignals; p->name; ++p) {
    CHECK_ERR(sigaction(p->number, &sa, &p->oldAction));
  }
}

}}  // namespaces
<commit_msg>Log pid/uid of sending process in signal handler, too<commit_after>/*
 * Copyright 2015 Facebook, 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.
 */

// This is heavily inspired by the signal handler from google-glog

#include <folly/experimental/symbolizer/SignalHandler.h>

#include <sys/types.h>
#include <sys/syscall.h>
#include <atomic>
#include <ctime>
#include <mutex>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <vector>

#include <glog/logging.h>

#include <folly/Conv.h>
#include <folly/FileUtil.h>
#include <folly/Portability.h>
#include <folly/ScopeGuard.h>
#include <folly/experimental/symbolizer/Symbolizer.h>

namespace folly { namespace symbolizer {

namespace {

/**
 * Fatal signal handler registry.
 */
class FatalSignalCallbackRegistry {
 public:
  FatalSignalCallbackRegistry();

  void add(SignalCallback func);
  void markInstalled();
  void run();

 private:
  std::atomic<bool> installed_;
  std::mutex mutex_;
  std::vector<SignalCallback> handlers_;
};

FatalSignalCallbackRegistry::FatalSignalCallbackRegistry()
  : installed_(false) {
}

void FatalSignalCallbackRegistry::add(SignalCallback func) {
  std::lock_guard<std::mutex> lock(mutex_);
  CHECK(!installed_)
    << "FatalSignalCallbackRegistry::add may not be used "
       "after installing the signal handlers.";
  handlers_.push_back(func);
}

void FatalSignalCallbackRegistry::markInstalled() {
  std::lock_guard<std::mutex> lock(mutex_);
  CHECK(!installed_.exchange(true))
    << "FatalSignalCallbackRegistry::markInstalled must be called "
    << "at most once";
}

void FatalSignalCallbackRegistry::run() {
  if (!installed_) {
    return;
  }

  for (auto& fn : handlers_) {
    fn();
  }
}

// Leak it so we don't have to worry about destruction order
FatalSignalCallbackRegistry* gFatalSignalCallbackRegistry =
  new FatalSignalCallbackRegistry;

struct {
  int number;
  const char* name;
  struct sigaction oldAction;
} kFatalSignals[] = {
  { SIGSEGV, "SIGSEGV" },
  { SIGILL,  "SIGILL"  },
  { SIGFPE,  "SIGFPE"  },
  { SIGABRT, "SIGABRT" },
  { SIGBUS,  "SIGBUS"  },
  { SIGTERM, "SIGTERM" },
  { 0,       nullptr   }
};

void callPreviousSignalHandler(int signum) {
  // Restore disposition to old disposition, then kill ourselves with the same
  // signal. The signal will be blocked until we return from our handler,
  // then it will invoke the default handler and abort.
  for (auto p = kFatalSignals; p->name; ++p) {
    if (p->number == signum) {
      sigaction(signum, &p->oldAction, nullptr);
      raise(signum);
      return;
    }
  }

  // Not one of the signals we know about. Oh well. Reset to default.
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SIG_DFL;
  sigaction(signum, &sa, nullptr);
  raise(signum);
}

constexpr size_t kDefaultCapacity = 500;

// Note: not thread-safe, but that's okay, as we only let one thread
// in our signal handler at a time.
//
// Leak it so we don't have to worry about destruction order
auto gSignalSafeElfCache = new SignalSafeElfCache(kDefaultCapacity);

// Buffered writer (using a fixed-size buffer). We try to write only once
// to prevent interleaving with messages written from other threads.
//
// Leak it so we don't have to worry about destruction order.
auto gPrinter = new FDSymbolizePrinter(STDERR_FILENO,
                                       SymbolizePrinter::COLOR_IF_TTY,
                                       size_t(64) << 10);  // 64KiB

// Flush gPrinter, also fsync, in case we're about to crash again...
void flush() {
  gPrinter->flush();
  fsyncNoInt(STDERR_FILENO);
}

void printDec(uint64_t val) {
  char buf[20];
  uint32_t n = uint64ToBufferUnsafe(val, buf);
  gPrinter->print(StringPiece(buf, n));
}

const char kHexChars[] = "0123456789abcdef";
void printHex(uint64_t val) {
  // TODO(tudorb): Add this to folly/Conv.h
  char buf[2 + 2 * sizeof(uint64_t)];  // "0x" prefix, 2 digits for each byte

  char* end = buf + sizeof(buf);
  char* p = end;
  do {
    *--p = kHexChars[val & 0x0f];
    val >>= 4;
  } while (val != 0);
  *--p = 'x';
  *--p = '0';

  gPrinter->print(StringPiece(p, end));
}

void print(StringPiece sp) {
  gPrinter->print(sp);
}

void dumpTimeInfo() {
  SCOPE_EXIT { flush(); };
  time_t now = time(nullptr);
  print("*** Aborted at ");
  printDec(now);
  print(" (Unix time, try 'date -d @");
  printDec(now);
  print("') ***\n");
}

const char* sigill_reason(int si_code) {
  switch (si_code) {
    case ILL_ILLOPC:
      return "illegal opcode";
    case ILL_ILLOPN:
      return "illegal operand";
    case ILL_ILLADR:
      return "illegal addressing mode";
    case ILL_ILLTRP:
      return "illegal trap";
    case ILL_PRVOPC:
      return "privileged opcode";
    case ILL_PRVREG:
      return "privileged register";
    case ILL_COPROC:
      return "coprocessor error";
    case ILL_BADSTK:
      return "internal stack error";

    default:
      return nullptr;
  }
}

const char* sigfpe_reason(int si_code) {
  switch (si_code) {
    case FPE_INTDIV:
      return "integer divide by zero";
    case FPE_INTOVF:
      return "integer overflow";
    case FPE_FLTDIV:
      return "floating-point divide by zero";
    case FPE_FLTOVF:
      return "floating-point overflow";
    case FPE_FLTUND:
      return "floating-point underflow";
    case FPE_FLTRES:
      return "floating-point inexact result";
    case FPE_FLTINV:
      return "floating-point invalid operation";
    case FPE_FLTSUB:
      return "subscript out of range";

    default:
      return nullptr;
  }
}

const char* sigsegv_reason(int si_code) {
  switch (si_code) {
    case SEGV_MAPERR:
      return "address not mapped to object";
    case SEGV_ACCERR:
      return "invalid permissions for mapped object";

    default:
      return nullptr;
  }
}

const char* sigbus_reason(int si_code) {
  switch (si_code) {
    case BUS_ADRALN:
      return "invalid address alignment";
    case BUS_ADRERR:
      return "nonexistent physical address";
    case BUS_OBJERR:
      return "object-specific hardware error";

    // MCEERR_AR and MCEERR_AO: in sigaction(2) but not in headers.

    default:
      return nullptr;
  }
}

const char* sigtrap_reason(int si_code) {
  switch (si_code) {
    case TRAP_BRKPT:
      return "process breakpoint";
    case TRAP_TRACE:
      return "process trace trap";

    // TRAP_BRANCH and TRAP_HWBKPT: in sigaction(2) but not in headers.

    default:
      return nullptr;
  }
}

const char* sigchld_reason(int si_code) {
  switch (si_code) {
    case CLD_EXITED:
      return "child has exited";
    case CLD_KILLED:
      return "child was killed";
    case CLD_DUMPED:
      return "child terminated abnormally";
    case CLD_TRAPPED:
      return "traced child has trapped";
    case CLD_STOPPED:
      return "child has stopped";
    case CLD_CONTINUED:
      return "stopped child has continued";

    default:
      return nullptr;
  }
}

const char* sigio_reason(int si_code) {
  switch (si_code) {
    case POLL_IN:
      return "data input available";
    case POLL_OUT:
      return "output buffers available";
    case POLL_MSG:
      return "input message available";
    case POLL_ERR:
      return "I/O error";
    case POLL_PRI:
      return "high priority input available";
    case POLL_HUP:
      return "device disconnected";

    default:
      return nullptr;
  }
}

const char* signal_reason(int signum, int si_code) {
  switch (signum) {
    case SIGILL:
      return sigill_reason(si_code);
    case SIGFPE:
      return sigfpe_reason(si_code);
    case SIGSEGV:
      return sigsegv_reason(si_code);
    case SIGBUS:
      return sigbus_reason(si_code);
    case SIGTRAP:
      return sigtrap_reason(si_code);
    case SIGCHLD:
      return sigchld_reason(si_code);
    case SIGIO:
      return sigio_reason(si_code); // aka SIGPOLL

    default:
      return nullptr;
  }
}

void dumpSignalInfo(int signum, siginfo_t* siginfo) {
  SCOPE_EXIT { flush(); };
  // Get the signal name, if possible.
  const char* name = nullptr;
  for (auto p = kFatalSignals; p->name; ++p) {
    if (p->number == signum) {
      name = p->name;
      break;
    }
  }

  print("*** Signal ");
  printDec(signum);
  if (name) {
    print(" (");
    print(name);
    print(")");
  }

  print(" (");
  printHex(reinterpret_cast<uint64_t>(siginfo->si_addr));
  print(") received by PID ");
  printDec(getpid());
  print(" (pthread TID ");
  printHex((uint64_t)pthread_self());
  print(") (linux TID ");
  printDec(syscall(__NR_gettid));

  // Kernel-sourced signals don't give us useful info for pid/uid.
  if (siginfo->si_code != SI_KERNEL) {
    print(") (maybe from PID ");
    printDec(siginfo->si_pid);
    print(", UID ");
    printDec(siginfo->si_uid);
  }

  auto reason = signal_reason(signum, siginfo->si_code);

  if (reason != nullptr) {
    print(") (code: ");
    print(reason);
  }

  print("), stack trace: ***\n");
}

FOLLY_NOINLINE void dumpStackTrace(bool symbolize);

void dumpStackTrace(bool symbolize) {
  SCOPE_EXIT { flush(); };
  // Get and symbolize stack trace
  constexpr size_t kMaxStackTraceDepth = 100;
  FrameArray<kMaxStackTraceDepth> addresses;

  // Skip the getStackTrace frame
  if (!getStackTraceSafe(addresses)) {
    print("(error retrieving stack trace)\n");
  } else if (symbolize) {
    Symbolizer symbolizer(gSignalSafeElfCache);
    symbolizer.symbolize(addresses);

    // Skip the top 2 frames:
    // getStackTraceSafe
    // dumpStackTrace (here)
    //
    // Leaving signalHandler on the stack for clarity, I think.
    gPrinter->println(addresses, 2);
  } else {
    print("(safe mode, symbolizer not available)\n");
    AddressFormatter formatter;
    for (size_t i = 0; i < addresses.frameCount; ++i) {
      print(formatter.format(addresses.addresses[i]));
      print("\n");
    }
  }
}

// On Linux, pthread_t is a pointer, so 0 is an invalid value, which we
// take to indicate "no thread in the signal handler".
//
// POSIX defines PTHREAD_NULL for this purpose, but that's not available.
constexpr pthread_t kInvalidThreadId = 0;

std::atomic<pthread_t> gSignalThread(kInvalidThreadId);
std::atomic<bool> gInRecursiveSignalHandler(false);

// Here be dragons.
void innerSignalHandler(int signum, siginfo_t* info, void* uctx) {
  // First, let's only let one thread in here at a time.
  pthread_t myId = pthread_self();

  pthread_t prevSignalThread = kInvalidThreadId;
  while (!gSignalThread.compare_exchange_strong(prevSignalThread, myId)) {
    if (pthread_equal(prevSignalThread, myId)) {
      // First time here. Try to dump the stack trace without symbolization.
      // If we still fail, well, we're mightily screwed, so we do nothing the
      // next time around.
      if (!gInRecursiveSignalHandler.exchange(true)) {
        print("Entered fatal signal handler recursively. We're in trouble.\n");
        dumpStackTrace(false);  // no symbolization
      }
      return;
    }

    // Wait a while, try again.
    timespec ts;
    ts.tv_sec = 0;
    ts.tv_nsec = 100L * 1000 * 1000;  // 100ms
    nanosleep(&ts, nullptr);

    prevSignalThread = kInvalidThreadId;
  }

  dumpTimeInfo();
  dumpSignalInfo(signum, info);
  dumpStackTrace(true);  // with symbolization

  // Run user callbacks
  gFatalSignalCallbackRegistry->run();
}

void signalHandler(int signum, siginfo_t* info, void* uctx) {
  SCOPE_EXIT { flush(); };
  innerSignalHandler(signum, info, uctx);

  gSignalThread = kInvalidThreadId;
  // Kill ourselves with the previous handler.
  callPreviousSignalHandler(signum);
}

}  // namespace

void addFatalSignalCallback(SignalCallback cb) {
  gFatalSignalCallbackRegistry->add(cb);
}

void installFatalSignalCallbacks() {
  gFatalSignalCallbackRegistry->markInstalled();
}

namespace {

std::atomic<bool> gAlreadyInstalled;

}  // namespace

void installFatalSignalHandler() {
  if (gAlreadyInstalled.exchange(true)) {
    // Already done.
    return;
  }

  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sigemptyset(&sa.sa_mask);
  // By default signal handlers are run on the signaled thread's stack.
  // In case of stack overflow running the SIGSEGV signal handler on
  // the same stack leads to another SIGSEGV and crashes the program.
  // Use SA_ONSTACK, so alternate stack is used (only if configured via
  // sigaltstack).
  sa.sa_flags |= SA_SIGINFO | SA_ONSTACK;
  sa.sa_sigaction = &signalHandler;

  for (auto p = kFatalSignals; p->name; ++p) {
    CHECK_ERR(sigaction(p->number, &sa, &p->oldAction));
  }
}

}}  // namespaces
<|endoftext|>


<commit_before>#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Verifier.h>
#include <vector>
#include <string>

static llvm::LLVMContext &Context = llvm::getGlobalContext();
static llvm::Module *ModuleOb = new llvm::Module("my compiler", Context);

llvm::Function *createFunc(llvm::IRBuilder<> &Builder, std::string Name)
{
  llvm::FunctionType *funcTy = llvm::FunctionType::get(Builder.getInt32Ty(), false);
  llvm::Function *fooFunc = llvm::Function::Create(
      funcTy, llvm::Function::ExternalLinkage, Name, ModuleOb);
  return fooFunc;
}

llvm::GlobalVariable *createGlob(llvm::IRBuilder<> &Builder, std::string Name) {
  ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty());
  llvm::GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name);
  gVar->setLinkage(llvm::GlobalValue::CommonLinkage);
  gVar->setAlignment(4);
  return gVar;
}

llvm::BasicBlock *createBB(llvm::Function *fooFunc, std::string Name)
{
  return llvm::BasicBlock::Create(Context, Name, fooFunc);
}

int main(int argc, char *argv[]) {
  static llvm::IRBuilder<> Builder(Context);

  llvm::GlobalVariable *gVar = createGlob(Builder, "x");

  llvm::Function *fooFunc = createFunc(Builder, "foo");

  llvm::BasicBlock* entry = createBB(fooFunc, "entry");
  Builder.SetInsertPoint(entry);

  llvm::verifyFunction(*fooFunc);
  ModuleOb->dump();
  return 0;
}
<commit_msg>emit return<commit_after>#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Verifier.h>
#include <vector>
#include <string>

static llvm::LLVMContext &Context = llvm::getGlobalContext();
static llvm::Module *ModuleOb = new llvm::Module("my compiler", Context);

llvm::Function *createFunc(llvm::IRBuilder<> &Builder, std::string Name)
{
  llvm::FunctionType *funcTy = llvm::FunctionType::get(Builder.getInt32Ty(), false);
  llvm::Function *fooFunc = llvm::Function::Create(
      funcTy, llvm::Function::ExternalLinkage, Name, ModuleOb);
  return fooFunc;
}

llvm::GlobalVariable *createGlob(llvm::IRBuilder<> &Builder, std::string Name) {
  ModuleOb->getOrInsertGlobal(Name, Builder.getInt32Ty());
  llvm::GlobalVariable *gVar = ModuleOb->getNamedGlobal(Name);
  gVar->setLinkage(llvm::GlobalValue::CommonLinkage);
  gVar->setAlignment(4);
  return gVar;
}

llvm::BasicBlock *createBB(llvm::Function *fooFunc, std::string Name)
{
  return llvm::BasicBlock::Create(Context, Name, fooFunc);
}

int main(int argc, char *argv[]) {
  static llvm::IRBuilder<> Builder(Context);

  llvm::GlobalVariable *gVar = createGlob(Builder, "x");

  llvm::Function *fooFunc = createFunc(Builder, "foo");

  llvm::BasicBlock* entry = createBB(fooFunc, "entry");
  Builder.SetInsertPoint(entry);

  //Builder.CreateRet(Builder.getInt32(0));
  Builder.CreateRet(gVar);

  llvm::verifyFunction(*fooFunc);
  ModuleOb->dump();
  return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include <tuple>
#include <functional>
#include <exception>

namespace multi_iter {
#ifdef __cpp_concepts
template <typename T>
concept bool ForwardIterator = requires(T it) {
    {*it};
    {++it};
    {it == it}
};

template <typename T>
concept bool ForwardIterable = ForwardIterator<decltype (std::begin(std::declval<T>()))>
        && ForwardIterator<decltype (std::end(std::declval<T>()))>;

#define IS_ITERABLE(T) ForwardIterable T

#else
    //TODO do some enable_if
#define IS_ITERABLE(T) typename T
#endif

template <typename ... Args>
class multi_iterator {
	template <IS_ITERABLE(Container)>
	using start_iterator = decltype (std::begin(std::declval<Container>()));

	template <IS_ITERABLE(Container)>
	using end_iterator = decltype (std::end(std::declval<Container>()));

	template <IS_ITERABLE(Container)>
	using iterator_pair = std::pair<start_iterator<Container>, end_iterator<Container>>;

public:
	using iterators = std::tuple<iterator_pair<Args>...>;

    template <typename T>
    explicit multi_iterator(T&& t)
        :_data{std::forward<T>(t)}
    {
    }
    bool is_done() const noexcept {
        return std::get<0>(this->_data).first == std::get<0>(this->_data).second;
    }

    auto& operator++() {
        this->increment(std::make_index_sequence<sizeof...(Args)>());
        return *this;
    }
    auto operator*() {
        return this->deref(std::make_index_sequence<sizeof...(Args)>());
    }

    friend bool operator != (const multi_iterator& pthis, const multi_iterator<std::nullptr_t>& /*sentinel*/) noexcept {
        return !pthis.is_done();
    }
private:
    template <size_t ... index>
    void increment(std::index_sequence<index...>) {
        std::initializer_list<int>{(++std::get<index>(this->_data).first, 0) ...};
    }

    template <size_t ... index>
    auto deref(std::index_sequence<index...>) {
        return std::make_tuple(std::ref(*std::get<index>(this->_data).first) ...);
    }
    template <size_t ... index>
    auto deref(std::index_sequence<index...>) const {
        return std::make_tuple(std::cref(*std::get<index>(this->_data).first) ...);
    }

private:
    iterators _data;
};

template <>
class multi_iterator<std::nullptr_t> {
};

template <typename ... Args>
class multi_adapter {
public:
    template <typename ... T>
    explicit multi_adapter(T&& ... t)
        :_data{{std::begin(t), std::end(t)} ...}
    {
    }
    auto begin() {
        return multi_iterator<Args...>(this->_data);
    }
    auto end() {
        return multi_iterator<std::nullptr_t>();
    }
private:
    typename multi_iterator<Args...>::iterators _data;
};

template <IS_ITERABLE(C), typename ... Args>
auto get_size(C&& c, Args&& ...) {
    return std::size(c);
}

/**
    TODO:
        - allow different container sizes with user-defined fallback values
*/
template <typename ... Args>
auto iterate(Args && ... args) {
    const auto size = get_size(std::forward<Args>(args) ...);
    if (((get_size(args) != size) || ...)) {
        throw std::runtime_error("cannot multi-iterate containers of different sizes");
    }
    return multi_adapter<Args...>(std::forward<Args>(args)...);
}

} // namespace

<commit_msg>specify return types for iterator ops<commit_after>#pragma once

#include <tuple>
#include <functional>
#include <exception>

namespace multi_iter {
#ifdef __cpp_concepts
template <typename T>
concept bool ForwardIterator = requires(T it) {
    {*it};
    {++it} -> T;
    {it == it} -> bool
};

template <typename T>
concept bool ForwardIterable = ForwardIterator<decltype (std::begin(std::declval<T>()))>
        && ForwardIterator<decltype (std::end(std::declval<T>()))>;

#define IS_ITERABLE(T) ForwardIterable T

#else
    //TODO do some enable_if
#define IS_ITERABLE(T) typename T
#endif

template <typename ... Args>
class multi_iterator {
	template <IS_ITERABLE(Container)>
	using start_iterator = decltype (std::begin(std::declval<Container>()));

	template <IS_ITERABLE(Container)>
	using end_iterator = decltype (std::end(std::declval<Container>()));

	template <IS_ITERABLE(Container)>
	using iterator_pair = std::pair<start_iterator<Container>, end_iterator<Container>>;

public:
	using iterators = std::tuple<iterator_pair<Args>...>;

    template <typename T>
    explicit multi_iterator(T&& t)
        :_data{std::forward<T>(t)}
    {
    }
    bool is_done() const noexcept {
        return std::get<0>(this->_data).first == std::get<0>(this->_data).second;
    }

    auto& operator++() {
        this->increment(std::make_index_sequence<sizeof...(Args)>());
        return *this;
    }
    auto operator*() {
        return this->deref(std::make_index_sequence<sizeof...(Args)>());
    }

    friend bool operator != (const multi_iterator& pthis, const multi_iterator<std::nullptr_t>& /*sentinel*/) noexcept {
        return !pthis.is_done();
    }
private:
    template <size_t ... index>
    void increment(std::index_sequence<index...>) {
        std::initializer_list<int>{(++std::get<index>(this->_data).first, 0) ...};
    }

    template <size_t ... index>
    auto deref(std::index_sequence<index...>) {
        return std::make_tuple(std::ref(*std::get<index>(this->_data).first) ...);
    }
    template <size_t ... index>
    auto deref(std::index_sequence<index...>) const {
        return std::make_tuple(std::cref(*std::get<index>(this->_data).first) ...);
    }

private:
    iterators _data;
};

template <>
class multi_iterator<std::nullptr_t> {
};

template <typename ... Args>
class multi_adapter {
public:
    template <typename ... T>
    explicit multi_adapter(T&& ... t)
        :_data{{std::begin(t), std::end(t)} ...}
    {
    }
    auto begin() {
        return multi_iterator<Args...>(this->_data);
    }
    auto end() {
        return multi_iterator<std::nullptr_t>();
    }
private:
    typename multi_iterator<Args...>::iterators _data;
};

template <IS_ITERABLE(C), typename ... Args>
auto get_size(C&& c, Args&& ...) {
    return std::size(c);
}

/**
    TODO:
        - allow different container sizes with user-defined fallback values
*/
template <typename ... Args>
auto iterate(Args && ... args) {
    const auto size = get_size(std::forward<Args>(args) ...);
    if (((get_size(args) != size) || ...)) {
        throw std::runtime_error("cannot multi-iterate containers of different sizes");
    }
    return multi_adapter<Args...>(std::forward<Args>(args)...);
}

} // namespace

<|endoftext|>


<commit_before>// stack solution by hxdone

class Solution {
public:
	int romanToInt(string s) {
		map<char, int> sym_table;
		sym_table['I'] = 1;
		sym_table['V'] = 5;
		sym_table['X'] = 10;
		sym_table['L'] = 50;
		sym_table['C'] = 100;
		sym_table['D'] = 500;
		sym_table['M'] = 1000;
		stack<int> v_stack;
		for (int i = 0; i < s.length(); ++i) {
			int v = sym_table[s[i]];
			while (!v_stack.empty() && v > v_stack.top()) {
				v = v-v_stack.top();
				v_stack.pop();
			}
			v_stack.push(v);
		}
		int ret = 0;
		while (!v_stack.empty()) {
			ret += v_stack.top();
			v_stack.pop();
		}
		return ret;
	}
};
<commit_msg>improve solution for leetcode/Algorithms/RomanToInteger<commit_after>// char-array hashmap and backward-summing solution by hxdone

class Solution {
public:
    Solution() {
        sym_table['I'] = 1;
        sym_table['V'] = 5;
        sym_table['X'] = 10;
        sym_table['L'] = 50;
        sym_table['C'] = 100;
        sym_table['D'] = 500;
        sym_table['M'] = 1000;
    }
    int romanToInt(string s) {
        int ret = 0;
        int last = 0;
        for (int i = s.length()-1; i >= 0; --i) {
            int v = sym_table[s[i]];
            if (v >= last) {
                ret += v;
                last = v;
            }
            else
                ret -= v;
        }
        return ret;
    }
private:
    int sym_table[256];
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <QFile>
#include <QDebug>
#include <QTimer>
#include <QApplication>
#include <QJoysticks/SDL_Joysticks.h>

/**
 * Holds a generic mapping to be applied to joysticks that have not been mapped
 * by the SDL project or by the database.
 *
 * This mapping is different on each supported operating system.
 */
static QString GENERIC_MAPPINGS;

/**
 * Load a different generic/backup mapping for each operating system.
 */
#ifdef SDL_SUPPORTED
    #if defined Q_OS_WIN
        #define GENERIC_MAPPINGS_PATH ":/QJoysticks/SDL/GenericMappings/Windows.txt"
    #elif defined Q_OS_MAC
        #define GENERIC_MAPPINGS_PATH ":/QJoysticks/SDL/GenericMappings/OSX.txt"
    #elif defined Q_OS_LINUX && !defined Q_OS_ANDROID
        #define GENERIC_MAPPINGS_PATH ":/QJoysticks/SDL/GenericMappings/Linux.txt"
    #endif
#endif

SDL_Joysticks::SDL_Joysticks (QObject* parent) : QObject (parent)
{
    m_tracker = -1;

#ifdef SDL_SUPPORTED
    if (SDL_Init (SDL_INIT_HAPTIC | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER)) {
        qDebug() << "Cannot initialize SDL:" << SDL_GetError();
        qApp->quit();
    }

    QFile database (":/QJoysticks/SDL/Database.txt");
    if (database.open (QFile::ReadOnly)) {
        while (!database.atEnd()) {
            QString line = QString::fromUtf8 (database.readLine());
            SDL_GameControllerAddMapping (line.toStdString().c_str());
        }

        database.close();
    }

    QFile genericMappings (GENERIC_MAPPINGS_PATH);
    if (genericMappings.open (QFile::ReadOnly)) {
        GENERIC_MAPPINGS = QString::fromUtf8 (genericMappings.readAll());
        genericMappings.close();
    }

    QTimer::singleShot (100, Qt::PreciseTimer, this, &SDL_Joysticks::update);
#endif
}

SDL_Joysticks::~SDL_Joysticks()
{
#ifdef SDL_SUPPORTED
    SDL_Quit();
#endif
}

/**
 * Returns a list with all the registered joystick devices
 */
QList<QJoystickDevice*> SDL_Joysticks::joysticks()
{
    QList<QJoystickDevice*> list;

#ifdef SDL_SUPPORTED
    for (int i = 0; i < SDL_NumJoysticks(); ++i)
        list.append (getJoystick (i));
#endif

    return list;
}

/**
 * Based on the data contained in the \a request, this function will instruct
 * the appropriate joystick to rumble for
 */
void SDL_Joysticks::rumble (const QJoystickRumble& request)
{
#ifdef SDL_SUPPORTED
    SDL_Haptic* haptic = SDL_HapticOpen (request.joystick->id);

    if (haptic) {
        SDL_HapticRumbleInit (haptic);
        SDL_HapticRumblePlay (haptic, request.strength, request.length);
    }
#else
    Q_UNUSED (request);
#endif
}

/**
 * Polls for new SDL events and reacts to each event accordingly.
 */
void SDL_Joysticks::update()
{
#ifdef SDL_SUPPORTED
    SDL_Event event;

    while (SDL_PollEvent (&event)) {
        switch (event.type) {
        case SDL_JOYDEVICEADDED:
            configureJoystick (&event);
            break;
        case SDL_JOYDEVICEREMOVED:
            SDL_JoystickClose (SDL_JoystickOpen (event.jdevice.which));
            SDL_GameControllerClose (SDL_GameControllerOpen (event.cdevice.which));
            emit countChanged();
            break;
        case SDL_CONTROLLERAXISMOTION:
            emit axisEvent (getAxisEvent (&event));
            break;
        case SDL_JOYBUTTONUP:
            emit buttonEvent (getButtonEvent (&event));
            break;
        case SDL_JOYBUTTONDOWN:
            emit buttonEvent (getButtonEvent (&event));
            break;
        case SDL_JOYHATMOTION:
            emit POVEvent (getPOVEvent (&event));
            break;
        }
    }

    QTimer::singleShot (10, Qt::PreciseTimer, this, &SDL_Joysticks::update);
#endif
}

/**
 * Checks if the joystick referenced by the \a event can be initialized.
 * If not, the function will apply a generic mapping to the joystick and
 * attempt to initialize the joystick again.
 */
void SDL_Joysticks::configureJoystick (const SDL_Event* event)
{
#ifdef SDL_SUPPORTED
    if (!SDL_IsGameController (event->cdevice.which)) {
        SDL_Joystick* js = SDL_JoystickOpen (event->jdevice.which);

        if (js) {
            char guid [1024];
            SDL_JoystickGetGUIDString (SDL_JoystickGetGUID (js), guid, sizeof (guid));

            QString mapping = QString ("%1,%2,%3")
                              .arg (guid)
                              .arg (SDL_JoystickName (js))
                              .arg (GENERIC_MAPPINGS);

            SDL_GameControllerAddMapping (mapping.toStdString().c_str());
            SDL_JoystickClose (js);
        }
    }

    SDL_GameControllerOpen (event->cdevice.which);

    ++m_tracker;
    emit countChanged();
#else
    Q_UNUSED (event);
#endif
}

/**
 * Returns a joystick ID compatible with the \c QJoysticks system.
 * SDL assigns an ID to each joystick based on the order that they are attached,
 * but it does not decrease the ID counter when a joystick is removed.
 *
 * As noted earlier, the \c QJoysticks maintains an ID system similar to the
 * one used by a \c QList, since it eases the operation with most Qt classes
 * and widgets.
 */
int SDL_Joysticks::getDynamicID (int id)
{
#ifdef SDL_SUPPORTED
    id = abs (m_tracker - (id + 1));

    if (id >= SDL_NumJoysticks())
        id -= 1;

#endif

    return id;
}

/**
 * Returns the josytick device registered with the given \a id.
 * If no joystick with the given \a id is found, then the function will warn
 * the user through the console.
 */
QJoystickDevice* SDL_Joysticks::getJoystick (int id)
{
#ifdef SDL_SUPPORTED
    QJoystickDevice* joystick = new QJoystickDevice;
    SDL_Joystick* sdl_joystick = SDL_JoystickOpen (id);
    joystick->id = getDynamicID (id);

    if (sdl_joystick) {
        joystick->blacklisted = false;
        joystick->name = SDL_JoystickName (sdl_joystick);

        /* Get joystick properties */
        int povs = SDL_JoystickNumHats (sdl_joystick);
        int axes = SDL_JoystickNumAxes (sdl_joystick);
        int buttons = SDL_JoystickNumButtons (sdl_joystick);

        /* Initialize POVs */
        for (int i = 0; i < povs; ++i)
            joystick->povs.append (0);

        /* Initialize axes */
        for (int i = 0; i < axes; ++i)
            joystick->axes.append (0);

        /* Initialize buttons */
        for (int i = 0; i < buttons; ++i)
            joystick->buttons.append (false);
    }

    else
        qWarning() << Q_FUNC_INFO << "Cannot find joystick with id:" << id;

    return joystick;
#else
    Q_UNUSED (id);
    return NULL;
#endif
}

/**
 * Reads the contents of the given \a event and constructs a new
 * \c QJoystickPOVEvent to be used with the \c QJoysticks system.
 */
QJoystickPOVEvent SDL_Joysticks::getPOVEvent (const SDL_Event* sdl_event)
{
    QJoystickPOVEvent event;

#ifdef SDL_SUPPORTED
    event.pov = sdl_event->jhat.hat;
    event.joystick = getJoystick (sdl_event->jdevice.which);

    switch (sdl_event->jhat.value) {
    case SDL_HAT_RIGHTUP:
        event.angle = 45;
        break;
    case SDL_HAT_RIGHTDOWN:
        event.angle = 135;
        break;
    case SDL_HAT_LEFTDOWN:
        event.angle = 225;
        break;
    case SDL_HAT_LEFTUP:
        event.angle = 315;
        break;
    case SDL_HAT_UP:
        event.angle = 0;
        break;
    case SDL_HAT_RIGHT:
        event.angle = 90;
        break;
    case SDL_HAT_DOWN:
        event.angle = 180;
        break;
    case SDL_HAT_LEFT:
        event.angle = 270;
        break;
    default:
        event.angle = -1;
        break;
    }
#else
    Q_UNUSED (sdl_event);
#endif

    return event;
}

/**
 * Reads the contents of the given \a event and constructs a new
 * \c QJoystickAxisEvent to be used with the \c QJoysticks system.
 */
QJoystickAxisEvent SDL_Joysticks::getAxisEvent (const SDL_Event* sdl_event)
{
    QJoystickAxisEvent event;

#ifdef SDL_SUPPORTED
    event.axis = sdl_event->caxis.axis;
    event.value = static_cast<qreal> (sdl_event->caxis.value) / 32767;
    event.joystick = getJoystick (sdl_event->cdevice.which);
#else
    Q_UNUSED (sdl_event);
#endif

    return event;
}

/**
 * Reads the contents of the given \a event and constructs a new
 * \c QJoystickButtonEvent to be used with the \c QJoysticks system.
 */
QJoystickButtonEvent SDL_Joysticks::getButtonEvent (const SDL_Event*
        sdl_event)
{
    QJoystickButtonEvent event;

#ifdef SDL_SUPPORTED
    event.button = sdl_event->jbutton.button;
    event.pressed = sdl_event->jbutton.state == SDL_PRESSED;
    event.joystick = getJoystick (sdl_event->jdevice.which);
#else
    Q_UNUSED (sdl_event);
#endif

    return event;
}
<commit_msg>Update SDL_Joysticks.cpp<commit_after>/*
 * Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <QFile>
#include <QDebug>
#include <QTimer>
#include <QApplication>
#include <QJoysticks/SDL_Joysticks.h>

/**
 * Holds a generic mapping to be applied to joysticks that have not been mapped
 * by the SDL project or by the database.
 *
 * This mapping is different on each supported operating system.
 */
static QString GENERIC_MAPPINGS;

/**
 * Load a different generic/backup mapping for each operating system.
 */
#ifdef SDL_SUPPORTED
    #if defined Q_OS_WIN
        #define GENERIC_MAPPINGS_PATH ":/QJoysticks/SDL/GenericMappings/Windows.txt"
    #elif defined Q_OS_MAC
        #define GENERIC_MAPPINGS_PATH ":/QJoysticks/SDL/GenericMappings/OSX.txt"
    #elif defined Q_OS_LINUX && !defined Q_OS_ANDROID
        #define GENERIC_MAPPINGS_PATH ":/QJoysticks/SDL/GenericMappings/Linux.txt"
    #endif
#endif

SDL_Joysticks::SDL_Joysticks (QObject* parent) : QObject (parent)
{
    m_tracker = -1;

#ifdef SDL_SUPPORTED
    if (SDL_Init (SDL_INIT_HAPTIC | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER)) {
        qDebug() << "Cannot initialize SDL:" << SDL_GetError();
        qApp->quit();
    }

    QFile database (":/QJoysticks/SDL/Database.txt");
    if (database.open (QFile::ReadOnly)) {
        while (!database.atEnd()) {
            QString line = QString::fromUtf8 (database.readLine());
            SDL_GameControllerAddMapping (line.toStdString().c_str());
        }

        database.close();
    }

    QFile genericMappings (GENERIC_MAPPINGS_PATH);
    if (genericMappings.open (QFile::ReadOnly)) {
        GENERIC_MAPPINGS = QString::fromUtf8 (genericMappings.readAll());
        genericMappings.close();
    }

    QTimer::singleShot (100, Qt::PreciseTimer, this, SLOT (update()));
#endif
}

SDL_Joysticks::~SDL_Joysticks()
{
#ifdef SDL_SUPPORTED
    SDL_Quit();
#endif
}

/**
 * Returns a list with all the registered joystick devices
 */
QList<QJoystickDevice*> SDL_Joysticks::joysticks()
{
    QList<QJoystickDevice*> list;

#ifdef SDL_SUPPORTED
    for (int i = 0; i < SDL_NumJoysticks(); ++i)
        list.append (getJoystick (i));
#endif

    return list;
}

/**
 * Based on the data contained in the \a request, this function will instruct
 * the appropriate joystick to rumble for
 */
void SDL_Joysticks::rumble (const QJoystickRumble& request)
{
#ifdef SDL_SUPPORTED
    SDL_Haptic* haptic = SDL_HapticOpen (request.joystick->id);

    if (haptic) {
        SDL_HapticRumbleInit (haptic);
        SDL_HapticRumblePlay (haptic, request.strength, request.length);
    }
#else
    Q_UNUSED (request);
#endif
}

/**
 * Polls for new SDL events and reacts to each event accordingly.
 */
void SDL_Joysticks::update()
{
#ifdef SDL_SUPPORTED
    SDL_Event event;

    while (SDL_PollEvent (&event)) {
        switch (event.type) {
        case SDL_JOYDEVICEADDED:
            configureJoystick (&event);
            break;
        case SDL_JOYDEVICEREMOVED:
            SDL_JoystickClose (SDL_JoystickOpen (event.jdevice.which));
            SDL_GameControllerClose (SDL_GameControllerOpen (event.cdevice.which));
            emit countChanged();
            break;
        case SDL_CONTROLLERAXISMOTION:
            emit axisEvent (getAxisEvent (&event));
            break;
        case SDL_JOYBUTTONUP:
            emit buttonEvent (getButtonEvent (&event));
            break;
        case SDL_JOYBUTTONDOWN:
            emit buttonEvent (getButtonEvent (&event));
            break;
        case SDL_JOYHATMOTION:
            emit POVEvent (getPOVEvent (&event));
            break;
        }
    }

    QTimer::singleShot (10, Qt::PreciseTimer, this, &SDL_Joysticks::update);
#endif
}

/**
 * Checks if the joystick referenced by the \a event can be initialized.
 * If not, the function will apply a generic mapping to the joystick and
 * attempt to initialize the joystick again.
 */
void SDL_Joysticks::configureJoystick (const SDL_Event* event)
{
#ifdef SDL_SUPPORTED
    if (!SDL_IsGameController (event->cdevice.which)) {
        SDL_Joystick* js = SDL_JoystickOpen (event->jdevice.which);

        if (js) {
            char guid [1024];
            SDL_JoystickGetGUIDString (SDL_JoystickGetGUID (js), guid, sizeof (guid));

            QString mapping = QString ("%1,%2,%3")
                              .arg (guid)
                              .arg (SDL_JoystickName (js))
                              .arg (GENERIC_MAPPINGS);

            SDL_GameControllerAddMapping (mapping.toStdString().c_str());
            SDL_JoystickClose (js);
        }
    }

    SDL_GameControllerOpen (event->cdevice.which);

    ++m_tracker;
    emit countChanged();
#else
    Q_UNUSED (event);
#endif
}

/**
 * Returns a joystick ID compatible with the \c QJoysticks system.
 * SDL assigns an ID to each joystick based on the order that they are attached,
 * but it does not decrease the ID counter when a joystick is removed.
 *
 * As noted earlier, the \c QJoysticks maintains an ID system similar to the
 * one used by a \c QList, since it eases the operation with most Qt classes
 * and widgets.
 */
int SDL_Joysticks::getDynamicID (int id)
{
#ifdef SDL_SUPPORTED
    id = abs (m_tracker - (id + 1));

    if (id >= SDL_NumJoysticks())
        id -= 1;

#endif

    return id;
}

/**
 * Returns the josytick device registered with the given \a id.
 * If no joystick with the given \a id is found, then the function will warn
 * the user through the console.
 */
QJoystickDevice* SDL_Joysticks::getJoystick (int id)
{
#ifdef SDL_SUPPORTED
    QJoystickDevice* joystick = new QJoystickDevice;
    SDL_Joystick* sdl_joystick = SDL_JoystickOpen (id);
    joystick->id = getDynamicID (id);

    if (sdl_joystick) {
        joystick->blacklisted = false;
        joystick->name = SDL_JoystickName (sdl_joystick);

        /* Get joystick properties */
        int povs = SDL_JoystickNumHats (sdl_joystick);
        int axes = SDL_JoystickNumAxes (sdl_joystick);
        int buttons = SDL_JoystickNumButtons (sdl_joystick);

        /* Initialize POVs */
        for (int i = 0; i < povs; ++i)
            joystick->povs.append (0);

        /* Initialize axes */
        for (int i = 0; i < axes; ++i)
            joystick->axes.append (0);

        /* Initialize buttons */
        for (int i = 0; i < buttons; ++i)
            joystick->buttons.append (false);
    }

    else
        qWarning() << Q_FUNC_INFO << "Cannot find joystick with id:" << id;

    return joystick;
#else
    Q_UNUSED (id);
    return NULL;
#endif
}

/**
 * Reads the contents of the given \a event and constructs a new
 * \c QJoystickPOVEvent to be used with the \c QJoysticks system.
 */
QJoystickPOVEvent SDL_Joysticks::getPOVEvent (const SDL_Event* sdl_event)
{
    QJoystickPOVEvent event;

#ifdef SDL_SUPPORTED
    event.pov = sdl_event->jhat.hat;
    event.joystick = getJoystick (sdl_event->jdevice.which);

    switch (sdl_event->jhat.value) {
    case SDL_HAT_RIGHTUP:
        event.angle = 45;
        break;
    case SDL_HAT_RIGHTDOWN:
        event.angle = 135;
        break;
    case SDL_HAT_LEFTDOWN:
        event.angle = 225;
        break;
    case SDL_HAT_LEFTUP:
        event.angle = 315;
        break;
    case SDL_HAT_UP:
        event.angle = 0;
        break;
    case SDL_HAT_RIGHT:
        event.angle = 90;
        break;
    case SDL_HAT_DOWN:
        event.angle = 180;
        break;
    case SDL_HAT_LEFT:
        event.angle = 270;
        break;
    default:
        event.angle = -1;
        break;
    }
#else
    Q_UNUSED (sdl_event);
#endif

    return event;
}

/**
 * Reads the contents of the given \a event and constructs a new
 * \c QJoystickAxisEvent to be used with the \c QJoysticks system.
 */
QJoystickAxisEvent SDL_Joysticks::getAxisEvent (const SDL_Event* sdl_event)
{
    QJoystickAxisEvent event;

#ifdef SDL_SUPPORTED
    event.axis = sdl_event->caxis.axis;
    event.value = static_cast<qreal> (sdl_event->caxis.value) / 32767;
    event.joystick = getJoystick (sdl_event->cdevice.which);
#else
    Q_UNUSED (sdl_event);
#endif

    return event;
}

/**
 * Reads the contents of the given \a event and constructs a new
 * \c QJoystickButtonEvent to be used with the \c QJoysticks system.
 */
QJoystickButtonEvent SDL_Joysticks::getButtonEvent (const SDL_Event*
        sdl_event)
{
    QJoystickButtonEvent event;

#ifdef SDL_SUPPORTED
    event.button = sdl_event->jbutton.button;
    event.pressed = sdl_event->jbutton.state == SDL_PRESSED;
    event.joystick = getJoystick (sdl_event->jdevice.which);
#else
    Q_UNUSED (sdl_event);
#endif

    return event;
}
<|endoftext|>


<commit_before>#pragma once

#include "eigen.hh"

#include "numerics/optimization/error_function.hh"

#include <vector>

namespace numerics {

template <int dim_in, int dim_out>
struct MinimizationResult {
  VecNd<dim_in> solution = VecNd<dim_in>::Zero();
  VecNd<dim_in> terminal_jti = VecNd<dim_in>::Zero();
  VecNd<dim_out> terminal_error = VecNd<dim_out>::Zero();

  bool success = false;
};

struct OptimizationConfiguration {
  int max_iterations = 5;
  double levenberg_mu = 1e-3;
};

template <int dim_in, int dim_out>
MinimizationResult<dim_in, dim_out> gauss_newton_minimize(
    const std::vector<ErrorFunctionDifferentials<dim_in, dim_out>> &funcs,
    const VecNd<dim_in> &initialization,
    const OptimizationConfiguration &opt_cfg) {
  using OutVec = VecNd<dim_out>;
  using InVec = VecNd<dim_in>;
  using Information = MatNd<dim_in, dim_in>;
  using ErrorJacobian = MatNd<dim_out, dim_in>;

  MinimizationResult<dim_in, dim_out> result;
  InVec x = initialization;

  for (int k = 0; k < opt_cfg.max_iterations; ++k) {
    Information jtj = Information::Zero();
    InVec jti = InVec::Zero();

    result.terminal_error.setZero();
    ErrorJacobian jac;
    for (const auto &func : funcs) {
      jac.setZero();
      const OutVec innovation = func(x, &jac);
      jtj += jac.transpose() * jac;
      jti += jac.transpose() * innovation;
      result.terminal_error += innovation;
    }

    const Eigen::LLT<Information> llt_jtj(opt_cfg.levenberg_mu * Information::Identity() +
                                          jtj);
    if (llt_jtj.info() != Eigen::Success) {
      result.success = false;
      break;
    }

    const InVec update = llt_jtj.solve(jti);

    x -= update;

    result.solution = x;
    result.terminal_jti = jti;
    result.success = true;
  }

  return result;
}

template <int dim_in, int dim_out>
MinimizationResult<dim_in, dim_out> gauss_newton_minimize(
    const ErrorFunction<dim_in, dim_out> &func,
    const VecNd<dim_in> &initialization,
    const OptimizationConfiguration &opt_cfg = {}) {
  const std::vector<ErrorFunctionDifferentials<dim_in, dim_out>> fncs = {
      wrap_numerical_diff(func)};
  const auto result = gauss_newton_minimize(fncs, initialization, opt_cfg);
  return result;
}

}  // namespace numerics
<commit_msg>Experiment with permitting dynamic-sized matrices in GN<commit_after>#pragma once

#include "eigen.hh"

#include "numerics/optimization/error_function.hh"

#include <vector>

namespace numerics {

template <int dim_in, int dim_out>
struct MinimizationResult {
  VecNd<dim_in> solution = VecNd<dim_in>::Zero();
  VecNd<dim_in> terminal_jti = VecNd<dim_in>::Zero();
  VecNd<dim_out> terminal_error = VecNd<dim_out>::Zero();

  bool success = false;
};

struct OptimizationConfiguration {
  int max_iterations = 5;
  double levenberg_mu = 1e-3;
};

template <int dim_in, int dim_out>
MinimizationResult<dim_in, dim_out> gauss_newton_minimize(
    const std::vector<ErrorFunctionDifferentials<dim_in, dim_out>> &funcs,
    const VecNd<dim_in> &initialization,
    const OptimizationConfiguration &opt_cfg) {
  using OutVec = VecNd<dim_out>;
  using InVec = VecNd<dim_in>;
  using Information = MatNd<dim_in, dim_in>;
  using ErrorJacobian = MatNd<dim_out, dim_in>;

  MinimizationResult<dim_in, dim_out> result;
  InVec x = initialization;

  Information jtj;
  InVec jti;
  for (int k = 0; k < opt_cfg.max_iterations; ++k) {
    jtj.setZero();
    jti.setZero();

    result.terminal_error.setZero();
    ErrorJacobian jac;
    for (const auto &func : funcs) {
      jac.setZero();
      const OutVec innovation = func(x, &jac);
      jtj += jac.transpose() * jac;
      jti += jac.transpose() * innovation;
      result.terminal_error += innovation;
    }

    const Eigen::LLT<Information> llt_jtj(opt_cfg.levenberg_mu * Information::Identity() +
                                          jtj);
    if (llt_jtj.info() != Eigen::Success) {
      result.success = false;
      break;
    }

    const InVec update = llt_jtj.solve(jti);

    x -= update;

    result.solution = x;
    result.terminal_jti = jti;
    result.success = true;
  }

  return result;
}

template <int dim_in, int dim_out>
MinimizationResult<dim_in, dim_out> gauss_newton_minimize(
    const ErrorFunction<dim_in, dim_out> &func,
    const VecNd<dim_in> &initialization,
    const OptimizationConfiguration &opt_cfg = {}) {
  const std::vector<ErrorFunctionDifferentials<dim_in, dim_out>> fncs = {
      wrap_numerical_diff(func)};
  const auto result = gauss_newton_minimize(fncs, initialization, opt_cfg);
  return result;
}

}  // namespace numerics
<|endoftext|>