<commit_before>#include "particle.h"

#include <algorithm>
#include <cassert>
#include <iostream>

namespace SPHack {

ParticleSystem::ParticleSystem(const AABB& bounds, Real radius) : bounds_(bounds), radius_(radius), kernel_(radius) {
  available_particles_.reserve(kMaxParticles);
  for (int i = kMaxParticles - 1; i >= 0; --i) {
    available_particles_.push_back(i);
  }

  gravity_ = Vec2(0.0, -1.0);

  grid_delta_ = radius;
  grid_width_ = static_cast<int>(ceil(bounds.width() / grid_delta_));
  grid_height_ = static_cast<int>(ceil(bounds.height() / grid_delta_));
  grid_.resize(grid_width_*grid_height_);
  static const int estimated_particles_per_cell = 8;
  for (auto& grid_cell : grid_) {
    grid_cell.reserve(estimated_particles_per_cell);
  }

  radius2_ = radius_ * radius_;
  static const Real density = 1.7e2 / radius2_;
  density_inv_ = 1.0 / density;
  cfm_epsilon_ = 1e3;

  kernel_ = KernelEvaluator(radius_);

  boundary_margin_ = radius_ * 0.5;

  random_.seed(144438);
  jitter_dist_ = std::uniform_real_distribution<>(-1e-6, 1e-6);
}

void ParticleSystem::AddParticles(const AABB& region, int max) {
  AABB clipped_region = bounds_.Intersect(region);

  int particles_added = 0;
  for (Real x = clipped_region.min()[0] + boundary_margin_; x < clipped_region.max()[0] - boundary_margin_; x += 0.6*radius_) {
    for (Real y = clipped_region.min()[1] + boundary_margin_; y < clipped_region.max()[1] - boundary_margin_; y += 0.6*radius_) {
      if (max >= 0 && particles_added >= max) {
        continue;
      }
      if (!CreateParticle(Vec2(x, y), Vec2(0.0, 0.0))) {
        std::cerr << "Failed to create particle at: " << x << " " << y << std::endl;
      } else {
        ++particles_added;
      }
    }
  }
  std::cerr << particles_added << " particles added" << std::endl;
}

void ParticleSystem::ApplyForces(Real dt) {
  for (size_t i = 0; i < size(); ++i) {
    vel_[i] += gravity_ * dt;
  }
}

void ParticleSystem::PredictPositions(Real dt) {
  for (size_t i = 0; i < size(); ++i) {
    predicted_pos_[i] = dt * vel_[i] + pos_[i];
  }
}

void ParticleSystem::UpdateVelocities(Real dt) {
  for (size_t i = 0; i < size(); ++i) {
    Vec2 old_vel = vel_[i];
    vel_[i] = (predicted_pos_[i] - pos_[i]) * (1.0 / dt);
    accel_[i] += (vel_[i] - old_vel) / dt;
  }
}

void ParticleSystem::CommitPositions() {
  pos_.swap(predicted_pos_);
}

void ParticleSystem::Step(Real dt) {
  static const int kSubsteps = 2;
  dt /= kSubsteps;

  for (size_t i = 0; i < size(); ++i) {
    accel_[i] = Vec2(0.0, 0.0);
  }

  for (int substep = 0; substep < kSubsteps; ++substep) {
    ApplyForces(dt);
    PredictPositions(dt);
    BuildGrid();
    static const int kIters = 4;
    for (int i = 0; i < kIters; ++i) {
      SubstepResetGrid();
      CalculateLambdaOnGrid();
      CalculatePressureDeltaOnGrid();
      ApplyPressureDeltaOnGrid();
      EnforceBoundariesOnGrid();
    }
    CopyPositionsFromGrid();
    UpdateVelocities(dt);
    ApplyViscosityOnGrid(dt);
    CommitPositions();
  }
}

void ParticleSystem::InitDensity() {
  for (size_t i = 0; i < pos_.size(); i++) {
    predicted_pos_[i] = pos_[i];
  }
  BuildGrid();
  CalculateLambdaOnGrid();
  Real max_density = 0.0;
  for (size_t i = 0; i < density_.size(); i++) {
    if (isActive(i)) {
      max_density = std::max(max_density, density_[i]);
    }
  }

  density_inv_ /= max_density;
  cfm_epsilon_ = 0.03 / density_inv_;
  std::cerr << "density: " << (1.0 / density_inv_) << std::endl;
  std::cerr << "cfm eps: " << cfm_epsilon_ << std::endl;
}

void ParticleSystem::Clear() {
  available_particles_.clear();
  for (int i = kMaxParticles - 1; i >= 0; --i) {
    available_particles_.push_back(i);
    flag_[i] = 0;
  }
}

bool ParticleSystem::CreateParticle(const Vec2& pos, const Vec2& vel) {
  if (available_particles_.empty()) {
    return false;
  }

  ParticleIDType id = available_particles_.back();
  available_particles_.pop_back();
  pos_[id] = pos;
  vel_[id] = vel;
  accel_[id] = Vec2();
  flag_[id] = PARTICLE_FLAG_ACTIVE;

  return true;
}

void ParticleSystem::BuildGrid() {
  for (auto& grid_cell : grid_) {
    grid_cell.clear();
  }

  for (size_t i = 0; i < predicted_pos_.size(); ++i) {
    if (isActive(i)) {
      int x = static_cast<int>(predicted_pos_[i].x / grid_delta_);
      x = std::max(0, std::min(grid_width_ - 1, x));
      int y = static_cast<int>(predicted_pos_[i].y / grid_delta_);
      y = std::max(0, std::min(grid_height_ - 1, y));

      grid_[CellID(x, y)].push_back(
          PressureParticle {
              predicted_pos_[i],
              Vec2(0.0, 0.0),
              static_cast<ParticleIDType>(i)
          });
    }
  }
}

void ParticleSystem::SubstepResetGrid() {
  for (int ox = 0; ox < grid_width_; ++ox) {
    for (int oy = 0; oy < grid_height_; ++oy) {
      int cell_i = CellID(ox, oy);
      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];
        pi.lambda = 0.0;
        pi.density = 0.0;
        pi.cj_grad_norm_squared_sum = 0.0;
        pi.ci_grad_sum = Vec2(0.0, 0.0);
        pi.pos_delta = Vec2(0.0, 0.0);
      }
    }
  }
}

void ParticleSystem::AccumulateLambdaData(PressureParticle& pi, PressureParticle& pj) {
  const Vec2 r = pi.pos - pj.pos;
  if (r.squaredNorm() > radius2_) return;
  const Real poly6_weight = kernel_.Poly6NonNorm(r);
  pi.density += poly6_weight;
  pj.density += poly6_weight;
  const Vec2 grad = kernel_.SpikyGradNonNorm(r);
  const Real gradSquaredNorm = grad.squaredNorm();
  pi.cj_grad_norm_squared_sum += gradSquaredNorm;
  pj.cj_grad_norm_squared_sum += gradSquaredNorm;
  pi.ci_grad_sum += grad;
  pj.ci_grad_sum -= grad;
}

void ParticleSystem::CalculateLambdaOnGrid() {
  for (int ox = 0; ox < grid_width_; ++ox) {
    for (int oy = 0; oy < grid_height_; ++oy) {
      int cell_i = CellID(ox, oy);
      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];

        for (int j = i+1; j < grid_[cell_i].size(); ++j) {
          PressureParticle& pj = grid_[cell_i][j];
          AccumulateLambdaData(pi, pj);
        }
      }

      for (int dx = 0; dx <= 1; ++dx) {
        const int nx = ox + dx;
        if (nx >= grid_width_) continue;
        for (int dy = ((dx == 0) ? 1 : -1); dy <= 1; ++dy) {
          const int ny = oy + dy;
          if (ny < 0) continue;
          if (ny >= grid_width_) continue;

          int cell_j = CellID(nx, ny);

          for (int i = 0; i < grid_[cell_i].size(); ++i) {
            PressureParticle& pi = grid_[cell_i][i];
            for (int j = 0; j < grid_[cell_j].size(); ++j) {
              PressureParticle& pj = grid_[cell_j][j];
              AccumulateLambdaData(pi, pj);
            }
          }
        }
      }

      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];

        pi.density *= density_inv_ * kernel_.poly6_norm();
        density_[pi.id] = pi.density;
        const Real den = (pi.cj_grad_norm_squared_sum*kernel_.spiky_grad_norm()*kernel_.spiky_grad_norm() + (pi.ci_grad_sum * kernel_.spiky_grad_norm()).squaredNorm())*density_inv_*density_inv_ + cfm_epsilon_;
        pi.lambda = -(pi.density - 1.0) / den;
      }
    }
  }
}

void ParticleSystem::AccumulatePressureDelta(PressureParticle& pi, PressureParticle& pj) {
  const Vec2 r = pi.pos - pj.pos;
  if (r.squaredNorm() > radius2_) return;
  Real scorr = kernel_.Poly6NonNorm(r)/kernel_.Poly6NonNorm(Vec2(0.0,0.2*radius_));
  scorr = scorr*scorr*scorr*scorr;
  scorr *= -0.000005;
  const Vec2 delta = (pi.lambda + pj.lambda + scorr) * kernel_.SpikyGradNonNorm(r);
  pi.pos_delta += delta;
  pj.pos_delta -= delta;
}

void ParticleSystem::CalculatePressureDeltaOnGrid() {
  for (int ox = 0; ox < grid_width_; ++ox) {
    for (int oy = 0; oy < grid_height_; ++oy) {
      int cell_i = CellID(ox, oy);
      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];

        for (int j = i+1; j < grid_[cell_i].size(); ++j) {
          PressureParticle& pj = grid_[cell_i][j];
          AccumulatePressureDelta(pi, pj);
        }
      }

      for (int dx = 0; dx <= 1; ++dx) {
        const int nx = ox + dx;
        if (nx >= grid_width_) continue;
        for (int dy = ((dx == 0) ? 1 : -1); dy <= 1; ++dy) {
          const int ny = oy + dy;
          if (ny < 0) continue;
          if (ny >= grid_width_) continue;

          int cell_j = CellID(nx, ny);

          for (int i = 0; i < grid_[cell_i].size(); ++i) {
            PressureParticle& pi = grid_[cell_i][i];
            for (int j = 0; j < grid_[cell_j].size(); ++j) {
              PressureParticle& pj = grid_[cell_j][j];
              AccumulatePressureDelta(pi, pj);
            }
          }
        }
      }

      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];
        pi.pos_delta *= density_inv_ * kernel_.spiky_grad_norm();
      }
    }
  }
}

void ParticleSystem::ApplyPressureDeltaOnGrid() {
  for (int ox = 0; ox < grid_width_; ++ox) {
    for (int oy = 0; oy < grid_height_; ++oy) {
      for (auto& pi : grid_[CellID(ox, oy)]) {
        pi.pos += pi.pos_delta;
      }
    }
  }
}

void ParticleSystem::EnforceBoundariesOnGrid() {
  AABB shrunk_bounds = bounds_.Shrink(boundary_margin_);
  for (auto& grid_cell : grid_) {
    for (auto& particle : grid_cell) {
      if (!shrunk_bounds.IsInside(particle.pos)) {
        particle.pos = shrunk_bounds.Clip(particle.pos);
        particle.pos.x += jitter_dist_(random_);
        particle.pos.y += jitter_dist_(random_);
      }
    }
  }
}

void ParticleSystem::CopyPositionsFromGrid() {
  for (auto& grid_cell : grid_) {
    for (auto& particle: grid_cell) {
      predicted_pos_[particle.id] = particle.pos;
    }
  }
}

