<commit_before>// Copyright (c) 2011 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 "views/controls/menu/menu_runner.h"

namespace views {

// Manages the menu. To destroy a Holder invoke Release(). Release() deletes
// immediately if the menu isn't showing. If the menu is showing Release()
// cancels the menu and when the nested RunMenuAt() call returns, deletes itself
// and the menu.
class MenuRunner::Holder {
 public:
  explicit Holder(MenuItemView* menu);

  // See description above class for details.
  void Release();

  // Runs the menu.
  void RunMenuAt(Widget* parent,
                 MenuButton* button,
                 const gfx::Rect& bounds,
                 MenuItemView::AnchorPosition anchor,
                 bool has_mnemonics);

 private:
  ~Holder();

  scoped_ptr<MenuItemView> menu_;

  // Are we in run waiting for it to return?
  bool running_;

  // Set if |running_| and Release() has been invoked.
  bool delete_after_run_;

  DISALLOW_COPY_AND_ASSIGN(Holder);
};

MenuRunner::Holder::Holder(MenuItemView* menu)
    : menu_(menu),
      running_(false),
      delete_after_run_(false) {
}

void MenuRunner::Holder::Release() {
  if (running_) {
    // The menu is running a nested message loop, we can't delete it now
    // otherwise the stack would be in a really bad state (many frames would
    // have deleted objects on them). Instead cancel the menu, when it returns
    // Holder will delete itself.
    delete_after_run_ = true;
    menu_->Cancel();
  } else {
    delete this;
  }
}

void MenuRunner::Holder::RunMenuAt(Widget* parent,
                                   MenuButton* button,
                                   const gfx::Rect& bounds,
                                   MenuItemView::AnchorPosition anchor,
                                   bool has_mnemonics) {
  running_ = true;
  menu_->RunMenuAt(parent, button, bounds, anchor, has_mnemonics);
  if (delete_after_run_) {
    delete this;
    return;
  }
  running_ = false;
}

MenuRunner::Holder::~Holder() {
}

MenuRunner::MenuRunner(MenuItemView* menu) : holder_(new Holder(menu)) {
}

MenuRunner::~MenuRunner() {
  holder_->Release();
}

void MenuRunner::RunMenuAt(Widget* parent,
                           MenuButton* button,
                           const gfx::Rect& bounds,
                           MenuItemView::AnchorPosition anchor,
                           bool has_mnemonics) {
  holder_->RunMenuAt(parent, button, bounds, anchor, has_mnemonics);
}

}  // namespace views
<commit_msg>Fixes crash in menu code. MenuItemView doesn't handle trying to show a menu while it's already showing.<commit_after>// Copyright (c) 2011 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 "views/controls/menu/menu_runner.h"

namespace views {

// Manages the menu. To destroy a Holder invoke Release(). Release() deletes
// immediately if the menu isn't showing. If the menu is showing Release()
// cancels the menu and when the nested RunMenuAt() call returns, deletes itself
// and the menu.
class MenuRunner::Holder {
 public:
  explicit Holder(MenuItemView* menu);

  // See description above class for details.
  void Release();

  // Runs the menu.
  void RunMenuAt(Widget* parent,
                 MenuButton* button,
                 const gfx::Rect& bounds,
                 MenuItemView::AnchorPosition anchor,
                 bool has_mnemonics);

 private:
  ~Holder();

  scoped_ptr<MenuItemView> menu_;

  // Are we in run waiting for it to return?
  bool running_;

  // Set if |running_| and Release() has been invoked.
  bool delete_after_run_;

  DISALLOW_COPY_AND_ASSIGN(Holder);
};

MenuRunner::Holder::Holder(MenuItemView* menu)
    : menu_(menu),
      running_(false),
      delete_after_run_(false) {
}

void MenuRunner::Holder::Release() {
  if (running_) {
    // The menu is running a nested message loop, we can't delete it now
    // otherwise the stack would be in a really bad state (many frames would
    // have deleted objects on them). Instead cancel the menu, when it returns
    // Holder will delete itself.
    delete_after_run_ = true;
    menu_->Cancel();
  } else {
    delete this;
  }
}

void MenuRunner::Holder::RunMenuAt(Widget* parent,
                                   MenuButton* button,
                                   const gfx::Rect& bounds,
                                   MenuItemView::AnchorPosition anchor,
                                   bool has_mnemonics) {
  if (running_) {
    // Ignore requests to show the menu while it's already showing. MenuItemView
    // doesn't handle this very well (meaning it crashes).
    return;
  }
  running_ = true;
  menu_->RunMenuAt(parent, button, bounds, anchor, has_mnemonics);
  if (delete_after_run_) {
    delete this;
    return;
  }
  running_ = false;
}

MenuRunner::Holder::~Holder() {
}

MenuRunner::MenuRunner(MenuItemView* menu) : holder_(new Holder(menu)) {
}

MenuRunner::~MenuRunner() {
  holder_->Release();
}

void MenuRunner::RunMenuAt(Widget* parent,
                           MenuButton* button,
                           const gfx::Rect& bounds,
                           MenuItemView::AnchorPosition anchor,
                           bool has_mnemonics) {
  holder_->RunMenuAt(parent, button, bounds, anchor, has_mnemonics);
}

}  // namespace views
<|endoftext|>


<commit_before>
#include <QApplication>

#include "wd.h"
#include "cmd.h"
#include "font.h"
#include "../base/bedit.h"
#include "../base/jsvr.h"
#include "../base/note.h"
#include "../base/state.h"
#include "../base/tedit.h"
#include "../base/term.h"

// sm does its own parsing of the wd command
extern Cmd cmd;
extern int rc;

static string smact();
static string smactive();
static string smclose();
static string smerror(string p);
static string smfocus();
static string smfont();
static string smget();
static string smgetactive();
static string smgetscript(string);
static string smgettabs(QString);
static string smgetwin(string);
static string smgetwin1(Bedit *);
static string smgetwin2(Note *n);
static string smgetxywh();
static string smgetxywh1(QWidget *);
static string smopen();
static string smprompt();
static string smreplace();
static string smrun();
static string smsave();
static string smsaveactive();
static string smsaveall();
static string smset();
static string smsetselect(Bedit *,string);
static string smsettext(string,string);
static string smsetxywh(string,string);

// ---------------------------------------------------------------------
string sm(string c)
{
  rc=0;
  if (c=="act")
    return smact();
  if (c=="active")
    return smactive();
  if (c=="close")
    return smclose();
  if (c=="focus")
    return smfocus();
  if (c=="font")
    return smfont();
  if (c=="get")
    return smget();
  if (c=="new")
    return smopen();
  if (c=="open")
    return smopen();
  if (c=="replace")
    return smreplace();
  if (c=="run")
    return smrun();
  if (c=="save")
    return smsave();
  if (c=="set")
    return smset();
  else if (c=="prompt")
    return smprompt();
  cmd.getparms();
  return smerror("unrecognized sm command: " + c);
}

// ---------------------------------------------------------------------
string smact()
{
  cmd.getparms();
  term->smact();
  return"";
}

// ---------------------------------------------------------------------
string smactive()
{
  string p=cmd.getparms();
  QStringList opt=qsplit(p);
  if (note==0 || note->editIndex()<0)
    return smerror ("No active edit window");
  if (opt[0]!="tab")
    return smerror ("unrecognized sm command parameters: " + p);
  int ndx=opt[1].toInt();
  if (ndx<0 || ndx>=note->count())
    return smerror ("invalid tab index: " + p);
  note->setindex(ndx);
  return "";
}

// ---------------------------------------------------------------------
string smclose()
{
  string c=cmd.getid();
  string p=cmd.getparms();
  if (c=="tab") {
    if (note==0 || note->editIndex()<0)
      return smerror ("No active edit window");
    int ndx=s2q(p).toInt();
    if (ndx<0 || ndx>=note->count())
      return smerror ("invalid tab index: " + p);
    note->tabclose(ndx);
  } else if (c=="edit") {
    if (note==0)
      return smerror ("No edit window");
    note->close();
  } else if (c=="edit2") {
    if (note2==0)
      return smerror ("No edit2 window");
    note2->close();
  } else
    return smerror ("unrecognized sm command parameters: " + p);
  return "";
}

// ---------------------------------------------------------------------
string smerror(string p)
{
  rc=1;
  return p;
}

// ---------------------------------------------------------------------
string smfocus()
{
  string p=cmd.getparms();
  if (p.empty())
    return smerror("sm focus needs additional parameters");
  if (p=="term")
    term->smact();
  else if (p=="edit") {
    if (note==0 || note->editIndex()==-1)
      return smerror("No active edit window");
    note->activateWindow();
    note->raise();
    note->repaint();
  } else if (p=="edit2") {
    if (note2==0 || note2->editIndex()==-1)
      return smerror("No active edit2 window");
    setnote(note2);
    note->activateWindow();
    note->raise();
    note->repaint();
  } else
    return smerror("unrecognized sm command: focus " + p);
  return "";
}

// ---------------------------------------------------------------------
string smfont()
{
  string p=cmd.getparms();
  if (!p.empty()) {
    Font *fnt = new Font(p);
    if (fnt->error) {
      delete fnt;
      return smerror("unrecognized sm command: font " + p);
    } else {
      config.Font=fnt->font;
      delete fnt;
    }
  }
  fontset(config.Font);
  return "";
}

