<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban, Justin Madsen, Daniel Melanz
// =============================================================================
//
// Main driver function for the HMMWV full model with solid axle suspension,
// using rigid tire-terrain contact.
//
// If using the Irrlicht interface, river inputs are obtained from the keyboard.
//
// The global reference frame has Z up, X towards the back of the vehicle, and
// Y pointing to the right.
//
// =============================================================================

#include <vector>

#include "core/ChFileutils.h"
#include "core/ChStream.h"
#include "core/ChRealtimeStep.h"
#include "physics/ChSystem.h"
#include "physics/ChLinkDistance.h"

#include "utils/ChUtilsInputOutput.h"

#include "models/hmmwv/HMMWV.h"
#include "models/hmmwv/vehicle/HMMWV_VehicleSolidAxle.h"
#include "models/hmmwv/tire/HMMWV_RigidTire.h"
#include "models/hmmwv/HMMWV_FuncDriver.h"
#include "models/hmmwv/HMMWV_RigidTerrain.h"

// If Irrlicht support is available...
#if IRRLICHT_ENABLED
  // ...include additional headers
# include "unit_IRRLICHT/ChIrrApp.h"
# include "subsys/driver/ChIrrGuiDriver.h"

  // ...and specify whether the demo should actually use Irrlicht
# define USE_IRRLICHT
#endif

// DEBUGGING:  Uncomment the following line to print shock data
//#define DEBUG_LOG

using namespace chrono;
using namespace hmmwv;

// =============================================================================

// Initial vehicle position
ChVector<>     initLoc(0, 0, 1.7);   // sprung mass height at design = 49.68 in
ChQuaternion<> initRot(1,0,0,0);      // forward is in the negative global x-direction

// Rigid terrain dimensions
double terrainHeight = 0;
double terrainLength = 100.0;   // size in X direction
double terrainWidth  = 100.0;   // size in Y directoin

// Simulation step size
double step_size = 0.001;

// Time interval between two render frames
double render_step_size = 1.0 / 50;   // FPS = 50

// Time interval between two output frames
double output_step_size = 1.0 / 1;    // once a second

#ifdef USE_IRRLICHT
  // Point on chassis tracked by the camera
  ChVector<> trackPoint(0.0, 0.0, 1.0);
#else
  double tend = 20.0;

  const std::string out_dir = "../HMMWV";
  const std::string pov_dir = out_dir + "/POVRAY";
#endif

// =============================================================================

int main(int argc, char* argv[])
{
  SetChronoDataPath(CHRONO_DATA_DIR);

  // --------------------------
  // Create the various modules
  // --------------------------

  // Create the HMMWV vehicle
  HMMWV_VehicleSolidAxle vehicle(false,
                        hmmwv::PRIMITIVES,
                        hmmwv::NONE);

  vehicle.Initialize(ChCoordsys<>(initLoc, initRot));

  // Create the ground
  HMMWV_RigidTerrain terrain(vehicle, terrainHeight, terrainLength, terrainWidth, 0.8);
  //terrain.AddMovingObstacles(10);
  terrain.AddFixedObstacles();

  // Create the tires
  HMMWV_RigidTire tire_front_right(terrain, 0.7f);
  HMMWV_RigidTire tire_front_left(terrain, 0.7f);
  HMMWV_RigidTire tire_rear_right(terrain, 0.7f);
  HMMWV_RigidTire tire_rear_left(terrain, 0.7f);

  tire_front_right.Initialize(vehicle.GetWheelBody(FRONT_RIGHT));
  tire_front_left.Initialize(vehicle.GetWheelBody(FRONT_LEFT));
  tire_rear_right.Initialize(vehicle.GetWheelBody(REAR_RIGHT));
  tire_rear_left.Initialize(vehicle.GetWheelBody(REAR_LEFT));

#ifdef USE_IRRLICHT
  irr::ChIrrApp application(&vehicle,
                            L"HMMWV demo",
                            irr::core::dimension2d<irr::u32>(1000, 800),
                            false,
                            true);

  // make a skybox that has Z pointing up (default application.AddTypicalSky() makes Y up)
  std::string mtexturedir = GetChronoDataFile("skybox/");
  std::string str_lf = mtexturedir + "sky_lf.jpg";
  std::string str_up = mtexturedir + "sky_up.jpg";
  std::string str_dn = mtexturedir + "sky_dn.jpg";
  irr::video::ITexture* map_skybox_side =
      application.GetVideoDriver()->getTexture(str_lf.c_str());
  irr::scene::ISceneNode* mbox = application.GetSceneManager()->addSkyBoxSceneNode(
      application.GetVideoDriver()->getTexture(str_up.c_str()),
      application.GetVideoDriver()->getTexture(str_dn.c_str()),
      map_skybox_side,
      map_skybox_side,
      map_skybox_side,
      map_skybox_side);
  mbox->setRotation( irr::core::vector3df(90,0,0));

  bool do_shadows = true; // shadow map is experimental
  irr::scene::ILightSceneNode* mlight = 0;

  if (!do_shadows)
  {
    application.AddTypicalLights(
      irr::core::vector3df(30.f, -30.f, 100.f),
      irr::core::vector3df(30.f, 50.f, 100.f),
      250, 130);
  }
  else
  {
    mlight = application.AddLightWithShadow(
      irr::core::vector3df(10.f, 30.f, 60.f),
      irr::core::vector3df(0.f, 0.f, 0.f),
      150, 60, 80, 15, 512, irr::video::SColorf(1, 1, 1), false, false);
  }

  application.SetTimestep(step_size);

  ChIrrGuiDriver driver(application, vehicle, trackPoint, 6.0, 0.5);

  // Set the time response for steering and throttle keyboard inputs.
  // NOTE: this is not exact, since we do not render quite at the specified FPS.
  double steering_time = 1.0;  // time to go from 0 to +1 (or from 0 to -1)
  double throttle_time = 1.0;  // time to go from 0 to +1
  double braking_time = 0.3;   // time to go from 0 to +1
  driver.SetSteeringDelta(render_step_size / steering_time);
  driver.SetThrottleDelta(render_step_size / throttle_time);
  driver.SetBrakingDelta(render_step_size / braking_time);

  // Set up the assets for rendering
  application.AssetBindAll();
  application.AssetUpdateAll();
  if (do_shadows)
  {
    application.AddShadowAll();
  }
#else
  HMMWV_FuncDriver driver;
#endif

  // ---------------
  // Simulation loop
  // ---------------

#ifdef DEBUG_LOG
  GetLog() << "\n\n============ System Configuration ============\n";
  vehicle.LogHardpointLocations();
#endif

  ChTireForces tire_forces(4);

  // Number of simulation steps between two 3D view render frames
  int render_steps = (int)std::ceil(render_step_size / step_size);

  // Number of simulation steps between two output frames
  int output_steps = (int)std::ceil(output_step_size / step_size);

  // Initialize simulation frame counter and simulation time
  int step_number = 0;
  double time = 0;

#ifdef USE_IRRLICHT

  ChRealtimeStepTimer realtime_timer;

  while (application.GetDevice()->run())
  {
    // update the position of the shadow mapping so that it follows the car
    if (do_shadows)
    {
      ChVector<> lightaim = vehicle.GetChassisPos();
      ChVector<> lightpos = vehicle.GetChassisPos() + ChVector<>(10, 30, 60);
      irr::core::vector3df mlightpos((irr::f32)lightpos.x, (irr::f32)lightpos.y, (irr::f32)lightpos.z);
      irr::core::vector3df mlightaim((irr::f32)lightaim.x, (irr::f32)lightaim.y, (irr::f32)lightaim.z);
      application.GetEffects()->getShadowLight(0).setPosition(mlightpos);
      application.GetEffects()->getShadowLight(0).setTarget(mlightaim);
      mlight->setPosition(mlightpos);
    }

    // Render scene
    if (step_number % render_steps == 0) {
      application.GetVideoDriver()->beginScene(true, true, irr::video::SColor(255, 140, 161, 192));
      driver.DrawAll();
      application.GetVideoDriver()->endScene();
    }

#ifdef DEBUG_LOG
    if (step_number % output_steps == 0) {
      GetLog() << "\n\n============ System Information ============\n";
      GetLog() << "Time = " << time << "\n\n";
      vehicle.DebugLog(DBG_SPRINGS | DBG_SHOCKS | DBG_CONSTRAINTS);
    }
#endif

    // Update modules (inter-module communication)
    time = vehicle.GetChTime();

    driver.Update(time);

    terrain.Update(time);

    tire_front_right.Update(time, vehicle.GetWheelState(FRONT_RIGHT));
    tire_front_left.Update(time, vehicle.GetWheelState(FRONT_LEFT));
    tire_rear_right.Update(time, vehicle.GetWheelState(REAR_RIGHT));
    tire_rear_left.Update(time, vehicle.GetWheelState(REAR_LEFT));

    tire_forces[FRONT_LEFT] = tire_front_left.GetTireForce();
    tire_forces[FRONT_RIGHT] = tire_front_right.GetTireForce();
    tire_forces[REAR_LEFT] = tire_rear_left.GetTireForce();
    tire_forces[REAR_RIGHT] = tire_rear_right.GetTireForce();

    vehicle.Update(time, driver.getThrottle(), driver.getSteering(), driver.getBraking(), tire_forces);

    // Advance simulation for one timestep for all modules
    double step = realtime_timer.SuggestSimulationStep(step_size);

    driver.Advance(step);

    terrain.Advance(step);

    tire_front_right.Advance(step);
    tire_front_left.Advance(step);
    tire_rear_right.Advance(step);
    tire_rear_left.Advance(step);

    vehicle.Advance(step);

    // Increment frame number
    step_number++;
  }

  application.GetDevice()->drop();

#else

  int render_frame = 0;

  if(ChFileutils::MakeDirectory(out_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << out_dir << std::endl;
    return 1;
  }
  if(ChFileutils::MakeDirectory(pov_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << pov_dir << std::endl;
    return 1;
  }

  HMMWV_Vehicle::ExportMeshPovray(out_dir);
  HMMWV_WheelLeft::ExportMeshPovray(out_dir);
  HMMWV_WheelRight::ExportMeshPovray(out_dir);

  char filename[100];

  while (time < tend)
  {
    if (step_number % render_steps == 0) {
      // Output render data
      sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), render_frame + 1);
      utils::WriteShapesPovray(&vehicle, filename);
      std::cout << "Output frame:   " << render_frame << std::endl;
      std::cout << "Sim frame:      " << step_number << std::endl;
      std::cout << "Time:           " << time << std::endl;
      std::cout << "             throttle: " << driver.getThrottle() << " steering: " << driver.getSteering() << std::endl;
      std::cout << std::endl;
      render_frame++;
    }

    // Update modules
    time = vehicle.GetChTime();

    driver.Update(time);

    terrain.Update(time);

    tire_front_right.Update(time, vehicle.GetWheelState(FRONT_RIGHT));
    tire_front_left.Update(time, vehicle.GetWheelState(FRONT_LEFT));
    tire_rear_right.Update(time, vehicle.GetWheelState(REAR_RIGHT));
    tire_rear_left.Update(time, vehicle.GetWheelState(REAR_LEFT));

    tire_forces[FRONT_LEFT] = tire_front_left.GetTireForce();
    tire_forces[FRONT_RIGHT] = tire_front_right.GetTireForce();
    tire_forces[REAR_LEFT] = tire_rear_left.GetTireForce();
    tire_forces[REAR_RIGHT] = tire_rear_right.GetTireForce();

    vehicle.Update(time, driver.getThrottle(), driver.getSteering(), driver.getBraking(), tire_forces);

    // Advance simulation for one timestep for all modules
    driver.Advance(step_size);

    terrain.Advance(step_size);

    tire_front_right.Advance(step_size);
    tire_front_left.Advance(step_size);
    tire_rear_right.Advance(step_size);
    tire_rear_left.Advance(step_size);

    vehicle.Advance(step_size);

    // Increment frame number
    step_number++;
  }

#endif

  return 0;
}
<commit_msg>Update main driver function for the solid axle HMMWV demo.<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban, Justin Madsen, Daniel Melanz
// =============================================================================
//
// Main driver function for the HMMWV full model with solid axle suspension,
// using rigid tire-terrain contact.
//
// If using the Irrlicht interface, river inputs are obtained from the keyboard.
//
// The global reference frame has Z up, X towards the back of the vehicle, and
// Y pointing to the right.
//
// =============================================================================