void ParticleSystem::ApplyViscosityOnGrid(Real dt) {

}

}  // namespace SPHack
<commit_msg>More demo tuning.<commit_after>#include "particle.h"

#include <algorithm>
#include <cassert>
#include <iostream>

namespace SPHack {

ParticleSystem::ParticleSystem(const AABB& bounds, Real radius) : bounds_(bounds), radius_(radius), kernel_(radius) {
  available_particles_.reserve(kMaxParticles);
  for (int i = kMaxParticles - 1; i >= 0; --i) {
    available_particles_.push_back(i);
  }

  gravity_ = Vec2(0.0, -1.0);

  grid_delta_ = radius;
  grid_width_ = static_cast<int>(ceil(bounds.width() / grid_delta_));
  grid_height_ = static_cast<int>(ceil(bounds.height() / grid_delta_));
  grid_.resize(grid_width_*grid_height_);
  static const int estimated_particles_per_cell = 16;
  for (auto& grid_cell : grid_) {
    grid_cell.reserve(estimated_particles_per_cell);
  }

  radius2_ = radius_ * radius_;
  static const Real density = 1.7e2 / radius2_;
  density_inv_ = 1.0 / density;
  cfm_epsilon_ = 1e3;

  kernel_ = KernelEvaluator(radius_);

  boundary_margin_ = radius_ * 0.5;

  random_.seed(144438);
  jitter_dist_ = std::uniform_real_distribution<>(-1e-6, 1e-6);
}

void ParticleSystem::AddParticles(const AABB& region, int max) {
  AABB clipped_region = bounds_.Intersect(region);

  int particles_added = 0;
  for (Real x = clipped_region.min()[0] + boundary_margin_; x < clipped_region.max()[0] - boundary_margin_; x += 0.6*radius_) {
    for (Real y = clipped_region.min()[1] + boundary_margin_; y < clipped_region.max()[1] - boundary_margin_; y += 0.6*radius_) {
      if (max >= 0 && particles_added >= max) {
        continue;
      }
      if (!CreateParticle(Vec2(x, y), Vec2(0.0, 0.0))) {
        std::cerr << "Failed to create particle at: " << x << " " << y << std::endl;
      } else {
        ++particles_added;
      }
    }
  }
  std::cerr << particles_added << " particles added" << std::endl;
}

void ParticleSystem::ApplyForces(Real dt) {
  for (size_t i = 0; i < size(); ++i) {
    vel_[i] += gravity_ * dt;
  }
}

void ParticleSystem::PredictPositions(Real dt) {
  for (size_t i = 0; i < size(); ++i) {
    predicted_pos_[i] = dt * vel_[i] + pos_[i];
  }
}

void ParticleSystem::UpdateVelocities(Real dt) {
  for (size_t i = 0; i < size(); ++i) {
    Vec2 old_vel = vel_[i];
    vel_[i] = (predicted_pos_[i] - pos_[i]) * (1.0 / dt);
    accel_[i] += (vel_[i] - old_vel) / dt;
  }
}

void ParticleSystem::CommitPositions() {
  pos_.swap(predicted_pos_);
}

void ParticleSystem::Step(Real dt) {
  static const int kSubsteps = 2;
  dt /= kSubsteps;

  for (size_t i = 0; i < size(); ++i) {
    accel_[i] = Vec2(0.0, 0.0);
  }

  for (int substep = 0; substep < kSubsteps; ++substep) {
    ApplyForces(dt);
    PredictPositions(dt);
    BuildGrid();
    static const int kIters = 4;
    for (int i = 0; i < kIters; ++i) {
      SubstepResetGrid();
      CalculateLambdaOnGrid();
      CalculatePressureDeltaOnGrid();
      ApplyPressureDeltaOnGrid();
      EnforceBoundariesOnGrid();
    }
    CopyPositionsFromGrid();
    UpdateVelocities(dt);
    ApplyViscosityOnGrid(dt);
    CommitPositions();
  }
}

void ParticleSystem::InitDensity() {
  for (size_t i = 0; i < pos_.size(); i++) {
    predicted_pos_[i] = pos_[i];
  }
  BuildGrid();
  CalculateLambdaOnGrid();
  Real max_density = 0.0;
  for (size_t i = 0; i < density_.size(); i++) {
    if (isActive(i)) {
      max_density = std::max(max_density, density_[i]);
    }
  }

  density_inv_ /= max_density;
  cfm_epsilon_ = 0.03 / density_inv_;
  std::cerr << "density: " << (1.0 / density_inv_) << std::endl;
  std::cerr << "cfm eps: " << cfm_epsilon_ << std::endl;
}

void ParticleSystem::Clear() {
  available_particles_.clear();
  for (int i = kMaxParticles - 1; i >= 0; --i) {
    available_particles_.push_back(i);
    flag_[i] = 0;
  }
}

bool ParticleSystem::CreateParticle(const Vec2& pos, const Vec2& vel) {
  if (available_particles_.empty()) {
    return false;
  }

  ParticleIDType id = available_particles_.back();
  available_particles_.pop_back();
  pos_[id] = pos;
  vel_[id] = vel;
  accel_[id] = Vec2();
  flag_[id] = PARTICLE_FLAG_ACTIVE;

  return true;
}

void ParticleSystem::BuildGrid() {
  for (auto& grid_cell : grid_) {
    grid_cell.clear();
  }

  for (size_t i = 0; i < predicted_pos_.size(); ++i) {
    if (isActive(i)) {
      int x = static_cast<int>(predicted_pos_[i].x / grid_delta_);
      x = std::max(0, std::min(grid_width_ - 1, x));
      int y = static_cast<int>(predicted_pos_[i].y / grid_delta_);
      y = std::max(0, std::min(grid_height_ - 1, y));

      grid_[CellID(x, y)].push_back(
          PressureParticle {
              predicted_pos_[i],
              Vec2(0.0, 0.0),
              static_cast<ParticleIDType>(i)
          });
    }
  }
}

void ParticleSystem::SubstepResetGrid() {
  for (int ox = 0; ox < grid_width_; ++ox) {
    for (int oy = 0; oy < grid_height_; ++oy) {
      int cell_i = CellID(ox, oy);
      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];
        pi.lambda = 0.0;
        pi.density = 0.0;
        pi.cj_grad_norm_squared_sum = 0.0;
        pi.ci_grad_sum = Vec2(0.0, 0.0);
        pi.pos_delta = Vec2(0.0, 0.0);
      }
    }
  }
}

void ParticleSystem::AccumulateLambdaData(PressureParticle& pi, PressureParticle& pj) {
  const Vec2 r = pi.pos - pj.pos;
  if (r.squaredNorm() > radius2_) return;
  const Real poly6_weight = kernel_.Poly6NonNorm(r);
  pi.density += poly6_weight;
  pj.density += poly6_weight;
  const Vec2 grad = kernel_.SpikyGradNonNorm(r);
  const Real gradSquaredNorm = grad.squaredNorm();
  pi.cj_grad_norm_squared_sum += gradSquaredNorm;
  pj.cj_grad_norm_squared_sum += gradSquaredNorm;
  pi.ci_grad_sum += grad;
  pj.ci_grad_sum -= grad;
}

void ParticleSystem::CalculateLambdaOnGrid() {
  for (int ox = 0; ox < grid_width_; ++ox) {
    for (int oy = 0; oy < grid_height_; ++oy) {
      int cell_i = CellID(ox, oy);
      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];

        for (int j = i+1; j < grid_[cell_i].size(); ++j) {
          PressureParticle& pj = grid_[cell_i][j];
          AccumulateLambdaData(pi, pj);
        }
      }

      for (int dx = 0; dx <= 1; ++dx) {
        const int nx = ox + dx;
        if (nx >= grid_width_) continue;
        for (int dy = ((dx == 0) ? 1 : -1); dy <= 1; ++dy) {
          const int ny = oy + dy;
          if (ny < 0) continue;
          if (ny >= grid_width_) continue;

          int cell_j = CellID(nx, ny);

          for (int i = 0; i < grid_[cell_i].size(); ++i) {
            PressureParticle& pi = grid_[cell_i][i];
            for (int j = 0; j < grid_[cell_j].size(); ++j) {
              PressureParticle& pj = grid_[cell_j][j];
              AccumulateLambdaData(pi, pj);
            }
          }
        }
      }

      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];

        pi.density *= density_inv_ * kernel_.poly6_norm();
        density_[pi.id] = pi.density;
        const Real den = (pi.cj_grad_norm_squared_sum*kernel_.spiky_grad_norm()*kernel_.spiky_grad_norm() + (pi.ci_grad_sum * kernel_.spiky_grad_norm()).squaredNorm())*density_inv_*density_inv_ + cfm_epsilon_;
        pi.lambda = -(pi.density - 1.0) / den;
      }
    }
  }
}

void ParticleSystem::AccumulatePressureDelta(PressureParticle& pi, PressureParticle& pj) {
  const Vec2 r = pi.pos - pj.pos;
  if (r.squaredNorm() > radius2_) return;
  Real scorr = kernel_.Poly6NonNorm(r)/kernel_.Poly6NonNorm(Vec2(0.0,0.2*radius_));
  scorr = scorr*scorr*scorr*scorr;
  scorr *= -0.000005;
  const Vec2 delta = (pi.lambda + pj.lambda + scorr) * kernel_.SpikyGradNonNorm(r);
  pi.pos_delta += delta;
  pj.pos_delta -= delta;
}

void ParticleSystem::CalculatePressureDeltaOnGrid() {
  for (int ox = 0; ox < grid_width_; ++ox) {
    for (int oy = 0; oy < grid_height_; ++oy) {
      int cell_i = CellID(ox, oy);
      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];

        for (int j = i+1; j < grid_[cell_i].size(); ++j) {
          PressureParticle& pj = grid_[cell_i][j];
          AccumulatePressureDelta(pi, pj);
        }
      }

      for (int dx = 0; dx <= 1; ++dx) {
        const int nx = ox + dx;
        if (nx >= grid_width_) continue;
        for (int dy = ((dx == 0) ? 1 : -1); dy <= 1; ++dy) {
          const int ny = oy + dy;
          if (ny < 0) continue;
          if (ny >= grid_width_) continue;

          int cell_j = CellID(nx, ny);

          for (int i = 0; i < grid_[cell_i].size(); ++i) {
            PressureParticle& pi = grid_[cell_i][i];
            for (int j = 0; j < grid_[cell_j].size(); ++j) {
              PressureParticle& pj = grid_[cell_j][j];
              AccumulatePressureDelta(pi, pj);
            }
          }
        }
      }

      for (int i = 0; i < grid_[cell_i].size(); ++i) {
        PressureParticle& pi = grid_[cell_i][i];
        pi.pos_delta *= density_inv_ * kernel_.spiky_grad_norm();
      }
    }
  }
}

void ParticleSystem::ApplyPressureDeltaOnGrid() {
  for (int ox = 0; ox < grid_width_; ++ox) {
    for (int oy = 0; oy < grid_height_; ++oy) {
      for (auto& pi : grid_[CellID(ox, oy)]) {
        pi.pos += pi.pos_delta;
      }
    }
  }
}

void ParticleSystem::EnforceBoundariesOnGrid() {
  AABB shrunk_bounds = bounds_.Shrink(boundary_margin_);
  for (auto& grid_cell : grid_) {
    for (auto& particle : grid_cell) {
      if (!shrunk_bounds.IsInside(particle.pos)) {
        particle.pos = shrunk_bounds.Clip(particle.pos);
        particle.pos.x += jitter_dist_(random_);
        particle.pos.y += jitter_dist_(random_);
      }
    }
  }
}

void ParticleSystem::CopyPositionsFromGrid() {
  for (auto& grid_cell : grid_) {
    for (auto& particle: grid_cell) {
      predicted_pos_[particle.id] = particle.pos;
    }
  }
}

