<commit_before>// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-

/* This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Authors:
 * Caner Candan <caner.candan@univ-angers.fr>
 */

#include <boost/mpi.hpp>
#include <eo>
#include <ga.h>
#include <dim/dim>
#include <dim/feedbacker/Easy.h>
#include <dim/migrator/Easy.h>
#include <dim/vectorupdater/Easy.h>
#include <dim/algo/Easy.h>

using namespace std;
using namespace boost::mpi;
using namespace boost;

typedef dim::core::Bit<double> EOT;

int main(int argc, char *argv[])
{
    /*************************
     * Initialisation de MPI *
     *************************/

    environment env(argc, argv);
    communicator world;

    /****************************
     * Il faut au moins 4 nœuds *
     ****************************/

    const size_t ALL = world.size();
    const size_t RANK = world.rank();

    // if ( ALL < 4 )
    // 	{
    // 	    if ( 0 == RANK )
    // 		{
    // 		    cerr << "Needs at least 4 processes to be launched!" << endl;
    // 		}
    // 	    return 0;
    // 	}

    /************************
     * Initialisation de EO *
     ************************/

    eoParser parser(argc, argv);
    eoState state;    // keeps all things allocated

    /*****************************
     * Definition des paramètres *
     *****************************/

    // a
    double alpha = parser.createParam(double(0.8), "alpha", "Alpha", 'a', "Islands Model").value();
    // b
    double beta = parser.createParam(double(0.99), "beta", "Beta", 'b', "Islands Model").value();
    // p
    /*size_t probaMin = */parser.createParam(size_t(10), "probaMin", "Minimum probability to stay in the same island", 'p', "Islands Model").value();
    // d
    size_t probaSame = parser.createParam(size_t(100/ALL), "probaSame", "Probability for an individual to stay in the same island", 'd', "Islands Model").value();
    // r
    /*size_t reward = */parser.createParam(size_t(2), "reward", "reward", 'r', "Islands Model")/*.value()*/;
    /*size_t penalty = */parser.createParam(size_t(1), "penalty", "penalty", 0, "Islands Model")/*.value()*/;
    // I
    bool initG = parser.createParam(bool(true), "initG", "initG", 'I', "Islands Model").value();

    /*********************************
     * Déclaration des composants EO *
     *********************************/

    unsigned chromSize = parser.getORcreateParam(unsigned(1000), "chromSize", "The length of the bitstrings", 'n',"Problem").value();
    eoInit<EOT>& init = dim::do_make::genotype(parser, state, EOT(), 0);

    dim::evaluation::OneMax<EOT> mainEval;
    eoEvalFuncCounter<EOT> eval(mainEval);

    unsigned popSize = parser.getORcreateParam(unsigned(100), "popSize", "Population Size", 'P', "Evolution Engine").value();
    dim::core::Pop<EOT>& pop = dim::do_make::pop(parser, state, init);

    /*unsigned maxGen = */parser.getORcreateParam(unsigned(0), "maxGen", "Maximum number of generations () = none)",'G',"Stopping criterion")/*.value()*/;
    /*double targetFitness = */parser.getORcreateParam(double(chromSize), "targetFitness", "Stop when fitness reaches",'T', "Stopping criterion")/*.value()*/;
    dim::continuator::Base<EOT>& continuator = dim::do_make::continuator<EOT>(parser, state, eval);

    dim::core::IslandData<EOT> data;

    dim::utils::CheckPoint<EOT>& checkpoint = dim::do_make::checkpoint(parser, state, continuator, data);

    /**************
     * EO routine *
     **************/

    make_parallel(parser);
    make_verbose(parser);
    make_help(parser);

    /****************************************
     * Distribution des opérateurs aux iles *
     ****************************************/

    eoMonOp<EOT>* ptMon = NULL;
    if ( RANK == 0 )
    	{
    	    eo::log << eo::logging << RANK << ": bitflip ";
    	    ptMon = new eoBitMutation<EOT>( 1, true );
    	}
    else
	{
	    eo::log << eo::logging << RANK << ": kflip(" << (RANK-1) * 2 + 1 << ") ";
	    ptMon = new eoDetPermutBitFlip<EOT>( (RANK-1) * 2 + 1 );
	}
    eo::log << eo::logging << endl;
    eo::log.flush();
    state.storeFunctor(ptMon);

    /**********************************
     * Déclaration des composants DIM *
     **********************************/

    // dim::evolver::sync::Easy<EOT> evolver( eval, *ptMon );
    // dim::feedbacker::sync::Easy<EOT> feedbacker;
    // dim::inputprobasender::sync::Easy<EOT> probasender;
    // dim::vectorupdater::sync::Easy<EOT> updater(alpha, beta);
    // dim::memorizer::sync::Easy<EOT> memorizer;
    // dim::migrator::sync::Easy<EOT> migrator;
    // dim::algo::sync::Easy<EOT> island( evolver, feedbacker, probasender, updater, memorizer, migrator, checkpoint );

    dim::evolver::async::Easy<EOT> evolver( eval, *ptMon );
    dim::feedbacker::async::Easy<EOT> feedbacker;
    feedbacker.popSize = popSize;
    // dim::inputprobasender::async::Easy<EOT> probasender;
    dim::vectorupdater::async::Easy<EOT> updater(alpha, beta);
    dim::memorizer::async::Easy<EOT> memorizer;
    dim::migrator::async::Easy<EOT> migrator;

    // dim::algo::async::Easy<EOT>::DummyEvolver evolver;
    // dim::algo::async::Easy<EOT>::DummyFeedbacker feedbacker;
    // dim::algo::async::Easy<EOT>::DummyInputProbaSender probasender;
    // dim::algo::async::Easy<EOT>::DummyVectorUpdater updater;
    // dim::algo::async::Easy<EOT>::DummyMemorizer memorizer;

    dim::algo::async::Easy<EOT> island( evolver, feedbacker/*, probasender*/, updater, memorizer, migrator, checkpoint );

    /***************
     * Rock & Roll *
     ***************/

    /******************************************************************************
     * Création de la matrice de transition et distribution aux iles des vecteurs *
     ******************************************************************************/

    dim::core::MigrationMatrix<EOT> probabilities( ALL );
    dim::core::InitMatrix<EOT> initmatrix( initG, probaSame );

    // ublas::matrix< double > m(ALL, ALL);

    if ( 0 == RANK )
	{
	    initmatrix( probabilities );
	    std::cout << probabilities;
	    data.proba = probabilities(RANK);

	    for (size_t i = 1; i < ALL; ++i)
		{
		    world.send( i, 100, probabilities(i) );
		}
	}
    else
	{
	    world.recv( 0, 100, data.proba );
	}

    /******************************************
     * Get the population size of all islands *
     ******************************************/

    world.barrier();
    dim::utils::print_sum(pop);

    apply<EOT>(eval, pop);

    island( pop, data );

    world.abort(0);

    return 0;
}
<commit_msg>* OneMax/threaded.cpp: removed deprecated codes<commit_after>// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-

/* This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Authors:
 * Caner Candan <caner.candan@univ-angers.fr>
 */

#include <boost/mpi.hpp>
#include <eo>
#include <ga.h>
#include <dim/dim>
#include <dim/feedbacker/Easy.h>
#include <dim/migrator/Easy.h>
#include <dim/vectorupdater/Easy.h>
#include <dim/algo/Easy.h>

using namespace std;
using namespace boost::mpi;
using namespace boost;

typedef dim::core::Bit<double> EOT;

int main(int argc, char *argv[])
{
    /*************************
     * Initialisation de MPI *
     *************************/

    environment env(argc, argv);
    communicator world;

    /****************************
     * Il faut au moins 4 nœuds *
     ****************************/

    const size_t ALL = world.size();
    const size_t RANK = world.rank();

    // if ( ALL < 4 )
    // 	{
    // 	    if ( 0 == RANK )
    // 		{
    // 		    cerr << "Needs at least 4 processes to be launched!" << endl;
    // 		}
    // 	    return 0;
    // 	}

    /************************
     * Initialisation de EO *
     ************************/

    eoParser parser(argc, argv);
    eoState state;    // keeps all things allocated

    /*****************************
     * Definition des paramètres *
     *****************************/

    // a
    double alpha = parser.createParam(double(0.8), "alpha", "Alpha", 'a', "Islands Model").value();
    // b
    double beta = parser.createParam(double(0.99), "beta", "Beta", 'b', "Islands Model").value();
    // p
    /*size_t probaMin = */parser.createParam(size_t(10), "probaMin", "Minimum probability to stay in the same island", 'p', "Islands Model").value();
    // d
    size_t probaSame = parser.createParam(size_t(100/ALL), "probaSame", "Probability for an individual to stay in the same island", 'd', "Islands Model").value();
    // r
    /*size_t reward = */parser.createParam(size_t(2), "reward", "reward", 'r', "Islands Model")/*.value()*/;
    /*size_t penalty = */parser.createParam(size_t(1), "penalty", "penalty", 0, "Islands Model")/*.value()*/;
    // I
    bool initG = parser.createParam(bool(true), "initG", "initG", 'I', "Islands Model").value();

    /*********************************
     * Déclaration des composants EO *
     *********************************/

    unsigned chromSize = parser.getORcreateParam(unsigned(1000), "chromSize", "The length of the bitstrings", 'n',"Problem").value();
    eoInit<EOT>& init = dim::do_make::genotype(parser, state, EOT(), 0);

    dim::evaluation::OneMax<EOT> mainEval;
    eoEvalFuncCounter<EOT> eval(mainEval);

    /*unsigned popSize = */parser.getORcreateParam(unsigned(100), "popSize", "Population Size", 'P', "Evolution Engine")/*.value()*/;
    dim::core::Pop<EOT>& pop = dim::do_make::pop(parser, state, init);

    /*unsigned maxGen = */parser.getORcreateParam(unsigned(0), "maxGen", "Maximum number of generations () = none)",'G',"Stopping criterion")/*.value()*/;
    /*double targetFitness = */parser.getORcreateParam(double(chromSize), "targetFitness", "Stop when fitness reaches",'T', "Stopping criterion")/*.value()*/;
    dim::continuator::Base<EOT>& continuator = dim::do_make::continuator<EOT>(parser, state, eval);

    dim::core::IslandData<EOT> data;

    dim::utils::CheckPoint<EOT>& checkpoint = dim::do_make::checkpoint(parser, state, continuator, data);

    /**************
     * EO routine *
     **************/

    make_parallel(parser);
    make_verbose(parser);
    make_help(parser);

    /****************************************
     * Distribution des opérateurs aux iles *
     ****************************************/

    eoMonOp<EOT>* ptMon = NULL;
    if ( RANK == 0 )
    	{
    	    eo::log << eo::logging << RANK << ": bitflip ";
    	    ptMon = new eoBitMutation<EOT>( 1, true );
    	}
    else
	{
	    eo::log << eo::logging << RANK << ": kflip(" << (RANK-1) * 2 + 1 << ") ";
	    ptMon = new eoDetPermutBitFlip<EOT>( (RANK-1) * 2 + 1 );
	}
    eo::log << eo::logging << endl;
    eo::log.flush();
    state.storeFunctor(ptMon);

    /**********************************
     * Déclaration des composants DIM *
     **********************************/

    dim::evolver::Easy<EOT> evolver( eval, *ptMon );
    dim::feedbacker::async::Easy<EOT> feedbacker;
    dim::vectorupdater::Easy<EOT> updater(alpha, beta);
    dim::memorizer::Easy<EOT> memorizer;
    dim::migrator::async::Easy<EOT> migrator;
    dim::algo::Easy<EOT> island( evolver, feedbacker, updater, memorizer, migrator, checkpoint );

    /***************
     * Rock & Roll *
     ***************/

    /******************************************************************************
     * Création de la matrice de transition et distribution aux iles des vecteurs *
     ******************************************************************************/

    dim::core::MigrationMatrix<EOT> probabilities( ALL );
    dim::core::InitMatrix<EOT> initmatrix( initG, probaSame );

    // ublas::matrix< double > m(ALL, ALL);

    if ( 0 == RANK )
	{
	    initmatrix( probabilities );
	    std::cout << probabilities;
	    data.proba = probabilities(RANK);

	    for (size_t i = 1; i < ALL; ++i)
		{
		    world.send( i, 100, probabilities(i) );
		}
	}
    else
	{
	    world.recv( 0, 100, data.proba );
	}

    /******************************************
     * Get the population size of all islands *
     ******************************************/

    world.barrier();
    dim::utils::print_sum(pop);

    apply<EOT>(eval, pop);

    island( pop, data );

    world.abort(0);

    return 0;
}
<|endoftext|>