// ---------------------------------------------------------------------
string smget()
{
  string p=cmd.getparms();
  if (p.size()==0)
    return smerror("sm get needs additional parameters");
  if (p=="active")
    return smgetactive();
  if (p=="term" || p=="edit" || p=="edit2")
    return smgetwin(p);
  if (p=="xywh")
    return smgetxywh();
  QStringList s=qsplit(p);
  if (s[0]=="tabs") {
    if(s.size()<=1)
      return smerror("sm command requires another parameter: get tabs");
    else
      return smgettabs(s[1]);
  }
  return smerror("unrecognized sm command: get " + p);
}

// ---------------------------------------------------------------------
string smgetactive()
{
  rc=-1;
  return (note && ActiveWindows.indexOf(note)<ActiveWindows.indexOf(term))
         ? "edit" : "term";
}

// ---------------------------------------------------------------------
string smgetscript(string f)
{
  return dors(">{.getscripts_j_ '" + f + "'");
}

// ---------------------------------------------------------------------
string smgettabs(QString p)
{
  Note *n;
  if (p=="edit") {
    if (note==0)
      return smerror("No active edit window");
    n=note;
  } else if (p=="edit2") {
    if (note2==0)
      return smerror("No active edit2 window");
    n=note2;
  } else
    return smerror("sm get tabs needs edit or edit2 parameter");
  rc=-2;
  return n->gettabstate();
}

// ---------------------------------------------------------------------
string smgetwin(string p)
{
  rc=-2;
  if (p=="term")
    return smgetwin1(tedit);
  if (p=="edit") {
    if (note==0)
      return smerror("No active edit window");
    return smgetwin2(note);
  }
  if (note2==0)
    return smerror("No active edit2 window");
  return smgetwin2(note2);
}

// ---------------------------------------------------------------------
string smgetwin1(Bedit *t)
{
  string r;
  if (t==0) {
    r+=spair("text",(string)"");
    r+=spair("select",(string)"");
  } else {
    QTextCursor c=t->textCursor();
    int b=c.selectionStart();
    int e=c.selectionEnd();
    r+=spair("text",t->toPlainText());
    r+=spair("select",QString::number(b)+" "+QString::number(e));
  }
  return r;
}

// ---------------------------------------------------------------------
string smgetwin2(Note *n)
{
  if (n->editIndex()==-1)
    return smgetwin1((Bedit *)0);
  string r=smgetwin1((Bedit *)n->editPage());
  r+=spair("file",n->editFile());
  return r;
}

// ---------------------------------------------------------------------
string smgetxywh()
{
  rc=-2;
  string r;
  r+=spair("text",smgetxywh1(term));
  if (note)
    r+=spair("edit",smgetxywh1(note));
  if (note2)
    r+=spair("edit2",smgetxywh1(note2));
  return r;
}

// ---------------------------------------------------------------------
string smgetxywh1(QWidget *w)
{
  QPoint p=w->pos();
  QSize z=w->size();
  return q2s(QString::number(p.rx())+" "+QString::number(p.ry())+" "+
             QString::number(z.width())+" "+QString::number(z.height()));
}

// ---------------------------------------------------------------------
string smopen()
{
  string c=cmd.getid();
  string p=cmd.getparms();

  if (c=="edit")
    term->vieweditor();
  if (c=="edit2") {
    if (note==0)
      return smerror("no edit window open");
    note->on_winotherAct_triggered();
  }
  if (c=="edit" || c=="edit2")
    return "";
  if (c!="tab") {
    return smerror("unrecognized sm command: open " + c);
  }
  term->vieweditor();
  if (p.empty())
    note->newtemp();
  else {
    QString f=s2q(smgetscript(p));
    if (!cfexist(f))
      return smerror("file not found: " + q2s(f));
    note->fileopen(f);
  }
  rc=-1;
  return i2s(note->editIndex());
}

// ---------------------------------------------------------------------
string smprompt()
{
  string p=cmd.getparms();
  term->smprompt(s2q(p));
  return"";
}

// ---------------------------------------------------------------------
string smreplace()
{
  string c=cmd.getid();
  string p=cmd.getparms();
  if (note==0 || note->editIndex()<0)
    return smerror ("No active edit window");
  if (c!="edit")
    return smerror("unrecognized sm command: replace " + c);
  if (p.empty())
    return smerror("replace needs 2 parameters: edit filename");
  QString f=s2q(smgetscript(p));
  if (!cfexist(f))
    return smerror("file not found: " + q2s(f));
  note->filereplace(f);
  return"";
}

// ---------------------------------------------------------------------
string smrun()
{
  string p=cmd.getparms();
  if (p!="edit")
    return smerror("unrecognized sm command: run " + p);
  if (note==0 || note->editIndex()<0)
    return smerror("No active edit window");
  note->runlines(true,false);  // all lines, no display
  return"";
}

// ---------------------------------------------------------------------
string smsave()
{
  string p=cmd.getparms();
  if (note==0)
    return smerror("No active edit window");
  if (p.empty())
    return smerror("sm save parameter not given");
  if (p=="edit")
    return smsaveactive();
  if (p=="tabs")
    return smsaveall();
  return smerror("sm save parameter should be 'edit' or 'tabs': " + p);
}

// ---------------------------------------------------------------------
string smsaveactive()
{
  note->savecurrent();
  return "";
}

// ---------------------------------------------------------------------
string smsaveall()
{
  note->saveall();
  return "";
}

// ---------------------------------------------------------------------
string smset()
{
  string p=cmd.getid();
  if (p.empty())
    return smerror("sm set parameters not given");
  string c=cmd.getid();
  if (c.empty())
    return smerror("sm set " + p + " parameters not given");
  string q=cmd.getparms();
  Bedit *e;

  if (p=="term") {
    e=tedit;
  } else if (p=="edit") {
    if (note==0)
      return smerror("No active edit window");
    e=(Bedit *)note->editPage();
  } else if (p=="edit2") {
    if (note2==0)
      return smerror("No active edit2 window");
    e=(Bedit *)note2->editPage();
  } else
    return smerror("unrecognized sm command: set " + p);

  if (e==0 && (q=="select" || q=="text"))
    return smerror("no edit window for sm command: set " + q);

  if (c=="select")
    return smsetselect(e,q);
  if (c=="text")
    return smsettext(p,q);
  if (c=="xywh")
    return smsetxywh(p,q);

  return smerror("unrecognized sm command: set " + p + " " + q);
}

// ---------------------------------------------------------------------
string smsetselect(Bedit *e, string q)
{
  QList<int> s=qsl2intlist(qsplit(q));
  if (s.size()!= 2)
    return smerror("sm set select should have begin and end parameters");
  int m=e->toPlainText().size();
  if (s[1]==-1) s[1]=m;
  s[1]=qMin(m,s[1]);
  s[0]=qMin(s[0],s[1]);
  e->setselect(s[0],s[1]-s[0]);
  return"";
}

// ---------------------------------------------------------------------
string smsettext(string p,string s)
{
  QString t=s2q(s);
  if (p=="term")
    tedit->setPlainText(t);
  else if (p=="edit")
    note->settext(t);
  else
    note2->settext(t);
  return"";
}

// ---------------------------------------------------------------------
string smsetxywh(string m,string q)
{
  QWidget *w;
  if (m=="term")
    w=term;
  else if (m=="edit")
    w=note;
  else
    w=note2;
  QList<int> s=qsl2intlist(qsplit(q));
  QPoint p=w->pos();
  QSize z=w->size();
  if (s[0]==-1) s[0]=p.rx();
  if (s[1]==-1) s[1]=p.ry();
  if (s[2]==-1) s[2]=z.width();
  if (s[3]==-1) s[3]=z.height();
  w->move(s[0],s[1]);
  w->resize(s[2],s[3]);
  return"";
}

<commit_msg>Remove call to smrun, and comment it out, decommitting the 'sm run edit' command<commit_after>
#include <QApplication>

#include "wd.h"
#include "cmd.h"
#include "font.h"
#include "../base/bedit.h"
#include "../base/jsvr.h"
#include "../base/note.h"
#include "../base/state.h"
#include "../base/tedit.h"
#include "../base/term.h"

// sm does its own parsing of the wd command
extern Cmd cmd;
extern int rc;

static string smact();
static string smactive();
static string smclose();
static string smerror(string p);
static string smfocus();
static string smfont();
static string smget();
static string smgetactive();
static string smgetscript(string);
static string smgettabs(QString);
static string smgetwin(string);
static string smgetwin1(Bedit *);
static string smgetwin2(Note *n);
static string smgetxywh();
static string smgetxywh1(QWidget *);
static string smopen();
static string smprompt();
static string smreplace();
static string smrun();
static string smsave();
static string smsaveactive();
static string smsaveall();
static string smset();
static string smsetselect(Bedit *,string);
static string smsettext(string,string);
static string smsetxywh(string,string);

// ---------------------------------------------------------------------
string sm(string c)
{
  rc=0;
  if (c=="act")
    return smact();
  if (c=="active")
    return smactive();
  if (c=="close")
    return smclose();
  if (c=="focus")
    return smfocus();
  if (c=="font")
    return smfont();
  if (c=="get")
    return smget();
  if (c=="new")
    return smopen();
  if (c=="open")
    return smopen();
  if (c=="replace")
    return smreplace();
  if (c=="save")
    return smsave();
  if (c=="set")
    return smset();
  else if (c=="prompt")
    return smprompt();
  cmd.getparms();
  return smerror("unrecognized sm command: " + c);
}