void ParticleSystem::ApplyViscosityOnGrid(Real dt) {

}

}  // namespace SPHack
<|endoftext|>


<commit_before>#include "includes.hpp"
#include "interface.hpp"

namespace ProjectInfo {
const char* const projectName = "Kiwano";
const char* const versionString = "0.1";
const int versionNumber = 0x10000;
}

class MainWindow : public DocumentWindow {
	user_interface itf;
	base::lisp gl;
	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainWindow);
    LookAndFeel_V1 lookAndFeelV1;
    LookAndFeel_V2 lookAndFeelV2;
    LookAndFeel_V3 lookAndFeelV3;

public:
	MainWindow(String name) : DocumentWindow(name, Colours::lightgrey, DocumentWindow::allButtons),
							  itf(gl) {
		//setUsingNativeTitleBar(true); // TODO: fix blink on startup
		setContentOwned(&itf, false);
		setSize(800, 600);
		setTopLeftPosition(200, 200);
		setResizable(true, true);
		setVisible(true);
		LookAndFeel::setDefaultLookAndFeel(&lookAndFeelV3);

		// initialize playback
		playback::init(gl);

		// initialize GLISP
		using namespace std::placeholders;
		gl.init();

		// GUI
		gl.addProcedure("create-interpreter", std::bind(&user_interface::create_interpreter, &itf, _1, _2));
		gl.addProcedure("audio-settings", std::bind(&user_interface::audio_settings, &itf, _1, _2));
		gl.addProcedure("create-text-button", std::bind(&user_interface::create_text_button, &itf, _1, _2));
		gl.addProcedure("set-main-component", std::bind(&user_interface::set_main_component, &itf, _1, _2));
		gl.addProcedure("has-component", std::bind(&user_interface::has_component, &itf, _1, _2));
		gl.addProcedure("refresh-interface", std::bind(&user_interface::refresh_interface, &itf, _1, _2));

		// GUI event binding
		gl.addProcedure("bind-mouse-click", std::bind(&user_interface::bind_listener<mouseUpListener>, &itf, _1, _2, &user_interface::add_mouse_listener_fn));
		gl.addProcedure("bind-mouse-up", std::bind(&user_interface::bind_listener<mouseUpListener>, &itf, _1, _2, &user_interface::add_mouse_listener_fn));
		gl.addProcedure("bind-mouse-double-click", std::bind(&user_interface::bind_listener<mouseDoubleClickListener>, &itf, _1, _2, &user_interface::add_mouse_listener_fn));
		gl.addProcedure("bind-mouse-down", std::bind(&user_interface::bind_listener<mouseDownListener>, &itf, _1, _2, &user_interface::add_mouse_listener_fn));
		gl.addProcedure("unbind-mouse", std::bind(&user_interface::unbind_listener, &itf, _1, _2, &user_interface::remove_mouse_listener_fx));

		// layouts
		gl.addProcedure("create-layout", std::bind(&user_interface::create_layout, &itf, _1, _2));
		gl.addProcedure("layout-add-component", std::bind(&user_interface::layout_add_component, &itf, _1, _2));
		gl.addProcedure("layout-remove-component", std::bind(&user_interface::layout_remove_component, &itf, _1, _2));
		gl.addProcedure("layout-add-splitter", std::bind(&user_interface::layout_add_splitter, &itf, _1, _2));
		gl.addProcedure("layout-get-splitter-count", std::bind(&user_interface::layout_get_splitters_count, &itf, _1, _2));
		gl.addProcedure("layout-remove-splitter", std::bind(&user_interface::layout_remove_splitter, &itf, _1, _2));

		// playlist
		gl.addProcedure("create-playlist", std::bind(&user_interface::create_playlist, &itf, _1, _2));
		gl.addProcedure("playlist-get-selected", std::bind(&user_interface::playlist_get_selected, &itf, _1, _2));

		// slider
		gl.addProcedure("create-slider", std::bind(&user_interface::create_slider, &itf, _1, _2));
		gl.addProcedure("slider-range", std::bind(&user_interface::slider_range, &itf, _1, _2));
		gl.addProcedure("slider-value", std::bind(&user_interface::slider_value, &itf, _1, _2));
		gl.addProcedure("bind-slider-changed", std::bind(&user_interface::bind_listener<sliderValueChangedListener>, &itf, _1, _2, &user_interface::add_slider_listener_fn));
		gl.addProcedure("bind-slider-drag-begin", std::bind(&user_interface::bind_listener<sliderDragBeginListener>, &itf, _1, _2, &user_interface::add_slider_listener_fn));
		gl.addProcedure("bind-slider-drag-end", std::bind(&user_interface::bind_listener<sliderDragEndedListener>, &itf, _1, _2, &user_interface::add_slider_listener_fn));
		gl.addProcedure("unbind-slider", std::bind(&user_interface::unbind_listener, &itf, _1, _2, &user_interface::remove_slider_listener_fx));

		// tabs
		gl.addProcedure("create-tabs", std::bind(&user_interface::create_tabs, &itf, _1, _2));
		gl.addProcedure("tabs-add-component", std::bind(&user_interface::tabs_add_component, &itf, _1, _2));
		gl.addProcedure("tabs-count", std::bind(&user_interface::tabs_count, &itf, _1, _2));
		gl.addProcedure("tabs-remove", std::bind(&user_interface::tabs_remove, &itf, _1, _2));
		gl.addProcedure("tabs-index", std::bind(&user_interface::tabs_index, &itf, _1, _2));

		// timers
		gl.addProcedure("create-timer", std::bind(&user_interface::create_timer, &itf, _1, _2));
		gl.addProcedure("remove-timer", std::bind(&user_interface::remove_timer, &itf, _1, _2));
		gl.addProcedure("start-timer", std::bind(&user_interface::start_timer, &itf, _1, _2));
		gl.addProcedure("stop-timer", std::bind(&user_interface::stop_timer, &itf, _1, _2));

		// playback API
		gl.addProcedure("playback-set-file", std::bind(&playback::set_file, std::ref(gl), _1, _2));
		gl.addProcedure("playback-unload-file", std::bind(&playback::unload_file, std::ref(gl), _1, _2));
		gl.addProcedure("playback-start", std::bind(&playback::start, std::ref(gl), _1, _2));
		gl.addProcedure("playback-stop", std::bind(&playback::stop, std::ref(gl), _1, _2));
		gl.addProcedure("playback-seek", std::bind(&playback::seek, std::ref(gl), _1, _2));
		gl.addProcedure("playback-length", std::bind(&playback::length, std::ref(gl), _1, _2));
		gl.addProcedure("playback-get-pos", std::bind(&playback::get_pos, std::ref(gl), _1, _2));
		gl.addProcedure("playback-is-playing", std::bind(&playback::is_playing, std::ref(gl), _1, _2));
		gl.addProcedure("playback-gain", std::bind(&playback::gain, std::ref(gl), _1, _2));
		gl.addProcedure("bind-playback", std::bind(&playback::bind_playback, std::ref(gl), _1, _2));
		gl.addProcedure("unbind-playback", std::bind(&playback::unbind_playback, std::ref(gl), _1, _2));

		// prepare settings folder
		base::string appPath = base::fs::getUserDirectory() + "/.kiwano";
		base::fs::createFolderTree(appPath);
		base::fs::open(appPath);

		// load ELISP config file
		gl.eval(base::toStr(base::fs::load("init.lisp")));
	}

	void closeButtonPressed() override {
		base::fs::close();
		gl.close();
		playback::shutdown();
		JUCEApplication::getInstance()->systemRequestedQuit();
	}
};

class KiwanoApplication : public JUCEApplication {
    ScopedPointer<MainWindow> mainWindow;

public:
    KiwanoApplication() {}

    const String getApplicationName() override { return ProjectInfo::projectName; }
    const String getApplicationVersion() override { return ProjectInfo::versionString; }
    bool moreThanOneInstanceAllowed() override { return false; }

    void initialise(const String& commandLine) override {
        mainWindow = new MainWindow(getApplicationName());
    }

    void shutdown() override {
        mainWindow = nullptr;
    }

    void systemRequestedQuit() override {
        quit();
    }

    void anotherInstanceStarted (const String& commandLine) override {
    }
};

START_JUCE_APPLICATION(KiwanoApplication);

// TODO: load default config
// TODO: lisp include
<commit_msg>+ logger added<commit_after>#include "includes.hpp"
#include "interface.hpp"

namespace ProjectInfo {
const char* const projectName = "Kiwano";
const char* const versionString = "0.1";
const int versionNumber = 0x10000;
}

class MainWindow : public DocumentWindow {
	user_interface itf;
	base::lisp gl;
	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainWindow);
    LookAndFeel_V1 lookAndFeelV1;
    LookAndFeel_V2 lookAndFeelV2;
    LookAndFeel_V3 lookAndFeelV3;