<commit_before>#include <taichi/visual/gui.h>
#include <taichi/common/task.h>
#include <taichi/common/bit.h>

#if defined(TC_GUI_COCOA)

// https://stackoverflow.com/questions/4356441/mac-os-cocoa-draw-a-simple-pixel-on-a-canvas
// http://cocoadevcentral.com/d/intro_to_quartz/
// Modified based on
// https://github.com/CodaFi/C-Macs

// Obj-c runtime doc:
// https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc

#include <objc/objc.h>
#include <objc/message.h>
#include <objc/runtime.h>
#include <objc/runtime.h>
#include <objc/message.h>
#include <objc/NSObjCRuntime.h>
#include <CoreGraphics/CGBase.h>
#include <CoreGraphics/CGGeometry.h>
#include <ApplicationServices/ApplicationServices.h>

template <typename C=id, typename ... Args>
C call(id i, const char *select, Args ... args) {
  using func = C(id, SEL, Args...);
  return ((func *)(objc_msgSend))(i, sel_getUid(select), args...);
}

template <typename C=id, typename ... Args>
C call(const char *class_name, const char *select, Args ... args) {
  using func = C(id, SEL, Args...);
  return ((func *)(objc_msgSend))((id)objc_getClass(class_name), sel_getUid(select), args...);
}

extern id NSApp;
extern id const NSDefaultRunLoopMode;

typedef struct AppDel {
  Class isa;
  id window;
} AppDelegate;

class IdComparator {
public:
  bool operator() (id a, id b) const {
    TC_STATIC_ASSERT(sizeof(a) == sizeof(taichi::int64));
    return taichi::bit::reinterpret_bits<taichi::int64>(a) <
           taichi::bit::reinterpret_bits<taichi::int64>(b);
  }
};

std::map<id, taichi::GUI *, IdComparator> gui_from_id;

enum {
  NSBorderlessWindowMask		= 0,
  NSTitledWindowMask			= 1 << 0,
  NSClosableWindowMask		= 1 << 1,
  NSMiniaturizableWindowMask	= 1 << 2,
  NSResizableWindowMask		= 1 << 3,
};

// This is a strong reference to the class of our custom view,
// In case we need it in the future.
Class ViewClass;

// This is a simple -drawRect implementation for our class. We could have
// used a NSTextField  or something of that sort instead, but I felt that this
// stuck with the C-based mentality of the application.

void redraw(id self, SEL _, CGRect __) {
  auto *gui = gui_from_id[self];
  auto width = gui->width, height = gui->height;
  NSInteger dataLength = width * height * 4;
  UInt8 *data = (UInt8*)malloc(dataLength * sizeof(UInt8));
  static int t = 0;
  t++;
  for (int j=0; j < height; j++) {
    for (int i=0; i < width; i++) {
      int index = 4 * (i + j * width);
      data[index] = 255; //red
      data[++index] = (i + t * 100) % 255; //green
      data[++index] = 0;       //blue
      data[++index] = 255;     //alpha
    }
  }

  CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, data, dataLength, nullptr);
  CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
  CGImageRef image = CGImageCreate(width, height, 8, 32, width * 4, colorspace,
                                   kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
                                   provider, nullptr, true, kCGRenderingIntentDefault);

  CGContextRef context = call<CGContextRef>(call((id)objc_getClass("NSGraphicsContext"), "currentContext"), "graphicsPort");
  CGRect rect{{0, 0}, {CGFloat(width), CGFloat(height)}};
  CGContextDrawImage(context, rect, image);

  CGColorSpaceRelease(colorspace);
  CGDataProviderRelease(provider);
}

Class AppDelClass;
__attribute__((constructor))
static void initView() {
  ViewClass = objc_allocateClassPair((Class)objc_getClass("NSView"), "View", 0);
  // and again, we tell the runtime to add a function called -drawRect:
  // to our custom view. Note that there is an error in the type-specification
  // of this method, as I do not know the @encode sequence of 'CGRect' off
  // of the top of my head. As a result, there is a chance that the rect
  // parameter of the method may not get passed properly.
  class_addMethod(ViewClass, sel_getUid("drawRect:"), (IMP)redraw, "v@:");
  objc_registerClassPair(ViewClass);

  AppDelClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "AppDelegate", 0);
  objc_registerClassPair(AppDelClass);
}

TC_NAMESPACE_BEGIN

GUI::GUI(const std::string &window_name, int width, int height, bool normalized_coord)
    : window_name(window_name),
      width(width),
      height(height),
      key_pressed(false) {
  call("NSApplication", "sharedApplication");
  if (NSApp == nullptr) {
    fprintf(stderr,"Failed to initialized NSApplication.\nterminating.\n");
    return;
  }
  auto appDelObj = call("AppDelegate", "alloc");
  appDelObj = call(appDelObj, "init");
  call(NSApp, "setDelegate:", appDelObj);
  auto window = call("NSWindow", "alloc");
  auto rect = (CGRect){{0,0},{CGFloat(width),CGFloat(height)}};
  call(window, "initWithContentRect:styleMask:backing:defer:", rect, (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask), 0, false);
  view = call(call("View", "alloc"), "initWithFrame:", rect);
  gui_from_id[view] = this;
  call(window, "setContentView:", view);
  call(window, "becomeFirstResponder");
  call(window, "makeKeyAndOrderFront:", window);
}

void GUI::redraw() {

}

void GUI::update() {
  printf("1\n");
  call(call((id)objc_getClass("NSRunLoop"), "currentRunLoop"), "runMode:beforeDate:", NSDefaultRunLoopMode, call("NSDate", "distantPast"));
  printf("2\n");
  auto event = call("NSApp",
                    "nextEventMatchingMask:untilDate:inMode:dequeue:",
                    NSUIntegerMax,
                    call("NSDate", "distantPast"),
                    NSDefaultRunLoopMode,
                    YES);
  call(view, "setNeedsDisplay:", YES);

  if (event != nullptr) {
    call("NSApp", "sendEvent:event", event);
  }
  // call("NSApp", "updateWindows");
}

GUI::~GUI() {

}

auto test_cocoa_gui = []() {
  GUI gui("Cocoa test", 800, 400);
  while (1) {
    gui.update();
  }
};

TC_REGISTER_TASK(test_cocoa_gui);

TC_NAMESPACE_END

#endif<commit_msg>osx event loop<commit_after>#include <taichi/visual/gui.h>
#include <taichi/common/task.h>
#include <taichi/common/bit.h>

#if defined(TC_GUI_COCOA)

// https://stackoverflow.com/questions/4356441/mac-os-cocoa-draw-a-simple-pixel-on-a-canvas
// http://cocoadevcentral.com/d/intro_to_quartz/
// Modified based on
// https://github.com/CodaFi/C-Macs

// Obj-c runtime doc:
// https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc

#include <objc/objc.h>
#include <objc/message.h>
#include <objc/runtime.h>
#include <objc/runtime.h>
#include <objc/message.h>
#include <objc/NSObjCRuntime.h>
#include <CoreGraphics/CGBase.h>
#include <CoreGraphics/CGGeometry.h>
#include <ApplicationServices/ApplicationServices.h>

template <typename C=id, typename ... Args>
C call(id i, const char *select, Args ... args) {
  using func = C(id, SEL, Args...);
  return ((func *)(objc_msgSend))(i, sel_getUid(select), args...);
}

template <typename C=id, typename ... Args>
C call(const char *class_name, const char *select, Args ... args) {
  using func = C(id, SEL, Args...);
  return ((func *)(objc_msgSend))((id)objc_getClass(class_name), sel_getUid(select), args...);
}

extern id NSApp;
extern id const NSDefaultRunLoopMode;

typedef struct AppDel {
  Class isa;
  id window;
} AppDelegate;

class IdComparator {
public:
  bool operator() (id a, id b) const {
    TC_STATIC_ASSERT(sizeof(a) == sizeof(taichi::int64));
    return taichi::bit::reinterpret_bits<taichi::int64>(a) <
           taichi::bit::reinterpret_bits<taichi::int64>(b);
  }
};

std::map<id, taichi::GUI *, IdComparator> gui_from_id;

enum {
  NSBorderlessWindowMask		= 0,
  NSTitledWindowMask			= 1 << 0,
  NSClosableWindowMask		= 1 << 1,
  NSMiniaturizableWindowMask	= 1 << 2,
  NSResizableWindowMask		= 1 << 3,
};

// This is a strong reference to the class of our custom view,
// In case we need it in the future.
Class ViewClass;

// This is a simple -drawRect implementation for our class. We could have
// used a NSTextField  or something of that sort instead, but I felt that this
// stuck with the C-based mentality of the application.

void redraw(id self, SEL _, CGRect __) {
  auto *gui = gui_from_id[self];
  auto width = gui->width, height = gui->height;
  NSInteger dataLength = width * height * 4;
  UInt8 *data = (UInt8*)malloc(dataLength * sizeof(UInt8));
  static int t = 0;
  t++;
  for (int j=0; j < height; j++) {
    for (int i=0; i < width; i++) {
      int index = 4 * (i + j * width);
      data[index] = 255; //red
      data[++index] = (i + t * 100) % 255; //green
      data[++index] = 0;       //blue
      data[++index] = 255;     //alpha
    }
  }

  CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, data, dataLength, nullptr);
  CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
  CGImageRef image = CGImageCreate(width, height, 8, 32, width * 4, colorspace,
                                   kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
                                   provider, nullptr, true, kCGRenderingIntentDefault);

  CGContextRef context = call<CGContextRef>(call((id)objc_getClass("NSGraphicsContext"), "currentContext"), "graphicsPort");
  CGRect rect{{0, 0}, {CGFloat(width), CGFloat(height)}};
  CGContextDrawImage(context, rect, image);

  CGColorSpaceRelease(colorspace);
  CGDataProviderRelease(provider);
}