#include <vector>

#include "core/ChFileutils.h"
#include "core/ChStream.h"
#include "core/ChRealtimeStep.h"
#include "physics/ChSystem.h"
#include "physics/ChLinkDistance.h"

#include "utils/ChUtilsInputOutput.h"

#include "models/hmmwv/HMMWV.h"
#include "models/hmmwv/vehicle/HMMWV_VehicleSolidAxle.h"
#include "models/hmmwv/tire/HMMWV_RigidTire.h"
#include "models/hmmwv/tire/HMMWV_LugreTire.h"
#include "models/hmmwv/HMMWV_FuncDriver.h"
#include "models/hmmwv/HMMWV_RigidTerrain.h"

// If Irrlicht support is available...
#if IRRLICHT_ENABLED
  // ...include additional headers
# include "unit_IRRLICHT/ChIrrApp.h"
# include "subsys/driver/ChIrrGuiDriver.h"

  // ...and specify whether the demo should actually use Irrlicht
# define USE_IRRLICHT
#endif

// DEBUGGING:  Uncomment the following line to print shock data
//#define DEBUG_LOG

using namespace chrono;
using namespace hmmwv;

// =============================================================================

// Initial vehicle position
ChVector<>     initLoc(0, 0, 1.7);   // sprung mass height at design = 49.68 in
ChQuaternion<> initRot(1,0,0,0);      // forward is in the negative global x-direction

// Type of tire model (RIGID, PACEJKA, or LUGRE)
TireModelType tire_model = RIGID;

// Rigid terrain dimensions
double terrainHeight = 0;
double terrainLength = 100.0;   // size in X direction
double terrainWidth  = 100.0;   // size in Y directoin

// Simulation step size
double step_size = 0.001;

// Time interval between two render frames
double render_step_size = 1.0 / 50;   // FPS = 50

// Time interval between two output frames
double output_step_size = 1.0 / 1;    // once a second

#ifdef USE_IRRLICHT
  // Point on chassis tracked by the camera
  ChVector<> trackPoint(0.0, 0.0, 1.0);
#else
  double tend = 20.0;

  const std::string out_dir = "../HMMWV_SOLIDAXLE";
  const std::string pov_dir = out_dir + "/POVRAY";
#endif

// =============================================================================