public:
	MainWindow(String name) : DocumentWindow(name, Colours::lightgrey, DocumentWindow::allButtons),
							  itf(gl) {
		//setUsingNativeTitleBar(true); // TODO: fix blink on startup
		setContentOwned(&itf, false);
		setSize(800, 600);
		setTopLeftPosition(200, 200);
		setResizable(true, true);
		setVisible(true);
		LookAndFeel::setDefaultLookAndFeel(&lookAndFeelV3);

		// initialize playback
		playback::init(gl);

		// logger
		base::log::init(base::fs::getUserDirectory() + "\\.kiwano\\log.txt");

		// initialize GLISP
		using namespace std::placeholders;
		gl.init();

		// GUI
		gl.addProcedure("create-interpreter", std::bind(&user_interface::create_interpreter, &itf, _1, _2));
		gl.addProcedure("audio-settings", std::bind(&user_interface::audio_settings, &itf, _1, _2));
		gl.addProcedure("create-text-button", std::bind(&user_interface::create_text_button, &itf, _1, _2));
		gl.addProcedure("set-main-component", std::bind(&user_interface::set_main_component, &itf, _1, _2));
		gl.addProcedure("has-component", std::bind(&user_interface::has_component, &itf, _1, _2));
		gl.addProcedure("refresh-interface", std::bind(&user_interface::refresh_interface, &itf, _1, _2));

		// GUI event binding
		gl.addProcedure("bind-mouse-click", std::bind(&user_interface::bind_listener<mouseUpListener>, &itf, _1, _2, &user_interface::add_mouse_listener_fn));
		gl.addProcedure("bind-mouse-up", std::bind(&user_interface::bind_listener<mouseUpListener>, &itf, _1, _2, &user_interface::add_mouse_listener_fn));
		gl.addProcedure("bind-mouse-double-click", std::bind(&user_interface::bind_listener<mouseDoubleClickListener>, &itf, _1, _2, &user_interface::add_mouse_listener_fn));
		gl.addProcedure("bind-mouse-down", std::bind(&user_interface::bind_listener<mouseDownListener>, &itf, _1, _2, &user_interface::add_mouse_listener_fn));
		gl.addProcedure("unbind-mouse", std::bind(&user_interface::unbind_listener, &itf, _1, _2, &user_interface::remove_mouse_listener_fx));

		// layouts
		gl.addProcedure("create-layout", std::bind(&user_interface::create_layout, &itf, _1, _2));
		gl.addProcedure("layout-add-component", std::bind(&user_interface::layout_add_component, &itf, _1, _2));
		gl.addProcedure("layout-remove-component", std::bind(&user_interface::layout_remove_component, &itf, _1, _2));
		gl.addProcedure("layout-add-splitter", std::bind(&user_interface::layout_add_splitter, &itf, _1, _2));
		gl.addProcedure("layout-get-splitter-count", std::bind(&user_interface::layout_get_splitters_count, &itf, _1, _2));
		gl.addProcedure("layout-remove-splitter", std::bind(&user_interface::layout_remove_splitter, &itf, _1, _2));

		// playlist
		gl.addProcedure("create-playlist", std::bind(&user_interface::create_playlist, &itf, _1, _2));
		gl.addProcedure("playlist-get-selected", std::bind(&user_interface::playlist_get_selected, &itf, _1, _2));

		// slider
		gl.addProcedure("create-slider", std::bind(&user_interface::create_slider, &itf, _1, _2));
		gl.addProcedure("slider-range", std::bind(&user_interface::slider_range, &itf, _1, _2));
		gl.addProcedure("slider-value", std::bind(&user_interface::slider_value, &itf, _1, _2));
		gl.addProcedure("bind-slider-changed", std::bind(&user_interface::bind_listener<sliderValueChangedListener>, &itf, _1, _2, &user_interface::add_slider_listener_fn));
		gl.addProcedure("bind-slider-drag-begin", std::bind(&user_interface::bind_listener<sliderDragBeginListener>, &itf, _1, _2, &user_interface::add_slider_listener_fn));
		gl.addProcedure("bind-slider-drag-end", std::bind(&user_interface::bind_listener<sliderDragEndedListener>, &itf, _1, _2, &user_interface::add_slider_listener_fn));
		gl.addProcedure("unbind-slider", std::bind(&user_interface::unbind_listener, &itf, _1, _2, &user_interface::remove_slider_listener_fx));

		// tabs
		gl.addProcedure("create-tabs", std::bind(&user_interface::create_tabs, &itf, _1, _2));
		gl.addProcedure("tabs-add-component", std::bind(&user_interface::tabs_add_component, &itf, _1, _2));
		gl.addProcedure("tabs-count", std::bind(&user_interface::tabs_count, &itf, _1, _2));
		gl.addProcedure("tabs-remove", std::bind(&user_interface::tabs_remove, &itf, _1, _2));
		gl.addProcedure("tabs-index", std::bind(&user_interface::tabs_index, &itf, _1, _2));

		// timers
		gl.addProcedure("create-timer", std::bind(&user_interface::create_timer, &itf, _1, _2));
		gl.addProcedure("remove-timer", std::bind(&user_interface::remove_timer, &itf, _1, _2));
		gl.addProcedure("start-timer", std::bind(&user_interface::start_timer, &itf, _1, _2));
		gl.addProcedure("stop-timer", std::bind(&user_interface::stop_timer, &itf, _1, _2));

		// playback API
		gl.addProcedure("playback-set-file", std::bind(&playback::set_file, std::ref(gl), _1, _2));
		gl.addProcedure("playback-unload-file", std::bind(&playback::unload_file, std::ref(gl), _1, _2));
		gl.addProcedure("playback-start", std::bind(&playback::start, std::ref(gl), _1, _2));
		gl.addProcedure("playback-stop", std::bind(&playback::stop, std::ref(gl), _1, _2));
		gl.addProcedure("playback-seek", std::bind(&playback::seek, std::ref(gl), _1, _2));
		gl.addProcedure("playback-length", std::bind(&playback::length, std::ref(gl), _1, _2));
		gl.addProcedure("playback-get-pos", std::bind(&playback::get_pos, std::ref(gl), _1, _2));
		gl.addProcedure("playback-is-playing", std::bind(&playback::is_playing, std::ref(gl), _1, _2));
		gl.addProcedure("playback-gain", std::bind(&playback::gain, std::ref(gl), _1, _2));
		gl.addProcedure("bind-playback", std::bind(&playback::bind_playback, std::ref(gl), _1, _2));
		gl.addProcedure("unbind-playback", std::bind(&playback::unbind_playback, std::ref(gl), _1, _2));

		// prepare settings folder
		base::string appPath = base::fs::getUserDirectory() + "/.kiwano";
		base::fs::createFolderTree(appPath);
		base::fs::open(appPath);

		// load ELISP config file
		gl.eval(base::toStr(base::fs::load("init.lisp")));
	}

	void closeButtonPressed() override {
		base::fs::close();
		gl.close();
		base::log::shutdown();
		playback::shutdown();
		JUCEApplication::getInstance()->systemRequestedQuit();
	}
};

class KiwanoApplication : public JUCEApplication {
    ScopedPointer<MainWindow> mainWindow;

public:
    KiwanoApplication() {}

    const String getApplicationName() override { return ProjectInfo::projectName; }
    const String getApplicationVersion() override { return ProjectInfo::versionString; }
    bool moreThanOneInstanceAllowed() override { return false; }

    void initialise(const String& commandLine) override {
        mainWindow = new MainWindow(getApplicationName());
    }

    void shutdown() override {
        mainWindow = nullptr;
    }

    void systemRequestedQuit() override {
        quit();
    }

    void anotherInstanceStarted (const String& commandLine) override {
    }
};

START_JUCE_APPLICATION(KiwanoApplication);

// TODO: load default config
// TODO: lisp include
<|endoftext|>


<commit_before>#include "Command.h"
#include "Test.h"
#include "Or.h"
#include "And.h"
#include "Semicolon.h"

#include <sys/stat.h>
#include <stack>
#include <queue>

// split word into tokens and put them in a vector of char*
void parse(string keyword, vector<char*> &wordList)
{
    char *cs = new char[keyword.length()];
    for (unsigned i = 0; i < keyword.length(); i++)
    {
        cs[i] = keyword[i];
    }
    cs[keyword.length()] = '\0';        //add the null terminator at the end of

    char *tokens = strtok(cs, " ");
    while (tokens)
    {
        wordList.push_back(tokens);
        tokens = strtok(NULL, " ");
    }
}

void copy(char** &arr, vector<char*>& v)
{
    v.push_back(NULL);
    arr = new char*[v.size()];
    for (unsigned i = 0; i < v.size(); i++)
    {
        arr[i] = v.at(i);
    }
}

int main()
{
    string input;

    while (1)           // shell should run indefinitely unless exited
    {

        cout << "$ ";
        getline(cin, input);                        // get whole command line

        if(input == "exit")
        {
            exit(0);
            break;
        }

        vector<char*> words;
        parse(input, words);

        queue<string> connectors;
        stack<cmdComponent*> commands;

        // for (unsigned a = 0; a < words.size(); a++)
        // {
        //     cout << words.at(a) << endl;
        // }

        //break up the vector of words into commands
        //strcmp(args[0], "test") || strcmp(args[0], "[")
        //(argv.at(0) == "test") || (argv.at(0) == "[")
        vector<char*> argv;
        for (unsigned i = 0; i < words.size(); i++)
        {
            char *sc  = (char*) memchr (words.at(i), ';', strlen(words.at(i)));
            char *And = (char*) memchr (words.at(i), '&', strlen(words.at(i)));
            char *Or  = (char*) memchr (words.at(i), '|', strlen(words.at(i)));
            char *com = (char*) memchr (words.at(i), '#', strlen(words.at(i)));

            if ( (sc == NULL && Or == NULL && And == NULL) )
            {
                if ( (com == NULL) && (i == (words.size() - 1)) )
                {
                    argv.push_back(words.at(i));
                    char** args;
                    copy(args, argv);
                    if((string(argv.at(0)) == "test") || (string(argv.at(0)) == "["))
                    {
                        Test* tst = new Test();
                        tst->setTest(args);
                        commands.push(tst);
                    }
                    else
                    {
                        Command* com = new Command();
                        com->setCommand(args);
                        commands.push(com);
                    }
                    argv.clear();
                }
                else if (com == NULL)
                {
                    argv.push_back(words.at(i));
                }
                else
                {
                    char** args;
                    copy(args, argv);
                    if((string(argv.at(0)) == "test") || (string(argv.at(0)) == "["))
                    {
                        Test* tst = new Test();
                        tst->setTest(args);
                        commands.push(tst);
                    }
                    else
                    {
                        Command* com = new Command();
                        com->setCommand(args);
                        commands.push(com);
                    }
                    argv.clear();
                    break;
                }
            }
            else
            {
                string type = "";
                if (sc)
                {
                    type = ";";
                    connectors.push(type);
                }
                else if (And)
                {
                    type = "&&";
                    connectors.push(type);
                }
                else
                {
                    type = "||";
                    connectors.push(type);
                }

                char** args;
                copy(args, argv);
                if((string(argv.at(0)) == "test") || (string(argv.at(0)) == "["))
                {
                    Test* tst = new Test();
                    tst->setTest(args);
                    commands.push(tst);
                }
                else
                {
                    Command* com = new Command();
                    com->setCommand(args);
                    commands.push(com);
                }
                argv.clear();
            }
        }

        //cout << "commands size:" << commands.size() << endl;
        //set up the command tree
        if (commands.size() > connectors.size())
        {
            //cout << "command queue size: " << commands.size() << endl;
            stack<cmdComponent*> stack;

            while (!commands.empty())
            {
                stack.push(commands.top());
                commands.pop();
            }

            //cout <<"stack size before tree:" << stack.size() << endl;
            while ((!connectors.empty()) && !stack.empty())
            {
                cmdComponent* tleft = stack.top();
                stack.pop();
                cmdComponent* tright = stack.top();
                stack.pop();

                cmdComponent* tmp;

                if (connectors.front() == ";")
                {
                    tmp = new Semicolon(tleft, tright);
                }
                else if (connectors.front() == "&&")
                {
                    tmp = new And(tleft, tright);
                }
                else
                {
                    tmp = new Or(tleft, tright);
                }
                stack.push(tmp);
                connectors.pop();
            }

            // finally execute tree of commands
            if (!stack.empty())
            {
                stack.top()->execute();
            }

        }
        else
        {
            if (commands.size() == 0)
            {

            }
            else
            {
                cout << "Error: Invalid input" << endl;
            }
        }

    }

    return 0;
}

<commit_msg>removed unnecessary comments<commit_after>#include "Command.h"
#include "Test.h"
#include "Or.h"
#include "And.h"
#include "Semicolon.h"

#include <sys/stat.h>
#include <stack>
#include <queue>

// split word into tokens and put them in a vector of char*
void parse(string keyword, vector<char*> &wordList)
{
    char *cs = new char[keyword.length()];
    for (unsigned i = 0; i < keyword.length(); i++)
    {
        cs[i] = keyword[i];
    }
    cs[keyword.length()] = '\0';        //add the null terminator at the end of

    char *tokens = strtok(cs, " ");
    while (tokens)
    {
        wordList.push_back(tokens);
        tokens = strtok(NULL, " ");
    }
}

void copy(char** &arr, vector<char*>& v)
{
    v.push_back(NULL);
    arr = new char*[v.size()];
    for (unsigned i = 0; i < v.size(); i++)
    {
        arr[i] = v.at(i);
    }
}