Class AppDelClass;
__attribute__((constructor))
static void initView() {
  ViewClass = objc_allocateClassPair((Class)objc_getClass("NSView"), "View", 0);
  // and again, we tell the runtime to add a function called -drawRect:
  // to our custom view. Note that there is an error in the type-specification
  // of this method, as I do not know the @encode sequence of 'CGRect' off
  // of the top of my head. As a result, there is a chance that the rect
  // parameter of the method may not get passed properly.
  class_addMethod(ViewClass, sel_getUid("drawRect:"), (IMP)redraw, "v@:");
  objc_registerClassPair(ViewClass);

  AppDelClass = objc_allocateClassPair((Class)objc_getClass("NSObject"), "AppDelegate", 0);
  objc_registerClassPair(AppDelClass);
}

TC_NAMESPACE_BEGIN

GUI::GUI(const std::string &window_name, int width, int height, bool normalized_coord)
    : window_name(window_name),
      width(width),
      height(height),
      key_pressed(false) {
  call("NSApplication", "sharedApplication");
  if (NSApp == nullptr) {
    fprintf(stderr,"Failed to initialized NSApplication.\nterminating.\n");
    return;
  }
  auto appDelObj = call("AppDelegate", "alloc");
  appDelObj = call(appDelObj, "init");
  call(NSApp, "setDelegate:", appDelObj);
  auto window = call("NSWindow", "alloc");
  auto rect = (CGRect){{0,0},{CGFloat(width),CGFloat(height)}};
  call(window, "initWithContentRect:styleMask:backing:defer:", rect, (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask), 0, false);
  view = call(call("View", "alloc"), "initWithFrame:", rect);
  gui_from_id[view] = this;
  call(window, "setContentView:", view);
  call(window, "becomeFirstResponder");
  call(window, "makeKeyAndOrderFront:", window);
}

void GUI::redraw() {

}

void GUI::update() {
  call(call((id)objc_getClass("NSRunLoop"), "currentRunLoop"), "runMode:beforeDate:", NSDefaultRunLoopMode, call("NSDate", "distantPast"));
  while (1) {
    auto event = call("NSApp",
                      "nextEventMatchingMask:untilDate:inMode:dequeue:",
                      NSUIntegerMax,
                      call("NSDate", "distantPast"),
                      NSDefaultRunLoopMode,
                      YES);
    call(view, "setNeedsDisplay:", YES);
    if (event != nullptr) {
      call("NSApp", "sendEvent:event", event);
    } else {
      break;
    }
  }
  // call("NSApp", "updateWindows");
}

GUI::~GUI() {
}

auto test_cocoa_gui = []() {
  GUI gui("Cocoa test", 800, 400);
  while (1) {
    gui.update();
  }
};

TC_REGISTER_TASK(test_cocoa_gui);

TC_NAMESPACE_END

#endif<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 midnightBITS
 *
 * 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 "pch.h"
#include <handlers.hpp>
#include <dbconn.hpp>
#include <locale.hpp>
#include <string.h>
#include <http.hpp>
#include "args.hpp"
#include <exception>
#include <stdexcept>

#define THREAD_COUNT 1

#ifdef _WIN32
#define LOCALE_PATH "..\\locales\\"
#define CHARSET_PATH "..\\locales\\charset.db"
#define LOG_FILE "..\\reedr.log"
#define PID_FILE "..\\reedr.pid"
#endif

#ifdef POSIX
#define LOCALE_PATH "/usr/share/reedr/locales/"
#define LOG_FILE "/usr/share/reedr/reedr.log"
#define CHARSET_PATH "/usr/share/reedr/locales/charset.db"
#define PID_FILE "/usr/share/reedr/reedr.pid"
#endif

REGISTER_REDIRECT("/", "/view/");

class Thread: public FastCGI::Thread
{
	unsigned long m_load;
public:
	Thread(): m_load(0) {}
	Thread(const char* uri):  FastCGI::Thread(uri) {}
	void onRequest(FastCGI::Request& req)
	{
		++m_load;
		FastCGI::app::HandlerPtr handler = FastCGI::app::Handlers::handler(req);
		if (handler.get() != nullptr)
			handler->visit(req);
		else
			req.on404();
	}
	unsigned long getLoad() const
	{
		return m_load;
	}
};

#define RETURN_IF_ERROR(cmd) do { auto ret = (cmd); if (ret) return ret; } while (0)

int main (int argc, char* argv[])
{
	Args args;
	RETURN_IF_ERROR(args.read(argc, argv));

	if (args.command != ECommands::NONE)
	{
		std::cerr << "-k not yet supported\n";
		return 1;
	}

	FastCGI::FLogSource log(LOG_FILE);
	try
	{
		FLOG << "Application started";

		db::environment env;
		if (env.failed) return 1;

		http::init(CHARSET_PATH);

		FastCGI::Application app;
		RETURN_IF_ERROR(app.init(LOCALE_PATH));

		if (!args.uri.empty())
		{
			Thread local(args.uri.c_str());
			local.setApplication(app);

			app.addStlSession();

			local.handleRequest();
			return 0;
		}

		if (!app.addThreads<Thread>(THREAD_COUNT))
			return 1;

		app.run();

		FLOG << "Application stopped";
		return 0;
	}
	catch (std::exception& ex)
	{
		std::cout << "error:" << ex.what() << std::endl;
		FLOG << "error: " << ex.what();
		return 1;
	}
	catch (...)
	{
		std::cout << "unknown error." << std::endl;
		FLOG << "unknown error";
		return 1;
	}
}
<commit_msg>Adding SIGTERM signal support and the pid file<commit_after>/*
 * Copyright (C) 2013 midnightBITS
 *
 * 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 "pch.h"
#include <handlers.hpp>
#include <dbconn.hpp>
#include <locale.hpp>
#include <string.h>
#include <http.hpp>
#include "args.hpp"
#include <exception>
#include <stdexcept>
#include <remote/signals.hpp>
#include <remote/pid.hpp>

#define THREAD_COUNT 1

#ifdef _WIN32
#define LOCALE_PATH "..\\locales\\"
#define CHARSET_PATH "..\\locales\\charset.db"
#define LOG_FILE "..\\reedr.log"
#define PID_FILE "..\\reedr.pid"
#endif

#ifdef POSIX
#define LOCALE_PATH "/usr/share/reedr/locales/"
#define LOG_FILE "/usr/share/reedr/reedr.log"
#define CHARSET_PATH "/usr/share/reedr/locales/charset.db"
#define PID_FILE "/usr/share/reedr/reedr.pid"
#endif

REGISTER_REDIRECT("/", "/view/");

class Thread: public FastCGI::Thread
{
	unsigned long m_load;
public:
	Thread(): m_load(0) {}
	Thread(const char* uri):  FastCGI::Thread(uri) {}
	void onRequest(FastCGI::Request& req)
	{
		++m_load;
		FastCGI::app::HandlerPtr handler = FastCGI::app::Handlers::handler(req);
		if (handler.get() != nullptr)
			handler->visit(req);
		else
			req.on404();
	}
	unsigned long getLoad() const
	{
		return m_load;
	}
};

#define RETURN_IF_ERROR(cmd) do { auto ret = (cmd); if (ret) return ret; } while (0)

class RemoteLogger : public remote::logger
{
	class StreamLogger : public remote::stream_logger
	{
		FastCGI::ApplicationLog m_log;
	public:
		StreamLogger(const char* path, int line)
			: m_log{ path, line }
		{}

		std::ostream& out() override { return m_log.log(); }
	};
public:
	remote::stream_logger_ptr line(const char* path, int line) override
	{
		return std::make_shared<StreamLogger>(path, line);
	}
};

int main (int argc, char* argv[])
{
	remote::signals signals{ std::make_shared<RemoteLogger>() };

	Args args;
	RETURN_IF_ERROR(args.read(argc, argv));

	if (args.command != ECommands::NONE)
	{
		std::cerr << "-k not yet supported\n";
		return 1;
	}

	FastCGI::FLogSource log(LOG_FILE);
	try
	{
		FLOG << "Application started";

		remote::pid guard(PID_FILE);

		db::environment env;
		if (env.failed) return 1;

		http::init(CHARSET_PATH);

		FastCGI::Application app;
		RETURN_IF_ERROR(app.init(LOCALE_PATH));

		signals.set("stop", [&app](){ app.shutdown(); });

		if (!args.uri.empty())
		{
			Thread local(args.uri.c_str());
			local.setApplication(app);

			app.addStlSession();

			local.handleRequest();
			return 0;
		}

		if (!app.addThreads<Thread>(THREAD_COUNT))
			return 1;

		app.run();

		FLOG << "Application stopped";
		return 0;
	}
	catch (std::exception& ex)
	{
		std::cout << "error:" << ex.what() << std::endl;
		FLOG << "error: " << ex.what();
		return 1;
	}
	catch (...)
	{
		std::cout << "unknown error." << std::endl;
		FLOG << "unknown error";
		return 1;
	}
}
<|endoftext|>


<commit_before>// vim: ts=2 sw=2 et
#include <hx/CFFI.h>
#include <cstring>
#include <dns_sd.h>

/**
 * DNSServiceConstructFullName()
 *
 * Concatenate a three-part domain name (as returned by the above callbacks) into a
 * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE
 * strings where necessary.
 *
 * Parameters:
 *
 * fullName:        A pointer to a buffer that where the resulting full domain name is to be written.
 *                  The buffer must be kDNSServiceMaxDomainName (1009) bytes in length to
 *                  accommodate the longest legal domain name without buffer overrun.
 *
 * service:         The service name - any dots or backslashes must NOT be escaped.
 *                  May be NULL (to construct a PTR record name, e.g.
 *                  "_ftp._tcp.apple.com.").
 *
 * regtype:         The service type followed by the protocol, separated by a dot
 *                  (e.g. "_ftp._tcp").
 *
 * domain:          The domain name, e.g. "apple.com.". Literal dots or backslashes,
 *                  if any, must be escaped, e.g. "1st\. Floor.apple.com."
 *
 * return value:    Returns kDNSServiceErr_NoError (0) on success, kDNSServiceErr_BadParam on error.
 *
 */
value hxbonjour_DNSServiceConstructFullName(value service, value regtype, value domain)
{
    char fullName[kDNSServiceMaxDomainName];
    const char *_service, *_regtype, *_domain;
    DNSServiceErrorType error;

    if (!val_is_string(regtype))
        val_throw(alloc_string("regtype cannot be null"));

    if (!val_is_string(domain))
        val_throw(alloc_string("domain cannot be null"));

    if (val_is_null(service)) _service = NULL;
    else if (!val_is_string(service))
        val_throw(alloc_string("service must be a string"));
    else _service = val_get_string(service);

    _regtype = val_get_string(regtype);
    _domain = val_get_string(domain);

    bool regtype_format_ok = _regtype[0] == '_';
    if (regtype_format_ok)
    {
        const char *dot_pos = strchr(_regtype, '.');
        if (dot_pos != NULL)
        {
            regtype_format_ok = !strncmp(dot_pos, "._tcp", 6) || !strncmp(dot_pos, "._udp", 6);
        }
    }

    if (!regtype_format_ok)
        val_throw(alloc_string("regtype should be in the form _proto._(tcp|udp)"));

    error = DNSServiceConstructFullName(fullName, _service, _regtype, _domain);

    if (error != kDNSServiceErr_NoError)
    {
        if (error == kDNSServiceErr_BadParam) val_throw(alloc_string("kDNSServiceErr_BadParam"));
        else val_throw(alloc_string("kDNSServiceErr_Unknown"));
    }

    return alloc_string(fullName);
}