// ---------------------------------------------------------------------
string smact()
{
  cmd.getparms();
  term->smact();
  return"";
}

// ---------------------------------------------------------------------
string smactive()
{
  string p=cmd.getparms();
  QStringList opt=qsplit(p);
  if (note==0 || note->editIndex()<0)
    return smerror ("No active edit window");
  if (opt[0]!="tab")
    return smerror ("unrecognized sm command parameters: " + p);
  int ndx=opt[1].toInt();
  if (ndx<0 || ndx>=note->count())
    return smerror ("invalid tab index: " + p);
  note->setindex(ndx);
  return "";
}

// ---------------------------------------------------------------------
string smclose()
{
  string c=cmd.getid();
  string p=cmd.getparms();
  if (c=="tab") {
    if (note==0 || note->editIndex()<0)
      return smerror ("No active edit window");
    int ndx=s2q(p).toInt();
    if (ndx<0 || ndx>=note->count())
      return smerror ("invalid tab index: " + p);
    note->tabclose(ndx);
  } else if (c=="edit") {
    if (note==0)
      return smerror ("No edit window");
    note->close();
  } else if (c=="edit2") {
    if (note2==0)
      return smerror ("No edit2 window");
    note2->close();
  } else
    return smerror ("unrecognized sm command parameters: " + p);
  return "";
}

// ---------------------------------------------------------------------
string smerror(string p)
{
  rc=1;
  return p;
}

// ---------------------------------------------------------------------
string smfocus()
{
  string p=cmd.getparms();
  if (p.empty())
    return smerror("sm focus needs additional parameters");
  if (p=="term")
    term->smact();
  else if (p=="edit") {
    if (note==0 || note->editIndex()==-1)
      return smerror("No active edit window");
    note->activateWindow();
    note->raise();
    note->repaint();
  } else if (p=="edit2") {
    if (note2==0 || note2->editIndex()==-1)
      return smerror("No active edit2 window");
    setnote(note2);
    note->activateWindow();
    note->raise();
    note->repaint();
  } else
    return smerror("unrecognized sm command: focus " + p);
  return "";
}

// ---------------------------------------------------------------------
string smfont()
{
  string p=cmd.getparms();
  if (!p.empty()) {
    Font *fnt = new Font(p);
    if (fnt->error) {
      delete fnt;
      return smerror("unrecognized sm command: font " + p);
    } else {
      config.Font=fnt->font;
      delete fnt;
    }
  }
  fontset(config.Font);
  return "";
}

// ---------------------------------------------------------------------
string smget()
{
  string p=cmd.getparms();
  if (p.size()==0)
    return smerror("sm get needs additional parameters");
  if (p=="active")
    return smgetactive();
  if (p=="term" || p=="edit" || p=="edit2")
    return smgetwin(p);
  if (p=="xywh")
    return smgetxywh();
  QStringList s=qsplit(p);
  if (s[0]=="tabs") {
    if(s.size()<=1)
      return smerror("sm command requires another parameter: get tabs");
    else
      return smgettabs(s[1]);
  }
  return smerror("unrecognized sm command: get " + p);
}

// ---------------------------------------------------------------------
string smgetactive()
{
  rc=-1;
  return (note && ActiveWindows.indexOf(note)<ActiveWindows.indexOf(term))
         ? "edit" : "term";
}

// ---------------------------------------------------------------------
string smgetscript(string f)
{
  return dors(">{.getscripts_j_ '" + f + "'");
}

// ---------------------------------------------------------------------
string smgettabs(QString p)
{
  Note *n;
  if (p=="edit") {
    if (note==0)
      return smerror("No active edit window");
    n=note;
  } else if (p=="edit2") {
    if (note2==0)
      return smerror("No active edit2 window");
    n=note2;
  } else
    return smerror("sm get tabs needs edit or edit2 parameter");
  rc=-2;
  return n->gettabstate();
}

// ---------------------------------------------------------------------
string smgetwin(string p)
{
  rc=-2;
  if (p=="term")
    return smgetwin1(tedit);
  if (p=="edit") {
    if (note==0)
      return smerror("No active edit window");
    return smgetwin2(note);
  }
  if (note2==0)
    return smerror("No active edit2 window");
  return smgetwin2(note2);
}

// ---------------------------------------------------------------------
string smgetwin1(Bedit *t)
{
  string r;
  if (t==0) {
    r+=spair("text",(string)"");
    r+=spair("select",(string)"");
  } else {
    QTextCursor c=t->textCursor();
    int b=c.selectionStart();
    int e=c.selectionEnd();
    r+=spair("text",t->toPlainText());
    r+=spair("select",QString::number(b)+" "+QString::number(e));
  }
  return r;
}

// ---------------------------------------------------------------------
string smgetwin2(Note *n)
{
  if (n->editIndex()==-1)
    return smgetwin1((Bedit *)0);
  string r=smgetwin1((Bedit *)n->editPage());
  r+=spair("file",n->editFile());
  return r;
}

// ---------------------------------------------------------------------
string smgetxywh()
{
  rc=-2;
  string r;
  r+=spair("text",smgetxywh1(term));
  if (note)
    r+=spair("edit",smgetxywh1(note));
  if (note2)
    r+=spair("edit2",smgetxywh1(note2));
  return r;
}

// ---------------------------------------------------------------------
string smgetxywh1(QWidget *w)
{
  QPoint p=w->pos();
  QSize z=w->size();
  return q2s(QString::number(p.rx())+" "+QString::number(p.ry())+" "+
             QString::number(z.width())+" "+QString::number(z.height()));
}

// ---------------------------------------------------------------------
string smopen()
{
  string c=cmd.getid();
  string p=cmd.getparms();

  if (c=="edit")
    term->vieweditor();
  if (c=="edit2") {
    if (note==0)
      return smerror("no edit window open");
    note->on_winotherAct_triggered();
  }
  if (c=="edit" || c=="edit2")
    return "";
  if (c!="tab") {
    return smerror("unrecognized sm command: open " + c);
  }
  term->vieweditor();
  if (p.empty())
    note->newtemp();
  else {
    QString f=s2q(smgetscript(p));
    if (!cfexist(f))
      return smerror("file not found: " + q2s(f));
    note->fileopen(f);
  }
  rc=-1;
  return i2s(note->editIndex());
}

// ---------------------------------------------------------------------
string smprompt()
{
  string p=cmd.getparms();
  term->smprompt(s2q(p));
  return"";
}

// ---------------------------------------------------------------------
string smreplace()
{
  string c=cmd.getid();
  string p=cmd.getparms();
  if (note==0 || note->editIndex()<0)
    return smerror ("No active edit window");
  if (c!="edit")
    return smerror("unrecognized sm command: replace " + c);
  if (p.empty())
    return smerror("replace needs 2 parameters: edit filename");
  QString f=s2q(smgetscript(p));
  if (!cfexist(f))
    return smerror("file not found: " + q2s(f));
  note->filereplace(f);
  return"";
}

// ---------------------------------------------------------------------
// string smrun()
// {
//   string p=cmd.getparms();
//   if (p!="edit")
//     return smerror("unrecognized sm command: run " + p);
//   if (note==0 || note->editIndex()<0)
//     return smerror("No active edit window");
//   note->runlines(true,false);  // all lines, no display
//   return"";
// }
//
// ---------------------------------------------------------------------
string smsave()
{
  string p=cmd.getparms();
  if (note==0)
    return smerror("No active edit window");
  if (p.empty())
    return smerror("sm save parameter not given");
  if (p=="edit")
    return smsaveactive();
  if (p=="tabs")
    return smsaveall();
  return smerror("sm save parameter should be 'edit' or 'tabs': " + p);
}

// ---------------------------------------------------------------------
string smsaveactive()
{
  note->savecurrent();
  return "";
}

// ---------------------------------------------------------------------
string smsaveall()
{
  note->saveall();
  return "";
}

// ---------------------------------------------------------------------
string smset()
{
  string p=cmd.getid();
  if (p.empty())
    return smerror("sm set parameters not given");
  string c=cmd.getid();
  if (c.empty())
    return smerror("sm set " + p + " parameters not given");
  string q=cmd.getparms();
  Bedit *e;

  if (p=="term") {
    e=tedit;
  } else if (p=="edit") {
    if (note==0)
      return smerror("No active edit window");
    e=(Bedit *)note->editPage();
  } else if (p=="edit2") {
    if (note2==0)
      return smerror("No active edit2 window");
    e=(Bedit *)note2->editPage();
  } else
    return smerror("unrecognized sm command: set " + p);

  if (e==0 && (q=="select" || q=="text"))
    return smerror("no edit window for sm command: set " + q);

  if (c=="select")
    return smsetselect(e,q);
  if (c=="text")
    return smsettext(p,q);
  if (c=="xywh")
    return smsetxywh(p,q);

  return smerror("unrecognized sm command: set " + p + " " + q);
}

// ---------------------------------------------------------------------
string smsetselect(Bedit *e, string q)
{
  QList<int> s=qsl2intlist(qsplit(q));
  if (s.size()!= 2)
    return smerror("sm set select should have begin and end parameters");
  int m=e->toPlainText().size();
  if (s[1]==-1) s[1]=m;
  s[1]=qMin(m,s[1]);
  s[0]=qMin(s[0],s[1]);
  e->setselect(s[0],s[1]-s[0]);
  return"";
}