int main()
{
    string input;

    while (1)           // shell should run indefinitely unless exited
    {

        cout << "$ ";
        getline(cin, input);                        // get whole command line

        if(input == "exit")
        {
            exit(0);
            break;
        }

        vector<char*> words;
        parse(input, words);

        queue<string> connectors;
        stack<cmdComponent*> commands;

        // for (unsigned a = 0; a < words.size(); a++)
        // {
        //     cout << words.at(a) << endl;
        // }

        //break up the vector of words into commands
        vector<char*> argv;
        for (unsigned i = 0; i < words.size(); i++)
        {
            char *sc  = (char*) memchr (words.at(i), ';', strlen(words.at(i)));
            char *And = (char*) memchr (words.at(i), '&', strlen(words.at(i)));
            char *Or  = (char*) memchr (words.at(i), '|', strlen(words.at(i)));
            char *com = (char*) memchr (words.at(i), '#', strlen(words.at(i)));

            if ( (sc == NULL && Or == NULL && And == NULL) )
            {
                if ( (com == NULL) && (i == (words.size() - 1)) )
                {
                    argv.push_back(words.at(i));
                    char** args;
                    copy(args, argv);
                    if((string(argv.at(0)) == "test") || (string(argv.at(0)) == "["))
                    {
                        Test* tst = new Test();
                        tst->setTest(args);
                        commands.push(tst);
                    }
                    else
                    {
                        Command* com = new Command();
                        com->setCommand(args);
                        commands.push(com);
                    }
                    argv.clear();
                }
                else if (com == NULL)
                {
                    argv.push_back(words.at(i));
                }
                else
                {
                    char** args;
                    copy(args, argv);
                    if((string(argv.at(0)) == "test") || (string(argv.at(0)) == "["))
                    {
                        Test* tst = new Test();
                        tst->setTest(args);
                        commands.push(tst);
                    }
                    else
                    {
                        Command* com = new Command();
                        com->setCommand(args);
                        commands.push(com);
                    }
                    argv.clear();
                    break;
                }
            }
            else
            {
                string type = "";
                if (sc)
                {
                    type = ";";
                    connectors.push(type);
                }
                else if (And)
                {
                    type = "&&";
                    connectors.push(type);
                }
                else
                {
                    type = "||";
                    connectors.push(type);
                }

                char** args;
                copy(args, argv);
                if((string(argv.at(0)) == "test") || (string(argv.at(0)) == "["))
                {
                    Test* tst = new Test();
                    tst->setTest(args);
                    commands.push(tst);
                }
                else
                {
                    Command* com = new Command();
                    com->setCommand(args);
                    commands.push(com);
                }
                argv.clear();
            }
        }

        //cout << "commands size:" << commands.size() << endl;
        //set up the command tree
        if (commands.size() > connectors.size())
        {
            //cout << "command queue size: " << commands.size() << endl;
            stack<cmdComponent*> stack;

            while (!commands.empty())
            {
                stack.push(commands.top());
                commands.pop();
            }

            //cout <<"stack size before tree:" << stack.size() << endl;
            while ((!connectors.empty()) && !stack.empty())
            {
                cmdComponent* tleft = stack.top();
                stack.pop();
                cmdComponent* tright = stack.top();
                stack.pop();

                cmdComponent* tmp;

                if (connectors.front() == ";")
                {
                    tmp = new Semicolon(tleft, tright);
                }
                else if (connectors.front() == "&&")
                {
                    tmp = new And(tleft, tright);
                }
                else
                {
                    tmp = new Or(tleft, tright);
                }
                stack.push(tmp);
                connectors.pop();
            }

            // finally execute tree of commands
            if (!stack.empty())
            {
                stack.top()->execute();
            }

        }
        else
        {
            if (commands.size() == 0)
            {

            }
            else
            {
                cout << "Error: Invalid input" << endl;
            }
        }

    }

    return 0;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014-2015, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Jeongseok Lee <jslee02@gmail.com>
 *
 * Georgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include "dart/constraint/ConstrainedGroup.h"

#include <algorithm>
#include <iostream>
#include <vector>

#include "dart/common/Console.h"
#include "dart/constraint/ConstraintBase.h"
#include "dart/constraint/ConstraintSolver.h"

namespace dart {
namespace constraint {

//==============================================================================
ConstrainedGroup::ConstrainedGroup()
{
}

//==============================================================================
ConstrainedGroup::~ConstrainedGroup()
{
}

//==============================================================================
void ConstrainedGroup::addConstraint(const ConstraintBasePtr& _constraint)
{
  assert(_constraint != nullptr && "Attempted to add nullptr.");
  assert(!containConstraint(_constraint)
         && "Attempted to add a duplicate constraint.");
  assert(_constraint->isActive());

  mConstraints.push_back(_constraint);
}

//==============================================================================
size_t ConstrainedGroup::getNumConstraints() const
{
  return mConstraints.size();
}

//==============================================================================
ConstraintBasePtr ConstrainedGroup::getConstraint(size_t _index) const
{
  assert(_index < mConstraints.size());
  return mConstraints[_index];
}

//==============================================================================
void ConstrainedGroup::removeConstraint(const ConstraintBasePtr& _constraint)
{
  assert(_constraint != nullptr && "Attempted to add nullptr.");
  assert(containConstraint(_constraint)
         && "Attempted to remove not existing constraint.");

  mConstraints.erase(
        remove(mConstraints.begin(), mConstraints.end(), _constraint),
        mConstraints.end());
}

//==============================================================================
void ConstrainedGroup::removeAllConstraints()
{
  mConstraints.clear();
}

//==============================================================================
bool ConstrainedGroup::containConstraint(
    const ConstConstraintBasePtr& _constraint) const
{
  return std::find(mConstraints.begin(), mConstraints.end(), _constraint)
      != mConstraints.end();
}

//==============================================================================
size_t ConstrainedGroup::getTotalDimension() const
{
  size_t totalDim = 0;

  for (size_t i = 0; i < mConstraints.size(); ++i)
    totalDim += mConstraints[i]->getDimension();

  return totalDim;
}

}  // namespace constraint
}  // namespace dart
<commit_msg>Hide definition of ConstrainedGroup::containConstraint() when it's not in debug mode<commit_after>/*
 * Copyright (c) 2014-2015, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Jeongseok Lee <jslee02@gmail.com>
 *
 * Georgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include "dart/constraint/ConstrainedGroup.h"

#include <algorithm>
#include <iostream>
#include <vector>

#include "dart/common/Console.h"
#include "dart/constraint/ConstraintBase.h"
#include "dart/constraint/ConstraintSolver.h"

namespace dart {
namespace constraint {

//==============================================================================
ConstrainedGroup::ConstrainedGroup()
{
}

//==============================================================================
ConstrainedGroup::~ConstrainedGroup()
{
}

//==============================================================================
void ConstrainedGroup::addConstraint(const ConstraintBasePtr& _constraint)
{
  assert(_constraint != nullptr && "Attempted to add nullptr.");
  assert(!containConstraint(_constraint)
         && "Attempted to add a duplicate constraint.");
  assert(_constraint->isActive());

  mConstraints.push_back(_constraint);
}

//==============================================================================
size_t ConstrainedGroup::getNumConstraints() const
{
  return mConstraints.size();
}

//==============================================================================
ConstraintBasePtr ConstrainedGroup::getConstraint(size_t _index) const
{
  assert(_index < mConstraints.size());
  return mConstraints[_index];
}

//==============================================================================
void ConstrainedGroup::removeConstraint(const ConstraintBasePtr& _constraint)
{
  assert(_constraint != nullptr && "Attempted to add nullptr.");
  assert(containConstraint(_constraint)
         && "Attempted to remove not existing constraint.");

  mConstraints.erase(
        remove(mConstraints.begin(), mConstraints.end(), _constraint),
        mConstraints.end());
}

//==============================================================================
void ConstrainedGroup::removeAllConstraints()
{
  mConstraints.clear();
}

//==============================================================================
#ifndef NDEBUG
bool ConstrainedGroup::containConstraint(
    const ConstConstraintBasePtr& _constraint) const
{
  return std::find(mConstraints.begin(), mConstraints.end(), _constraint)
      != mConstraints.end();
}
#endif

//==============================================================================
size_t ConstrainedGroup::getTotalDimension() const
{
  size_t totalDim = 0;

  for (size_t i = 0; i < mConstraints.size(); ++i)
    totalDim += mConstraints[i]->getDimension();

  return totalDim;
}

}  // namespace constraint
}  // namespace dart
<|endoftext|>


<commit_before>

/*
题意：

一条直线有N个村庄，要建p个邮局，使距离和最小。

思路：
明显dp：先处理各个区间的最短的距离（打表）。
dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2]; （村庄位置为x[i]）
dp[i][j]为i个村庄j个邮局的最短距离。
dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i])

*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
#include <cmath>
#include <list>
#include <bitset>

using namespace std;

#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const double FINF = 1e18;

#define x first
#define y second

#define REP(i,j,k) for(int i =(j);i<=(k);i++)
#define REPD(i,j,k) for(int i =(j);i>=(k);i--)
#define print(x) cout<<(x)<<endl;
#define IOS ios::sync_with_stdio(0);cin.tie(0);

int dp[500][35]={0};
int dis[500][500]={0};
int x[500];

int v,p,i,j,k;

void printarray2(int* a,int len1,int len2){

	REP(i,0,len1-1){
		REP(j,0,len2-1){
			cout<<(a+i*len2+j);
		}
		cout<<endl;
	}
}
void Init(){

	scanf("%d%d",&v,&p);
	REP(i,1,v)
		scanf("%d",&x[i]);

	return ;
}

void Solve(){
	REP(i,1,v)
        REP(j,i+1,v)
            dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2];
 	printarray2((int *) dis,v+1,v+1);
 	cout<<dis[2][2];
    REP(i,1,v)
    {
        dp[i][i]=0;
        dp[i][1]=dis[1][i]; //只有一个邮局
    }

    REP(j,2,p)
        REP(i,j+1,v)
        {
        	dp[i][j]=INF;
            REP(k,j-1,i-1)
            {
                dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i]);
            }
        }

    print(dp[v][p]);

	return ;
}

int main(){
#ifdef LOCAL
	freopen("poj1160.in","r",stdin);
#endif

	Init(),Solve();
	return 0;
}<commit_msg>update poj1160<commit_after>

/*
题意：

一条直线有N个村庄，要建p个邮局，使距离和最小。

思路：
明显dp：先处理各个区间的最短的距离（打表）。
dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2]; （村庄位置为x[i]）
dp[i][j]为i个村庄j个邮局的最短距离。
dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i])

*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <cstring>
#include <string>
#include <vector>
#include <iomanip>
#include <cmath>
#include <list>
#include <bitset>

using namespace std;

#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const double FINF = 1e18;

#define x first
#define y second

#define REP(i,j,k) for(int i =(j);i<=(k);i++)
#define REPD(i,j,k) for(int i =(j);i>=(k);i--)
#define print(x) cout<<(x)<<endl;
#define IOS ios::sync_with_stdio(0);cin.tie(0);

int dp[500][35]={0};
int dis[500][500]={0};
int x[500];

int v,p,i,j,k;

void printarray2(int* a,int len1,int len2){

	REP(i,0,len1-1){
		REP(j,0,len2-1){
			cout<<*(a+i*len2+j);
		}
		cout<<endl;
	}
}
void Init(){

	scanf("%d%d",&v,&p);
	REP(i,1,v)
		scanf("%d",&x[i]);

	return ;
}

void Solve(){
	REP(i,1,v)
        REP(j,i+1,v)
            dis[i][j]=dis[i][j-1]+x[j]-x[(i+j)/2];
 	printarray2((int *) dis,v+1,v+1);
 	cout<<dis[2][2];
    REP(i,1,v)
    {
        dp[i][i]=0;
        dp[i][1]=dis[1][i]; //只有一个邮局
    }

    REP(j,2,p)
        REP(i,j+1,v)
        {
        	dp[i][j]=INF;
            REP(k,j-1,i-1)
            {
                dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][i]);
            }
        }

    print(dp[v][p]);

	return ;
}

int main(){
#ifdef LOCAL
	freopen("poj1160.in","r",stdin);
#endif

	Init(),Solve();
	return 0;
}<|endoftext|>


<commit_before>#include <errno.h>
#include <iostream>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <vector>
#include <pwd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

string shell_prompt(); //prototype for prompt function
int cmd_interpreter(string); //prototype for command interpreter
void input_redir(vector<string>); //prototype for input redirection function
int input_helper(string, string);
void output_redir(vector<string>); //prototype for output redirection function
int output_helper(string, string);

int main (int argc, char** argv)
{
	while(true)
	{
		vector<string> inVector;
		string input;
		input = shell_prompt();
		//while (inVector.back() != "")
		if (input == "exit")
		{
			//exits
			cout << "Exiting rshell." << endl;
			exit(0);
		}
		else if (input == "cd")
		{
			//change current working directory
			//grab second string and use as path
		}
		else
		{
			//take in input
			char_separator<char> sep(";", "|&#<>");
			string t;
			tokenizer< char_separator<char> > tokens(input, sep);
			BOOST_FOREACH(t, tokens)
			{
				//TODO do different things depending on delimiters in vector
				inVector.push_back(t);
			} //end BOOST_FOREACH

			bool comment_sentinel = true;
			bool pipe_sentinel = false;

			for (unsigned i = 0; i < inVector.size(); i++) //go through vector of commands - looking for comments
			{
				if(comment_sentinel)	//if a comment sign is not found, execute
				{
					string in = inVector.at(i);
//			cerr << "[ " << in << " ]" << endl;
					if (in.at(0) == '#')
					{
						comment_sentinel = false;
					}

					else
					{
						for (unsigned k = 0; k < inVector.size(); k++)
						{

							if (inVector.at(k).at(0) == '&')
							{
								//TODO: remove later and fix
							}

							else if (inVector.at(k).at(0) == '|')
							{
								if (inVector.at(k + 1).at(0) == '|') //likely to go out of range if at end of command
								{
									pipe_sentinel = true;
								}
								if (pipe_sentinel)
								{
									//TODO: remove later and fix
								}

							}

							else if (inVector.at(k).at(0) == '<')
							{
								//input redirection
					//	cerr << "we indir i hope" << endl;
								input_redir(inVector);
								 //input_redir handles
								 comment_sentinel = false; //force a skip
								 break;
							}

							else if (inVector.at(k).at(0) == '>')
							{
								//output redirection
					//	cerr << "we outdir i hope" << endl;
								output_redir(inVector);
								 //output_redir function handles this
								 comment_sentinel = false; //force a skip
								 break;

							}
							else
							{
								; //nothing
								continue;
							}
						}
						cmd_interpreter(in);
					}
				}

				//TODO: this is for connectors
				// check if the current in.at(0) character equals a connector
				// if it does, check if the next one equals a connector
				// if it does, run both commands
				// check return values of both commands
				// ????
				// profit
			}//endfor
		}//endif
	}//endwhile

	return 0;
}

void input_redir(vector<string> input)
{
	//handles all of input redirection
	for (unsigned i = 0; i < input.size(); i++)
	{
		if (input.at(i).at(0) == '<')
		{
//	cerr << "we input now" << endl;
			input_helper(input.at(i-1), input.at(i+1));
		}
	}
}

int input_helper(string one, string two)
{
	int pid = fork();
	if (pid == 0)
	{
		//child
		//open close dup
		if (open(two.c_str(), O_RDONLY) != -1)
		{
			if(close(0) != -1) //stdin
			{
				if(dup(0) != -1)
				{
		//cerr << one << endl;
					cmd_interpreter(one);
					return 1;
				}
				else
				{
					perror("dup");
					exit(1);
				}
			}
			else
			{
				perror("close");
				exit(1);
			}
		}
		else
		{
			perror("open");
			exit(1);
		}
		if (close(0) == -1)
		{
			perror("close");
			exit(1);
		}
	}
	else
	{
		//parent
//		close(0);
		if (waitpid(-1, NULL, 0) == -1)
		{
			perror("waitpid");
			exit(1);
		}
		if(close(0) == -1)
		{
			perror("close");
			exit(1);
		}
		return 1;
	}

	return 0;
}

void output_redir(vector<string> input)
{
	//handles all output redirection
	for (unsigned i = 0; i < input.size(); i++)
	{
		//iterate through vector and finds redirection
		if (input.at(i).at(0) == '>')
		{
//		cerr << "we output now" << endl;
			output_helper(input.at(i-1), input.at(i+1));
		}
	}
}

int output_helper(string one, string two)
{
cerr << one << " " << two << endl;
	int pid = fork();
	if (pid == 0)
	{
		//child
		//open close dup
		if (open(two.c_str(), O_WRONLY | O_CREAT) != -1)
		{
			if(close(1) != -1) //stdin
			{
				if(dup(1) != -1)
				{
					cmd_interpreter(one);
					return 1;
				}
				else
				{
					perror("dup");
					exit(1);
				}
			}
			else
			{
				perror("close");
				exit(1);
			}
		}
		else
		{
			perror("open");
			exit(1);
		}
		if (close(1) == -1)
		{
			perror("close");
			exit(1);
		}
	}
	else
	{
		//parent
//		close(1);
		if (waitpid(-1, NULL, 0) == -1)
		{
			perror("waitpid");
			exit(1);
		}
		if (close(1) == -1)
		{
			perror("close");
			exit(1);
		}
		return 1;
	}

	return 0;
}

int cmd_interpreter(string input)//, char** argv)
{
	//parse command to seperate command and parameters

	//int len = input.length();

	vector<string> invector;
	string t;
	char_separator<char> sep(" ");
	tokenizer< char_separator<char> > tokens(input, sep);
	//int i = 0;
	BOOST_FOREACH(t, tokens)		//tokenize input string with flags to seperate items
	{
		invector.push_back(t);
	}
	unsigned len = invector.size();

	const char** cinput = new const char*[len+2];
	const char* program = invector.at(0).c_str();

	cinput[0] = program;

	for(unsigned i = 1; i < 1 + len; i++)
	{
		cinput[i] = invector[i].c_str();
	}
	cinput[len] = '\0';

//	int pipefd[
	int pid = fork();
	if(pid == 0)
	{
		if (execvp(program, (char**)cinput) == -1)
		{
			perror("execvp"); // throw an error
			exit(1);
		}
		else
		{
			return 1;
		}
	}
	else
	{
		//append stuff here

		//parent wait
		if (waitpid(-1, NULL, 0) == -1)
		{
			perror("waitpid");
			exit(1);
		}
	}

	return 0;
}

string shell_prompt()
{
	string in;
	//TODO - error checking for getlogin and gethostname
	//implement later
//	struct utsname name;
//	errno = 0;
//	uname(&name)
	/*
	char name[256];
	int maxlen = 64;
	if (!gethostname(name, maxlen))
	{
		string strname(name);
		cout << getlogin() << "@" << name  << "$ "; //custom prompt with hostname and login name
		cin >> in;
	}
	else
	{
		perror("gethostname"); //throw error if not found
	}
	*/
	cout << "rshell$ ";
	getline(cin, in);
	cin.clear();
	return in;
}
<commit_msg>user/host names enabled, fixing execv<commit_after>#include <errno.h>
#include <iostream>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <vector>
#include <pwd.h>
#include <algorithm>
#include <functional>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