DEFINE_PRIM(hxbonjour_DNSServiceConstructFullName, 3);
<commit_msg>Better error handling<commit_after>// vim: ts=2 sw=2 et
#include <hx/CFFI.h>
#include <cstring>
#include <dns_sd.h>

static void throw_error(DNSServiceErrorType error)
{
    switch (error)
    {
#define DECLARE_ERROR(name) case name: val_throw(alloc_string(#name));
        DECLARE_ERROR(kDNSServiceErr_NoError);
        DECLARE_ERROR(kDNSServiceErr_Unknown);
        DECLARE_ERROR(kDNSServiceErr_NoSuchName);
        DECLARE_ERROR(kDNSServiceErr_NoMemory);
        DECLARE_ERROR(kDNSServiceErr_BadParam);
        DECLARE_ERROR(kDNSServiceErr_BadReference);
        DECLARE_ERROR(kDNSServiceErr_BadState);
        DECLARE_ERROR(kDNSServiceErr_BadFlags);
        DECLARE_ERROR(kDNSServiceErr_Unsupported);
        DECLARE_ERROR(kDNSServiceErr_NotInitialized);
        DECLARE_ERROR(kDNSServiceErr_AlreadyRegistered);
        DECLARE_ERROR(kDNSServiceErr_NameConflict);
        DECLARE_ERROR(kDNSServiceErr_Invalid);
        DECLARE_ERROR(kDNSServiceErr_Firewall);
        DECLARE_ERROR(kDNSServiceErr_Incompatible);
        DECLARE_ERROR(kDNSServiceErr_BadInterfaceIndex);
        DECLARE_ERROR(kDNSServiceErr_Refused);
        DECLARE_ERROR(kDNSServiceErr_NoSuchRecord);
        DECLARE_ERROR(kDNSServiceErr_NoAuth);
        DECLARE_ERROR(kDNSServiceErr_NoSuchKey);
        DECLARE_ERROR(kDNSServiceErr_NATTraversal);
        DECLARE_ERROR(kDNSServiceErr_DoubleNAT);
        DECLARE_ERROR(kDNSServiceErr_BadTime);
        DECLARE_ERROR(kDNSServiceErr_BadSig);
        DECLARE_ERROR(kDNSServiceErr_BadKey);
        DECLARE_ERROR(kDNSServiceErr_Transient);
        DECLARE_ERROR(kDNSServiceErr_ServiceNotRunning);
        DECLARE_ERROR(kDNSServiceErr_NATPortMappingUnsupported);
        DECLARE_ERROR(kDNSServiceErr_NATPortMappingDisabled);
        DECLARE_ERROR(kDNSServiceErr_NoRouter);
        DECLARE_ERROR(kDNSServiceErr_PollingMode);
        DECLARE_ERROR(kDNSServiceErr_Timeout);

        default: val_throw(alloc_string("Unknown error"));
    }
}

/**
 * DNSServiceConstructFullName()
 *
 * Concatenate a three-part domain name (as returned by the above callbacks) into a
 * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE
 * strings where necessary.
 *
 * Parameters:
 *
 * fullName:        A pointer to a buffer that where the resulting full domain name is to be written.
 *                  The buffer must be kDNSServiceMaxDomainName (1009) bytes in length to
 *                  accommodate the longest legal domain name without buffer overrun.
 *
 * service:         The service name - any dots or backslashes must NOT be escaped.
 *                  May be NULL (to construct a PTR record name, e.g.
 *                  "_ftp._tcp.apple.com.").
 *
 * regtype:         The service type followed by the protocol, separated by a dot
 *                  (e.g. "_ftp._tcp").
 *
 * domain:          The domain name, e.g. "apple.com.". Literal dots or backslashes,
 *                  if any, must be escaped, e.g. "1st\. Floor.apple.com."
 *
 * return value:    Returns kDNSServiceErr_NoError (0) on success, kDNSServiceErr_BadParam on error.
 *
 */
value hxbonjour_DNSServiceConstructFullName(value service, value regtype, value domain)
{
    char fullName[kDNSServiceMaxDomainName];
    const char *_service, *_regtype, *_domain;
    DNSServiceErrorType error;

    if (!val_is_string(regtype))
        val_throw(alloc_string("regtype cannot be null"));

    if (!val_is_string(domain))
        val_throw(alloc_string("domain cannot be null"));

    if (val_is_null(service)) _service = NULL;
    else if (!val_is_string(service))
        val_throw(alloc_string("service must be a string"));
    else _service = val_get_string(service);

    _regtype = val_get_string(regtype);
    _domain = val_get_string(domain);

    bool regtype_format_ok = _regtype[0] == '_';
    if (regtype_format_ok)
    {
        const char *dot_pos = strchr(_regtype, '.');
        if (dot_pos != NULL)
        {
            regtype_format_ok = !strncmp(dot_pos, "._tcp", 6) || !strncmp(dot_pos, "._udp", 6);
        }
    }

    if (!regtype_format_ok)
        val_throw(alloc_string("regtype should be in the form _proto._(tcp|udp)"));

    error = DNSServiceConstructFullName(fullName, _service, _regtype, _domain);

    if (error != kDNSServiceErr_NoError) throw_error(error);

    return alloc_string(fullName);
}

DEFINE_PRIM(hxbonjour_DNSServiceConstructFullName, 3);
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmlstandaloneappwizardpages.h"
#include "ui_qmlstandaloneappwizardsourcespage.h"
#include "ui_qmlstandaloneappwizardoptionspage.h"
#include <coreplugin/coreconstants.h>

#include <QtGui/QDesktopServices>
#include <QtGui/QFileDialog>
#include <QtGui/QFileDialog>

namespace Qt4ProjectManager {
namespace Internal {

class QmlStandaloneAppWizardSourcesPagePrivate
{
    Ui::QmlStandaloneAppWizardSourcesPage ui;
    bool mainQmlFileChooserVisible;
    friend class QmlStandaloneAppWizardSourcesPage;
};

QmlStandaloneAppWizardSourcesPage::QmlStandaloneAppWizardSourcesPage(QWidget *parent)
    : QWizardPage(parent)
    , m_d(new QmlStandaloneAppWizardSourcesPagePrivate)
{
    m_d->ui.setupUi(this);
    m_d->ui.mainQmlFileLineEdit->setExpectedKind(Utils::PathChooser::File);
    m_d->ui.mainQmlFileLineEdit->setPromptDialogFilter(QLatin1String("*.qml"));
    m_d->ui.mainQmlFileLineEdit->setPromptDialogTitle(tr("Select the main QML file of the application."));
    m_d->ui.addModuleUriButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS)));
    m_d->ui.removeModuleUriButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS)));
    m_d->ui.addImportPathButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS)));
    m_d->ui.removeImportPathButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS)));
    setMainQmlFileChooserVisible(true);
    setModulesError(QString());
    connect(m_d->ui.mainQmlFileLineEdit, SIGNAL(changed(QString)), SIGNAL(completeChanged()));
    connect(m_d->ui.urisListWidget, SIGNAL(itemChanged(QListWidgetItem*)), SLOT(handleModulesChanged()));
    connect(m_d->ui.importPathsListWidget, SIGNAL(itemChanged(QListWidgetItem*)), SLOT(handleModulesChanged()));
}

QmlStandaloneAppWizardSourcesPage::~QmlStandaloneAppWizardSourcesPage()
{
    delete m_d;
}

QString QmlStandaloneAppWizardSourcesPage::mainQmlFile() const
{
    return m_d->ui.mainQmlFileLineEdit->path();
}

bool QmlStandaloneAppWizardSourcesPage::isComplete() const
{
    return (!m_d->mainQmlFileChooserVisible || m_d->ui.mainQmlFileLineEdit->isValid())
            && m_d->ui.errorLabel->text().isEmpty();
}

void QmlStandaloneAppWizardSourcesPage::setMainQmlFileChooserVisible(bool visible)
{
    m_d->mainQmlFileChooserVisible = visible;
    m_d->ui.mainQmlFileGroupBox->setVisible(m_d->mainQmlFileChooserVisible);
}

void QmlStandaloneAppWizardSourcesPage::setModulesError(const QString &error)
{
    m_d->ui.errorLabel->setText(error);
    m_d->ui.errorLabel->setVisible(!error.isEmpty());
}

void QmlStandaloneAppWizardSourcesPage::on_addModuleUriButton_clicked()
{
    QListWidgetItem *item = new QListWidgetItem(m_d->ui.urisListWidget);
    item->setFlags(item->flags() | Qt::ItemIsEditable);
    m_d->ui.urisListWidget->editItem(item);
}

void QmlStandaloneAppWizardSourcesPage::on_removeModuleUriButton_clicked()
{
    const int currentRow = m_d->ui.urisListWidget->currentRow();
    if (currentRow >= 0) {
        m_d->ui.urisListWidget->takeItem(currentRow);
        handleModulesChanged();
    }
}

void QmlStandaloneAppWizardSourcesPage::on_addImportPathButton_clicked()
{
    const QString path = QFileDialog::getExistingDirectory(this,
        tr("Select an import path for QML modules."), mainQmlFile());
    if (!path.isEmpty()) {
        QListWidgetItem *item = new QListWidgetItem(QDir::toNativeSeparators(path), m_d->ui.importPathsListWidget);
        item->setFlags(item->flags() | Qt::ItemIsEditable);
    }
}

void QmlStandaloneAppWizardSourcesPage::on_removeImportPathButton_clicked()
{
    const int currentRow = m_d->ui.importPathsListWidget->currentRow();
    if (currentRow >= 0) {
        m_d->ui.importPathsListWidget->takeItem(currentRow);
        handleModulesChanged();
    }
}

static inline QStringList ertriesFromListWidget(const QListWidget &listWidget)
{
    QStringList result;
    for (int i = 0; i < listWidget.count(); ++i) {
        const QString text = listWidget.item(i)->text().trimmed();
        if (!text.isEmpty())
            result.append(text);
    }
    return result;
}

void QmlStandaloneAppWizardSourcesPage::handleModulesChanged()
{
    const QStringList uris = ertriesFromListWidget(*m_d->ui.urisListWidget);
    const QStringList paths = ertriesFromListWidget(*m_d->ui.importPathsListWidget);
    emit externalModulesChanged(uris, paths);
    emit completeChanged();
}

QStringList QmlStandaloneAppWizardSourcesPage::moduleUris() const
{
    return ertriesFromListWidget(*m_d->ui.urisListWidget);
}

QStringList QmlStandaloneAppWizardSourcesPage::moduleImportPaths() const
{
    return ertriesFromListWidget(*m_d->ui.importPathsListWidget);
}