// ---------------------------------------------------------------------
string smsettext(string p,string s)
{
  QString t=s2q(s);
  if (p=="term")
    tedit->setPlainText(t);
  else if (p=="edit")
    note->settext(t);
  else
    note2->settext(t);
  return"";
}

// ---------------------------------------------------------------------
string smsetxywh(string m,string q)
{
  QWidget *w;
  if (m=="term")
    w=term;
  else if (m=="edit")
    w=note;
  else
    w=note2;
  QList<int> s=qsl2intlist(qsplit(q));
  QPoint p=w->pos();
  QSize z=w->size();
  if (s[0]==-1) s[0]=p.rx();
  if (s[1]==-1) s[1]=p.ry();
  if (s[2]==-1) s[2]=z.width();
  if (s[3]==-1) s[3]=z.height();
  w->move(s[0],s[1]);
  w->resize(s[2],s[3]);
  return"";
}

<|endoftext|>


<commit_before>// RuledSurface.cpp

#include "stdafx.h"
#include "RuledSurface.h"
#include "Wire.h"
#include "Face.h"
#include "ConversionTools.h"
#include "MarkedList.h"
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepOffsetAPI_ThruSections.hxx>

void PickCreateRuledSurface()
{
	if(wxGetApp().m_marked_list->size() == 0)
	{
		wxGetApp().PickObjects(_("pick some sketches"));
	}

	if(wxGetApp().m_marked_list->size() > 0)
	{
		std::list<TopoDS_Wire> wire_list;

		std::list<HeeksObj*> sketches_to_delete;

		for(std::list<HeeksObj *>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
		{
			HeeksObj* object = *It;
			if(object->GetType() == SketchType)
			{
				std::list<HeeksObj*> list;
				list.push_back(object);
				TopoDS_Wire wire;
				if(ConvertLineArcsToWire2(list, wire))
				{
					wire_list.push_back(wire);
					if(wxGetApp().m_loft_removes_sketches)sketches_to_delete.push_back(object);
				}
			}
		}

		wxGetApp().StartHistory();
		wxGetApp().DeleteUndoably(sketches_to_delete);

		TopoDS_Shape shape;
		if(CreateRuledSurface(wire_list, shape))
		{
			HeeksObj* new_object = CShape::MakeObject(shape, _("Ruled Surface"), SOLID_TYPE_UNKNOWN, HeeksColor(51, 45, 51));
			wxGetApp().AddUndoably(new_object, NULL, NULL);
			wxGetApp().Repaint();
		}

		wxGetApp().EndHistory();
	}
}

void PickCreateExtrusion()
{
	if(wxGetApp().m_marked_list->size() == 0)
	{
		wxGetApp().PickObjects(_("pick sketches"));
	}

	double height = 10;
	wxGetApp().InputDouble(_("Input extrusion height"), _("height"), height);

	if(wxGetApp().m_marked_list->size() > 0)
	{
		std::list<TopoDS_Face> faces;

		std::list<HeeksObj*> sketches_to_delete;

		for(std::list<HeeksObj *>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
		{
			HeeksObj* object = *It;
			switch(object->GetType())
			{
			case SketchType:
				TopoDS_Face face;
				if(ConvertSketchToFace2(object, face))
				{
					faces.push_back(face);
					if(wxGetApp().m_extrude_removes_sketches)sketches_to_delete.push_back(object);
				}
			}
		}

		wxGetApp().StartHistory();

		wxGetApp().DeleteUndoably(sketches_to_delete);

		std::list<TopoDS_Shape> new_shapes;
		CreateExtrusions(faces, new_shapes, gp_Vec(0, 0, height).Transformed(wxGetApp().GetDrawMatrix(false)));
		if(new_shapes.size() > 0)
		{
			for(std::list<TopoDS_Shape>::iterator It = new_shapes.begin(); It != new_shapes.end(); It++){
				TopoDS_Shape& shape = *It;
				HeeksObj* new_object = CShape::MakeObject(shape, _("Extruded Solid"), SOLID_TYPE_UNKNOWN, HeeksColor(89, 95, 89));
				wxGetApp().AddUndoably(new_object, NULL, NULL);
			}
			wxGetApp().Repaint();
		}

		wxGetApp().EndHistory();
	}
}

bool CreateRuledSurface(const std::list<TopoDS_Wire> &wire_list, TopoDS_Shape& shape)
{
	if(wire_list.size() > 0)
	{
		BRepOffsetAPI_ThruSections generator( Standard_True, Standard_False );
		for(std::list<TopoDS_Wire>::const_iterator It = wire_list.begin(); It != wire_list.end(); It++)
		{
			const TopoDS_Wire &wire = *It;
			generator.AddWire(wire);
		}

		generator.Build();
		shape = generator.Shape();

		return true;
	}
	return false;
}

void CreateExtrusions(const std::list<TopoDS_Face> &faces, std::list<TopoDS_Shape>& new_shapes, const gp_Vec& extrude_vector)
{
	for(std::list<TopoDS_Face>::const_iterator It = faces.begin(); It != faces.end(); It++)
	{
		const TopoDS_Face& face = *It;
		BRepPrimAPI_MakePrism generator( face, extrude_vector );
		generator.Build();
		new_shapes.push_back(generator.Shape());
	}
}

<commit_msg>added a try and catch to CreateRuledSurface<commit_after>// RuledSurface.cpp

#include "stdafx.h"
#include "RuledSurface.h"
#include "Wire.h"
#include "Face.h"
#include "ConversionTools.h"
#include "MarkedList.h"
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepOffsetAPI_ThruSections.hxx>

void PickCreateRuledSurface()
{
	if(wxGetApp().m_marked_list->size() == 0)
	{
		wxGetApp().PickObjects(_("pick some sketches"));
	}

	if(wxGetApp().m_marked_list->size() > 0)
	{
		std::list<TopoDS_Wire> wire_list;

		std::list<HeeksObj*> sketches_to_delete;

		for(std::list<HeeksObj *>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
		{
			HeeksObj* object = *It;
			if(object->GetType() == SketchType)
			{
				std::list<HeeksObj*> list;
				list.push_back(object);
				TopoDS_Wire wire;
				if(ConvertLineArcsToWire2(list, wire))
				{
					wire_list.push_back(wire);
					if(wxGetApp().m_loft_removes_sketches)sketches_to_delete.push_back(object);
				}
			}
		}

		wxGetApp().StartHistory();
		wxGetApp().DeleteUndoably(sketches_to_delete);

		TopoDS_Shape shape;
		if(CreateRuledSurface(wire_list, shape))
		{
			HeeksObj* new_object = CShape::MakeObject(shape, _("Ruled Surface"), SOLID_TYPE_UNKNOWN, HeeksColor(51, 45, 51));
			wxGetApp().AddUndoably(new_object, NULL, NULL);
			wxGetApp().Repaint();
		}

		wxGetApp().EndHistory();
	}
}

void PickCreateExtrusion()
{
	if(wxGetApp().m_marked_list->size() == 0)
	{
		wxGetApp().PickObjects(_("pick sketches"));
	}

	double height = 10;
	wxGetApp().InputDouble(_("Input extrusion height"), _("height"), height);

	if(wxGetApp().m_marked_list->size() > 0)
	{
		std::list<TopoDS_Face> faces;

		std::list<HeeksObj*> sketches_to_delete;

		for(std::list<HeeksObj *>::const_iterator It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++)
		{
			HeeksObj* object = *It;
			switch(object->GetType())
			{
			case SketchType:
				TopoDS_Face face;
				if(ConvertSketchToFace2(object, face))
				{
					faces.push_back(face);
					if(wxGetApp().m_extrude_removes_sketches)sketches_to_delete.push_back(object);
				}
			}
		}

		wxGetApp().StartHistory();

		wxGetApp().DeleteUndoably(sketches_to_delete);

		std::list<TopoDS_Shape> new_shapes;
		CreateExtrusions(faces, new_shapes, gp_Vec(0, 0, height).Transformed(wxGetApp().GetDrawMatrix(false)));
		if(new_shapes.size() > 0)
		{
			for(std::list<TopoDS_Shape>::iterator It = new_shapes.begin(); It != new_shapes.end(); It++){
				TopoDS_Shape& shape = *It;
				HeeksObj* new_object = CShape::MakeObject(shape, _("Extruded Solid"), SOLID_TYPE_UNKNOWN, HeeksColor(89, 95, 89));
				wxGetApp().AddUndoably(new_object, NULL, NULL);
			}
			wxGetApp().Repaint();
		}

		wxGetApp().EndHistory();
	}
}

bool CreateRuledSurface(const std::list<TopoDS_Wire> &wire_list, TopoDS_Shape& shape)
{
	if(wire_list.size() > 0)
	{
			BRepOffsetAPI_ThruSections generator( Standard_True, Standard_False );
			for(std::list<TopoDS_Wire>::const_iterator It = wire_list.begin(); It != wire_list.end(); It++)
			{
				const TopoDS_Wire &wire = *It;
				generator.AddWire(wire);
			}

		try{
			generator.Build();
		}
		catch(...)
		{
			wxMessageBox(_("Fatal error making ruled solid"));
		}
			shape = generator.Shape();

		return true;
	}
	return false;
}

void CreateExtrusions(const std::list<TopoDS_Face> &faces, std::list<TopoDS_Shape>& new_shapes, const gp_Vec& extrude_vector)
{
	for(std::list<TopoDS_Face>::const_iterator It = faces.begin(); It != faces.end(); It++)
	{
		const TopoDS_Face& face = *It;
		BRepPrimAPI_MakePrism generator( face, extrude_vector );
		generator.Build();
		new_shapes.push_back(generator.Shape());
	}
}

<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "ExecutionContext.h"

#include "cling/Interpreter/StoredValueRef.h"

#include "clang/AST/Type.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace cling;

std::set<std::string> ExecutionContext::m_unresolvedSymbols;
std::vector<ExecutionContext::LazyFunctionCreatorFunc_t>
  ExecutionContext::m_lazyFuncCreator;

bool ExecutionContext::m_LazyFuncCreatorDiagsSuppressed = false;

// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::ExecutionContext(llvm::Module* m)
  : m_RunningStaticInits(false), m_CxaAtExitRemapped(false)
{
  assert(m && "llvm::Module must not be null!");
  m_AtExitFuncs.reserve(256);
  InitializeBuilder(m);
}

// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::~ExecutionContext() {
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void ExecutionContext::InitializeBuilder(llvm::Module* m) {
  //
  //  Create an execution engine to use.
  //
  assert(m && "Module cannot be null");

  // Note: Engine takes ownership of the module.
  llvm::EngineBuilder builder(m);

  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);

  // EngineBuilder uses default c'ted TargetOptions, too:
  llvm::TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElim = 1;
  TargetOpts.JITEmitDebugInfo = 1;

  builder.setTargetOptions(TargetOpts);

  m_engine.reset(builder.create());
  if (!m_engine)
     llvm::errs() << "cling::ExecutionContext::InitializeBuilder(): " << errMsg;
  assert(m_engine && "Cannot create module!");

  // install lazy function creators
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

int ExecutionContext::CXAAtExit(void (*func) (void*), void* arg, void* dso,
                                void* clangDecl) {
  // Register a CXAAtExit function
  clang::Decl* LastTLD = (clang::Decl*)clangDecl;
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, dso, LastTLD));
  return 0; // happiness
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "ExecutionContext: calling unresolved symbol, "
    "see previous error message!\n";
}

void* ExecutionContext::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "ExecutionContext: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
ExecutionContext::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }

  if (m_LazyFuncCreatorDiagsSuppressed)
    return 0;

  return HandleMissingFunction(mangled_name);
}