string shell_prompt(); //prototype for prompt function
int cmd_interpreter(string); //prototype for command interpreter
void input_redir(vector<string>); //prototype for input redirection function
int input_helper(string, string);
void output_redir(vector<string>); //prototype for output redirection function
int output_helper(string, string);
const char* convert(const string);

int main (int argc, char** argv)
{
	while(true)
	{
		vector<string> inVector;
		string input;
		input = shell_prompt();
		//while (inVector.back() != "")
		if (input == "exit")
		{
			//exits
			cout << "Exiting rshell." << endl;
			exit(0);
		}
		else
		{
			//take in input
			char_separator<char> sep(";", "|&#<>");
			string t;
			tokenizer< char_separator<char> > tokens(input, sep);
			BOOST_FOREACH(t, tokens)
			{
				//TODO do different things depending on delimiters in vector
				inVector.push_back(t);
			} //end BOOST_FOREACH

			bool comment_sentinel = true;
			bool pipe_sentinel = false;

			for (unsigned i = 0; i < inVector.size(); i++) //go through vector of commands - looking for comments
			{
				if(comment_sentinel)	//if a comment sign is not found, execute
				{
					string in = inVector.at(i);
//			cerr << "[ " << in << " ]" << endl;
					if (in.at(0) == '#')
					{
						comment_sentinel = false;
					}

					else
					{
						if(inVector.at(i) == "cd")
						{
							//change directory

							continue;
						}
						for (unsigned k = 0; k < inVector.size(); k++)
						{

							if (inVector.at(k).at(0) == '&')
							{
								//TODO: remove later and fix
							}

							else if (inVector.at(k).at(0) == '|')
							{
								if (inVector.at(k + 1).at(0) == '|') //likely to go out of range if at end of command
								{
									pipe_sentinel = true;
								}
								if (pipe_sentinel)
								{
									//TODO: remove later and fix
								}

							}

							else if (inVector.at(k).at(0) == '<')
							{
								//input redirection
					//	cerr << "we indir i hope" << endl;
								input_redir(inVector);
								 //input_redir handles
								 comment_sentinel = false; //force a skip
								 break;
							}

							else if (inVector.at(k).at(0) == '>')
							{
								//output redirection
					//	cerr << "we outdir i hope" << endl;
								output_redir(inVector);
								 //output_redir function handles this
								 comment_sentinel = false; //force a skip
								 break;

							}
							else
							{
								; //nothing
								continue;
							}
						}
						cmd_interpreter(in);
					}
				}

				//TODO: this is for connectors
				// check if the current in.at(0) character equals a connector
				// if it does, check if the next one equals a connector
				// if it does, run both commands
				// check return values of both commands
				// ????
				// profit
			}//endfor
		}//endif
	}//endwhile

	return 0;
}

void input_redir(vector<string> input)
{
	//handles all of input redirection
	for (unsigned i = 0; i < input.size(); i++)
	{
		if (input.at(i).at(0) == '<')
		{
//	cerr << "we input now" << endl;
			input_helper(input.at(i-1), input.at(i+1));
		}
	}
}

int input_helper(string one, string two)
{
	int pid = fork();
	if (pid == 0)
	{
		//child
		//open close dup
		if (open(two.c_str(), O_RDONLY) != -1)
		{
			if(close(0) != -1) //stdin
			{
				if(dup(0) != -1)
				{
		//cerr << one << endl;
					cmd_interpreter(one);
					return 1;
				}
				else
				{
					perror("dup");
					exit(1);
				}
			}
			else
			{
				perror("close");
				exit(1);
			}
		}
		else
		{
			perror("open");
			exit(1);
		}
		if (close(0) == -1)
		{
			perror("close");
			exit(1);
		}
	}
	else
	{
		//parent
//		close(0);
		if (waitpid(-1, NULL, 0) == -1)
		{
			perror("waitpid");
			exit(1);
		}
		if(close(0) == -1)
		{
			perror("close");
			exit(1);
		}
		return 1;
	}

	return 0;
}

void output_redir(vector<string> input)
{
	//handles all output redirectionThen pass it to your function via the .data() member of vector:
	for (unsigned i = 0; i < input.size(); i++)
	{
		//iterate through vector and finds redirection
		if (input.at(i).at(0) == '>')
		{
//		cerr << "we output now" << endl;
			output_helper(input.at(i-1), input.at(i+1));
		}
	}
}