class QmlStandaloneAppWizardOptionsPagePrivate
{
    Ui::QmlStandaloneAppWizardOptionPage ui;
    QString symbianSvgIcon;
    friend class QmlStandaloneAppWizardOptionsPage;
};

QmlStandaloneAppWizardOptionsPage::QmlStandaloneAppWizardOptionsPage(QWidget *parent)
    : QWizardPage(parent)
    , m_d(new QmlStandaloneAppWizardOptionsPagePrivate)
{
    m_d->ui.setupUi(this);

    const QIcon open = QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon);
    m_d->ui.symbianAppIconLoadToolButton->setIcon(open);
    connect(m_d->ui.symbianAppIconLoadToolButton, SIGNAL(clicked()), SLOT(openSymbianSvgIcon()));

    m_d->ui.orientationBehaviorComboBox->addItem(tr("Auto rotate orientation"),
                                                   QmlStandaloneApp::Auto);
    m_d->ui.orientationBehaviorComboBox->addItem(tr("Lock to landscape orientation"),
                                                   QmlStandaloneApp::LockLandscape);
    m_d->ui.orientationBehaviorComboBox->addItem(tr("Lock to portrait orientation"),
                                                   QmlStandaloneApp::LockPortrait);
}

QmlStandaloneAppWizardOptionsPage::~QmlStandaloneAppWizardOptionsPage()
{
    delete m_d;
}

void QmlStandaloneAppWizardOptionsPage::setOrientation(QmlStandaloneApp::Orientation orientation)
{
    QComboBox *const comboBox = m_d->ui.orientationBehaviorComboBox;
    for (int i = 0; i < comboBox->count(); ++i)
        if (comboBox->itemData(i).toInt() == static_cast<int>(orientation)) {
            comboBox->setCurrentIndex(i);
            break;
        }
}

QmlStandaloneApp::Orientation QmlStandaloneAppWizardOptionsPage::orientation() const
{
    const int index = m_d->ui.orientationBehaviorComboBox->currentIndex();
    return static_cast<QmlStandaloneApp::Orientation>(m_d->ui.orientationBehaviorComboBox->itemData(index).toInt());
}

QString QmlStandaloneAppWizardOptionsPage::symbianSvgIcon() const
{
    return m_d->symbianSvgIcon;
}

void QmlStandaloneAppWizardOptionsPage::setSymbianSvgIcon(const QString &icon)
{
    QPixmap iconPixmap(icon);
    if (!iconPixmap.isNull()) {
        const int symbianIconSize = 44;
        if (iconPixmap.height() > symbianIconSize || iconPixmap.width() > symbianIconSize)
            iconPixmap = iconPixmap.scaledToHeight(symbianIconSize, Qt::SmoothTransformation);
        m_d->ui.symbianAppIconPreview->setPixmap(iconPixmap);
        m_d->symbianSvgIcon = icon;
    }
}

QString QmlStandaloneAppWizardOptionsPage::symbianUid() const
{
    return m_d->ui.symbianTargetUid3LineEdit->text();
}

void QmlStandaloneAppWizardOptionsPage::setSymbianUid(const QString &uid)
{
    m_d->ui.symbianTargetUid3LineEdit->setText(uid);
}

void QmlStandaloneAppWizardOptionsPage::setLoadDummyData(bool loadIt)
{
    m_d->ui.loadDummyDataCheckBox->setChecked(loadIt);
}

bool QmlStandaloneAppWizardOptionsPage::loadDummyData() const
{
    return m_d->ui.loadDummyDataCheckBox->isChecked();
}

void QmlStandaloneAppWizardOptionsPage::setNetworkEnabled(bool enableIt)
{
    m_d->ui.symbianEnableNetworkChackBox->setChecked(enableIt);
}

bool QmlStandaloneAppWizardOptionsPage::networkEnabled() const
{
    return m_d->ui.symbianEnableNetworkChackBox->isChecked();
}

void QmlStandaloneAppWizardOptionsPage::openSymbianSvgIcon()
{
    const QString svgIcon = QFileDialog::getOpenFileName(
            this,
            m_d->ui.symbianAppIconLabel->text(),
            QDesktopServices::storageLocation(QDesktopServices::PicturesLocation),
            QLatin1String("*.svg"));
    if (!svgIcon.isEmpty())
        setSymbianSvgIcon(svgIcon);
}

} // namespace Internal
} // namespace Qt4ProjectManager
<commit_msg>Make sure that the last added uri is in edit mode<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmlstandaloneappwizardpages.h"
#include "ui_qmlstandaloneappwizardsourcespage.h"
#include "ui_qmlstandaloneappwizardoptionspage.h"
#include <coreplugin/coreconstants.h>

#include <QtGui/QDesktopServices>
#include <QtGui/QFileDialog>
#include <QtGui/QFileDialog>

namespace Qt4ProjectManager {
namespace Internal {

class QmlStandaloneAppWizardSourcesPagePrivate
{
    Ui::QmlStandaloneAppWizardSourcesPage ui;
    bool mainQmlFileChooserVisible;
    friend class QmlStandaloneAppWizardSourcesPage;
};

QmlStandaloneAppWizardSourcesPage::QmlStandaloneAppWizardSourcesPage(QWidget *parent)
    : QWizardPage(parent)
    , m_d(new QmlStandaloneAppWizardSourcesPagePrivate)
{
    m_d->ui.setupUi(this);
    m_d->ui.mainQmlFileLineEdit->setExpectedKind(Utils::PathChooser::File);
    m_d->ui.mainQmlFileLineEdit->setPromptDialogFilter(QLatin1String("*.qml"));
    m_d->ui.mainQmlFileLineEdit->setPromptDialogTitle(tr("Select the main QML file of the application."));
    m_d->ui.addModuleUriButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS)));
    m_d->ui.removeModuleUriButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS)));
    m_d->ui.addImportPathButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PLUS)));
    m_d->ui.removeImportPathButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_MINUS)));
    setMainQmlFileChooserVisible(true);
    setModulesError(QString());
    connect(m_d->ui.mainQmlFileLineEdit, SIGNAL(changed(QString)), SIGNAL(completeChanged()));
    connect(m_d->ui.urisListWidget, SIGNAL(itemChanged(QListWidgetItem*)), SLOT(handleModulesChanged()));
    connect(m_d->ui.importPathsListWidget, SIGNAL(itemChanged(QListWidgetItem*)), SLOT(handleModulesChanged()));
}

QmlStandaloneAppWizardSourcesPage::~QmlStandaloneAppWizardSourcesPage()
{
    delete m_d;
}

QString QmlStandaloneAppWizardSourcesPage::mainQmlFile() const
{
    return m_d->ui.mainQmlFileLineEdit->path();
}

bool QmlStandaloneAppWizardSourcesPage::isComplete() const
{
    return (!m_d->mainQmlFileChooserVisible || m_d->ui.mainQmlFileLineEdit->isValid())
            && m_d->ui.errorLabel->text().isEmpty();
}

void QmlStandaloneAppWizardSourcesPage::setMainQmlFileChooserVisible(bool visible)
{
    m_d->mainQmlFileChooserVisible = visible;
    m_d->ui.mainQmlFileGroupBox->setVisible(m_d->mainQmlFileChooserVisible);
}

void QmlStandaloneAppWizardSourcesPage::setModulesError(const QString &error)
{
    m_d->ui.errorLabel->setText(error);
    m_d->ui.errorLabel->setVisible(!error.isEmpty());
}

void QmlStandaloneAppWizardSourcesPage::on_addModuleUriButton_clicked()
{
    setFocus(); // Interrupt any current editing
    QListWidgetItem *item = new QListWidgetItem(m_d->ui.urisListWidget);
    item->setFlags(item->flags() | Qt::ItemIsEditable);
    m_d->ui.urisListWidget->editItem(item);
}

void QmlStandaloneAppWizardSourcesPage::on_removeModuleUriButton_clicked()
{
    const int currentRow = m_d->ui.urisListWidget->currentRow();
    if (currentRow >= 0) {
        m_d->ui.urisListWidget->takeItem(currentRow);
        handleModulesChanged();
    }
}

void QmlStandaloneAppWizardSourcesPage::on_addImportPathButton_clicked()
{
    const QString path = QFileDialog::getExistingDirectory(this,
        tr("Select an import path for QML modules."), mainQmlFile());
    if (!path.isEmpty()) {
        QListWidgetItem *item = new QListWidgetItem(QDir::toNativeSeparators(path), m_d->ui.importPathsListWidget);
        item->setFlags(item->flags() | Qt::ItemIsEditable);
    }
}

void QmlStandaloneAppWizardSourcesPage::on_removeImportPathButton_clicked()
{
    const int currentRow = m_d->ui.importPathsListWidget->currentRow();
    if (currentRow >= 0) {
        m_d->ui.importPathsListWidget->takeItem(currentRow);
        handleModulesChanged();
    }
}

static inline QStringList ertriesFromListWidget(const QListWidget &listWidget)
{
    QStringList result;
    for (int i = 0; i < listWidget.count(); ++i) {
        const QString text = listWidget.item(i)->text().trimmed();
        if (!text.isEmpty())
            result.append(text);
    }
    return result;
}

void QmlStandaloneAppWizardSourcesPage::handleModulesChanged()
{
    const QStringList uris = ertriesFromListWidget(*m_d->ui.urisListWidget);
    const QStringList paths = ertriesFromListWidget(*m_d->ui.importPathsListWidget);
    emit externalModulesChanged(uris, paths);
    emit completeChanged();
}

QStringList QmlStandaloneAppWizardSourcesPage::moduleUris() const
{
    return ertriesFromListWidget(*m_d->ui.urisListWidget);
}

QStringList QmlStandaloneAppWizardSourcesPage::moduleImportPaths() const
{
    return ertriesFromListWidget(*m_d->ui.importPathsListWidget);
}

class QmlStandaloneAppWizardOptionsPagePrivate
{
    Ui::QmlStandaloneAppWizardOptionPage ui;
    QString symbianSvgIcon;
    friend class QmlStandaloneAppWizardOptionsPage;
};

QmlStandaloneAppWizardOptionsPage::QmlStandaloneAppWizardOptionsPage(QWidget *parent)
    : QWizardPage(parent)
    , m_d(new QmlStandaloneAppWizardOptionsPagePrivate)
{
    m_d->ui.setupUi(this);

    const QIcon open = QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon);
    m_d->ui.symbianAppIconLoadToolButton->setIcon(open);
    connect(m_d->ui.symbianAppIconLoadToolButton, SIGNAL(clicked()), SLOT(openSymbianSvgIcon()));

    m_d->ui.orientationBehaviorComboBox->addItem(tr("Auto rotate orientation"),
                                                   QmlStandaloneApp::Auto);
    m_d->ui.orientationBehaviorComboBox->addItem(tr("Lock to landscape orientation"),
                                                   QmlStandaloneApp::LockLandscape);
    m_d->ui.orientationBehaviorComboBox->addItem(tr("Lock to portrait orientation"),
                                                   QmlStandaloneApp::LockPortrait);
}

QmlStandaloneAppWizardOptionsPage::~QmlStandaloneAppWizardOptionsPage()
{
    delete m_d;
}