static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    if (funcsToFreeUnique.insert(func)) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}

ExecutionContext::ExecutionResult
ExecutionContext::executeFunction(llvm::StringRef funcname,
                                  const clang::ASTContext& Ctx,
                                  clang::QualType retType,
                                  StoredValueRef* returnValue)
{
  // Call a function without arguments, or with an SRet argument, see SRet below

  if (!m_CxaAtExitRemapped) {
    // Rewire atexit:
    llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
    llvm::Function* clingAtExit
      = m_engine->FindFunctionNamed("cling_cxa_atexit");
    if (atExit && clingAtExit) {
      void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
      assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
      m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
      m_CxaAtExitRemapped = true;
    }
  }

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.str().c_str());
  if (!f) {
    llvm::errs() << "ExecutionContext::executeFunction: "
      "could not find function named " << funcname << '\n';
    return kExeFunctionNotCompiled;
  }
  m_engine->getPointerToFunction(f);
  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    llvm::SmallVector<llvm::Function*, 100> funcsToFree;
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "ExecutionContext::executeFunction: symbol '" << *i
                   << "' unresolved while linking function '" << funcname
                   << "'!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      assert(ff && "cannot find function to free");
      funcsToFree.push_back(ff);
    }
    freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
    m_unresolvedSymbols.clear();
    return kExeUnresolvedSymbols;
  }

  std::vector<llvm::GenericValue> args;
  bool wantReturn = (returnValue);
  StoredValueRef aggregateRet;

  if (f->hasStructRetAttr()) {
    // Function expects to receive the storage for the returned aggregate as
    // first argument. Allocate returnValue:
    aggregateRet = StoredValueRef::allocate(Ctx, retType, f->getReturnType());
    if (returnValue) {
      *returnValue = aggregateRet;
    } else {
      returnValue = &aggregateRet;
    }
    args.push_back(returnValue->get().getGV());
    // will get set as arg0, must not assign.
    wantReturn = false;
  }

  if (wantReturn) {
    llvm::GenericValue gvRet = m_engine->runFunction(f, args);
    // rescue the ret value (which might be aggregate) from the stack
    *returnValue = StoredValueRef::bitwiseCopy(Ctx, Value(gvRet, retType));
  } else {
    m_engine->runFunction(f, args);
  }

  return kExeSuccess;
}

ExecutionContext::ExecutionResult
ExecutionContext::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  if (m_RunningStaticInits)
     return kExeSuccess;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());
  if (InitList == 0)
    return kExeSuccess;

  m_RunningStaticInits = true;

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      m_engine->getPointerToFunction(F);
      // check if there is any unresolved symbol in the list
      if (!m_unresolvedSymbols.empty()) {
        llvm::SmallVector<llvm::Function*, 100> funcsToFree;
        for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
               e = m_unresolvedSymbols.end(); i != e; ++i) {
          llvm::errs() << "ExecutionContext::runStaticInitializersOnce: symbol '" << *i
                       << "' unresolved while linking static initializer '"
                       << F->getName() << "'!\n";
          llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
          assert(ff && "cannot find function to free");
          funcsToFree.push_back(ff);
        }
        freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
        m_unresolvedSymbols.clear();
        m_RunningStaticInits = false;
        return kExeUnresolvedSymbols;
      }
      m_engine->runFunction(F, std::vector<llvm::GenericValue>());
    }
  }

  GV->eraseFromParent();

  m_RunningStaticInits = false;
  return kExeSuccess;
}

void
ExecutionContext::runStaticDestructorsOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* gdtors
    = m->getGlobalVariable("llvm.global_dtors", true);
  if (gdtors) {
    m_engine->runStaticConstructorsDestructors(true);
  }

  // 'Unload' the cxa_atexit entities.
  for (size_t I = 0, E = m_AtExitFuncs.size(); I < E; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[E-I-1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
  m_AtExitFuncs.clear();
}

int
ExecutionContext::verifyModule(llvm::Module* m)
{
  //
  //  Verify generated module.
  //
  bool mod_has_errs = llvm::verifyModule(*m, llvm::PrintMessageAction);
  if (mod_has_errs) {
    return 1;
  }
  return 0;
}

void
ExecutionContext::printModule(llvm::Module* m)
{
  //
  //  Print module LLVM code in human-readable form.
  //
  llvm::PassManager PM;
  PM.add(llvm::createPrintModulePass(&llvm::errs()));
  PM.run(*m);
}

void
ExecutionContext::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool ExecutionContext::addSymbol(const char* symbolName,  void* symbolAddress) {

  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* ExecutionContext::getAddressOfGlobal(llvm::Module* m,
                                           const char* symbolName,
                                           bool* fromJIT /*=0*/) const {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (address) {
    if (fromJIT) *fromJIT = false;
  } else {
    if (fromJIT) *fromJIT = true;
    llvm::GlobalVariable* gvar = m->getGlobalVariable(symbolName, true);
    if (!gvar)
      return 0;

    address = m_engine->getPointerToGlobal(gvar);
  }
  return address;
}
<commit_msg>Fix crash seen in ROOT-5570.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "ExecutionContext.h"

#include "cling/Interpreter/StoredValueRef.h"

#include "clang/AST/Type.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace cling;

std::set<std::string> ExecutionContext::m_unresolvedSymbols;
std::vector<ExecutionContext::LazyFunctionCreatorFunc_t>
  ExecutionContext::m_lazyFuncCreator;

bool ExecutionContext::m_LazyFuncCreatorDiagsSuppressed = false;

// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::ExecutionContext(llvm::Module* m)
  : m_RunningStaticInits(false), m_CxaAtExitRemapped(false)
{
  assert(m && "llvm::Module must not be null!");
  m_AtExitFuncs.reserve(256);
  InitializeBuilder(m);
}

// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::~ExecutionContext() {
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void ExecutionContext::InitializeBuilder(llvm::Module* m) {
  //
  //  Create an execution engine to use.
  //
  assert(m && "Module cannot be null");

  // Note: Engine takes ownership of the module.
  llvm::EngineBuilder builder(m);

  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);

  // EngineBuilder uses default c'ted TargetOptions, too:
  llvm::TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElim = 1;
  TargetOpts.JITEmitDebugInfo = 1;

  builder.setTargetOptions(TargetOpts);

  m_engine.reset(builder.create());
  if (!m_engine)
     llvm::errs() << "cling::ExecutionContext::InitializeBuilder(): " << errMsg;
  assert(m_engine && "Cannot create module!");

  // install lazy function creators
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

int ExecutionContext::CXAAtExit(void (*func) (void*), void* arg, void* dso,
                                void* clangDecl) {
  // Register a CXAAtExit function
  clang::Decl* LastTLD = (clang::Decl*)clangDecl;
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, dso, LastTLD));
  return 0; // happiness
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "ExecutionContext: calling unresolved symbol, "
    "see previous error message!\n";
}

void* ExecutionContext::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "ExecutionContext: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
ExecutionContext::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }

  if (m_LazyFuncCreatorDiagsSuppressed)
    return 0;

  return HandleMissingFunction(mangled_name);
}

static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    if (!func) continue;
    if (funcsToFreeUnique.insert(func)) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}