int main(int argc, char* argv[])
{
  SetChronoDataPath(CHRONO_DATA_DIR);

  // --------------------------
  // Create the various modules
  // --------------------------

  // Create the HMMWV vehicle
  HMMWV_VehicleSolidAxle vehicle(false,
                        hmmwv::PRIMITIVES,
                        hmmwv::NONE);

  vehicle.Initialize(ChCoordsys<>(initLoc, initRot));

  // Create the ground
  HMMWV_RigidTerrain terrain(vehicle, terrainHeight, terrainLength, terrainWidth, 0.8);
  //terrain.AddMovingObstacles(10);
  terrain.AddFixedObstacles();

  // Create the tires
  ChSharedPtr<ChTire> tire_front_right;
  ChSharedPtr<ChTire> tire_front_left;
  ChSharedPtr<ChTire> tire_rear_right;
  ChSharedPtr<ChTire> tire_rear_left;

  switch (tire_model) {
  case RIGID:
  {
    ChSharedPtr<HMMWV_RigidTire> tire_FR = ChSharedPtr<HMMWV_RigidTire>(new HMMWV_RigidTire(terrain, 0.7f));
    ChSharedPtr<HMMWV_RigidTire> tire_FL = ChSharedPtr<HMMWV_RigidTire>(new HMMWV_RigidTire(terrain, 0.7f));
    ChSharedPtr<HMMWV_RigidTire> tire_RR = ChSharedPtr<HMMWV_RigidTire>(new HMMWV_RigidTire(terrain, 0.7f));
    ChSharedPtr<HMMWV_RigidTire> tire_RL = ChSharedPtr<HMMWV_RigidTire>(new HMMWV_RigidTire(terrain, 0.7f));

    tire_FR->Initialize(vehicle.GetWheelBody(FRONT_RIGHT));
    tire_FL->Initialize(vehicle.GetWheelBody(FRONT_LEFT));
    tire_RR->Initialize(vehicle.GetWheelBody(REAR_RIGHT));
    tire_RL->Initialize(vehicle.GetWheelBody(REAR_LEFT));

    tire_front_right = tire_FR;
    tire_front_left = tire_FL;
    tire_rear_right = tire_RR;
    tire_rear_left = tire_RL;

    break;
  }
  case LUGRE:
  {
    ChSharedPtr<HMMWV_LugreTire> tire_FR = ChSharedPtr<HMMWV_LugreTire>(new HMMWV_LugreTire(terrain));
    ChSharedPtr<HMMWV_LugreTire> tire_FL = ChSharedPtr<HMMWV_LugreTire>(new HMMWV_LugreTire(terrain));
    ChSharedPtr<HMMWV_LugreTire> tire_RR = ChSharedPtr<HMMWV_LugreTire>(new HMMWV_LugreTire(terrain));
    ChSharedPtr<HMMWV_LugreTire> tire_RL = ChSharedPtr<HMMWV_LugreTire>(new HMMWV_LugreTire(terrain));

    tire_FR->Initialize();
    tire_FL->Initialize();
    tire_RR->Initialize();
    tire_RL->Initialize();

    tire_front_right = tire_FR;
    tire_front_left = tire_FL;
    tire_rear_right = tire_RR;
    tire_rear_left = tire_RL;

    break;
  }
  }

#ifdef USE_IRRLICHT
  irr::ChIrrApp application(&vehicle,
                            L"HMMWV Solid-Axle demo",
                            irr::core::dimension2d<irr::u32>(1000, 800),
                            false,
                            true);

  // make a skybox that has Z pointing up (default application.AddTypicalSky() makes Y up)
  std::string mtexturedir = GetChronoDataFile("skybox/");
  std::string str_lf = mtexturedir + "sky_lf.jpg";
  std::string str_up = mtexturedir + "sky_up.jpg";
  std::string str_dn = mtexturedir + "sky_dn.jpg";
  irr::video::ITexture* map_skybox_side =
      application.GetVideoDriver()->getTexture(str_lf.c_str());
  irr::scene::ISceneNode* mbox = application.GetSceneManager()->addSkyBoxSceneNode(
      application.GetVideoDriver()->getTexture(str_up.c_str()),
      application.GetVideoDriver()->getTexture(str_dn.c_str()),
      map_skybox_side,
      map_skybox_side,
      map_skybox_side,
      map_skybox_side);
  mbox->setRotation( irr::core::vector3df(90,0,0));

  bool do_shadows = true; // shadow map is experimental
  irr::scene::ILightSceneNode* mlight = 0;

  if (!do_shadows)
  {
    application.AddTypicalLights(
      irr::core::vector3df(30.f, -30.f, 100.f),
      irr::core::vector3df(30.f, 50.f, 100.f),
      250, 130);
  }
  else
  {
    mlight = application.AddLightWithShadow(
      irr::core::vector3df(10.f, 30.f, 60.f),
      irr::core::vector3df(0.f, 0.f, 0.f),
      150, 60, 80, 15, 512, irr::video::SColorf(1, 1, 1), false, false);
  }

  application.SetTimestep(step_size);

  ChIrrGuiDriver driver(application, vehicle, trackPoint, 6.0, 0.5, true);

  // Set the time response for steering and throttle keyboard inputs.
  // NOTE: this is not exact, since we do not render quite at the specified FPS.
  double steering_time = 1.0;  // time to go from 0 to +1 (or from 0 to -1)
  double throttle_time = 1.0;  // time to go from 0 to +1
  double braking_time = 0.3;   // time to go from 0 to +1
  driver.SetSteeringDelta(render_step_size / steering_time);
  driver.SetThrottleDelta(render_step_size / throttle_time);
  driver.SetBrakingDelta(render_step_size / braking_time);

  // Set up the assets for rendering
  application.AssetBindAll();
  application.AssetUpdateAll();
  if (do_shadows)
  {
    application.AddShadowAll();
  }
#else
  HMMWV_FuncDriver driver;
#endif

  // ---------------
  // Simulation loop
  // ---------------

#ifdef DEBUG_LOG
  GetLog() << "\n\n============ System Configuration ============\n";
  vehicle.LogHardpointLocations();
#endif

  // Inter-module communication data
  ChTireForces tire_forces(4);
  ChBodyState  wheel_states[4];
  double       throttle_input;
  double       steering_input;
  double       braking_input;

  // Number of simulation steps between two 3D view render frames
  int render_steps = (int)std::ceil(render_step_size / step_size);

  // Number of simulation steps between two output frames
  int output_steps = (int)std::ceil(output_step_size / step_size);

  // Initialize simulation frame counter and simulation time
  int step_number = 0;
  double time = 0;

#ifdef USE_IRRLICHT

  ChRealtimeStepTimer realtime_timer;

  while (application.GetDevice()->run())
  {
    // update the position of the shadow mapping so that it follows the car
    if (do_shadows)
    {
      ChVector<> lightaim = vehicle.GetChassisPos();
      ChVector<> lightpos = vehicle.GetChassisPos() + ChVector<>(10, 30, 60);
      irr::core::vector3df mlightpos((irr::f32)lightpos.x, (irr::f32)lightpos.y, (irr::f32)lightpos.z);
      irr::core::vector3df mlightaim((irr::f32)lightaim.x, (irr::f32)lightaim.y, (irr::f32)lightaim.z);
      application.GetEffects()->getShadowLight(0).setPosition(mlightpos);
      application.GetEffects()->getShadowLight(0).setTarget(mlightaim);
      mlight->setPosition(mlightpos);
    }

    // Render scene
    if (step_number % render_steps == 0) {
      application.GetVideoDriver()->beginScene(true, true, irr::video::SColor(255, 140, 161, 192));
      driver.DrawAll();
      application.GetVideoDriver()->endScene();
    }

#ifdef DEBUG_LOG
    if (step_number % output_steps == 0) {
      GetLog() << "\n\n============ System Information ============\n";
      GetLog() << "Time = " << time << "\n\n";
      vehicle.DebugLog(DBG_SPRINGS | DBG_SHOCKS | DBG_CONSTRAINTS);
    }
#endif

    // Collect output data from modules (for inter-module communication)
    throttle_input = driver.getThrottle();
    steering_input = driver.getSteering();
    braking_input = driver.getBraking();

    tire_forces[FRONT_LEFT] = tire_front_left->GetTireForce();
    tire_forces[FRONT_RIGHT] = tire_front_right->GetTireForce();
    tire_forces[REAR_LEFT] = tire_rear_left->GetTireForce();
    tire_forces[REAR_RIGHT] = tire_rear_right->GetTireForce();

    wheel_states[FRONT_LEFT] = vehicle.GetWheelState(FRONT_RIGHT);
    wheel_states[FRONT_RIGHT] = vehicle.GetWheelState(FRONT_LEFT);
    wheel_states[REAR_LEFT] = vehicle.GetWheelState(REAR_RIGHT);
    wheel_states[REAR_RIGHT] = vehicle.GetWheelState(REAR_LEFT);

    // Update modules (process inputs from other modules)
    time = vehicle.GetChTime();

    driver.Update(time);

    terrain.Update(time);

    tire_front_right->Update(time, wheel_states[FRONT_LEFT]);
    tire_front_left->Update(time, wheel_states[FRONT_RIGHT]);
    tire_rear_right->Update(time, wheel_states[REAR_LEFT]);
    tire_rear_left->Update(time, wheel_states[REAR_RIGHT]);

    vehicle.Update(time, throttle_input, steering_input, braking_input, tire_forces);

    // Advance simulation for one timestep for all modules
    double step = realtime_timer.SuggestSimulationStep(step_size);

    driver.Advance(step);

    terrain.Advance(step);

    tire_front_right->Advance(step);
    tire_front_left->Advance(step);
    tire_rear_right->Advance(step);
    tire_rear_left->Advance(step);

    vehicle.Advance(step);

    // Increment frame number
    step_number++;
  }

  application.GetDevice()->drop();

#else

  int render_frame = 0;

  if(ChFileutils::MakeDirectory(out_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << out_dir << std::endl;
    return 1;
  }
  if(ChFileutils::MakeDirectory(pov_dir.c_str()) < 0) {
    std::cout << "Error creating directory " << pov_dir << std::endl;
    return 1;
  }

  HMMWV_VehicleSolidAxle::ExportMeshPovray(out_dir);
  HMMWV_WheelLeft::ExportMeshPovray(out_dir);
  HMMWV_WheelRight::ExportMeshPovray(out_dir);

  char filename[100];

  while (time < tend)
  {
    if (step_number % render_steps == 0) {
      // Output render data
      sprintf(filename, "%s/data_%03d.dat", pov_dir.c_str(), render_frame + 1);
      utils::WriteShapesPovray(&vehicle, filename);
      std::cout << "Output frame:   " << render_frame << std::endl;
      std::cout << "Sim frame:      " << step_number << std::endl;
      std::cout << "Time:           " << time << std::endl;
      std::cout << "             throttle: " << driver.getThrottle() << " steering: " << driver.getSteering() << std::endl;
      std::cout << std::endl;
      render_frame++;
    }

    // Collect output data from modules (for inter-module communication)
    throttle_input = driver.getThrottle();
    steering_input = driver.getSteering();
    braking_input = driver.getBraking();

    tire_forces[FRONT_LEFT] = tire_front_left->GetTireForce();
    tire_forces[FRONT_RIGHT] = tire_front_right->GetTireForce();
    tire_forces[REAR_LEFT] = tire_rear_left->GetTireForce();
    tire_forces[REAR_RIGHT] = tire_rear_right->GetTireForce();

    wheel_states[FRONT_LEFT] = vehicle.GetWheelState(FRONT_RIGHT);
    wheel_states[FRONT_RIGHT] = vehicle.GetWheelState(FRONT_LEFT);
    wheel_states[REAR_LEFT] = vehicle.GetWheelState(REAR_RIGHT);
    wheel_states[REAR_RIGHT] = vehicle.GetWheelState(REAR_LEFT);

    // Update modules (process inputs from other modules)
    time = vehicle.GetChTime();

    driver.Update(time);

    terrain.Update(time);

    tire_front_right->Update(time, wheel_states[FRONT_LEFT]);
    tire_front_left->Update(time, wheel_states[FRONT_RIGHT]);
    tire_rear_right->Update(time, wheel_states[REAR_LEFT]);
    tire_rear_left->Update(time, wheel_states[REAR_RIGHT]);

    vehicle.Update(time, throttle_input, steering_input, braking_input, tire_forces);

    // Advance simulation for one timestep for all modules
    driver.Advance(step_size);

    terrain.Advance(step_size);

    tire_front_right->Advance(step_size);
    tire_front_left->Advance(step_size);
    tire_rear_right->Advance(step_size);
    tire_rear_left->Advance(step_size);

    vehicle.Advance(step_size);

    // Increment frame number
    step_number++;
  }

#endif

  return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include "base/macros.hpp"
#include OPTIONAL_HEADER

#include <deque>
#include <map>
#include <memory>

#include "base/not_null.hpp"
#include "geometry/named_quantities.hpp"
#include "serialization/physics.pb.h"

namespace principia {

using geometry::Instant;

namespace physics {

// This traits class must export declarations similar to the following:
//
// using TimelineConstIterator = ...;
// static Instant const& time(TimelineConstIterator const it);
//
// TimelineConstIterator must be an STL-like iterator in the timeline of
// Tr4jectory.  |time()| must return the corresponding time.
template<typename Tr4jectory>
struct ForkableTraits;

// This template represents a trajectory which is forkable and iterable.  It
// uses CRTP to achieve static polymorphism on the return type of the member
// functions: we want them to return Tr4jectory, not Forkable, so that the
// clients don't have to down_cast.
template<typename Tr4jectory>
class Forkable {
 public:
  // An iterator into the timeline of the trajectory.  Must be STL-like.
  // Beware, if these iterators are invalidated all the guarantees of Forkable
  // are void.
  using TimelineConstIterator =
      typename ForkableTraits<Tr4jectory>::TimelineConstIterator;

  Forkable() = default;
  virtual ~Forkable() = default;

  // Deletes the child trajectory denoted by |*trajectory|, which must be a
  // pointer previously returned by NewFork for this object.  Nulls
  // |*trajectory|.
  void DeleteFork(not_null<Tr4jectory**> const trajectory);

  // Returns true if this is a root trajectory.
  bool is_root() const;

  // Returns the root trajectory.
  not_null<Tr4jectory const*> root() const;
  not_null<Tr4jectory*> root();

  // Returns the fork time for a nonroot trajectory and null for a root
  // trajectory.
  std::experimental::optional<Instant> ForkTime() const;

  // A base class for iterating over the timeline of a trajectory, taking forks
  // into account.
  class Iterator {
   public:
    bool operator==(Iterator const& right) const;
    bool operator!=(Iterator const& right) const;

    Iterator& operator++();
    Iterator& operator--();

    // Returns the point in the timeline that is denoted by this iterator.
    TimelineConstIterator current() const;

    // Returns the (most forked) trajectory to which this iterator applies.
    not_null<Tr4jectory const*> trajectory() const;

   private:
    Iterator() = default;

    // We want a single representation for an end iterator.  In various places
    // we may end up with |current_| at the end of its timeline, but that
    // timeline is not the "most forked" one.  This function normalizes this
    // object so that there is only one entry in the |ancestry_| (the "most
    // forked" one) and |current_| is at its end.
    void NormalizeIfEnd();

    // Checks that this object verifies the invariants enforced by
    // NormalizeIfEnd and dies if it doesn't.
    void CheckNormalizedIfEnd();

    // |ancestry_| is never empty.  |current_| is an iterator in the timeline
    // for |ancestry_.front()|.  |current_| may be at end.
    TimelineConstIterator current_;
    std::deque<not_null<Tr4jectory const*>> ancestry_;  // Pointers not owned.

    template<typename Tr4jectory>
    friend class Forkable;
  };

  Iterator Begin() const;
  Iterator End() const;

  Iterator Find(Instant const& time) const;
  Iterator LowerBound(Instant const& time) const;

  // Constructs an Iterator by wrapping the timeline iterator
  // |position_in_ancestor_timeline| which must be an iterator in the timeline
  // of |ancestor|.  |ancestor| must be an ancestor of this trajectory
  // (it may be this object).  |position_in_ancestor_timeline| may only be at
  // end if it is an iterator in this object (and ancestor is this object).
  // TODO(phl): This is only used for |Begin|.  Unclear if it needs to be a
  // separate method.
  Iterator Wrap(
      not_null<const Tr4jectory*> const ancestor,
      TimelineConstIterator const position_in_ancestor_timeline) const;

  void WritePointerToMessage(
      not_null<serialization::Trajectory::Pointer*> const message) const;

  // |trajectory| must be a root.
  static not_null<Tr4jectory*> ReadPointerFromMessage(
      serialization::Trajectory::Pointer const& message,
      not_null<Tr4jectory*> const trajectory);

 protected:
  // The API that must be implemented by subclasses.
  // TODO(phl): Try to reduce this API.  Forkable should probably not modify the
  // timeline.

  // Must return |this| of the proper type
  virtual not_null<Tr4jectory*> that() = 0;
  virtual not_null<Tr4jectory const*> that() const = 0;

  // STL-like operations.
  virtual TimelineConstIterator timeline_begin() const = 0;
  virtual TimelineConstIterator timeline_end() const = 0;
  virtual TimelineConstIterator timeline_find(Instant const& time) const = 0;
  virtual TimelineConstIterator timeline_lower_bound(
                                    Instant const& time) const = 0;
  virtual bool timeline_empty() const = 0;

 protected:
  // The API that subclasses may use to implement their public operations.

  // Creates a new child trajectory forked at time |time|, and returns it.  The
  // child trajectory shares its data with the current trajectory for times less
  // than or equal to |time|.  It may be changed independently from the parent
  // trajectory for any time (strictly) greater than |time|.  The child
  // trajectory is owned by its parent trajectory.  Deleting the parent
  // trajectory deletes all child trajectories.  |time| must be one of the times
  // of this trajectory, and must be at or after the fork time, if any.
  not_null<Tr4jectory*> NewFork(Instant const& time);

  // Deletes all forks for times (strictly) greater than |time|.  |time| must be
  // at or after the fork time of this trajectory, if any.
  void DeleteAllForksAfter(Instant const& time);

  // Deletes all forks for times less than or equal to |time|.  This trajectory
  // must be a root.
  void DeleteAllForksBefore(Instant const& time);

  // This trajectory need not be a root.
  void WriteSubTreeToMessage(
      not_null<serialization::Trajectory*> const message) const;

  void FillSubTreeFromMessage(serialization::Trajectory const& message);

 private:
  // There may be several forks starting from the same time, hence the multimap.
  using Children = std::multimap<Instant, Tr4jectory>;

  // Null for a root.
  Tr4jectory* parent_ = nullptr;

  // This iterator is never at |end()|.
  std::experimental::optional<typename Children::const_iterator>
      position_in_parent_children_;

  // This iterator is at |end()| if the fork time is not in the parent timeline,
  // i.e. is the parent timeline's own fork time.
  std::experimental::optional<TimelineConstIterator>
      position_in_parent_timeline_;

  Children children_;
};

}  // namespace physics
}  // namespace principia

#include "physics/forkable_body.hpp"
<commit_msg>Rename shadowed typename.<commit_after>#pragma once

#include "base/macros.hpp"
#include OPTIONAL_HEADER

#include <deque>
#include <map>
#include <memory>

#include "base/not_null.hpp"
#include "geometry/named_quantities.hpp"
#include "serialization/physics.pb.h"

namespace principia {

using geometry::Instant;

namespace physics {

// This traits class must export declarations similar to the following:
//
// using TimelineConstIterator = ...;
// static Instant const& time(TimelineConstIterator const it);
//
// TimelineConstIterator must be an STL-like iterator in the timeline of
// Tr4jectory.  |time()| must return the corresponding time.
template<typename Tr4jectory>
struct ForkableTraits;

// This template represents a trajectory which is forkable and iterable.  It
// uses CRTP to achieve static polymorphism on the return type of the member
// functions: we want them to return Tr4jectory, not Forkable, so that the
// clients don't have to down_cast.
template<typename Tr4jectory>
class Forkable {
 public:
  // An iterator into the timeline of the trajectory.  Must be STL-like.
  // Beware, if these iterators are invalidated all the guarantees of Forkable
  // are void.
  using TimelineConstIterator =
      typename ForkableTraits<Tr4jectory>::TimelineConstIterator;

  Forkable() = default;
  virtual ~Forkable() = default;

  // Deletes the child trajectory denoted by |*trajectory|, which must be a
  // pointer previously returned by NewFork for this object.  Nulls
  // |*trajectory|.
  void DeleteFork(not_null<Tr4jectory**> const trajectory);

  // Returns true if this is a root trajectory.
  bool is_root() const;

  // Returns the root trajectory.
  not_null<Tr4jectory const*> root() const;
  not_null<Tr4jectory*> root();

  // Returns the fork time for a nonroot trajectory and null for a root
  // trajectory.
  std::experimental::optional<Instant> ForkTime() const;

  // A base class for iterating over the timeline of a trajectory, taking forks
  // into account.
  class Iterator {
   public:
    bool operator==(Iterator const& right) const;
    bool operator!=(Iterator const& right) const;

    Iterator& operator++();
    Iterator& operator--();

    // Returns the point in the timeline that is denoted by this iterator.
    TimelineConstIterator current() const;

    // Returns the (most forked) trajectory to which this iterator applies.
    not_null<Tr4jectory const*> trajectory() const;

   private:
    Iterator() = default;

    // We want a single representation for an end iterator.  In various places
    // we may end up with |current_| at the end of its timeline, but that
    // timeline is not the "most forked" one.  This function normalizes this
    // object so that there is only one entry in the |ancestry_| (the "most
    // forked" one) and |current_| is at its end.
    void NormalizeIfEnd();

    // Checks that this object verifies the invariants enforced by
    // NormalizeIfEnd and dies if it doesn't.
    void CheckNormalizedIfEnd();

    // |ancestry_| is never empty.  |current_| is an iterator in the timeline
    // for |ancestry_.front()|.  |current_| may be at end.
    TimelineConstIterator current_;
    std::deque<not_null<Tr4jectory const*>> ancestry_;  // Pointers not owned.

    template<typename Trajectory>
    friend class Forkable;
  };

  Iterator Begin() const;
  Iterator End() const;

  Iterator Find(Instant const& time) const;
  Iterator LowerBound(Instant const& time) const;

  // Constructs an Iterator by wrapping the timeline iterator
  // |position_in_ancestor_timeline| which must be an iterator in the timeline
  // of |ancestor|.  |ancestor| must be an ancestor of this trajectory
  // (it may be this object).  |position_in_ancestor_timeline| may only be at
  // end if it is an iterator in this object (and ancestor is this object).
  // TODO(phl): This is only used for |Begin|.  Unclear if it needs to be a
  // separate method.
  Iterator Wrap(
      not_null<const Tr4jectory*> const ancestor,
      TimelineConstIterator const position_in_ancestor_timeline) const;

  void WritePointerToMessage(
      not_null<serialization::Trajectory::Pointer*> const message) const;

  // |trajectory| must be a root.
  static not_null<Tr4jectory*> ReadPointerFromMessage(
      serialization::Trajectory::Pointer const& message,
      not_null<Tr4jectory*> const trajectory);

 protected:
  // The API that must be implemented by subclasses.
  // TODO(phl): Try to reduce this API.  Forkable should probably not modify the
  // timeline.

  // Must return |this| of the proper type
  virtual not_null<Tr4jectory*> that() = 0;
  virtual not_null<Tr4jectory const*> that() const = 0;

  // STL-like operations.
  virtual TimelineConstIterator timeline_begin() const = 0;
  virtual TimelineConstIterator timeline_end() const = 0;
  virtual TimelineConstIterator timeline_find(Instant const& time) const = 0;
  virtual TimelineConstIterator timeline_lower_bound(
                                    Instant const& time) const = 0;
  virtual bool timeline_empty() const = 0;

 protected:
  // The API that subclasses may use to implement their public operations.

  // Creates a new child trajectory forked at time |time|, and returns it.  The
  // child trajectory shares its data with the current trajectory for times less
  // than or equal to |time|.  It may be changed independently from the parent
  // trajectory for any time (strictly) greater than |time|.  The child
  // trajectory is owned by its parent trajectory.  Deleting the parent
  // trajectory deletes all child trajectories.  |time| must be one of the times
  // of this trajectory, and must be at or after the fork time, if any.
  not_null<Tr4jectory*> NewFork(Instant const& time);

  // Deletes all forks for times (strictly) greater than |time|.  |time| must be
  // at or after the fork time of this trajectory, if any.
  void DeleteAllForksAfter(Instant const& time);

  // Deletes all forks for times less than or equal to |time|.  This trajectory
  // must be a root.
  void DeleteAllForksBefore(Instant const& time);

  // This trajectory need not be a root.
  void WriteSubTreeToMessage(
      not_null<serialization::Trajectory*> const message) const;

  void FillSubTreeFromMessage(serialization::Trajectory const& message);

 private:
  // There may be several forks starting from the same time, hence the multimap.
  using Children = std::multimap<Instant, Tr4jectory>;

  // Null for a root.
  Tr4jectory* parent_ = nullptr;

  // This iterator is never at |end()|.
  std::experimental::optional<typename Children::const_iterator>
      position_in_parent_children_;

  // This iterator is at |end()| if the fork time is not in the parent timeline,
  // i.e. is the parent timeline's own fork time.
  std::experimental::optional<TimelineConstIterator>
      position_in_parent_timeline_;

  Children children_;
};

}  // namespace physics
}  // namespace principia

#include "physics/forkable_body.hpp"
<|endoftext|>


<commit_before>/***************************************************************************
 * pythonscript.cpp
 * This file is part of the KDE project
 * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.org)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * 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
 * Library General Public License for more details.
 * You should have received a copy of the GNU Library General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************************/

#include "pythonscript.h"
#include "pythonmodule.h"
#include "pythoninterpreter.h"
//#include "../api/object.h"
//#include "../api/list.h"
//#include "../main/manager.h"
#include "../main/scriptcontainer.h"
//#include "../api/qtobject.h"
//#include "../api/interpreter.h"

#include <kdebug.h>

using namespace Kross::Python;

namespace Kross { namespace Python {

    //! @internal
    class PythonScriptPrivate
    {
        public:
            Py::Module* m_module;
            Py::Object* m_code;

            QStringList m_functions;
            QStringList m_classes;
            //QMap<QString, Kross::Api::Object::Ptr> m_functions;
            //QMap<QString, Kross::Api::Object::Ptr> m_classes;
            //QValueList<Kross::Api::Object::Ptr> m_classinstances;
    };

}}

PythonScript::PythonScript(Kross::Api::Interpreter* interpreter, Kross::Api::ScriptContainer* scriptcontainer)
    : Kross::Api::Script(interpreter, scriptcontainer)
    , d(new PythonScriptPrivate())
{
#ifdef KROSS_PYTHON_SCRIPT_DEBUG
    kdDebug() << "PythonScript::PythonScript() Constructor." << endl;
#endif
    d->m_module = 0;
    d->m_code = 0;
}

PythonScript::~PythonScript()
{
#ifdef KROSS_PYTHON_SCRIPT_DEBUG
    kdDebug() << "PythonScript::~PythonScript() Destructor." << endl;
#endif
    finalize();
    delete d;
}

void PythonScript::initialize()
{
    finalize();

    try {
        PyObject* pymod = PyModule_New((char*)m_scriptcontainer->getName().latin1());
        d->m_module = new Py::Module(pymod, true);

#ifdef KROSS_PYTHON_SCRIPT_DEBUG
        if(d->m_module)
            kdDebug() << QString("PythonScript::initialize() module='%1' refcount='%2'").arg(d->m_module->as_string().c_str()).arg(d->m_module->reference_count()) << endl;
#endif

        // Compile the python script code. It will be later on request
        // executed. That way we cache the compiled code.
        PyObject* code = 0;
        bool restricted = ((PythonInterpreter*)m_interpreter)->getOption("restricted", QVariant((bool)true)).toBool();
        if(restricted) {
            // Use the RestrictedPython module wrapped by the PythonSecurity class.
/*TODO
            code = m_interpreter->m_security->compile_restricted(
                m_scriptcontainer->getCode(),
                m_scriptcontainer->getName(),
                "exec"
            );
*/
        }
        else {
            // Just compile the code without any restrictions.
            code = Py_CompileString(
                (char*)m_scriptcontainer->getCode().latin1(),
                (char*)m_scriptcontainer->getName().latin1(),
                Py_file_input
            );
        }

        if(! code)
            throw Py::Exception();
        d->m_code = new Py::Object(code, true);
    }
    catch(Py::Exception& e) {
        Py::Object errobj = Py::value(Py::Exception());
        throw Kross::Api::RuntimeException(i18n("Failed to compile python code: %1").arg(errobj.as_string().c_str()));
    }
}

void PythonScript::finalize()
{
#ifdef KROSS_PYTHON_SCRIPT_DEBUG
    if(d->m_module)
        kdDebug() << QString("PythonScript::finalize() module='%1' refcount='%2'").arg(d->m_module->as_string().c_str()).arg(d->m_module->reference_count()) << endl;
#endif

    delete d->m_module; d->m_module = 0;
    delete d->m_code; d->m_code = 0;
    d->m_functions.clear();
    d->m_classes.clear();
}

const QStringList& PythonScript::getFunctionNames()
{
    if(! d->m_module) initialize();
    return d->m_functions;
    /*
    QStringList list;
    Py::List l = d->m_module->getDict().keys();
    int length = l.length();
    for(Py::List::size_type i = 0; i < length; ++i)
        list.append( l[i].str().as_string().c_str() );
    return list;
    */
}

Kross::Api::Object::Ptr PythonScript::execute()
{
    if(! d->m_module)
        initialize();

#ifdef KROSS_PYTHON_SCRIPT_DEBUG
    kdDebug() << QString("PythonScript::execute()") << endl;
#endif

    try {
        Py::Dict mainmoduledict = ((PythonInterpreter*)m_interpreter)->m_module->getDict();
        PyObject* pyresult = PyEval_EvalCode(
            (PyCodeObject*)d->m_code->ptr(),
            mainmoduledict.ptr(),
            d->m_module->getDict().ptr()
        );
        if(! pyresult)
            throw Py::Exception();
        Py::Object result(pyresult, true);
        kdDebug()<<"PythonScript::execute() result="<<result.as_string().c_str()<<endl;

        Py::Dict moduledict( d->m_module->getDict().ptr() );
        for(Py::Dict::iterator it = moduledict.begin(); it != moduledict.end(); ++it) {
            Py::Dict::value_type vt(*it);
            if(PyClass_Check( vt.second.ptr() )) {
                kdDebug() << QString("PythonScript::execute() class '%1' added.").arg(vt.first.as_string().c_str()) << endl;
                d->m_classes.append( vt.first.as_string().c_str() );
            }
            else if(vt.second.isCallable()) {
                kdDebug() << QString("PythonScript::execute() function '%1' added.").arg(vt.first.as_string().c_str()) << endl;
                d->m_functions.append( vt.first.as_string().c_str() );
            }
        }

        Kross::Api::Object::Ptr r = PythonExtension::toObject(result);
        return r;
    }
    catch(Py::Exception& e) {
        throw Kross::Api::RuntimeException(i18n("Failed to execute python code: %1").arg(Py::value(e).as_string().c_str()));
    }

/*
    if(! d->m_module) initialize();
    try {
        Py::Dict mainmoduledict = ((PythonInterpreter*)m_interpreter)->m_module->getDict();
        PyObject* pyrun = PyRun_String(
            (char*)m_scriptcontainer->getCode().latin1(),
            Py_file_input,
            mainmoduledict.ptr(),
            d->m_module->getDict().ptr()
        );
        if(! pyrun) {
            Py::Object errobj = Py::value(Py::Exception()); // get last error
            throw Kross::Api::RuntimeException(i18n("Python Exception: %1").arg(errobj.as_string().c_str()));
        }
        Py::Object run(pyrun, true); // the run-object takes care of freeing our pyrun pyobject.
        //kdDebug() << QString("PythonScript::execute --------------------------- 1") << endl;
        Py::Dict moduledict( d->m_module->getDict().ptr() );
        for(Py::Dict::iterator it = moduledict.begin(); it != moduledict.end(); ++it) {
            Py::Dict::value_type vt(*it);
            if(PyClass_Check( vt.second.ptr() )) {
                kdDebug() << QString("PythonScript::execute() class '%1' added.").arg(vt.first.as_string().c_str()) << endl;
                d->m_classes.append( vt.first.as_string().c_str() );
            }
            else if(vt.second.isCallable()) {
                kdDebug() << QString("PythonScript::execute() function '%1' added.").arg(vt.first.as_string().c_str()) << endl;
                d->m_functions.append( vt.first.as_string().c_str() );
            }
*/
            /*
            QString s;
            if(vt.second.isCallable()) s += "isCallable ";
            if(vt.second.isDict()) s += "isDict ";
            if(vt.second.isList()) s += "isList ";
            if(vt.second.isMapping()) s += "isMapping ";
            if(vt.second.isNumeric()) s += "isNumeric ";
            if(vt.second.isSequence()) s += "isSequence ";
            if(vt.second.isTrue()) s += "isTrue ";
            if(vt.second.isInstance()) s += "isInstance ";
            if(PyClass_Check( vt.second.ptr() )) s += "vt.second.isClass ";
            Py::String rf = vt.first.repr();
            Py::String rs = vt.second.repr();
            kdDebug() << QString("PythonScript::execute d->m_module->getDict() rs='%1' vt.first='%2' rf='%3' test='%4' s='%5'")
                        .arg(rs.as_string().c_str())
                        .arg(vt.first.as_string().c_str())
                        .arg(rf.as_string().c_str())
                        .arg("")
                        .arg(s) << endl;
            //m_objects.replace(vt.first.repr().as_string().c_str(), vt.second);
            if(PyClass_Check( vt.second.ptr() )) {
                //PyObject *aclarg = Py_BuildValue("(s)", rs.as_string().c_str());
                PyObject *pyinst = PyInstance_New(vt.second.ptr(), 0, 0);//aclarg, 0);
                //Py_DECREF(aclarg);
                if (pyinst == 0)
                    kdDebug() << QString("PythonScript::execute PyInstance_New() returned NULL !!!") << endl;
                else {
                    Py::Object inst(pyinst, true);
                    kdDebug() << QString("====> PythonScript::execute inst='%1'").arg(inst.as_string().c_str()) << endl;
                }
            }
            */
/*
        }
        //kdDebug() << QString("PythonScript::execute --------------------------- 2") << endl;
        //kdDebug() << QString("PythonScript::execute() PyRun_String='%1'").arg(run.str().as_string().c_str()) << endl;
        return PythonExtension::toObject(run);
    }
    catch(Py::Exception& e) {
        Py::Object errobj = Py::value(e);
        throw Kross::Api::RuntimeException(i18n("Python Exception: %1").arg(errobj.as_string().c_str()));
    }
*/
}

Kross::Api::Object::Ptr PythonScript::callFunction(const QString& name, Kross::Api::List::Ptr args)
{
    if(! d->m_module)
        throw Kross::Api::RuntimeException(i18n("Script not initialized."));

    try {
        kdDebug() << QString("PythonScript::callFunction(%1, %2)")
                     .arg(name)
                     .arg(args ? QString::number(args->count()) : QString("NULL"))
                     << endl;

        Py::Dict moduledict = d->m_module->getDict();

        // Try to determinate the function we like to execute.
        PyObject* func = PyDict_GetItemString(moduledict.ptr(), name.latin1());

        if( (! d->m_functions.contains(name)) || (! func) )
            throw Kross::Api::AttributeException(i18n("No such function '%1'.").arg(name));

        Py::Callable funcobject(func, true); // the funcobject takes care of freeing our func pyobject.

        // Check if the object is really a function and therefore callable.
        if(! funcobject.isCallable())
            throw Kross::Api::AttributeException(i18n("Function is not callable."));

        // Call the function.
        Py::Object result = funcobject.apply(PythonExtension::toPyTuple(args));

/* TESTCASE
//PyObject* pDict = PyObject_GetAttrString(func,"__dict__");
//kdDebug()<<"INT => "<< PyObject_IsInstance(func,d->m_module->ptr()) <<endl;
//( PyCallable_Check(func)){//PyModule_CheckExact(func)){//PyModule_Check(func)){//PyMethod_Check(func)){//PyMethod_Function(func)){//PyInstance_Check(func) )
        kdDebug() << QString("PythonScript::callFunction result='%1' type='%2'").arg(result.as_string().c_str()).arg(result.type().as_string().c_str()) << endl;
        if(result.isInstance()) {
            kdDebug() << ">>> IS_INSTANCE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"<<endl;
        }
        if(result.isCallable()) {
            kdDebug() << ">>> IS_CALLABLE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"<<endl;
        }
*/

        return PythonExtension::toObject(result);
    }
    catch(Py::Exception& e) {
        Py::Object errobj = Py::value(e);
        throw Kross::Api::RuntimeException(i18n("Python Exception: %1").arg(errobj.as_string().c_str()));
    }
}

const QStringList& PythonScript::getClassNames()
{
    if(! d->m_module) initialize();
    return d->m_classes;
}

Kross::Api::Object::Ptr PythonScript::classInstance(const QString& name)
{
    if(! d->m_module)
        throw Kross::Api::RuntimeException(i18n("Script not initialized."));

    try {
        Py::Dict moduledict = d->m_module->getDict();

        // Try to determinate the class.
        PyObject* pyclass = PyDict_GetItemString(moduledict.ptr(), name.latin1());
        if( (! d->m_classes.contains(name)) || (! pyclass) )
            throw Kross::Api::AttributeException(i18n("No such class '%1'.").arg(name));

        //PyClass_Check( vt.second.ptr() ))
        //PyObject *aclarg = Py_BuildValue("(s)", rs.as_string().c_str());
        PyObject *pyobj = PyInstance_New(pyclass, 0, 0);//aclarg, 0);
        if(! pyobj)
            throw Kross::Api::AttributeException(i18n("Failed to create instance of class '%1'.").arg(name));

        Py::Object classobject(pyobj, true);
kdDebug() << QString("====> PythonScript::classInstance() inst='%1'").arg(classobject.as_string().c_str()) << endl;
        return PythonExtension::toObject(classobject);
    }
    catch(Py::Exception& e) {
        Py::Object errobj = Py::value(e);
        throw Kross::Api::RuntimeException(i18n("Python Exception: %1").arg(errobj.as_string().c_str()));
    }
}

<commit_msg>/// @internal<commit_after>/***************************************************************************
 * pythonscript.cpp
 * This file is part of the KDE project
 * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.org)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * 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
 * Library General Public License for more details.
 * You should have received a copy of the GNU Library General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************************/

#include "pythonscript.h"
#include "pythonmodule.h"
#include "pythoninterpreter.h"
//#include "../api/object.h"
//#include "../api/list.h"
//#include "../main/manager.h"
#include "../main/scriptcontainer.h"
//#include "../api/qtobject.h"
//#include "../api/interpreter.h"

#include <kdebug.h>

using namespace Kross::Python;

namespace Kross { namespace Python {

    /// @internal
    class PythonScriptPrivate
    {
        public:
            Py::Module* m_module;
            Py::Object* m_code;

            QStringList m_functions;
            QStringList m_classes;
            //QMap<QString, Kross::Api::Object::Ptr> m_functions;
            //QMap<QString, Kross::Api::Object::Ptr> m_classes;
            //QValueList<Kross::Api::Object::Ptr> m_classinstances;
    };

}}

PythonScript::PythonScript(Kross::Api::Interpreter* interpreter, Kross::Api::ScriptContainer* scriptcontainer)
    : Kross::Api::Script(interpreter, scriptcontainer)
    , d(new PythonScriptPrivate())
{
#ifdef KROSS_PYTHON_SCRIPT_DEBUG
    kdDebug() << "PythonScript::PythonScript() Constructor." << endl;
#endif
    d->m_module = 0;
    d->m_code = 0;
}

PythonScript::~PythonScript()
{
#ifdef KROSS_PYTHON_SCRIPT_DEBUG
    kdDebug() << "PythonScript::~PythonScript() Destructor." << endl;
#endif
    finalize();
    delete d;
}

void PythonScript::initialize()
{
    finalize();

    try {
        PyObject* pymod = PyModule_New((char*)m_scriptcontainer->getName().latin1());
        d->m_module = new Py::Module(pymod, true);

#ifdef KROSS_PYTHON_SCRIPT_DEBUG
        if(d->m_module)
            kdDebug() << QString("PythonScript::initialize() module='%1' refcount='%2'").arg(d->m_module->as_string().c_str()).arg(d->m_module->reference_count()) << endl;
#endif

        // Compile the python script code. It will be later on request
        // executed. That way we cache the compiled code.
        PyObject* code = 0;
        bool restricted = ((PythonInterpreter*)m_interpreter)->getOption("restricted", QVariant((bool)true)).toBool();
        if(restricted) {
            // Use the RestrictedPython module wrapped by the PythonSecurity class.
/*TODO
            code = m_interpreter->m_security->compile_restricted(
                m_scriptcontainer->getCode(),
                m_scriptcontainer->getName(),
                "exec"
            );
*/
        }
        else {
            // Just compile the code without any restrictions.
            code = Py_CompileString(
                (char*)m_scriptcontainer->getCode().latin1(),
                (char*)m_scriptcontainer->getName().latin1(),
                Py_file_input
            );
        }

        if(! code)
            throw Py::Exception();
        d->m_code = new Py::Object(code, true);
    }
    catch(Py::Exception& e) {
        Py::Object errobj = Py::value(Py::Exception());
        throw Kross::Api::RuntimeException(i18n("Failed to compile python code: %1").arg(errobj.as_string().c_str()));
    }
}

void PythonScript::finalize()
{
#ifdef KROSS_PYTHON_SCRIPT_DEBUG
    if(d->m_module)
        kdDebug() << QString("PythonScript::finalize() module='%1' refcount='%2'").arg(d->m_module->as_string().c_str()).arg(d->m_module->reference_count()) << endl;
#endif

    delete d->m_module; d->m_module = 0;
    delete d->m_code; d->m_code = 0;
    d->m_functions.clear();
    d->m_classes.clear();
}

const QStringList& PythonScript::getFunctionNames()
{
    if(! d->m_module) initialize();
    return d->m_functions;
    /*
    QStringList list;
    Py::List l = d->m_module->getDict().keys();
    int length = l.length();
    for(Py::List::size_type i = 0; i < length; ++i)
        list.append( l[i].str().as_string().c_str() );
    return list;
    */
}

Kross::Api::Object::Ptr PythonScript::execute()
{
    if(! d->m_module)
        initialize();

#ifdef KROSS_PYTHON_SCRIPT_DEBUG
    kdDebug() << QString("PythonScript::execute()") << endl;
#endif

    try {
        Py::Dict mainmoduledict = ((PythonInterpreter*)m_interpreter)->m_module->getDict();
        PyObject* pyresult = PyEval_EvalCode(
            (PyCodeObject*)d->m_code->ptr(),
            mainmoduledict.ptr(),
            d->m_module->getDict().ptr()
        );
        if(! pyresult)
            throw Py::Exception();
        Py::Object result(pyresult, true);
        kdDebug()<<"PythonScript::execute() result="<<result.as_string().c_str()<<endl;

        Py::Dict moduledict( d->m_module->getDict().ptr() );
        for(Py::Dict::iterator it = moduledict.begin(); it != moduledict.end(); ++it) {
            Py::Dict::value_type vt(*it);
            if(PyClass_Check( vt.second.ptr() )) {
                kdDebug() << QString("PythonScript::execute() class '%1' added.").arg(vt.first.as_string().c_str()) << endl;
                d->m_classes.append( vt.first.as_string().c_str() );
            }
            else if(vt.second.isCallable()) {
                kdDebug() << QString("PythonScript::execute() function '%1' added.").arg(vt.first.as_string().c_str()) << endl;
                d->m_functions.append( vt.first.as_string().c_str() );
            }
        }

        Kross::Api::Object::Ptr r = PythonExtension::toObject(result);
        return r;
    }
    catch(Py::Exception& e) {
        throw Kross::Api::RuntimeException(i18n("Failed to execute python code: %1").arg(Py::value(e).as_string().c_str()));
    }

/*
    if(! d->m_module) initialize();
    try {
        Py::Dict mainmoduledict = ((PythonInterpreter*)m_interpreter)->m_module->getDict();
        PyObject* pyrun = PyRun_String(
            (char*)m_scriptcontainer->getCode().latin1(),
            Py_file_input,
            mainmoduledict.ptr(),
            d->m_module->getDict().ptr()
        );
        if(! pyrun) {
            Py::Object errobj = Py::value(Py::Exception()); // get last error
            throw Kross::Api::RuntimeException(i18n("Python Exception: %1").arg(errobj.as_string().c_str()));
        }
        Py::Object run(pyrun, true); // the run-object takes care of freeing our pyrun pyobject.
        //kdDebug() << QString("PythonScript::execute --------------------------- 1") << endl;
        Py::Dict moduledict( d->m_module->getDict().ptr() );
        for(Py::Dict::iterator it = moduledict.begin(); it != moduledict.end(); ++it) {
            Py::Dict::value_type vt(*it);
            if(PyClass_Check( vt.second.ptr() )) {
                kdDebug() << QString("PythonScript::execute() class '%1' added.").arg(vt.first.as_string().c_str()) << endl;
                d->m_classes.append( vt.first.as_string().c_str() );
            }
            else if(vt.second.isCallable()) {
                kdDebug() << QString("PythonScript::execute() function '%1' added.").arg(vt.first.as_string().c_str()) << endl;
                d->m_functions.append( vt.first.as_string().c_str() );
            }
*/
            /*
            QString s;
            if(vt.second.isCallable()) s += "isCallable ";
            if(vt.second.isDict()) s += "isDict ";
            if(vt.second.isList()) s += "isList ";
            if(vt.second.isMapping()) s += "isMapping ";
            if(vt.second.isNumeric()) s += "isNumeric ";
            if(vt.second.isSequence()) s += "isSequence ";
            if(vt.second.isTrue()) s += "isTrue ";
            if(vt.second.isInstance()) s += "isInstance ";
            if(PyClass_Check( vt.second.ptr() )) s += "vt.second.isClass ";
            Py::String rf = vt.first.repr();
            Py::String rs = vt.second.repr();
            kdDebug() << QString("PythonScript::execute d->m_module->getDict() rs='%1' vt.first='%2' rf='%3' test='%4' s='%5'")
                        .arg(rs.as_string().c_str())
                        .arg(vt.first.as_string().c_str())
                        .arg(rf.as_string().c_str())
                        .arg("")
                        .arg(s) << endl;
            //m_objects.replace(vt.first.repr().as_string().c_str(), vt.second);
            if(PyClass_Check( vt.second.ptr() )) {
                //PyObject *aclarg = Py_BuildValue("(s)", rs.as_string().c_str());
                PyObject *pyinst = PyInstance_New(vt.second.ptr(), 0, 0);//aclarg, 0);
                //Py_DECREF(aclarg);
                if (pyinst == 0)
                    kdDebug() << QString("PythonScript::execute PyInstance_New() returned NULL !!!") << endl;
                else {
                    Py::Object inst(pyinst, true);
                    kdDebug() << QString("====> PythonScript::execute inst='%1'").arg(inst.as_string().c_str()) << endl;
                }
            }
            */
/*
        }
        //kdDebug() << QString("PythonScript::execute --------------------------- 2") << endl;
        //kdDebug() << QString("PythonScript::execute() PyRun_String='%1'").arg(run.str().as_string().c_str()) << endl;
        return PythonExtension::toObject(run);
    }
    catch(Py::Exception& e) {
        Py::Object errobj = Py::value(e);
        throw Kross::Api::RuntimeException(i18n("Python Exception: %1").arg(errobj.as_string().c_str()));
    }
*/
}

Kross::Api::Object::Ptr PythonScript::callFunction(const QString& name, Kross::Api::List::Ptr args)
{
    if(! d->m_module)
        throw Kross::Api::RuntimeException(i18n("Script not initialized."));

    try {
        kdDebug() << QString("PythonScript::callFunction(%1, %2)")
                     .arg(name)
                     .arg(args ? QString::number(args->count()) : QString("NULL"))
                     << endl;

        Py::Dict moduledict = d->m_module->getDict();

        // Try to determinate the function we like to execute.
        PyObject* func = PyDict_GetItemString(moduledict.ptr(), name.latin1());

        if( (! d->m_functions.contains(name)) || (! func) )
            throw Kross::Api::AttributeException(i18n("No such function '%1'.").arg(name));

        Py::Callable funcobject(func, true); // the funcobject takes care of freeing our func pyobject.

        // Check if the object is really a function and therefore callable.
        if(! funcobject.isCallable())
            throw Kross::Api::AttributeException(i18n("Function is not callable."));

        // Call the function.
        Py::Object result = funcobject.apply(PythonExtension::toPyTuple(args));

/* TESTCASE
//PyObject* pDict = PyObject_GetAttrString(func,"__dict__");
//kdDebug()<<"INT => "<< PyObject_IsInstance(func,d->m_module->ptr()) <<endl;
//( PyCallable_Check(func)){//PyModule_CheckExact(func)){//PyModule_Check(func)){//PyMethod_Check(func)){//PyMethod_Function(func)){//PyInstance_Check(func) )
        kdDebug() << QString("PythonScript::callFunction result='%1' type='%2'").arg(result.as_string().c_str()).arg(result.type().as_string().c_str()) << endl;
        if(result.isInstance()) {
            kdDebug() << ">>> IS_INSTANCE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"<<endl;
        }
        if(result.isCallable()) {
            kdDebug() << ">>> IS_CALLABLE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"<<endl;
        }
*/

        return PythonExtension::toObject(result);
    }
    catch(Py::Exception& e) {
        Py::Object errobj = Py::value(e);
        throw Kross::Api::RuntimeException(i18n("Python Exception: %1").arg(errobj.as_string().c_str()));
    }
}

const QStringList& PythonScript::getClassNames()
{
    if(! d->m_module) initialize();
    return d->m_classes;
}

Kross::Api::Object::Ptr PythonScript::classInstance(const QString& name)
{
    if(! d->m_module)
        throw Kross::Api::RuntimeException(i18n("Script not initialized."));

    try {
        Py::Dict moduledict = d->m_module->getDict();

        // Try to determinate the class.
        PyObject* pyclass = PyDict_GetItemString(moduledict.ptr(), name.latin1());
        if( (! d->m_classes.contains(name)) || (! pyclass) )
            throw Kross::Api::AttributeException(i18n("No such class '%1'.").arg(name));

        //PyClass_Check( vt.second.ptr() ))
        //PyObject *aclarg = Py_BuildValue("(s)", rs.as_string().c_str());
        PyObject *pyobj = PyInstance_New(pyclass, 0, 0);//aclarg, 0);
        if(! pyobj)
            throw Kross::Api::AttributeException(i18n("Failed to create instance of class '%1'.").arg(name));

        Py::Object classobject(pyobj, true);
kdDebug() << QString("====> PythonScript::classInstance() inst='%1'").arg(classobject.as_string().c_str()) << endl;
        return PythonExtension::toObject(classobject);
    }
    catch(Py::Exception& e) {
        Py::Object errobj = Py::value(e);
        throw Kross::Api::RuntimeException(i18n("Python Exception: %1").arg(errobj.as_string().c_str()));
    }
}

<|endoftext|>


<commit_before>//===- lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp ----------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "MipsTargetHandler.h"
#include "MipsLinkingContext.h"
#include "MipsRelocationHandler.h"

#include "lld/ReaderWriter/RelocationHelperFunctions.h"

using namespace lld;
using namespace elf;
using namespace llvm::ELF;

namespace {

inline void applyReloc(uint8_t *location, uint32_t result) {
  auto target = reinterpret_cast<llvm::support::ulittle32_t *>(location);
  *target = result | *target;
}

/// \brief Calculate AHL value combines addends from 'hi' and 'lo' relocations.
inline int64_t calcAHL(int64_t AHI, int64_t ALO) {
  AHI &= 0xffff;
  ALO &= 0xffff;
  return (AHI << 16) + (int16_t)ALO;
}

/// \brief R_MIPS_32
/// local/external: word32 S + A (truncate)
void reloc32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
  uint32_t result = (uint32_t)(S + A);
  applyReloc(location, result);
}

/// \brief R_MIPS_HI16
/// local/external: hi16 (AHL + S) - (short)(AHL + S) (truncate)
/// _gp_disp      : hi16 (AHL + GP - P) - (short)(AHL + GP - P) (verify)
void relocHi16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
               uint64_t GP, bool isGPDisp) {
  int32_t result = 0;

  if (isGPDisp)
    result = (AHL + GP - P) - (int16_t)(AHL + GP - P);
  else
    result = (AHL + S) - (int16_t)(AHL + S);

  result = lld::scatterBits<uint32_t>(result >> 16, 0xffff);
  applyReloc(location, result);
}