void QmlStandaloneAppWizardOptionsPage::setOrientation(QmlStandaloneApp::Orientation orientation)
{
    QComboBox *const comboBox = m_d->ui.orientationBehaviorComboBox;
    for (int i = 0; i < comboBox->count(); ++i)
        if (comboBox->itemData(i).toInt() == static_cast<int>(orientation)) {
            comboBox->setCurrentIndex(i);
            break;
        }
}

QmlStandaloneApp::Orientation QmlStandaloneAppWizardOptionsPage::orientation() const
{
    const int index = m_d->ui.orientationBehaviorComboBox->currentIndex();
    return static_cast<QmlStandaloneApp::Orientation>(m_d->ui.orientationBehaviorComboBox->itemData(index).toInt());
}

QString QmlStandaloneAppWizardOptionsPage::symbianSvgIcon() const
{
    return m_d->symbianSvgIcon;
}

void QmlStandaloneAppWizardOptionsPage::setSymbianSvgIcon(const QString &icon)
{
    QPixmap iconPixmap(icon);
    if (!iconPixmap.isNull()) {
        const int symbianIconSize = 44;
        if (iconPixmap.height() > symbianIconSize || iconPixmap.width() > symbianIconSize)
            iconPixmap = iconPixmap.scaledToHeight(symbianIconSize, Qt::SmoothTransformation);
        m_d->ui.symbianAppIconPreview->setPixmap(iconPixmap);
        m_d->symbianSvgIcon = icon;
    }
}

QString QmlStandaloneAppWizardOptionsPage::symbianUid() const
{
    return m_d->ui.symbianTargetUid3LineEdit->text();
}

void QmlStandaloneAppWizardOptionsPage::setSymbianUid(const QString &uid)
{
    m_d->ui.symbianTargetUid3LineEdit->setText(uid);
}

void QmlStandaloneAppWizardOptionsPage::setLoadDummyData(bool loadIt)
{
    m_d->ui.loadDummyDataCheckBox->setChecked(loadIt);
}

bool QmlStandaloneAppWizardOptionsPage::loadDummyData() const
{
    return m_d->ui.loadDummyDataCheckBox->isChecked();
}

void QmlStandaloneAppWizardOptionsPage::setNetworkEnabled(bool enableIt)
{
    m_d->ui.symbianEnableNetworkChackBox->setChecked(enableIt);
}

bool QmlStandaloneAppWizardOptionsPage::networkEnabled() const
{
    return m_d->ui.symbianEnableNetworkChackBox->isChecked();
}

void QmlStandaloneAppWizardOptionsPage::openSymbianSvgIcon()
{
    const QString svgIcon = QFileDialog::getOpenFileName(
            this,
            m_d->ui.symbianAppIconLabel->text(),
            QDesktopServices::storageLocation(QDesktopServices::PicturesLocation),
            QLatin1String("*.svg"));
    if (!svgIcon.isEmpty())
        setSymbianSvgIcon(svgIcon);
}

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


<commit_before>// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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.
//
// Implements the BranchHookTransform class.

#include "syzygy/instrument/transforms/branch_hook_transform.h"

#include "base/logging.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "syzygy/agent/basic_block_entry/basic_block_entry.h"
#include "syzygy/block_graph/block_builder.h"
#include "syzygy/block_graph/block_util.h"
#include "syzygy/common/defs.h"
#include "syzygy/common/indexed_frequency_data.h"
#include "syzygy/instrument/transforms/entry_thunk_transform.h"
#include "syzygy/pe/block_util.h"
#include "syzygy/pe/pe_utils.h"
#include "syzygy/pe/transforms/pe_add_imports_transform.h"

namespace instrument {
namespace transforms {

namespace {

using agent::basic_block_entry::BasicBlockEntry;
using block_graph::BasicBlock;
using block_graph::BasicBlockAssembler;
using block_graph::BasicBlockReference;
using block_graph::BasicCodeBlock;
using block_graph::BlockBuilder;
using block_graph::BlockGraph;
using block_graph::Displacement;
using block_graph::Immediate;
using block_graph::Operand;
using block_graph::Successor;
using common::kBasicBlockEntryAgentId;
using pe::transforms::PEAddImportsTransform;

typedef BasicBlockEntry::BasicBlockIndexedFrequencyData
    BasicBlockIndexedFrequencyData;
typedef pe::transforms::ImportedModule ImportedModule;

const char kDefaultModuleName[] = "basic_block_entry_client.dll";
const char kBranchFunctionEnter[] = "_function_enter";
const char kBranchEnter[] = "_branch_enter";
const char kBranchEnterBuffered[] = "_branch_enter_buffered";
const char kBranchExit[] = "_branch_exit";
const size_t kNumBranchSlot = 4;

// Sets up the entry and the exit hooks import.
bool SetupEntryHooks(BlockGraph* block_graph,
                     BlockGraph::Block* header_block,
                     const std::string& module_name,
                     bool buffering,
                     uint32 fs_slot,
                     BlockGraph::Reference* function_enter,
                     BlockGraph::Reference* branch_enter,
                     BlockGraph::Reference* branch_exit) {
  DCHECK(block_graph != NULL);
  DCHECK(header_block != NULL);
  DCHECK(branch_enter != NULL);
  DCHECK(branch_exit != NULL);

  // Determine which hooks to use.
  std::string function_enter_name;
  std::string branch_enter_name;
  std::string branch_exit_name;

  if (buffering) {
    branch_enter_name = kBranchEnterBuffered;
    branch_exit_name = kBranchExit;
  } else {
    branch_enter_name = kBranchEnter;
    branch_exit_name = kBranchExit;
  }

  if (fs_slot != 0) {
    function_enter_name =
        base::StringPrintf("%s_s%d", kBranchFunctionEnter, fs_slot);
    branch_enter_name =
        base::StringPrintf("%s_s%d", branch_enter_name.c_str(), fs_slot);
    branch_exit_name =
        base::StringPrintf("%s_s%d", branch_exit_name.c_str(), fs_slot);
  }

  // Setup the import module.
  ImportedModule module(module_name);
  size_t enter_index = module.AddSymbol(branch_enter_name,
                                        ImportedModule::kAlwaysImport);

  size_t exit_index = module.AddSymbol(branch_exit_name,
                                       ImportedModule::kAlwaysImport);
  size_t function_enter_index = 0;
  if (!function_enter_name.empty()) {
    function_enter_index = module.AddSymbol(function_enter_name,
                                            ImportedModule::kAlwaysImport);
  }

  // Setup the add-imports transform.
  PEAddImportsTransform add_imports;
  add_imports.AddModule(&module);

  // Add the imports to the block-graph.
  if (!ApplyBlockGraphTransform(&add_imports, block_graph, header_block)) {
    LOG(ERROR) << "Unable to add import entry hook functions.";
    return false;
  }

  // Get a reference to the entry-hook function.
  if (!module.GetSymbolReference(enter_index, branch_enter)) {
    LOG(ERROR) << "Unable to get " << kBranchEnter << ".";
    return false;
  }
  DCHECK(branch_enter->IsValid());

  // Get a reference to the exit-hook function.
  if (!module.GetSymbolReference(exit_index, branch_exit)) {
    LOG(ERROR) << "Unable to get " << kBranchExit << ".";
    return false;
  }
  DCHECK(branch_exit->IsValid());

  if (!function_enter_name.empty()) {
    if (!module.GetSymbolReference(function_enter_index, function_enter)) {
      LOG(ERROR) << "Unable to get " << function_enter_name << ".";
      return false;
    }
    DCHECK(function_enter->IsValid());
  }

  return true;
}

}  // namespace

const char BranchHookTransform::kTransformName[] = "BranchTransform";

BranchHookTransform::BranchHookTransform()
  : add_frequency_data_(kBasicBlockEntryAgentId,
                        "Basic-Block Branch Information Data",
                        common::kBranchFrequencyDataVersion,
                        common::IndexedFrequencyData::BRANCH,
                        sizeof(BasicBlockIndexedFrequencyData)),
    thunk_section_(NULL),
    instrument_dll_name_(kDefaultModuleName),
    buffering_(false),
    fs_slot_(0U) {
}

bool BranchHookTransform::PreBlockGraphIteration(
    BlockGraph* block_graph,
    BlockGraph::Block* header_block) {
  DCHECK(block_graph != NULL);
  DCHECK(header_block != NULL);

  // Setup instrumentation functions hooks.
  if (!SetupEntryHooks(block_graph,
                      header_block,
                      instrument_dll_name_,
                      buffering_,
                      fs_slot_,
                      &function_enter_hook_ref_,
                      &enter_hook_ref_,
                      &exit_hook_ref_)) {
    return false;
  }

  // Add the static basic-block frequency data.
  if (!ApplyBlockGraphTransform(
          &add_frequency_data_, block_graph, header_block)) {
    LOG(ERROR) << "Failed to insert basic-block frequency data.";
    return false;
  }

  return true;
}

bool BranchHookTransform::OnBlock(BlockGraph* block_graph,
                                  BlockGraph::Block* block) {
  DCHECK(block_graph != NULL);
  DCHECK(block != NULL);

  if (block->type() != BlockGraph::CODE_BLOCK)
    return true;

  // Ignore non-decomposable block.
  if (!pe::CodeBlockIsBasicBlockDecomposable(block))
    return true;

  if (!ApplyBasicBlockSubGraphTransform(this, block_graph, block, NULL))
    return false;

  return true;
}

bool BranchHookTransform::TransformBasicBlockSubGraph(
    BlockGraph* block_graph , BasicBlockSubGraph* subgraph) {
  DCHECK(block_graph != NULL);
  DCHECK(subgraph != NULL);
  DCHECK(enter_hook_ref_.IsValid());
  DCHECK(exit_hook_ref_.IsValid());
  DCHECK(add_frequency_data_.frequency_data_block() != NULL);

  // Determine whether we must pass the module_data pointer to the hooks.
  bool need_module_data = true;
  if (fs_slot_ != 0)
    need_module_data = false;

  // Insert a call to the basic-block entry hook at the top of each code
  // basic-block.
  BasicBlockSubGraph::BBCollection::iterator it =
      subgraph->basic_blocks().begin();
  for (; it != subgraph->basic_blocks().end(); ++it) {
    BasicCodeBlock* bb = BasicCodeBlock::Cast(*it);
    if (bb == NULL || bb->is_padding())
      continue;

    // Find the source range associated with this basic-block.
    BlockGraph::Block::SourceRange source_range;
    if (!GetBasicBlockSourceRange(*bb, &source_range)) {
      LOG(ERROR) << "Unable to get source range for basic block '"
                 << bb->name() << "'";
      return false;
    }

    // We use the location/index in the bb_ranges vector of the current
    // basic-block range as the basic_block_id, and we pass a pointer to the
    // frequency data block as the module_data parameter. We then make a memory
    // indirect call to the bb_entry_hook.
    Immediate basic_block_id(bb_ranges_.size(), core::kSize32Bit);
    Immediate module_data(add_frequency_data_.frequency_data_block(), 0);

    // Assemble entry hook instrumentation into the instruction stream.
    Operand enter_hook(Displacement(enter_hook_ref_.referenced(),
                                    enter_hook_ref_.offset()));
    BasicBlockAssembler bb_asm_enter(bb->instructions().begin(),
                                     &bb->instructions());
    bb_asm_enter.push(basic_block_id);
    if (need_module_data)
      bb_asm_enter.push(module_data);
    bb_asm_enter.call(enter_hook);

    // Find the last non jumping instruction in the basic block.
    BasicBlock::Instructions::iterator last = bb->instructions().begin();
    BasicBlock::Instructions::iterator last_instruction = last;
    for (; last != bb->instructions().end(); ++last) {
      if (!last->IsReturn() && !last->IsBranch()) {
        last_instruction = last;
        ++last_instruction;
      }
    }

    if (last == bb->instructions().end() ||
        !last->CallsNonReturningFunction()) {
      // Assemble exit hook instrumentation into the instruction stream.
      Operand exit_hook(Displacement(exit_hook_ref_.referenced(),
                                     exit_hook_ref_.offset()));
      BasicBlockAssembler bb_asm_exit(last_instruction,
                                      &bb->instructions());
      bb_asm_exit.push(basic_block_id);
      if (need_module_data)
        bb_asm_exit.push(module_data);
      bb_asm_exit.call(exit_hook);
    }

    // Push the range for the current basic block.
    bb_ranges_.push_back(source_range);
  }

  // Insert a call to the function entry hook at the beginning of the function.
  if (function_enter_hook_ref_.IsValid()) {
    // Get the basic block ordering.
    DCHECK_EQ(1U, subgraph->block_descriptions().size());
    const BasicBlockSubGraph::BasicBlockOrdering& original_order =
        subgraph->block_descriptions().front().basic_block_order;

    BasicCodeBlock* first_bb = BasicCodeBlock::Cast(*original_order.begin());
    DCHECK(first_bb != NULL);

    // Assemble function enter hook instrumentation into the instruction stream.
    Immediate module_data(add_frequency_data_.frequency_data_block(), 0);
    Operand func_hook(Displacement(function_enter_hook_ref_.referenced(),
                                   function_enter_hook_ref_.offset()));
    BasicBlockAssembler func_asm_enter(first_bb->instructions().begin(),
                                       &first_bb->instructions());
    func_asm_enter.push(module_data);
    func_asm_enter.call(func_hook);
  }

  return true;
}

bool BranchHookTransform::PostBlockGraphIteration(
    BlockGraph* block_graph, BlockGraph::Block* header_block) {
  DCHECK(block_graph != NULL);
  DCHECK(header_block != NULL);

  size_t num_basic_blocks = bb_ranges_.size();
  if (num_basic_blocks == 0) {
    LOG(WARNING) << "Encountered no basic code blocks during instrumentation.";
    return true;
  }

  if (!add_frequency_data_.ConfigureFrequencyDataBuffer(num_basic_blocks,
                                                        3,
                                                        sizeof(uint32))) {
    LOG(ERROR) << "Failed to configure frequency data buffer.";
    return false;
  }

  // Initialized BasicBlock agent specific fields
  block_graph::TypedBlock<BasicBlockIndexedFrequencyData> frequency_data;
  CHECK(frequency_data.Init(0, add_frequency_data_.frequency_data_block()));
  frequency_data->fs_slot = fs_slot_;
  frequency_data->tls_index = TLS_OUT_OF_INDEXES;

  // Add the module entry thunks.
  EntryThunkTransform add_thunks;
  add_thunks.set_only_instrument_module_entry(true);
  add_thunks.set_instrument_dll_name(instrument_dll_name_);
  add_thunks.set_src_ranges_for_thunks(true);

  Immediate module_data(add_frequency_data_.frequency_data_block(), 0);
  if (!add_thunks.SetEntryThunkParameter(module_data)) {
    LOG(ERROR) << "Failed to configure the entry thunks with the module_data "
               << "parameter.";
    return false;
  }

  if (!ApplyBlockGraphTransform(&add_thunks, block_graph, header_block)) {
    LOG(ERROR) << "Unable to thunk module entry points.";
    return false;
  }

  // Find or create the section we put our thunks in.
  thunk_section_ = block_graph->FindOrAddSection(common::kThunkSectionName,
                                                 pe::kCodeCharacteristics);
  DCHECK(thunk_section_ != NULL);

  return true;
}

}  // namespace transforms
}  // namespace instrument
<commit_msg>Force sequential ordering of basic block allocation in branch instrumentation.<commit_after>// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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.
//
// Implements the BranchHookTransform class.