int output_helper(string one, string two)
{
//cerr << one << " " << two << endl;
	int pid = fork();
	if (pid == 0)
	{
		//child
		//open close dup
		if (open(two.c_str(), O_WRONLY | O_CREAT) != -1)
		{
			if(close(1) != -1) //stdin
			{
				if(dup(1) != -1)
				{
					cmd_interpreter(one);
					return 1;
				}
				else
				{
					perror("dup");
					exit(1);
				}
			}
			else
			{
				perror("close");
				exit(1);
			}
		}
		else
		{
			perror("open");
			exit(1);
		}
		if (close(1) == -1)
		{
			perror("close");
			exit(1);
		}
	}
	else
	{
		//parent
//		close(1);
		if (waitpid(-1, NULL, 0) == -1)
		{
			perror("waitpid");
			exit(1);
		}
		if (close(1) == -1)
		{
			perror("close");
			exit(1);
		}
		return 1;
	}

	return 0;
}

int cmd_interpreter(string input)//, char** argv)
{
	//parse command to seperate command and parameters

	//int len = input.length();

	vector<string> invector;
	string t;
	vector<const char*> cinput;
	char_separator<char> sep(" ");
	tokenizer< char_separator<char> > tokens(input, sep);
	//int i = 0;
	BOOST_FOREACH(t, tokens)		//tokenize input string with flags to seperate items
	{
		invector.push_back(t);
	}

	transform(invector.begin(), invector.end(), back_inserter(cinput), convert);

//	for (unsigned i = 0; i < len; i++)
//	{
//		cinput.push_back(invector.at(i).c_str());
//	}
//	const char** cinput = new const char*[len+2];
//	const char* program = invector.at(0).c_str();

//	cinput[0] = program;

//	for(unsigned i = 1; i < 1 + len; i++)
//	{
//		cinput[i] = invector[i].c_str();
//	}
//	cinput[len] = '\0';

	char*  envstr = getenv("PATH");
	if (envstr == NULL)
	{
		perror("getenv");
		exit(0);
	}
	string env (envstr);
	vector<string> paths;
	split(paths, env, is_any_of(":"));

	//iterate through entire path vector and check if file exists
	for(unsigned i = 0; i < paths.size(); i++)
	{
		paths.at(i) += "/";
		paths.at(i) += cinput.at(0);

		int pid = fork();
		if(pid == 0)
		{
			if ((execv(paths.at(i).c_str(), cinput.front())) == -1)
			{
				perror("execv"); // throw an error
				exit(1);
			}
			else
			{
				return 1;
			}
		}
		else
		{
			//append stuff here

			//parent wait
			if (waitpid(-1, NULL, 0) == -1)
			{
				perror("waitpid");
				exit(1);
			}
		}
	}
	return 0;
}

string shell_prompt()
{
	string in;
	//TODO - error checking for getlogin and gethostname
	//implement later
//	struct utsname name;
//	errno = 0;
//	uname(&name)

	char name[256];
	size_t maxlen = 64;
	if (gethostname(name, maxlen) != -1)
	{
//		string strname(name);
		char* strlogin = getlogin();
		if (strlogin == NULL)
		{
			perror("getlogin");
			exit(1);
		}

		cout << strlogin << "@" << name  << "$ "; //custom prompt with hostname and login name
//		cin >> in;
	}
	else
	{
		perror("gethostname"); //throw error if not found
	}

//	cout << "rshell$ ";
	getline(cin, in);
	cin.clear();
	return in;
}