ExecutionContext::ExecutionResult
ExecutionContext::executeFunction(llvm::StringRef funcname,
                                  const clang::ASTContext& Ctx,
                                  clang::QualType retType,
                                  StoredValueRef* returnValue)
{
  // Call a function without arguments, or with an SRet argument, see SRet below

  if (!m_CxaAtExitRemapped) {
    // Rewire atexit:
    llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
    llvm::Function* clingAtExit
      = m_engine->FindFunctionNamed("cling_cxa_atexit");
    if (atExit && clingAtExit) {
      void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
      assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
      m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
      m_CxaAtExitRemapped = true;
    }
  }

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.str().c_str());
  if (!f) {
    llvm::errs() << "ExecutionContext::executeFunction: "
      "could not find function named " << funcname << '\n';
    return kExeFunctionNotCompiled;
  }
  m_engine->getPointerToFunction(f);
  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    llvm::SmallVector<llvm::Function*, 100> funcsToFree;
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "ExecutionContext::executeFunction: symbol '" << *i
                   << "' unresolved while linking function '" << funcname
                   << "'!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      assert(ff && "cannot find function to free");
      funcsToFree.push_back(ff);
    }
    freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
    m_unresolvedSymbols.clear();
    return kExeUnresolvedSymbols;
  }

  std::vector<llvm::GenericValue> args;
  bool wantReturn = (returnValue);
  StoredValueRef aggregateRet;

  if (f->hasStructRetAttr()) {
    // Function expects to receive the storage for the returned aggregate as
    // first argument. Allocate returnValue:
    aggregateRet = StoredValueRef::allocate(Ctx, retType, f->getReturnType());
    if (returnValue) {
      *returnValue = aggregateRet;
    } else {
      returnValue = &aggregateRet;
    }
    args.push_back(returnValue->get().getGV());
    // will get set as arg0, must not assign.
    wantReturn = false;
  }

  if (wantReturn) {
    llvm::GenericValue gvRet = m_engine->runFunction(f, args);
    // rescue the ret value (which might be aggregate) from the stack
    *returnValue = StoredValueRef::bitwiseCopy(Ctx, Value(gvRet, retType));
  } else {
    m_engine->runFunction(f, args);
  }

  return kExeSuccess;
}

ExecutionContext::ExecutionResult
ExecutionContext::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  if (m_RunningStaticInits)
     return kExeSuccess;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());
  if (InitList == 0)
    return kExeSuccess;

  m_RunningStaticInits = true;

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      m_engine->getPointerToFunction(F);
      // check if there is any unresolved symbol in the list
      if (!m_unresolvedSymbols.empty()) {
        llvm::SmallVector<llvm::Function*, 100> funcsToFree;
        for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
               e = m_unresolvedSymbols.end(); i != e; ++i) {
          llvm::errs() << "ExecutionContext::runStaticInitializersOnce: symbol '" << *i
                       << "' unresolved while linking static initializer '"
                       << F->getName() << "'!\n";
          llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
          assert(ff && "cannot find function to free");
          funcsToFree.push_back(ff);
        }
        freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
        m_unresolvedSymbols.clear();
        m_RunningStaticInits = false;
        return kExeUnresolvedSymbols;
      }
      m_engine->runFunction(F, std::vector<llvm::GenericValue>());
    }
  }

  GV->eraseFromParent();

  m_RunningStaticInits = false;
  return kExeSuccess;
}