#include "syzygy/instrument/transforms/branch_hook_transform.h"

#include "base/logging.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "syzygy/agent/basic_block_entry/basic_block_entry.h"
#include "syzygy/block_graph/block_builder.h"
#include "syzygy/block_graph/block_util.h"
#include "syzygy/common/defs.h"
#include "syzygy/common/indexed_frequency_data.h"
#include "syzygy/instrument/transforms/entry_thunk_transform.h"
#include "syzygy/pe/block_util.h"
#include "syzygy/pe/pe_utils.h"
#include "syzygy/pe/transforms/pe_add_imports_transform.h"

namespace instrument {
namespace transforms {

namespace {

using agent::basic_block_entry::BasicBlockEntry;
using block_graph::BasicBlock;
using block_graph::BasicBlockAssembler;
using block_graph::BasicBlockReference;
using block_graph::BasicBlockSubGraph;
using block_graph::BasicCodeBlock;
using block_graph::BlockBuilder;
using block_graph::BlockGraph;
using block_graph::Displacement;
using block_graph::Immediate;
using block_graph::Operand;
using block_graph::Successor;
using common::kBasicBlockEntryAgentId;
using pe::transforms::PEAddImportsTransform;

typedef BasicBlockEntry::BasicBlockIndexedFrequencyData
    BasicBlockIndexedFrequencyData;
typedef BasicBlockSubGraph::BlockDescriptionList
    BlockDescriptionList;
typedef pe::transforms::ImportedModule ImportedModule;

const char kDefaultModuleName[] = "basic_block_entry_client.dll";
const char kBranchFunctionEnter[] = "_function_enter";
const char kBranchEnter[] = "_branch_enter";
const char kBranchEnterBuffered[] = "_branch_enter_buffered";
const char kBranchExit[] = "_branch_exit";
const size_t kNumBranchSlot = 4;

// Sets up the entry and the exit hooks import.
bool SetupEntryHooks(BlockGraph* block_graph,
                     BlockGraph::Block* header_block,
                     const std::string& module_name,
                     bool buffering,
                     uint32 fs_slot,
                     BlockGraph::Reference* function_enter,
                     BlockGraph::Reference* branch_enter,
                     BlockGraph::Reference* branch_exit) {
  DCHECK(block_graph != NULL);
  DCHECK(header_block != NULL);
  DCHECK(branch_enter != NULL);
  DCHECK(branch_exit != NULL);

  // Determine which hooks to use.
  std::string function_enter_name;
  std::string branch_enter_name;
  std::string branch_exit_name;

  if (buffering) {
    branch_enter_name = kBranchEnterBuffered;
    branch_exit_name = kBranchExit;
  } else {
    branch_enter_name = kBranchEnter;
    branch_exit_name = kBranchExit;
  }

  if (fs_slot != 0) {
    function_enter_name =
        base::StringPrintf("%s_s%d", kBranchFunctionEnter, fs_slot);
    branch_enter_name =
        base::StringPrintf("%s_s%d", branch_enter_name.c_str(), fs_slot);
    branch_exit_name =
        base::StringPrintf("%s_s%d", branch_exit_name.c_str(), fs_slot);
  }

  // Setup the import module.
  ImportedModule module(module_name);
  size_t enter_index = module.AddSymbol(branch_enter_name,
                                        ImportedModule::kAlwaysImport);

  size_t exit_index = module.AddSymbol(branch_exit_name,
                                       ImportedModule::kAlwaysImport);
  size_t function_enter_index = 0;
  if (!function_enter_name.empty()) {
    function_enter_index = module.AddSymbol(function_enter_name,
                                            ImportedModule::kAlwaysImport);
  }

  // Setup the add-imports transform.
  PEAddImportsTransform add_imports;
  add_imports.AddModule(&module);

  // Add the imports to the block-graph.
  if (!ApplyBlockGraphTransform(&add_imports, block_graph, header_block)) {
    LOG(ERROR) << "Unable to add import entry hook functions.";
    return false;
  }

  // Get a reference to the entry-hook function.
  if (!module.GetSymbolReference(enter_index, branch_enter)) {
    LOG(ERROR) << "Unable to get " << kBranchEnter << ".";
    return false;
  }
  DCHECK(branch_enter->IsValid());

  // Get a reference to the exit-hook function.
  if (!module.GetSymbolReference(exit_index, branch_exit)) {
    LOG(ERROR) << "Unable to get " << kBranchExit << ".";
    return false;
  }
  DCHECK(branch_exit->IsValid());

  if (!function_enter_name.empty()) {
    if (!module.GetSymbolReference(function_enter_index, function_enter)) {
      LOG(ERROR) << "Unable to get " << function_enter_name << ".";
      return false;
    }
    DCHECK(function_enter->IsValid());
  }

  return true;
}

}  // namespace

const char BranchHookTransform::kTransformName[] = "BranchTransform";

BranchHookTransform::BranchHookTransform()
  : add_frequency_data_(kBasicBlockEntryAgentId,
                        "Basic-Block Branch Information Data",
                        common::kBranchFrequencyDataVersion,
                        common::IndexedFrequencyData::BRANCH,
                        sizeof(BasicBlockIndexedFrequencyData)),
    thunk_section_(NULL),
    instrument_dll_name_(kDefaultModuleName),
    buffering_(false),
    fs_slot_(0U) {
}

bool BranchHookTransform::PreBlockGraphIteration(
    BlockGraph* block_graph,
    BlockGraph::Block* header_block) {
  DCHECK(block_graph != NULL);
  DCHECK(header_block != NULL);

  // Setup instrumentation functions hooks.
  if (!SetupEntryHooks(block_graph,
                      header_block,
                      instrument_dll_name_,
                      buffering_,
                      fs_slot_,
                      &function_enter_hook_ref_,
                      &enter_hook_ref_,
                      &exit_hook_ref_)) {
    return false;
  }

  // Add the static basic-block frequency data.
  if (!ApplyBlockGraphTransform(
          &add_frequency_data_, block_graph, header_block)) {
    LOG(ERROR) << "Failed to insert basic-block frequency data.";
    return false;
  }

  return true;
}

bool BranchHookTransform::OnBlock(BlockGraph* block_graph,
                                  BlockGraph::Block* block) {
  DCHECK(block_graph != NULL);
  DCHECK(block != NULL);

  if (block->type() != BlockGraph::CODE_BLOCK)
    return true;

  // Ignore non-decomposable block.
  if (!pe::CodeBlockIsBasicBlockDecomposable(block))
    return true;

  if (!ApplyBasicBlockSubGraphTransform(this, block_graph, block, NULL))
    return false;

  return true;
}

bool BranchHookTransform::TransformBasicBlockSubGraph(
    BlockGraph* block_graph , BasicBlockSubGraph* subgraph) {
  DCHECK(block_graph != NULL);
  DCHECK(subgraph != NULL);
  DCHECK(enter_hook_ref_.IsValid());
  DCHECK(exit_hook_ref_.IsValid());
  DCHECK(add_frequency_data_.frequency_data_block() != NULL);

  // Determine whether we must pass the module_data pointer to the hooks.
  bool need_module_data = true;
  if (fs_slot_ != 0)
    need_module_data = false;

  BlockDescriptionList& descriptions = subgraph->block_descriptions();
  BlockDescriptionList::iterator description = descriptions.begin();
  for (; description != descriptions.end(); ++description) {
    BasicBlockSubGraph::BasicBlockOrdering& original_order =
        (*description).basic_block_order;

    // Get the first basic block of this ordering.
    DCHECK(!original_order.empty());
    BasicCodeBlock* first_bb = BasicCodeBlock::Cast(*original_order.begin());
    DCHECK(first_bb != NULL);

    // Insert a call to the basic-block entry hook at the beginning and the end
    // of each code basic-block.
    BasicBlockSubGraph::BasicBlockOrdering::const_iterator it =
      original_order.begin();
    for (; it != original_order.end(); ++it) {
      BasicCodeBlock* bb = BasicCodeBlock::Cast(*it);
      if (bb == NULL || bb->is_padding())
        continue;

      // Find the source range associated with this basic-block.
      BlockGraph::Block::SourceRange source_range;
      if (!GetBasicBlockSourceRange(*bb, &source_range)) {
        LOG(ERROR) << "Unable to get source range for basic block '"
                   << bb->name() << "'";
        return false;
      }

      // We use the index in the bb_ranges vector of the current basic-block
      // range as the basic_block_id, and we pass a pointer to the frequency
      // data block as the module_data parameter. We then make a memory indirect
      // call to the bb_entry_hook.
      Immediate basic_block_id(bb_ranges_.size(), core::kSize32Bit);
      Immediate module_data(add_frequency_data_.frequency_data_block(), 0);

      // Assemble entry hook instrumentation into the instruction stream.
      BlockGraph::Reference* enter_hook_ref = &enter_hook_ref_;
      Operand enter_hook(Displacement(enter_hook_ref->referenced(),
                                      enter_hook_ref->offset()));
      BasicBlockAssembler bb_asm_enter(bb->instructions().begin(),
                                       &bb->instructions());
      bb_asm_enter.push(basic_block_id);
      if (need_module_data)
        bb_asm_enter.push(module_data);
      bb_asm_enter.call(enter_hook);

      // Find the last non jumping instruction in the basic block.
      BasicBlock::Instructions::iterator last = bb->instructions().begin();
      BasicBlock::Instructions::iterator last_instruction = last;
      for (; last != bb->instructions().end(); ++last) {
        if (!last->IsReturn() && !last->IsBranch()) {
          last_instruction = last;
          ++last_instruction;
        }
      }

      if (last == bb->instructions().end() ||
          !last->CallsNonReturningFunction()) {
        // Assemble exit hook instrumentation into the instruction stream.
        Operand exit_hook(Displacement(exit_hook_ref_.referenced(),
                                       exit_hook_ref_.offset()));
        BasicBlockAssembler bb_asm_exit(last_instruction,
                                        &bb->instructions());
        bb_asm_exit.push(basic_block_id);
        if (need_module_data)
          bb_asm_exit.push(module_data);
        bb_asm_exit.call(exit_hook);
      }

      // Push the range for the current basic block.
      bb_ranges_.push_back(source_range);
    }

    // Insert a call to the function entry hook at the beginning of the
    // function.
    if (function_enter_hook_ref_.IsValid()) {
      // Assemble function enter hook instrumentation into the instruction
      // stream.
      Immediate module_data(add_frequency_data_.frequency_data_block(), 0);
      Operand func_hook(Displacement(function_enter_hook_ref_.referenced(),
                                     function_enter_hook_ref_.offset()));
      BasicBlockAssembler func_asm_enter(first_bb->instructions().begin(),
                                         &first_bb->instructions());
      func_asm_enter.push(module_data);
      func_asm_enter.call(func_hook);
    }
  }

  return true;
}

bool BranchHookTransform::PostBlockGraphIteration(
    BlockGraph* block_graph, BlockGraph::Block* header_block) {
  DCHECK(block_graph != NULL);
  DCHECK(header_block != NULL);

  size_t num_basic_blocks = bb_ranges_.size();
  if (num_basic_blocks == 0) {
    LOG(WARNING) << "Encountered no basic code blocks during instrumentation.";
    return true;
  }

  if (!add_frequency_data_.ConfigureFrequencyDataBuffer(num_basic_blocks,
                                                        3,
                                                        sizeof(uint32))) {
    LOG(ERROR) << "Failed to configure frequency data buffer.";
    return false;
  }

  // Initialized BasicBlock agent specific fields
  block_graph::TypedBlock<BasicBlockIndexedFrequencyData> frequency_data;
  CHECK(frequency_data.Init(0, add_frequency_data_.frequency_data_block()));
  frequency_data->fs_slot = fs_slot_;
  frequency_data->tls_index = TLS_OUT_OF_INDEXES;

  // Add the module entry thunks.
  EntryThunkTransform add_thunks;
  add_thunks.set_only_instrument_module_entry(true);
  add_thunks.set_instrument_dll_name(instrument_dll_name_);
  add_thunks.set_src_ranges_for_thunks(true);

  Immediate module_data(add_frequency_data_.frequency_data_block(), 0);
  if (!add_thunks.SetEntryThunkParameter(module_data)) {
    LOG(ERROR) << "Failed to configure the entry thunks with the module_data "
               << "parameter.";
    return false;
  }

  if (!ApplyBlockGraphTransform(&add_thunks, block_graph, header_block)) {
    LOG(ERROR) << "Unable to thunk module entry points.";
    return false;
  }

  // Find or create the section we put our thunks in.
  thunk_section_ = block_graph->FindOrAddSection(common::kThunkSectionName,
                                                 pe::kCodeCharacteristics);
  DCHECK(thunk_section_ != NULL);

  return true;
}

}  // namespace transforms
}  // namespace instrument
<|endoftext|>