const char* convert(const string &str)
{
	return str.c_str();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include "Command.h"

void getInput(std::vector<std::string>* v)
{
    // Clear out the vector
    v->clear();

    // Extract a buffer for the input
    std::string line;
    std::getline(std::cin, line);
    std::stringstream sBuffer(line);

    // Get words
    std::string word;
    while(sBuffer >> word)
    {
        v->push_back(word);
    }
}

void printVec(std::vector<std::string>* v)
{
    for(std::vector<std::string>::iterator it = v->begin(); it != v->end(); ++ it)
    {
        std::cout << *it << std::endl;
    }
}

class CmdEat: public Command
{
    public:
        unsigned int execute(std::vector<std::string>* v)
        {
            if(v->size() < 2)
            {
                std::cout << "You ate nothing!" << std::endl;

                return 0;
            }
            std::cout << "You munched on a " << v->at(1) << std::endl;

            return 100;
        }
};

class CmdErroneous: public Command
{
    public:
        unsigned int execute(std::vector<std::string>* v)
        {
            std::cout << "This is an erroneous statement!" << std::endl;

            return 666;
        }
};

int main()
{
    //CommandFunction cf = new

    // Commands
    (new CmdErroneous())->setErroneous();
    (new CmdEat())->addAlias(0, "eat");

    std::cout << "Fuzzy Computing Machine" << std::endl;

    bool running = true;

    std::vector<std::string>* v = new std::vector<std::string>();

    while(running)
    {
        std::cout << "Enter something:" << std::endl;
        std::cout << "FCM:\\>";
        getInput(v);
        std::cout << std::endl;
        std::cout << "You entered:" << std::endl;
        printVec(v);
        std::cout << std::endl;
        std::cout << "Trying to recognize command..." << std::endl;

        Command* theCmd = Command::getCommand(v->at(0));

        if(theCmd == Command::erroneous())
        {
            std::cout << "Failed!" << std::endl;
        }
        else
        {
            std::cout << "Command recognized!" << std::endl;

            theCmd->execute(v);
        }

        std::cout << std::endl;
    }

    return 0;
}
<commit_msg>Multi-word commands<commit_after>#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <map>

#include "Command.h"

void getInput(std::vector<std::string>* v)
{
    // Clear out the vector
    v->clear();

    // Extract a buffer for the input
    std::string line;
    std::getline(std::cin, line);
    std::stringstream sBuffer(line);

    // Get words
    std::string word;
    while(sBuffer >> word)
    {
        v->push_back(word);
    }
}

void splitWords(std::string str, std::vector<std::string>* v)
{
    v->clear();

    std::stringstream sBuffer(str);
    std::string word;
    while(sBuffer >> word)
    {
        v->push_back(word);
    }
}

void printVec(std::vector<std::string>* v)
{
    for(std::vector<std::string>::iterator it = v->begin(); it != v->end(); ++ it)
    {
        std::cout << *it << std::endl;
    }
}

std::map<std::string, std::string> cmdByAlias;

bool alistatify(std::vector<std::string>* words)
{
    if(words->size() == 0)
    {
        return false;
    }

    // loop through all commands
    for(std::map<std::string, std::string>::iterator cait = cmdByAlias.begin(); cait != cmdByAlias.end(); ++ cait)
    {
        //
        std::cout << "- Testing for " << cait->first << std::endl;

        // get the words in its name
        std::vector<std::string> cmdsWords;
        splitWords(cait->first, &cmdsWords);

        // check if we don't have enough input for this to be it
        if(words->size() < cmdsWords.size())
        {
            // skip
            continue;
        }

        //
        bool itIs = true;

        // loop through all command words
        std::vector<std::string>::iterator cmdsWordIt = cmdsWords.begin();
        std::vector<std::string>::iterator wordIt = words->begin();
        while(cmdsWordIt != cmdsWords.end())
        {
            // compare it to the input
            if(*cmdsWordIt != *wordIt)
            {
                itIs = false;
                break;
            }

            ++ cmdsWordIt;
            ++ wordIt;
        }

        //
        if(itIs)
        {
            // Do whatever
            std::cout << cait->second << std::endl;

            // We did something!
            break;
        }
    }
}

int main()
{
    cmdByAlias.insert(std::pair<std::string, std::string>("eat", "MUNCH!"));
    cmdByAlias.insert(std::pair<std::string, std::string>("two words", "DOUBLE TROUBLE!"));
    cmdByAlias.insert(std::pair<std::string, std::string>("take", "KLEPTOMANIA!"));
    cmdByAlias.insert(std::pair<std::string, std::string>("take a dump", "PLOP!"));

    std::cout << "Fuzzy Computing Machine" << std::endl;

    bool running = true;

    std::vector<std::string> v;

    while(running)
    {
        std::cout << "Enter something:" << std::endl;
        std::cout << "FCM:\\>";
        getInput(&v);
        std::cout << std::endl;
        std::cout << "You entered:" << std::endl;
        printVec(&v);
        std::cout << std::endl;
        std::cout << "Trying to recognize command..." << std::endl;

        alistatify(&v);

        std::cout << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2008-2014, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "avian/process.h"

#include <avian/util/runtime-array.h>

using namespace vm;

namespace {

unsigned mangledSize(int8_t c)
{
  switch (c) {
  case '_':
  case ';':
  case '[':
    return 2;

  case '$':
    return 6;

  default:
    return 1;
  }
}

unsigned mangle(int8_t c, char* dst)
{
  switch (c) {
  case '/':
    dst[0] = '_';
    return 1;

  case '_':
    dst[0] = '_';
    dst[1] = '1';
    return 2;

  case ';':
    dst[0] = '_';
    dst[1] = '2';
    return 2;

  case '[':
    dst[0] = '_';
    dst[1] = '3';
    return 2;

  case '$':
    memcpy(dst, "_00024", 6);
    return 6;

  default:
    dst[0] = c;
    return 1;
  }
}

unsigned jniNameLength(Thread* t UNUSED, GcMethod* method, bool decorate)
{
  unsigned size = 0;

  GcByteArray* className = method->class_()->name();
  for (unsigned i = 0; i < className->length() - 1; ++i) {
    size += mangledSize(className->body()[i]);
  }

  ++size;

  GcByteArray* methodName = method->name();
  for (unsigned i = 0; i < methodName->length() - 1; ++i) {
    size += mangledSize(methodName->body()[i]);
  }

  if (decorate) {
    size += 2;

    GcByteArray* methodSpec = method->spec();
    for (unsigned i = 1;
         i < methodSpec->length() - 1 and methodSpec->body()[i] != ')';
         ++i) {
      size += mangledSize(methodSpec->body()[i]);
    }
  }

  return size;
}

void makeJNIName(Thread* t UNUSED,
                 const char* prefix,
                 unsigned prefixLength,
                 char* name,
                 GcMethod* method,
                 bool decorate)
{
  memcpy(name, prefix, prefixLength);
  name += prefixLength;

  GcByteArray* className = method->class_()->name();
  for (unsigned i = 0; i < className->length() - 1; ++i) {
    name += mangle(className->body()[i], name);
  }

  *(name++) = '_';

  GcByteArray* methodName = method->name();
  for (unsigned i = 0; i < methodName->length() - 1; ++i) {
    name += mangle(methodName->body()[i], name);
  }

  if (decorate) {
    *(name++) = '_';
    *(name++) = '_';

    GcByteArray* methodSpec = method->spec();
    for (unsigned i = 1;
         i < methodSpec->length() - 1 and methodSpec->body()[i] != ')';
         ++i) {
      name += mangle(methodSpec->body()[i], name);
    }
  }

  *(name++) = 0;
}

void* resolveNativeMethod(Thread* t,
                          const char* undecorated,
                          const char* decorated)
{
  for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
    void* p = lib->resolve(undecorated);
    if (p) {
      return p;
    } else {
      p = lib->resolve(decorated);
      if (p) {
        return p;
      }
    }
  }

  return 0;
}

void* resolveNativeMethod(Thread* t,
                          GcMethod* method,
                          const char* prefix,
                          unsigned prefixLength,
                          int footprint UNUSED)
{
  unsigned undecoratedSize = prefixLength + jniNameLength(t, method, false);
  // extra 6 is for code below:
  THREAD_RUNTIME_ARRAY(t, char, undecorated, undecoratedSize + 1 + 6);
  makeJNIName(t,
              prefix,
              prefixLength,
              RUNTIME_ARRAY_BODY(undecorated) + 1,
              method,
              false);

  unsigned decoratedSize = prefixLength + jniNameLength(t, method, true);
  // extra 6 is for code below:
  THREAD_RUNTIME_ARRAY(t, char, decorated, decoratedSize + 1 + 6);
  makeJNIName(
      t, prefix, prefixLength, RUNTIME_ARRAY_BODY(decorated) + 1, method, true);

  void* p = resolveNativeMethod(t,
                                RUNTIME_ARRAY_BODY(undecorated) + 1,
                                RUNTIME_ARRAY_BODY(decorated) + 1);
  if (p) {
    return p;
  }

#ifdef PLATFORM_WINDOWS
  // on windows, we also try the _%s@%d and %s@%d variants
  if (footprint == -1) {
    footprint = methodParameterFootprint(t, method) + 1;
    if (method->flags() & ACC_STATIC) {
      ++footprint;
    }
  }

  *RUNTIME_ARRAY_BODY(undecorated) = '_';
  vm::snprintf(RUNTIME_ARRAY_BODY(undecorated) + undecoratedSize + 1,
               5,
               "@%d",
               footprint * BytesPerWord);

  *RUNTIME_ARRAY_BODY(decorated) = '_';
  vm::snprintf(RUNTIME_ARRAY_BODY(decorated) + decoratedSize + 1,
               5,
               "@%d",
               footprint * BytesPerWord);

  p = resolveNativeMethod(
      t, RUNTIME_ARRAY_BODY(undecorated), RUNTIME_ARRAY_BODY(decorated));
  if (p) {
    return p;
  }

  // one more try without the leading underscore
  p = resolveNativeMethod(t,
                          RUNTIME_ARRAY_BODY(undecorated) + 1,
                          RUNTIME_ARRAY_BODY(decorated) + 1);
  if (p) {
    return p;
  }
#endif

  return 0;
}

GcNative* resolveNativeMethod(Thread* t, GcMethod* method)
{
  void* p = resolveNativeMethod(t, method, "Avian_", 6, 3);
  if (p) {
    return makeNative(t, p, true);
  }

  p = resolveNativeMethod(t, method, "Java_", 5, -1);
  if (p) {
    return makeNative(t, p, false);
  }

  return 0;
}

}  // namespace

namespace vm {

void resolveNative(Thread* t, GcMethod* method)
{
  PROTECT(t, method);

  assertT(t, method->flags() & ACC_NATIVE);

  initClass(t, method->class_());

  if (getMethodRuntimeData(t, method)->native() == 0) {
    GcNative* native = resolveNativeMethod(t, method);
    if (UNLIKELY(native == 0)) {
      throwNew(t,
               GcUnsatisfiedLinkError::Type,
               "%s.%s%s",
               method->class_()->name()->body().begin(),
               method->name()->body().begin(),
               method->spec()->body().begin());
    }

    PROTECT(t, native);

    GcMethodRuntimeData* runtimeData = getMethodRuntimeData(t, method);

    // ensure other threads only see the methodRuntimeDataNative field
    // populated once the object it points to has been populated:
    storeStoreMemoryBarrier();

    runtimeData->setNative(t, native);
  }
}

int findLineNumber(Thread* t UNUSED, GcMethod* method, unsigned ip)
{
  if (method->flags() & ACC_NATIVE) {
    return NativeLine;
  }

  // our parameter indicates the instruction following the one we care
  // about, so we back up first:
  --ip;

  GcLineNumberTable* lnt = method->code()->lineNumberTable();
  if (lnt) {
    unsigned bottom = 0;
    unsigned top = lnt->length();
    for (unsigned span = top - bottom; span; span = top - bottom) {
      unsigned middle = bottom + (span / 2);
      uint64_t ln = lnt->body()[middle];

      if (ip >= lineNumberIp(ln)
          and (middle + 1 == lnt->length()
               or ip < lineNumberIp(lnt->body()[middle + 1]))) {
        return lineNumberLine(ln);
      } else if (ip < lineNumberIp(ln)) {
        top = middle;
      } else if (ip > lineNumberIp(ln)) {
        bottom = middle + 1;
      }
    }

    if (top < lnt->length()) {
      return lineNumberLine(lnt->body()[top]);
    } else {
      return UnknownLine;
    }
  } else {
    return UnknownLine;
  }
}

}  // namespace vm
<commit_msg>fix windows build<commit_after>/* Copyright (c) 2008-2014, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "avian/process.h"

#include <avian/util/runtime-array.h>

using namespace vm;

namespace {

unsigned mangledSize(int8_t c)
{
  switch (c) {
  case '_':
  case ';':
  case '[':
    return 2;

  case '$':
    return 6;

  default:
    return 1;
  }
}

unsigned mangle(int8_t c, char* dst)
{
  switch (c) {
  case '/':
    dst[0] = '_';
    return 1;

  case '_':
    dst[0] = '_';
    dst[1] = '1';
    return 2;

  case ';':
    dst[0] = '_';
    dst[1] = '2';
    return 2;

  case '[':
    dst[0] = '_';
    dst[1] = '3';
    return 2;

  case '$':
    memcpy(dst, "_00024", 6);
    return 6;

  default:
    dst[0] = c;
    return 1;
  }
}

unsigned jniNameLength(Thread* t UNUSED, GcMethod* method, bool decorate)
{
  unsigned size = 0;

  GcByteArray* className = method->class_()->name();
  for (unsigned i = 0; i < className->length() - 1; ++i) {
    size += mangledSize(className->body()[i]);
  }

  ++size;

  GcByteArray* methodName = method->name();
  for (unsigned i = 0; i < methodName->length() - 1; ++i) {
    size += mangledSize(methodName->body()[i]);
  }

  if (decorate) {
    size += 2;

    GcByteArray* methodSpec = method->spec();
    for (unsigned i = 1;
         i < methodSpec->length() - 1 and methodSpec->body()[i] != ')';
         ++i) {
      size += mangledSize(methodSpec->body()[i]);
    }
  }

  return size;
}

void makeJNIName(Thread* t UNUSED,
                 const char* prefix,
                 unsigned prefixLength,
                 char* name,
                 GcMethod* method,
                 bool decorate)
{
  memcpy(name, prefix, prefixLength);
  name += prefixLength;

  GcByteArray* className = method->class_()->name();
  for (unsigned i = 0; i < className->length() - 1; ++i) {
    name += mangle(className->body()[i], name);
  }

  *(name++) = '_';

  GcByteArray* methodName = method->name();
  for (unsigned i = 0; i < methodName->length() - 1; ++i) {
    name += mangle(methodName->body()[i], name);
  }

  if (decorate) {
    *(name++) = '_';
    *(name++) = '_';

    GcByteArray* methodSpec = method->spec();
    for (unsigned i = 1;
         i < methodSpec->length() - 1 and methodSpec->body()[i] != ')';
         ++i) {
      name += mangle(methodSpec->body()[i], name);
    }
  }

  *(name++) = 0;
}

void* resolveNativeMethod(Thread* t,
                          const char* undecorated,
                          const char* decorated)
{
  for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
    void* p = lib->resolve(undecorated);
    if (p) {
      return p;
    } else {
      p = lib->resolve(decorated);
      if (p) {
        return p;
      }
    }
  }

  return 0;
}

void* resolveNativeMethod(Thread* t,
                          GcMethod* method,
                          const char* prefix,
                          unsigned prefixLength,
                          int footprint UNUSED)
{
  unsigned undecoratedSize = prefixLength + jniNameLength(t, method, false);
  // extra 6 is for code below:
  THREAD_RUNTIME_ARRAY(t, char, undecorated, undecoratedSize + 1 + 6);
  makeJNIName(t,
              prefix,
              prefixLength,
              RUNTIME_ARRAY_BODY(undecorated) + 1,
              method,
              false);

  unsigned decoratedSize = prefixLength + jniNameLength(t, method, true);
  // extra 6 is for code below:
  THREAD_RUNTIME_ARRAY(t, char, decorated, decoratedSize + 1 + 6);
  makeJNIName(
      t, prefix, prefixLength, RUNTIME_ARRAY_BODY(decorated) + 1, method, true);

  void* p = resolveNativeMethod(t,
                                RUNTIME_ARRAY_BODY(undecorated) + 1,
                                RUNTIME_ARRAY_BODY(decorated) + 1);
  if (p) {
    return p;
  }

#ifdef PLATFORM_WINDOWS
  // on windows, we also try the _%s@%d and %s@%d variants
  if (footprint == -1) {
    footprint = method->parameterFootprint() + 1;
    if (method->flags() & ACC_STATIC) {
      ++footprint;
    }
  }

  *RUNTIME_ARRAY_BODY(undecorated) = '_';
  vm::snprintf(RUNTIME_ARRAY_BODY(undecorated) + undecoratedSize + 1,
               5,
               "@%d",
               footprint * BytesPerWord);

  *RUNTIME_ARRAY_BODY(decorated) = '_';
  vm::snprintf(RUNTIME_ARRAY_BODY(decorated) + decoratedSize + 1,
               5,
               "@%d",
               footprint * BytesPerWord);

  p = resolveNativeMethod(
      t, RUNTIME_ARRAY_BODY(undecorated), RUNTIME_ARRAY_BODY(decorated));
  if (p) {
    return p;
  }

  // one more try without the leading underscore
  p = resolveNativeMethod(t,
                          RUNTIME_ARRAY_BODY(undecorated) + 1,
                          RUNTIME_ARRAY_BODY(decorated) + 1);
  if (p) {
    return p;
  }
#endif

  return 0;
}

GcNative* resolveNativeMethod(Thread* t, GcMethod* method)
{
  void* p = resolveNativeMethod(t, method, "Avian_", 6, 3);
  if (p) {
    return makeNative(t, p, true);
  }

  p = resolveNativeMethod(t, method, "Java_", 5, -1);
  if (p) {
    return makeNative(t, p, false);
  }

  return 0;
}

}  // namespace

namespace vm {

void resolveNative(Thread* t, GcMethod* method)
{
  PROTECT(t, method);

  assertT(t, method->flags() & ACC_NATIVE);

  initClass(t, method->class_());

  if (getMethodRuntimeData(t, method)->native() == 0) {
    GcNative* native = resolveNativeMethod(t, method);
    if (UNLIKELY(native == 0)) {
      throwNew(t,
               GcUnsatisfiedLinkError::Type,
               "%s.%s%s",
               method->class_()->name()->body().begin(),
               method->name()->body().begin(),
               method->spec()->body().begin());
    }

    PROTECT(t, native);

    GcMethodRuntimeData* runtimeData = getMethodRuntimeData(t, method);

    // ensure other threads only see the methodRuntimeDataNative field
    // populated once the object it points to has been populated:
    storeStoreMemoryBarrier();

    runtimeData->setNative(t, native);
  }
}

int findLineNumber(Thread* t UNUSED, GcMethod* method, unsigned ip)
{
  if (method->flags() & ACC_NATIVE) {
    return NativeLine;
  }

  // our parameter indicates the instruction following the one we care
  // about, so we back up first:
  --ip;

  GcLineNumberTable* lnt = method->code()->lineNumberTable();
  if (lnt) {
    unsigned bottom = 0;
    unsigned top = lnt->length();
    for (unsigned span = top - bottom; span; span = top - bottom) {
      unsigned middle = bottom + (span / 2);
      uint64_t ln = lnt->body()[middle];

      if (ip >= lineNumberIp(ln)
          and (middle + 1 == lnt->length()
               or ip < lineNumberIp(lnt->body()[middle + 1]))) {
        return lineNumberLine(ln);
      } else if (ip < lineNumberIp(ln)) {
        top = middle;
      } else if (ip > lineNumberIp(ln)) {
        bottom = middle + 1;
      }
    }

    if (top < lnt->length()) {
      return lineNumberLine(lnt->body()[top]);
    } else {
      return UnknownLine;
    }
  } else {
    return UnknownLine;
  }
}

}  // namespace vm
<|endoftext|>