/// \brief R_MIPS_LO16
/// local/external: lo16 AHL + S (truncate)
/// _gp_disp      : lo16 AHL + GP - P + 4 (verify)
void relocLo16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
               uint64_t GP, bool isGPDisp) {
  int32_t result = 0;

  if (isGPDisp)
    result = AHL + GP - P + 4;
  else
    result = AHL + S;

  result = lld::scatterBits<uint32_t>(result, 0xffff);
  applyReloc(location, result);
}

/// \brief R_MIPS_GOT16
/// local/external: rel16 G (verify)
void relocGOT16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
                uint64_t GP) {
  // FIXME (simon): for local sym put high 16 bit of AHL to the GOT
  int32_t G = (int32_t)(S - GP);
  int32_t result = lld::scatterBits<uint32_t>(G, 0xffff);
  applyReloc(location, result);
}

/// \brief R_MIPS_CALL16
/// external: rel16 G (verify)
void relocCall16(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
                 uint64_t GP) {
  int32_t G = (int32_t)(S - GP);
  int32_t result = lld::scatterBits<uint32_t>(G, 0xffff);
  applyReloc(location, result);
}

} // end anon namespace

MipsTargetRelocationHandler::MipsTargetRelocationHandler(
    const MipsLinkingContext &context, const MipsTargetHandler &handler)
    : _context(context), _targetHandler(handler) {}