<commit_before>#include "cdm_gtest.hpp"
#include <silicium/cmake.hpp>
#include <cdm/configure_result.hpp>

namespace CDM_CONFIGURE_NAMESPACE
{
	cdm::configure_result configure(
		Si::absolute_path const &module_temporaries,
		Si::absolute_path const &module_permanent,
		Si::absolute_path const &application_source,
		Si::absolute_path const &application_build_dir,
		unsigned cpu_parallelism,
		Si::Sink<char, Si::success>::interface &output
		)
	{
		boost::ignore_unused_variable_warning(cpu_parallelism);
		Si::optional<Si::absolute_path> const applications = Si::parent(application_source);
		if (!applications)
		{
			throw std::runtime_error("expected the source dir to have a parent");
		}
		Si::optional<Si::absolute_path> const cdm = Si::parent(*applications);
		if (!applications)
		{
			throw std::runtime_error("expected the applications dir to have a parent");
		}
		Si::absolute_path const gtest_source = *cdm / Si::relative_path("original_sources/gtest-1.7.0");
		cdm::gtest_paths const gtest_installed = cdm::install_gtest(gtest_source, module_temporaries, module_permanent, Si::cmake_exe, output);
		std::vector<Si::os_string> arguments;
		arguments.push_back("-DGTEST_INCLUDE_DIRS=" + to_os_string(gtest_installed.include));
		arguments.push_back("-DGTEST_LIBRARIES=" + to_os_string(gtest_installed.library) + SILICIUM_SYSTEM_LITERAL(";") + to_os_string(gtest_installed.library_main));
#ifdef _MSC_VER
		arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-G \"Visual Studio 12 2013\""));
#endif
		arguments.push_back(Si::to_os_string(application_source));
		if (Si::run_process(Si::cmake_exe, arguments, application_build_dir, output).get() != 0)
		{
			throw std::runtime_error("CMake configure failed");
		}
		return cdm::configure_result();
	}
}
<commit_msg>fix for Windows<commit_after>#include "cdm_gtest.hpp"
#include <silicium/cmake.hpp>
#include <cdm/configure_result.hpp>

namespace CDM_CONFIGURE_NAMESPACE
{
	cdm::configure_result configure(
		Si::absolute_path const &module_temporaries,
		Si::absolute_path const &module_permanent,
		Si::absolute_path const &application_source,
		Si::absolute_path const &application_build_dir,
		unsigned cpu_parallelism,
		Si::Sink<char, Si::success>::interface &output
		)
	{
		boost::ignore_unused_variable_warning(cpu_parallelism);
		Si::optional<Si::absolute_path> const applications = Si::parent(application_source);
		if (!applications)
		{
			throw std::runtime_error("expected the source dir to have a parent");
		}
		Si::optional<Si::absolute_path> const cdm = Si::parent(*applications);
		if (!applications)
		{
			throw std::runtime_error("expected the applications dir to have a parent");
		}
		Si::absolute_path const gtest_source = *cdm / Si::relative_path("original_sources/gtest-1.7.0");
		cdm::gtest_paths const gtest_installed = cdm::install_gtest(gtest_source, module_temporaries, module_permanent, Si::cmake_exe, output);
		std::vector<Si::os_string> arguments;
		arguments.push_back(SILICIUM_SYSTEM_LITERAL("-DGTEST_INCLUDE_DIRS=") + to_os_string(gtest_installed.include));
		arguments.push_back(SILICIUM_SYSTEM_LITERAL("-DGTEST_LIBRARIES=") + to_os_string(gtest_installed.library) + SILICIUM_SYSTEM_LITERAL(";") + to_os_string(gtest_installed.library_main));
#ifdef _MSC_VER
		arguments.emplace_back(SILICIUM_SYSTEM_LITERAL("-G \"Visual Studio 12 2013\""));
#endif
		arguments.push_back(Si::to_os_string(application_source));
		if (Si::run_process(Si::cmake_exe, arguments, application_build_dir, output).get() != 0)
		{
			throw std::runtime_error("CMake configure failed");
		}
		return cdm::configure_result();
	}
}
<|endoftext|>


<commit_before>#ifndef MATH_ALGEBRA_NVBLAS_DOUBLE_IMPL_TPP
#define MATH_ALGEBRA_NVBLAS_DOUBLE_IMPL_TPP

#include "../algebra.hpp"
#include "nnlib/core/detail/tensor.tpp"

#ifdef __APPLE__
    #include <Accelerate/Accelerate.h>
#else
    #include <cblas.h>
#endif

#define gemm dgemm
#include "algebra_nvblas_impl.tpp"
#undef gemm

#endif
<commit_msg>GPU bug fix.<commit_after>#ifndef MATH_ALGEBRA_NVBLAS_DOUBLE_IMPL_TPP
#define MATH_ALGEBRA_NVBLAS_DOUBLE_IMPL_TPP

#include "../algebra.hpp"
#include "nnlib/core/detail/tensor.tpp"

#include <nvblas.h>

#define gemm dgemm
#include "algebra_nvblas_impl.tpp"
#undef gemm

#endif
<|endoftext|>