void
ExecutionContext::runStaticDestructorsOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* gdtors
    = m->getGlobalVariable("llvm.global_dtors", true);
  if (gdtors) {
    m_engine->runStaticConstructorsDestructors(true);
  }

  // 'Unload' the cxa_atexit entities.
  for (size_t I = 0, E = m_AtExitFuncs.size(); I < E; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[E-I-1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
  m_AtExitFuncs.clear();
}

int
ExecutionContext::verifyModule(llvm::Module* m)
{
  //
  //  Verify generated module.
  //
  bool mod_has_errs = llvm::verifyModule(*m, llvm::PrintMessageAction);
  if (mod_has_errs) {
    return 1;
  }
  return 0;
}

void
ExecutionContext::printModule(llvm::Module* m)
{
  //
  //  Print module LLVM code in human-readable form.
  //
  llvm::PassManager PM;
  PM.add(llvm::createPrintModulePass(&llvm::errs()));
  PM.run(*m);
}

void
ExecutionContext::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool ExecutionContext::addSymbol(const char* symbolName,  void* symbolAddress) {

  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* ExecutionContext::getAddressOfGlobal(llvm::Module* m,
                                           const char* symbolName,
                                           bool* fromJIT /*=0*/) const {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (address) {
    if (fromJIT) *fromJIT = false;
  } else {
    if (fromJIT) *fromJIT = true;
    llvm::GlobalVariable* gvar = m->getGlobalVariable(symbolName, true);
    if (!gvar)
      return 0;

    address = m_engine->getPointerToGlobal(gvar);
  }
  return address;
}
<|endoftext|>


<commit_before>#include "ScriptRunner.h"
#include <QFile>
#include <QTimer>
#include <QMainWindow>
#include <QDebug>
#include <QCoreApplication>

ScriptRunner::ScriptRunner(QUrl url, QString script_file, bool debug, bool headless, QObject *parent) :
    QObject(parent),
    m_url(url),
    m_script_filename(script_file),
    m_debug(debug),
    m_headless(headless),
    m_engine(NULL),
    m_server(NULL),
    m_exiting(false),
    m_stderr(stderr),
    m_stdout(stdout)
{
}

bool ScriptRunner::go()
{
    m_engine = new QScriptEngine(this);
    if (m_debug) {
        QScriptEngineDebugger debugger;
        debugger.attachTo(m_engine);
        QMainWindow * debug_window = debugger.standardWindow();
        debug_window->resize(1024, 640);
        debug_window->show();
    }

    QFile script_file(m_script_filename);
    script_file.open(QIODevice::ReadOnly);
    m_engine->evaluate(script_file.readAll(), m_script_filename);
    script_file.close();
    if (m_engine->hasUncaughtException()) {
        qWarning() << "Error while evaluating script file:" << m_engine->uncaughtException().toString();
        qWarning() << m_engine->uncaughtExceptionBacktrace();
        return false;
    }

    // initialize the MF object before we run any user code
    m_engine->globalObject().setProperty("mf", m_engine->newQObject(this));
    QScriptValue mf_obj = m_engine->globalObject().property("mf");

    // create JavaScript enums from C++ enums
    QFile enum_file(":/enums/ItemTypeEnum.h");
    enum_file.open(QIODevice::ReadOnly);
    QString enum_contents = QString::fromUtf8(enum_file.readAll()).trimmed();
    enum_file.close();
    QStringList lines = enum_contents.split("\n");
    QStringList values = lines.takeFirst().split(" ");
    Q_ASSERT(values.size() == 2);
    QString prop_name = values.at(1);
    Q_ASSERT(values.at(0) == "enum");
    enum_contents = lines.join("\n");
    Q_ASSERT(enum_contents.endsWith(";"));
    enum_contents.chop(1);
    QString json = QString("(") + enum_contents.replace("=", ":") + QString(")");
    mf_obj.setProperty(prop_name, m_engine->evaluate(json));

    // create functions
    mf_obj.setProperty("username", m_engine->newFunction(username));

    QScriptValue ctor = m_engine->evaluate("MineflayerBot");
    if (m_engine->hasUncaughtException()) {
        qWarning() << "Error while evaluating MineflayerBot constructor:" << m_engine->uncaughtException().toString();
        qWarning() << m_engine->uncaughtExceptionBacktrace();
        return false;
    }
    if (m_exiting)
        return false;
    m_bot = ctor.construct();
    if (m_engine->hasUncaughtException()) {
        qWarning() << "Error while calling MineflayerBot constructor:" << m_engine->uncaughtException().toString();
        qWarning() << m_engine->uncaughtExceptionBacktrace();
        return false;
    }
    if (m_exiting)
        return false;

    // connect to server
    m_server = new Server(m_url);
    bool success;
    success = connect(m_server, SIGNAL(mapChunkUpdated(QSharedPointer<Chunk>)), this, SLOT(updateChunk(QSharedPointer<Chunk>)));
    Q_ASSERT(success);
    success = connect(m_server, SIGNAL(playerPositionAndLookUpdated(Server::EntityPosition)), this, SLOT(movePlayerPosition(Server::EntityPosition)));
    Q_ASSERT(success);
    success = connect(m_server, SIGNAL(loginStatusUpdated(Server::LoginStatus)), this, SLOT(handleLoginStatusUpdated(Server::LoginStatus)));
    Q_ASSERT(success);
    success = connect(m_server, SIGNAL(chatReceived(QString,QString)), this, SLOT(handleChatReceived(QString,QString)));
    Q_ASSERT(success);
    m_server->socketConnect();

    return true;
}

void ScriptRunner::process()
{
    callBotMethod("onNextFrame");
    QTimer::singleShot(1, this, SLOT(process()));
}

void ScriptRunner::callBotMethod(QString method_name, const QScriptValueList &args)
{
    QScriptValue method = m_bot.property(method_name);
    if (method.isValid()) {
        method.call(m_bot, args);
        if (m_engine->hasUncaughtException()) {
            qWarning() << "Error while calling method" << method_name;
            qWarning() << m_engine->uncaughtException().toString();
            qWarning() << m_engine->uncaughtExceptionBacktrace();
            m_engine->clearExceptions();
        }
    }
}

void ScriptRunner::print(QString text)
{
    m_stdout << text;
}

void ScriptRunner::debug(QString line)
{
    m_stderr << line << "\n";
}

void ScriptRunner::chat(QString message)
{
    m_server->sendChat(message);
}

void ScriptRunner::exit()
{
    m_exiting = true;
    QCoreApplication::instance()->quit();
}

QScriptValue ScriptRunner::username(QScriptContext *context, QScriptEngine *engine)
{
    ScriptRunner * me = (ScriptRunner *) engine->parent();
    return me->m_url.userName();
}

void ScriptRunner::updateChunk(QSharedPointer<Chunk> chunk)
{
    // TODO
}

void ScriptRunner::movePlayerPosition(Server::EntityPosition position)
{
    // TODO
}

void ScriptRunner::handleChatReceived(QString username, QString message)
{
    callBotMethod("onChat", QScriptValueList() << username << message);
}

void ScriptRunner::handleLoginStatusUpdated(Server::LoginStatus status)
{
    switch (status) {
        case Server::Disconnected:
            qWarning() << "Got disconnected from server";
            exit();
            break;
        case Server::Success:
            callBotMethod("onConnected");
            QTimer::singleShot(1, this, SLOT(process()));
            break;
        case Server::SocketError:
            qWarning() << "Unable to connect to server";
            exit();
            break;
        default:;
    }
}
<commit_msg>flushing stderr<commit_after>#include "ScriptRunner.h"
#include <QFile>
#include <QTimer>
#include <QMainWindow>
#include <QDebug>
#include <QCoreApplication>

ScriptRunner::ScriptRunner(QUrl url, QString script_file, bool debug, bool headless, QObject *parent) :
    QObject(parent),
    m_url(url),
    m_script_filename(script_file),
    m_debug(debug),
    m_headless(headless),
    m_engine(NULL),
    m_server(NULL),
    m_exiting(false),
    m_stderr(stderr),
    m_stdout(stdout)
{
}

bool ScriptRunner::go()
{
    m_engine = new QScriptEngine(this);
    if (m_debug) {
        QScriptEngineDebugger debugger;
        debugger.attachTo(m_engine);
        QMainWindow * debug_window = debugger.standardWindow();
        debug_window->resize(1024, 640);
        debug_window->show();
    }

    QFile script_file(m_script_filename);
    script_file.open(QIODevice::ReadOnly);
    m_engine->evaluate(script_file.readAll(), m_script_filename);
    script_file.close();
    if (m_engine->hasUncaughtException()) {
        qWarning() << "Error while evaluating script file:" << m_engine->uncaughtException().toString();
        qWarning() << m_engine->uncaughtExceptionBacktrace();
        return false;
    }

    // initialize the MF object before we run any user code
    m_engine->globalObject().setProperty("mf", m_engine->newQObject(this));
    QScriptValue mf_obj = m_engine->globalObject().property("mf");

    // create JavaScript enums from C++ enums
    QFile enum_file(":/enums/ItemTypeEnum.h");
    enum_file.open(QIODevice::ReadOnly);
    QString enum_contents = QString::fromUtf8(enum_file.readAll()).trimmed();
    enum_file.close();
    QStringList lines = enum_contents.split("\n");
    QStringList values = lines.takeFirst().split(" ");
    Q_ASSERT(values.size() == 2);
    QString prop_name = values.at(1);
    Q_ASSERT(values.at(0) == "enum");
    enum_contents = lines.join("\n");
    Q_ASSERT(enum_contents.endsWith(";"));
    enum_contents.chop(1);
    QString json = QString("(") + enum_contents.replace("=", ":") + QString(")");
    mf_obj.setProperty(prop_name, m_engine->evaluate(json));

    // create functions
    mf_obj.setProperty("username", m_engine->newFunction(username));

    QScriptValue ctor = m_engine->evaluate("MineflayerBot");
    if (m_engine->hasUncaughtException()) {
        qWarning() << "Error while evaluating MineflayerBot constructor:" << m_engine->uncaughtException().toString();
        qWarning() << m_engine->uncaughtExceptionBacktrace();
        return false;
    }
    if (m_exiting)
        return false;
    m_bot = ctor.construct();
    if (m_engine->hasUncaughtException()) {
        qWarning() << "Error while calling MineflayerBot constructor:" << m_engine->uncaughtException().toString();
        qWarning() << m_engine->uncaughtExceptionBacktrace();
        return false;
    }
    if (m_exiting)
        return false;

    // connect to server
    m_server = new Server(m_url);
    bool success;
    success = connect(m_server, SIGNAL(mapChunkUpdated(QSharedPointer<Chunk>)), this, SLOT(updateChunk(QSharedPointer<Chunk>)));
    Q_ASSERT(success);
    success = connect(m_server, SIGNAL(playerPositionAndLookUpdated(Server::EntityPosition)), this, SLOT(movePlayerPosition(Server::EntityPosition)));
    Q_ASSERT(success);
    success = connect(m_server, SIGNAL(loginStatusUpdated(Server::LoginStatus)), this, SLOT(handleLoginStatusUpdated(Server::LoginStatus)));
    Q_ASSERT(success);
    success = connect(m_server, SIGNAL(chatReceived(QString,QString)), this, SLOT(handleChatReceived(QString,QString)));
    Q_ASSERT(success);
    m_server->socketConnect();

    return true;
}

void ScriptRunner::process()
{
    callBotMethod("onNextFrame");
    QTimer::singleShot(1, this, SLOT(process()));
}

void ScriptRunner::callBotMethod(QString method_name, const QScriptValueList &args)
{
    QScriptValue method = m_bot.property(method_name);
    if (method.isValid()) {
        method.call(m_bot, args);
        if (m_engine->hasUncaughtException()) {
            qWarning() << "Error while calling method" << method_name;
            qWarning() << m_engine->uncaughtException().toString();
            qWarning() << m_engine->uncaughtExceptionBacktrace();
            m_engine->clearExceptions();
        }
    }
}

void ScriptRunner::print(QString text)
{
    m_stdout << text;
}

void ScriptRunner::debug(QString line)
{
    m_stderr << line << "\n";
    m_stderr.flush();
}

void ScriptRunner::chat(QString message)
{
    m_server->sendChat(message);
}

void ScriptRunner::exit()
{
    m_exiting = true;
    QCoreApplication::instance()->quit();
}

QScriptValue ScriptRunner::username(QScriptContext *context, QScriptEngine *engine)
{
    ScriptRunner * me = (ScriptRunner *) engine->parent();
    return me->m_url.userName();
}

void ScriptRunner::updateChunk(QSharedPointer<Chunk> chunk)
{
    // TODO
}

void ScriptRunner::movePlayerPosition(Server::EntityPosition position)
{
    // TODO
}

void ScriptRunner::handleChatReceived(QString username, QString message)
{
    callBotMethod("onChat", QScriptValueList() << username << message);
}

void ScriptRunner::handleLoginStatusUpdated(Server::LoginStatus status)
{
    switch (status) {
        case Server::Disconnected:
            qWarning() << "Got disconnected from server";
            exit();
            break;
        case Server::Success:
            callBotMethod("onConnected");
            QTimer::singleShot(1, this, SLOT(process()));
            break;
        case Server::SocketError:
            qWarning() << "Unable to connect to server";
            exit();
            break;
        default:;
    }
}
<|endoftext|>


<commit_before>#include "SolarPayload.h"
#include "Payload.h"

//using namespace theapi;

namespace theapi {

  SolarPayload::SolarPayload() {
    setMsgType();
    _payload.DeviceId = 0;
    _payload.MessageId = 0;
    _payload.Flags = 0;
    _payload.VCC = 0;
    _payload.ChargeMv = 0;
    _payload.ChargeMa = 0;
    _payload.Light = 0;
    _payload.CpuTemperature = 0;
    _payload.Temperature = 0;
    _payload.rssi = 0;
    _payload.snr = 0;
    _payload.frq_error = 0;
  }

  uint8_t SolarPayload::size() {
    return SIZE;
  }

  uint8_t SolarPayload::dataSize() {
    return DATA_SIZE;
  }

  void SolarPayload::setMsgType() {
    _payload.MessageType = theapi::Payload::SOLAR;
  }

  uint8_t SolarPayload::getMsgType() {
    return _payload.MessageType;
  }

  uint16_t SolarPayload::getDeviceId() {
    return _payload.DeviceId;
  }

  void SolarPayload::setDeviceId(uint16_t val) {
    _payload.DeviceId = val;
  }

  // The id, not neccessarily unique, of the message.
  uint8_t SolarPayload::getMsgId() {
    return _payload.MessageId;
  }

  void SolarPayload::setMsgId(uint8_t id) {
    _payload.MessageId = id;
  }

  uint8_t SolarPayload::getFlags() {
    return _payload.Flags;
  }

  void SolarPayload::setFlags(uint8_t byte) {
    _payload.Flags = byte;
  }

  uint16_t SolarPayload::getVcc() {
    return _payload.VCC;
  }

  void SolarPayload::setVcc(uint16_t val) {
    _payload.VCC = val;
  }

  uint16_t SolarPayload::getChargeMv() {
    return _payload.ChargeMv;
  }

  void SolarPayload::setChargeMv(uint16_t val) {
    _payload.ChargeMv = val;
  }

  int16_t SolarPayload::getChargeMa() {
    return _payload.ChargeMa;
  }

  void SolarPayload::setChargeMa(int16_t val) {
    _payload.ChargeMa = val;
  }

  uint16_t SolarPayload::getLight() {
    return _payload.Light;
  }

  void SolarPayload::setLight(uint16_t val) {
    _payload.Light = val;
  }

  int16_t SolarPayload::getCpuTemperature() {
    return _payload.CpuTemperature;
  }

  void SolarPayload::setCpuTemperature(int16_t val) {
    _payload.CpuTemperature = val;
  }

  int16_t SolarPayload::getTemperature() {
    return _payload.Temperature;
  }

  void SolarPayload::setTemperature(int16_t val) {
    _payload.Temperature = val;
  }

  int16_t SignalPayload::getSnr() {
    return _payload.snr;
  }

  void SignalPayload::setSnr(int16_t val) {
    _payload.snr = val;
  }

  int16_t SignalPayload::getFreqError() {
    return _payload.frq_error;
  }

  // Populates the given buffer with the payload data.
  void SolarPayload::serialize(uint8_t buffer[SolarPayload::SIZE]) {
    buffer[0] = _payload.MessageType;
    buffer[1] = _payload.DeviceId;
    buffer[2] = _payload.MessageId;
    buffer[3] = _payload.Flags;
    buffer[4] = (_payload.VCC >> 8);
    buffer[5] = _payload.VCC;
    buffer[6] = (_payload.ChargeMv >> 8);
    buffer[7] = _payload.ChargeMv;
    buffer[8] = (_payload.ChargeMa >> 8);
    buffer[9] = _payload.ChargeMa;
    buffer[10] = (_payload.Light >> 8);
    buffer[11] = _payload.Light;
    buffer[12] = (_payload.CpuTemperature >> 8);
    buffer[13] = _payload.CpuTemperature;
    buffer[14] = (_payload.Temperature >> 8);
    buffer[15] = _payload.Temperature;
  }

  // Parse the byte data from the buffer.
  void SolarPayload::unserialize(uint8_t buffer[SolarPayload::SIZE]) {
    _payload.MessageType = buffer[0];
    _payload.DeviceId = buffer[1];
    _payload.MessageId = buffer[2];
    _payload.Flags = buffer[3];
    _payload.VCC = (buffer[4] << 8) | buffer[5];
    _payload.ChargeMv = (buffer[6] << 8) | buffer[7];
    _payload.ChargeMa = (buffer[8] << 8) | buffer[9];
    _payload.Light = (buffer[10] << 8) | buffer[11];
    _payload.CpuTemperature = (buffer[12] << 8) | buffer[13];
    _payload.Temperature = (buffer[14] << 8) | buffer[15];
    _payload.VCC = (buffer[4] << 8) | buffer[5];
  }

}
<commit_msg>Signal methods<commit_after>#include "SolarPayload.h"
#include "Payload.h"

//using namespace theapi;

namespace theapi {

  SolarPayload::SolarPayload() {
    setMsgType();
    _payload.DeviceId = 0;
    _payload.MessageId = 0;
    _payload.Flags = 0;
    _payload.VCC = 0;
    _payload.ChargeMv = 0;
    _payload.ChargeMa = 0;
    _payload.Light = 0;
    _payload.CpuTemperature = 0;
    _payload.Temperature = 0;
    _payload.rssi = 0;
    _payload.snr = 0;
    _payload.frq_error = 0;
  }

  uint8_t SolarPayload::size() {
    return SIZE;
  }

  uint8_t SolarPayload::dataSize() {
    return DATA_SIZE;
  }

  void SolarPayload::setMsgType() {
    _payload.MessageType = theapi::Payload::SOLAR;
  }

  uint8_t SolarPayload::getMsgType() {
    return _payload.MessageType;
  }

  uint16_t SolarPayload::getDeviceId() {
    return _payload.DeviceId;
  }

  void SolarPayload::setDeviceId(uint16_t val) {
    _payload.DeviceId = val;
  }

  // The id, not neccessarily unique, of the message.
  uint8_t SolarPayload::getMsgId() {
    return _payload.MessageId;
  }

  void SolarPayload::setMsgId(uint8_t id) {
    _payload.MessageId = id;
  }

  uint8_t SolarPayload::getFlags() {
    return _payload.Flags;
  }

  void SolarPayload::setFlags(uint8_t byte) {
    _payload.Flags = byte;
  }

  uint16_t SolarPayload::getVcc() {
    return _payload.VCC;
  }

  void SolarPayload::setVcc(uint16_t val) {
    _payload.VCC = val;
  }

  uint16_t SolarPayload::getChargeMv() {
    return _payload.ChargeMv;
  }

  void SolarPayload::setChargeMv(uint16_t val) {
    _payload.ChargeMv = val;
  }

  int16_t SolarPayload::getChargeMa() {
    return _payload.ChargeMa;
  }

  void SolarPayload::setChargeMa(int16_t val) {
    _payload.ChargeMa = val;
  }

  uint16_t SolarPayload::getLight() {
    return _payload.Light;
  }

  void SolarPayload::setLight(uint16_t val) {
    _payload.Light = val;
  }

  int16_t SolarPayload::getCpuTemperature() {
    return _payload.CpuTemperature;
  }

  void SolarPayload::setCpuTemperature(int16_t val) {
    _payload.CpuTemperature = val;
  }

  int16_t SolarPayload::getTemperature() {
    return _payload.Temperature;
  }

  void SolarPayload::setTemperature(int16_t val) {
    _payload.Temperature = val;
  }

  int16_t SolarPayload::getRssi() {
    return _payload.snr;
  }

  void SolarPayload::setRssi(int16_t val) {
    _payload.rssi = val;
  }

  int16_t SolarPayload::getSnr() {
    return _payload.snr;
  }

  void SolarPayload::setSnr(int16_t val) {
    _payload.snr = val;
  }

  int16_t SolarPayload::getFreqError() {
    return _payload.frq_error;
  }

  void SolarPayload::setFreqError(int16_t val) {
    _payload.frq_error = val;
  }

  // Populates the given buffer with the payload data.
  void SolarPayload::serialize(uint8_t buffer[SolarPayload::SIZE]) {
    buffer[0] = _payload.MessageType;
    buffer[1] = _payload.DeviceId;
    buffer[2] = _payload.MessageId;
    buffer[3] = _payload.Flags;
    buffer[4] = (_payload.VCC >> 8);
    buffer[5] = _payload.VCC;
    buffer[6] = (_payload.ChargeMv >> 8);
    buffer[7] = _payload.ChargeMv;
    buffer[8] = (_payload.ChargeMa >> 8);
    buffer[9] = _payload.ChargeMa;
    buffer[10] = (_payload.Light >> 8);
    buffer[11] = _payload.Light;
    buffer[12] = (_payload.CpuTemperature >> 8);
    buffer[13] = _payload.CpuTemperature;
    buffer[14] = (_payload.Temperature >> 8);
    buffer[15] = _payload.Temperature;
  }

  // Parse the byte data from the buffer.
  void SolarPayload::unserialize(uint8_t buffer[SolarPayload::SIZE]) {
    _payload.MessageType = buffer[0];
    _payload.DeviceId = buffer[1];
    _payload.MessageId = buffer[2];
    _payload.Flags = buffer[3];
    _payload.VCC = (buffer[4] << 8) | buffer[5];
    _payload.ChargeMv = (buffer[6] << 8) | buffer[7];
    _payload.ChargeMa = (buffer[8] << 8) | buffer[9];
    _payload.Light = (buffer[10] << 8) | buffer[11];
    _payload.CpuTemperature = (buffer[12] << 8) | buffer[13];
    _payload.Temperature = (buffer[14] << 8) | buffer[15];
    _payload.VCC = (buffer[4] << 8) | buffer[5];
  }

}
<|endoftext|>


<commit_before>#include "StateManager.hpp"
#include "SimulationObject.hpp"

namespace warped {

unsigned int StateManager::restoreState(unsigned int rollback_time, unsigned int object_id,
    SimulationObject *object) {

    state_queue_lock_[object_id].lock();

    auto max = std::prev(state_queue_[object_id].end());
    while (max->first > rollback_time) {
        state_queue_[object_id].erase(max--);
    }

    state_queue_lock_[object_id].unlock();

    object->getState() = *(max->second);

    return rollback_time;
}

void StateManager::fossilCollect(unsigned int gvt, unsigned int object_id) {

    state_queue_lock_[object_id].lock();

    auto min = state_queue_[object_id].begin();
    while (min->first < gvt) {
        state_queue_[object_id].erase(min++);
    }

    state_queue_lock_[object_id].unlock();

}

} // namespace warped
<commit_msg>Changed return value in restoreState<commit_after>#include "StateManager.hpp"
#include "SimulationObject.hpp"

namespace warped {

unsigned int StateManager::restoreState(unsigned int rollback_time, unsigned int object_id,
    SimulationObject *object) {

    state_queue_lock_[object_id].lock();

    auto max = std::prev(state_queue_[object_id].end());
    while (max->first > rollback_time) {
        state_queue_[object_id].erase(max--);
    }

    state_queue_lock_[object_id].unlock();

    object->getState() = *(max->second);

    return max->first;
}

void StateManager::fossilCollect(unsigned int gvt, unsigned int object_id) {

    state_queue_lock_[object_id].lock();

    auto min = state_queue_[object_id].begin();
    while (min->first < gvt) {
        state_queue_[object_id].erase(min++);
    }

    state_queue_lock_[object_id].unlock();

}

} // namespace warped
<|endoftext|>