void
MipsTargetRelocationHandler::savePairedRelocation(const lld::AtomLayout &atom,
                                                  const Reference &ref) const {
  auto pi = _pairedRelocations.find(&atom);
  if (pi == _pairedRelocations.end())
    pi = _pairedRelocations.emplace(&atom, PairedRelocationsT()).first;

  pi->second.push_back(&ref);
}

void MipsTargetRelocationHandler::applyPairedRelocations(
    ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
    int64_t loAddend) const {
  auto pi = _pairedRelocations.find(&atom);
  if (pi == _pairedRelocations.end())
    return;

  for (auto ri : pi->second) {
    uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
    uint8_t *location = atomContent + ri->offsetInAtom();
    uint64_t targetVAddress = writer.addressOfAtom(ri->target());
    uint64_t relocVAddress = atom._virtualAddr + ri->offsetInAtom();

    int64_t ahl = calcAHL(ri->addend(), loAddend);

    switch (ri->kind()) {
    case R_MIPS_HI16:
      relocHi16(location, relocVAddress, targetVAddress, ahl,
                _targetHandler.getGPDispSymAddr(),
                ri->target()->name() == "_gp_disp");
      break;
    case R_MIPS_GOT16:
      relocGOT16(location, relocVAddress, targetVAddress, ahl,
                 _targetHandler.getGPDispSymAddr());
      break;
    default:
      llvm_unreachable("Unknown type of paired relocation.");
    }
  }

  _pairedRelocations.erase(pi);
}

error_code MipsTargetRelocationHandler::applyRelocation(
    ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
    const Reference &ref) const {
  uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
  uint8_t *location = atomContent + ref.offsetInAtom();
  uint64_t targetVAddress = writer.addressOfAtom(ref.target());
  uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();

  switch (ref.kind()) {
  case R_MIPS_NONE:
    break;
  case R_MIPS_32:
    reloc32(location, relocVAddress, targetVAddress, ref.addend());
    break;
  case R_MIPS_HI16:
    savePairedRelocation(atom, ref);
    break;
  case R_MIPS_LO16:
    relocLo16(location, relocVAddress, targetVAddress, calcAHL(0, ref.addend()),
              _targetHandler.getGPDispSymAddr(),
              ref.target()->name() == "_gp_disp");
    applyPairedRelocations(writer, buf, atom, ref.addend());
    break;
  case R_MIPS_GOT16:
    savePairedRelocation(atom, ref);
    break;
  case R_MIPS_CALL16:
    relocCall16(location, relocVAddress, targetVAddress, ref.addend(),
                _targetHandler.getGPDispSymAddr());
    break;
  case R_MIPS_JALR:
    // We do not do JALR optimization now.
    break;
  case lld::Reference::kindLayoutAfter:
  case lld::Reference::kindLayoutBefore:
  case lld::Reference::kindInGroup:
    break;
  default: {
    std::string str;
    llvm::raw_string_ostream s(str);
    auto name = _context.stringFromRelocKind(ref.kind());
    s << "Unhandled relocation: "
      << (name ? *name : "<unknown>") << " (" << ref.kind() << ")";
    llvm_unreachable(s.str().c_str());
  }
  }

  return error_code::success();
}
<commit_msg>[Mips] Explicitly cast ulittle32_t to the uint32_t to fix Visual Studio compile error.<commit_after>//===- lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp ----------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "MipsTargetHandler.h"
#include "MipsLinkingContext.h"
#include "MipsRelocationHandler.h"

#include "lld/ReaderWriter/RelocationHelperFunctions.h"

using namespace lld;
using namespace elf;
using namespace llvm::ELF;

namespace {

inline void applyReloc(uint8_t *location, uint32_t result) {
  auto target = reinterpret_cast<llvm::support::ulittle32_t *>(location);
  *target = result | uint32_t(*target);
}

/// \brief Calculate AHL value combines addends from 'hi' and 'lo' relocations.
inline int64_t calcAHL(int64_t AHI, int64_t ALO) {
  AHI &= 0xffff;
  ALO &= 0xffff;
  return (AHI << 16) + (int16_t)ALO;
}

/// \brief R_MIPS_32
/// local/external: word32 S + A (truncate)
void reloc32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
  uint32_t result = (uint32_t)(S + A);
  applyReloc(location, result);
}

/// \brief R_MIPS_HI16
/// local/external: hi16 (AHL + S) - (short)(AHL + S) (truncate)
/// _gp_disp      : hi16 (AHL + GP - P) - (short)(AHL + GP - P) (verify)
void relocHi16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
               uint64_t GP, bool isGPDisp) {
  int32_t result = 0;

  if (isGPDisp)
    result = (AHL + GP - P) - (int16_t)(AHL + GP - P);
  else
    result = (AHL + S) - (int16_t)(AHL + S);

  result = lld::scatterBits<uint32_t>(result >> 16, 0xffff);
  applyReloc(location, result);
}

/// \brief R_MIPS_LO16
/// local/external: lo16 AHL + S (truncate)
/// _gp_disp      : lo16 AHL + GP - P + 4 (verify)
void relocLo16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
               uint64_t GP, bool isGPDisp) {
  int32_t result = 0;

  if (isGPDisp)
    result = AHL + GP - P + 4;
  else
    result = AHL + S;

  result = lld::scatterBits<uint32_t>(result, 0xffff);
  applyReloc(location, result);
}

/// \brief R_MIPS_GOT16
/// local/external: rel16 G (verify)
void relocGOT16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
                uint64_t GP) {
  // FIXME (simon): for local sym put high 16 bit of AHL to the GOT
  int32_t G = (int32_t)(S - GP);
  int32_t result = lld::scatterBits<uint32_t>(G, 0xffff);
  applyReloc(location, result);
}

/// \brief R_MIPS_CALL16
/// external: rel16 G (verify)
void relocCall16(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
                 uint64_t GP) {
  int32_t G = (int32_t)(S - GP);
  int32_t result = lld::scatterBits<uint32_t>(G, 0xffff);
  applyReloc(location, result);
}

} // end anon namespace

MipsTargetRelocationHandler::MipsTargetRelocationHandler(
    const MipsLinkingContext &context, const MipsTargetHandler &handler)
    : _context(context), _targetHandler(handler) {}

void
MipsTargetRelocationHandler::savePairedRelocation(const lld::AtomLayout &atom,
                                                  const Reference &ref) const {
  auto pi = _pairedRelocations.find(&atom);
  if (pi == _pairedRelocations.end())
    pi = _pairedRelocations.emplace(&atom, PairedRelocationsT()).first;

  pi->second.push_back(&ref);
}

void MipsTargetRelocationHandler::applyPairedRelocations(
    ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
    int64_t loAddend) const {
  auto pi = _pairedRelocations.find(&atom);
  if (pi == _pairedRelocations.end())
    return;

  for (auto ri : pi->second) {
    uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
    uint8_t *location = atomContent + ri->offsetInAtom();
    uint64_t targetVAddress = writer.addressOfAtom(ri->target());
    uint64_t relocVAddress = atom._virtualAddr + ri->offsetInAtom();

    int64_t ahl = calcAHL(ri->addend(), loAddend);

    switch (ri->kind()) {
    case R_MIPS_HI16:
      relocHi16(location, relocVAddress, targetVAddress, ahl,
                _targetHandler.getGPDispSymAddr(),
                ri->target()->name() == "_gp_disp");
      break;
    case R_MIPS_GOT16:
      relocGOT16(location, relocVAddress, targetVAddress, ahl,
                 _targetHandler.getGPDispSymAddr());
      break;
    default:
      llvm_unreachable("Unknown type of paired relocation.");
    }
  }

  _pairedRelocations.erase(pi);
}

error_code MipsTargetRelocationHandler::applyRelocation(
    ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
    const Reference &ref) const {
  uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
  uint8_t *location = atomContent + ref.offsetInAtom();
  uint64_t targetVAddress = writer.addressOfAtom(ref.target());
  uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();

  switch (ref.kind()) {
  case R_MIPS_NONE:
    break;
  case R_MIPS_32:
    reloc32(location, relocVAddress, targetVAddress, ref.addend());
    break;
  case R_MIPS_HI16:
    savePairedRelocation(atom, ref);
    break;
  case R_MIPS_LO16:
    relocLo16(location, relocVAddress, targetVAddress, calcAHL(0, ref.addend()),
              _targetHandler.getGPDispSymAddr(),
              ref.target()->name() == "_gp_disp");
    applyPairedRelocations(writer, buf, atom, ref.addend());
    break;
  case R_MIPS_GOT16:
    savePairedRelocation(atom, ref);
    break;
  case R_MIPS_CALL16:
    relocCall16(location, relocVAddress, targetVAddress, ref.addend(),
                _targetHandler.getGPDispSymAddr());
    break;
  case R_MIPS_JALR:
    // We do not do JALR optimization now.
    break;
  case lld::Reference::kindLayoutAfter:
  case lld::Reference::kindLayoutBefore:
  case lld::Reference::kindInGroup:
    break;
  default: {
    std::string str;
    llvm::raw_string_ostream s(str);
    auto name = _context.stringFromRelocKind(ref.kind());
    s << "Unhandled relocation: "
      << (name ? *name : "<unknown>") << " (" << ref.kind() << ")";
    llvm_unreachable(s.str().c_str());
  }
  }

  return error_code::success();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dlg_InsertDataLabel.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2007-10-22 16:50:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef CHART2_DLG_INSERT_DATALABELS_GRID_HXX
#define CHART2_DLG_INSERT_DATALABELS_GRID_HXX

// header for class ModalDialog
#ifndef _SV_DIALOG_HXX
#include <vcl/dialog.hxx>
#endif
// header for class CheckBox
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
// header for class SfxItemSet
#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif
//for auto_ptr
#include <memory>

class SvNumberFormatter;

//.............................................................................
namespace chart
{
//.............................................................................

class DataLabelResources;
class DataLabelsDialog : public ModalDialog
{
private:
    OKButton            m_aBtnOK;
    CancelButton        m_aBtnCancel;
    HelpButton          m_aBtnHelp;
    ::std::auto_ptr< DataLabelResources >    m_apDataLabelResources;

    const SfxItemSet&   m_rInAttrs;

    void Reset();

public:
    DataLabelsDialog(Window* pParent, const SfxItemSet& rInAttrs, SvNumberFormatter* pFormatter);
    virtual ~DataLabelsDialog();

    void FillItemSet(SfxItemSet& rOutAttrs);
};

//.............................................................................
} //namespace chart
//.............................................................................

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.5.66); FILE MERGED 2008/04/01 15:04:08 thb 1.5.66.2: #i85898# Stripping all external header guards 2008/03/28 16:43:46 rt 1.5.66.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dlg_InsertDataLabel.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef CHART2_DLG_INSERT_DATALABELS_GRID_HXX
#define CHART2_DLG_INSERT_DATALABELS_GRID_HXX

// header for class ModalDialog
#include <vcl/dialog.hxx>
// header for class CheckBox
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
// header for class SfxItemSet
#include <svtools/itemset.hxx>
//for auto_ptr
#include <memory>

class SvNumberFormatter;

//.............................................................................
namespace chart
{
//.............................................................................

class DataLabelResources;
class DataLabelsDialog : public ModalDialog
{
private:
    OKButton            m_aBtnOK;
    CancelButton        m_aBtnCancel;
    HelpButton          m_aBtnHelp;
    ::std::auto_ptr< DataLabelResources >    m_apDataLabelResources;

    const SfxItemSet&   m_rInAttrs;

    void Reset();

public:
    DataLabelsDialog(Window* pParent, const SfxItemSet& rInAttrs, SvNumberFormatter* pFormatter);
    virtual ~DataLabelsDialog();

    void FillItemSet(SfxItemSet& rOutAttrs);
};

//.............................................................................
} //namespace chart
//.............................................................................

#endif
<|endoftext|>