<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "face_quad.h"
#include "edge_edge2.h"

namespace libMesh
{

// ------------------------------------------------------------
// Quad class member functions
unsigned int Quad::key (const unsigned int s) const
{
  libmesh_assert (s < this->n_sides());

  switch (s)
    {
    case 0:
      return
	this->compute_key (this->node(0),
			   this->node(1));

    case 1:
      return
	this->compute_key (this->node(1),
			   this->node(2));

    case 2:
      return
	this->compute_key (this->node(2),
			   this->node(3));

    case 3:
      return
	this->compute_key (this->node(3),
			   this->node(0));
    }

  // We will never get here...  Look at the code above.
  libmesh_error();
  return 0;
}

AutoPtr<Elem> Quad::side (const unsigned int i) const
{
  libmesh_assert (i < this->n_sides());

  Elem* edge = new Edge2;

  switch (i)
    {
    case 0:
      {
	edge->set_node(0) = this->get_node(0);
	edge->set_node(1) = this->get_node(1);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 1:
      {
	edge->set_node(0) = this->get_node(1);
	edge->set_node(1) = this->get_node(2);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 2:
      {
	edge->set_node(0) = this->get_node(2);
	edge->set_node(1) = this->get_node(3);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 3:
      {
	edge->set_node(0) = this->get_node(3);
	edge->set_node(1) = this->get_node(0);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    default:
      {
	libmesh_error();
      }
    }

  // We will never get here...  Look at the code above.
  libmesh_error();
  AutoPtr<Elem> ap_edge(edge);
  return ap_edge;
}

bool Quad::is_child_on_side(const unsigned int c,
                             const unsigned int s) const
{
  libmesh_assert (c < this->n_children());
  libmesh_assert (s < this->n_sides());

  // A quad's children and nodes don't share the same ordering:
  // child 2 and 3 are swapped;
  unsigned int n = (c < 2) ? c : 5-c;
  return (n == s || n == (s+1)%4);
}

unsigned int Quad::opposite_side(const unsigned int side) const
{
  libmesh_assert(side < 4);

  return (side + 2) % 4;
}

unsigned int Quad::opposite_node(const unsigned int node,
                                 const unsigned int side) const
{
  libmesh_assert(node < 8);
  libmesh_assert(node < this->n_nodes());
  libmesh_assert(side < this->n_sides());
  libmesh_assert(this->is_node_on_side(node, side));

  unsigned int opposite;

  switch (side)
  {
  case 0:
  case 2:
    static const unsigned char side02_nodes_map[] =
      {3, 2, 1, 0, 6, 255, 4, 255};
    return side02_nodes_map[node];
    break;
  case 1:
  case 3:
    static const unsigned char side13_nodes_map[] =
      {1, 0, 3, 2, 255, 7, 255, 5};
    return side13_nodes_map[node];
    break;
  }

  libmesh_error();
  return 255;
}

Real Quad::quality (const ElemQuality q) const
{
  switch (q)
    {

      /**
       * Compue the min/max diagonal ratio.
       * This is modeled after the Hex element
       */
    case DISTORTION:
    case DIAGONAL:
    case STRETCH:
      {
	// Diagonal between node 0 and node 2
	const Real d02 = this->length(0,2);

	// Diagonal between node 1 and node 3
	const Real d13 = this->length(1,3);

	// Find the biggest and smallest diagonals
        if ( (d02 > 0.) && (d13 >0.) )
          if (d02 < d13) return d02 / d13;
          else return d13 / d02;
        else
          return 0.;
	break;
      }

    default:
      return Elem::quality(q);
    }

  /**
   * I don't know what to do for this metric.
   * Maybe the base class knows.  We won't get
   * here because of the default case above.
   */
  return Elem::quality(q);
}

std::pair<Real, Real> Quad::qual_bounds (const ElemQuality q) const
{
  std::pair<Real, Real> bounds;

  switch (q)
    {

    case ASPECT_RATIO:
      bounds.first  = 1.;
      bounds.second = 4.;
      break;

    case SKEW:
      bounds.first  = 0.;
      bounds.second = 0.5;
      break;

    case TAPER:
      bounds.first  = 0.;
      bounds.second = 0.7;
      break;

    case WARP:
      bounds.first  = 0.9;
      bounds.second = 1.;
      break;

    case STRETCH:
      bounds.first  = 0.25;
      bounds.second = 1.;
      break;

    case MIN_ANGLE:
      bounds.first  = 45.;
      bounds.second = 90.;
      break;

    case MAX_ANGLE:
      bounds.first  = 90.;
      bounds.second = 135.;
      break;

    case CONDITION:
      bounds.first  = 1.;
      bounds.second = 4.;
      break;

    case JACOBIAN:
      bounds.first  = 0.5;
      bounds.second = 1.;
      break;

    case SHEAR:
    case SHAPE:
    case SIZE:
      bounds.first  = 0.3;
      bounds.second = 1.;
      break;

    case DISTORTION:
      bounds.first  = 0.6;
      bounds.second = 1.;
      break;

    default:
      libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
      bounds.first  = -1;
      bounds.second = -1;
    }

  return bounds;
}

const unsigned short int Quad::_second_order_adjacent_vertices[4][2] =
{
  {0, 1}, // vertices adjacent to node 4
  {1, 2}, // vertices adjacent to node 5
  {2, 3}, // vertices adjacent to node 6
  {0, 3}  // vertices adjacent to node 7
};

const unsigned short int Quad::_second_order_vertex_child_number[9] =
{
  99,99,99,99, // Vertices
  0,1,2,0,     // Edges
  0            // Interior
};

const unsigned short int Quad::_second_order_vertex_child_index[9] =
{
  99,99,99,99, // Vertices
  1,2,3,3,     // Edges
  2            // Interior
};

} // namespace libMesh
<commit_msg>Fix unused variable warning in DEBUG mode.<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "face_quad.h"
#include "edge_edge2.h"

namespace libMesh
{

// ------------------------------------------------------------
// Quad class member functions
unsigned int Quad::key (const unsigned int s) const
{
  libmesh_assert (s < this->n_sides());

  switch (s)
    {
    case 0:
      return
	this->compute_key (this->node(0),
			   this->node(1));

    case 1:
      return
	this->compute_key (this->node(1),
			   this->node(2));

    case 2:
      return
	this->compute_key (this->node(2),
			   this->node(3));

    case 3:
      return
	this->compute_key (this->node(3),
			   this->node(0));
    }

  // We will never get here...  Look at the code above.
  libmesh_error();
  return 0;
}

AutoPtr<Elem> Quad::side (const unsigned int i) const
{
  libmesh_assert (i < this->n_sides());

  Elem* edge = new Edge2;

  switch (i)
    {
    case 0:
      {
	edge->set_node(0) = this->get_node(0);
	edge->set_node(1) = this->get_node(1);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 1:
      {
	edge->set_node(0) = this->get_node(1);
	edge->set_node(1) = this->get_node(2);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 2:
      {
	edge->set_node(0) = this->get_node(2);
	edge->set_node(1) = this->get_node(3);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    case 3:
      {
	edge->set_node(0) = this->get_node(3);
	edge->set_node(1) = this->get_node(0);

        AutoPtr<Elem> ap_edge(edge);
	return ap_edge;
      }
    default:
      {
	libmesh_error();
      }
    }

  // We will never get here...  Look at the code above.
  libmesh_error();
  AutoPtr<Elem> ap_edge(edge);
  return ap_edge;
}

bool Quad::is_child_on_side(const unsigned int c,
                             const unsigned int s) const
{
  libmesh_assert (c < this->n_children());
  libmesh_assert (s < this->n_sides());

  // A quad's children and nodes don't share the same ordering:
  // child 2 and 3 are swapped;
  unsigned int n = (c < 2) ? c : 5-c;
  return (n == s || n == (s+1)%4);
}

unsigned int Quad::opposite_side(const unsigned int side) const
{
  libmesh_assert(side < 4);

  return (side + 2) % 4;
}

unsigned int Quad::opposite_node(const unsigned int node,
                                 const unsigned int side) const
{
  libmesh_assert(node < 8);
  libmesh_assert(node < this->n_nodes());
  libmesh_assert(side < this->n_sides());
  libmesh_assert(this->is_node_on_side(node, side));

  //unsigned int opposite;

  switch (side)
  {
  case 0:
  case 2:
    static const unsigned char side02_nodes_map[] =
      {3, 2, 1, 0, 6, 255, 4, 255};
    return side02_nodes_map[node];
    break;
  case 1:
  case 3:
    static const unsigned char side13_nodes_map[] =
      {1, 0, 3, 2, 255, 7, 255, 5};
    return side13_nodes_map[node];
    break;
  }

  libmesh_error();
  return 255;
}

Real Quad::quality (const ElemQuality q) const
{
  switch (q)
    {

      /**
       * Compue the min/max diagonal ratio.
       * This is modeled after the Hex element
       */
    case DISTORTION:
    case DIAGONAL:
    case STRETCH:
      {
	// Diagonal between node 0 and node 2
	const Real d02 = this->length(0,2);

	// Diagonal between node 1 and node 3
	const Real d13 = this->length(1,3);

	// Find the biggest and smallest diagonals
        if ( (d02 > 0.) && (d13 >0.) )
          if (d02 < d13) return d02 / d13;
          else return d13 / d02;
        else
          return 0.;
	break;
      }

    default:
      return Elem::quality(q);
    }

  /**
   * I don't know what to do for this metric.
   * Maybe the base class knows.  We won't get
   * here because of the default case above.
   */
  return Elem::quality(q);
}

std::pair<Real, Real> Quad::qual_bounds (const ElemQuality q) const
{
  std::pair<Real, Real> bounds;

  switch (q)
    {

    case ASPECT_RATIO:
      bounds.first  = 1.;
      bounds.second = 4.;
      break;

    case SKEW:
      bounds.first  = 0.;
      bounds.second = 0.5;
      break;

    case TAPER:
      bounds.first  = 0.;
      bounds.second = 0.7;
      break;

    case WARP:
      bounds.first  = 0.9;
      bounds.second = 1.;
      break;

    case STRETCH:
      bounds.first  = 0.25;
      bounds.second = 1.;
      break;

    case MIN_ANGLE:
      bounds.first  = 45.;
      bounds.second = 90.;
      break;

    case MAX_ANGLE:
      bounds.first  = 90.;
      bounds.second = 135.;
      break;

    case CONDITION:
      bounds.first  = 1.;
      bounds.second = 4.;
      break;

    case JACOBIAN:
      bounds.first  = 0.5;
      bounds.second = 1.;
      break;

    case SHEAR:
    case SHAPE:
    case SIZE:
      bounds.first  = 0.3;
      bounds.second = 1.;
      break;

    case DISTORTION:
      bounds.first  = 0.6;
      bounds.second = 1.;
      break;

    default:
      libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
      bounds.first  = -1;
      bounds.second = -1;
    }

  return bounds;
}

const unsigned short int Quad::_second_order_adjacent_vertices[4][2] =
{
  {0, 1}, // vertices adjacent to node 4
  {1, 2}, // vertices adjacent to node 5
  {2, 3}, // vertices adjacent to node 6
  {0, 3}  // vertices adjacent to node 7
};

const unsigned short int Quad::_second_order_vertex_child_number[9] =
{
  99,99,99,99, // Vertices
  0,1,2,0,     // Edges
  0            // Interior
};

const unsigned short int Quad::_second_order_vertex_child_index[9] =
{
  99,99,99,99, // Vertices
  1,2,3,3,     // Edges
  2            // Interior
};

} // namespace libMesh
<|endoftext|>


<commit_before>#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"
#include "EasyBMP.h"
#define _CRT_SECURE_NO_WARNINGS

int main() {
	for (int count = 0; count < 16; count++) {
		int sqSize = (2 << 3) + 1;
		int x = sqSize;
		int y = sqSize;
		int z = 50;
		World_Map Plot(x, y, z);
		//Diamond_Square terrain(5, 100);
		BMP *image = new BMP;
		/*
		int *tl = (int*)calloc(sizeof(int), 4);
		int *tr = (int*)calloc(sizeof(int), 4);
		int *br = (int*)calloc(sizeof(int), 4);
		int *bl = (int*)calloc(sizeof(int), 4);
		tl[0] = 0;
		tl[1] = terrain.get_size() - 1;
		tr[0] = terrain.get_size() - 1;
		tr[1] = terrain.get_size() - 1;
		br[0] = terrain.get_size() - 1;
		br[1] = 0;
		bl[0] = 0;
		bl[1] = 0;
		terrain.square(tl, tr, br, bl);
		*/
		//Generate_Shapes shape(4);
		//shape.make2dterrainimage(terrain.get_array2d());

		DS* obj = new DS(sqSize);
		obj->DiamondSquare(z - 1);
		Plot.convert_to_3d(obj->get_grid());
		Isometric_Render iso(&Plot, image, 0, x - 1, 0, y - 1, 0, z - 1);
		image->SetSize(iso.width + DEBUGGING_WIDTH, iso.height + DEBUGGING_HEIGHT);

		//for (int level = x + y + z - 3; level >=3; level--) {
		//for (int level = 3; level < x + y + z - 3; level++) {
		for (int level = ((count >> 3) % 2) ? 3 : x + y + z - 3; ((count >> 3) % 2) ? (level < x + y + z - 3) : (level >= 3); level += ((count >> 3) % 2) ? 1 : -1) {

			//cout << "hi" << endl;

			//for (i = 1; i < x - 1; i++) {
			//for (i = x - 1; i >= 1; i--) {
			for (int i = ((count >> 2) % 2) ? x - 1 : 1; ((count >> 2) % 2) ? (i >= 1) : (i < x - 1); i += ((count >> 2) % 2) ? -1 : 1) {

				//cout << "can" << endl;

				//for (j = 1; j < y - 1; j++) {
				//for (j = y - 1; j >= 1; j--) {
				for (int j = ((count >> 1) % 2) ? y - 1 : 1; ((count >> 1) % 2) ? (j >= 1) : (j < y - 1); j += ((count >> 1) % 2) ? -1 : 1) {

					//cout << "i" << endl;

					//for (k = z-1; k >= 1; k--) {
					//for (k = 1; k < z - 1; k++) {
					for (int k = ((count >> 0) % 2) ? z - 1 : 1; ((count >> 0) % 2) ? (k >= 1) : (k < z - 1); k += ((count >> 0) % 2) ? -1 : 1) {

						//cout << "help" << endl;

						if ((i + j + k) == level) {
							if (Plot.map[i][j][k]->isSet == 1) {
								/*Plot.map[i][j][k]->r = 192;
								Plot.map[i][j][k]->g = 192;
								Plot.map[i][j][k]->b = 192;
								*/iso.place_cube(i, j, k);
							}
						}
					}
				}
			}
		}
		time_t now = time(NULL);
		struct tm *time_info = new tm;
		localtime_s(time_info, &now);
		if (time_info) {}
		//time_t t = time(0);   // get time now
		//struct tm * now = localtime_s(&t);
		std::stringstream buffer;

		//buffer << "sets/isometric"
			/*	<< (time_info->tm_year + 1900) << '.'
			<< (time_info->tm_mon + 1) << '.'
			<< time_info->tm_mday << '-'
			<< time_info->tm_hour << "h_"
			<< time_info->tm_min << "m_"
			<< time_info->tm_sec << "s"
			*/
		buffer << "sets/"
			<< (count >> 3)%2 << (count >> 2) % 2 << (count >> 1) % 2 << (count >> 0) % 2
					<< ".bmp";
		image->WriteToFile(buffer.str().c_str());
		delete time_info;
		//delete[]iso;
		//delete[]obj;
		//delete[]image;
		//delete[]Plot;
		//delete[]terrain;

	}
	return EXIT_SUCCESS;
}
<commit_msg>added depricated code<commit_after>#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"
#include "EasyBMP.h"
#define _CRT_SECURE_NO_WARNINGS

int main() {
	for (int count = 0; count < 16; count++) {
		int sqSize = (2 << 3) + 1;
		int x = sqSize;
		int y = sqSize;
		int z = 50;
		World_Map Plot(x, y, z);
		//Diamond_Square terrain(5, 100);
		BMP *image = new BMP;
		/*
		int *tl = (int*)calloc(sizeof(int), 4);
		int *tr = (int*)calloc(sizeof(int), 4);
		int *br = (int*)calloc(sizeof(int), 4);
		int *bl = (int*)calloc(sizeof(int), 4);
		tl[0] = 0;
		tl[1] = terrain.get_size() - 1;
		tr[0] = terrain.get_size() - 1;
		tr[1] = terrain.get_size() - 1;
		br[0] = terrain.get_size() - 1;
		br[1] = 0;
		bl[0] = 0;
		bl[1] = 0;
		terrain.square(tl, tr, br, bl);
		*/
		//Generate_Shapes shape(4);
		//shape.make2dterrainimage(terrain.get_array2d());

		DS* obj = new DS(sqSize);
		obj->DiamondSquare(z - 1);
		Plot.convert_to_3d(obj->get_grid());
		Isometric_Render iso(&Plot, image, 0, x - 1, 0, y - 1, 0, z - 1);
		image->SetSize(iso.width + DEBUGGING_WIDTH, iso.height + DEBUGGING_HEIGHT);

		//for (int level = x + y + z - 3; level >=3; level--) {
		//for (int level = 3; level < x + y + z - 3; level++) {
		for (int level = ((count >> 3) % 2) ? 3 : x + y + z - 3; ((count >> 3) % 2) ? (level < x + y + z - 3) : (level >= 3); level += ((count >> 3) % 2) ? 1 : -1) {

			//cout << "hi" << endl;

			//for (i = 1; i < x - 1; i++) {
			//for (i = x - 1; i >= 1; i--) {
			for (int i = ((count >> 2) % 2) ? x - 1 : 1; ((count >> 2) % 2) ? (i >= 1) : (i < x - 1); i += ((count >> 2) % 2) ? -1 : 1) {

				//cout << "can" << endl;

				//for (j = 1; j < y - 1; j++) {
				//for (j = y - 1; j >= 1; j--) {
				for (int j = ((count >> 1) % 2) ? y - 1 : 1; ((count >> 1) % 2) ? (j >= 1) : (j < y - 1); j += ((count >> 1) % 2) ? -1 : 1) {

					//cout << "i" << endl;

					//for (k = z-1; k >= 1; k--) {
					//for (k = 1; k < z - 1; k++) {
					for (int k = ((count >> 0) % 2) ? z - 1 : 1; ((count >> 0) % 2) ? (k >= 1) : (k < z - 1); k += ((count >> 0) % 2) ? -1 : 1) {

						//cout << "help" << endl;

						if ((i + j + k) == level) {
							if (Plot.map[i][j][k]->isSet == 1) {
								/*Plot.map[i][j][k]->r = 192;
								Plot.map[i][j][k]->g = 192;
								Plot.map[i][j][k]->b = 192;
								*/iso.place_cube(i, j, k);
							}
						}
					}
				}
			}
		}
		//time_t now = time(NULL);
		//struct tm *time_info = new tm;
		//localtime_s(time_info, &now);
		time_t now = time(0);   // get time now
		struct tm * time_info = localtime(&now);
		std::stringstream buffer;

		//buffer << "sets/isometric"
			/*	<< (time_info->tm_year + 1900) << '.'
			<< (time_info->tm_mon + 1) << '.'
			<< time_info->tm_mday << '-'
			<< time_info->tm_hour << "h_"
			<< time_info->tm_min << "m_"
			<< time_info->tm_sec << "s"
			*/
		buffer << "sets/"
			<< (count >> 3)%2 << (count >> 2) % 2 << (count >> 1) % 2 << (count >> 0) % 2
					<< ".bmp";
		image->WriteToFile(buffer.str().c_str());
		delete time_info;
		//delete[]iso;
		//delete[]obj;
		//delete[]image;
		//delete[]Plot;
		//delete[]terrain;

	}
	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "geometry/ray.h"

//using glm::min;
//using glm::max;
//source
//http://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms

bool Ray::intersectAabb(const aabb &bb, float &t) const{
    // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
    // r.org is origin of ray
    float t1 = (bb.min.x - origin.x)*dirfrac.x;
    float t2 = (bb.max.x - origin.x)*dirfrac.x;
    float t3 = (bb.min.y - origin.y)*dirfrac.y;
    float t4 = (bb.max.y - origin.y)*dirfrac.y;
    float t5 = (bb.min.z - origin.z)*dirfrac.z;
    float t6 = (bb.max.z - origin.z)*dirfrac.z;

    float tmin = max(max(min(t1, t2), min(t3, t4)), min(t5, t6));
    float tmax = min(min(max(t1, t2), max(t3, t4)), max(t5, t6));

    // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
    if (tmax < 0)
    {
        t = tmax;
        return false;
    }

    // if tmin > tmax, ray doesn't intersect AABB
    if (tmin > tmax)
    {
        t = tmax;
        return false;
    }

    t = tmin;
    return true;
}

bool Ray::intersectSphere(const Sphere &s, float &t1, float &t2) const{
    vec3 L = origin-s.pos;
    float a = glm::dot(direction,direction);
    float b = 2*glm::dot(direction,( L));
    float c = glm::dot(L,L) - s.r*s.r;
    float D = b*b + (-4.0f)*a*c;

    // If ray can not intersect then stop
    if (D < 0)
        return false;

    if(D==0){
        t1 = t2 = - 0.5 * b / a;
    }else{
        t1 = -0.5 * (b + sqrt(D)) / a ;
        t2 =  -0.5 * (b - sqrt(D)) / a;
    }
    if (t1 > t2) std::swap(t1, t2);

    return true;
}

bool Ray::intersectTriangle(const Triangle &tri, float &out, bool &back) const{
#define EPSILON 0.000001
    vec3 e1, e2;  //Edge1, Edge2
    vec3 P, Q, T;
    float det, inv_det, u, v;
    float t;

    //Find vectors for two edges sharing V1
    e1 = tri.b - tri.a;
    e2 = tri.c-tri.a;

    //culling
    vec3 n = glm::cross(e1,e2);
    back = glm::dot(direction,n)>0;

    //Begin calculating determinant - also used to calculate u parameter
    P = glm::cross( direction, e2);
    //if determinant is near zero, ray lies in plane of triangle
    det = glm::dot(e1, P);

    //NOT CULLING
    if(det > -EPSILON && det < EPSILON) return 0;
    inv_det = 1.f / det;

    //calculate distance from V1 to ray origin
    T=origin-tri.a;

    //Calculate u parameter and test bound
    u = glm::dot(T, P) * inv_det;
    //The intersection lies outside of the triangle
    if(u < 0.f || u > 1.f) return 0;

    //Prepare to test v parameter
    Q = glm::cross( T, e1);

    //Calculate V parameter and test bound
    v = glm::dot(direction, Q) * inv_det;
    //The intersection lies outside of the triangle
    if(v < 0.f || u + v  > 1.f) return 0;

    t = glm::dot(e2, Q) * inv_det;

    if(t > EPSILON) { //ray intersection
        out = t;
        return 1;
    }

    // No hit, no win
    return 0;
}

bool Ray::intersectPlane(const Plane &p, float &t) const
{
#define EPSILON 0.000001

    float denom = glm::dot(p.normal, direction);
    if (abs(denom) > EPSILON)
    {
        t = glm::dot(p.point - origin, p.normal) / denom;
        if (t >= 0){
            return true;
        }
    }
    return false;
}

std::ostream& operator<<(std::ostream& os, const Ray& r)
{
    std::cout<<"Ray: ("<<r.origin.x<<","<<r.origin.y<<","<<r.origin.z<<")";
    std::cout<<" ("<<r.direction.x<<","<<r.direction.y<<","<<r.direction.z<<")";
    return os;
}
<commit_msg>ray intersectionfix<commit_after>#include "geometry/ray.h"

//using glm::min;
//using glm::max;
//source
//http://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms

bool Ray::intersectAabb(const aabb &bb, float &t) const{
    // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
    // r.org is origin of ray
    float t1 = (bb.min.x - origin.x)*dirfrac.x;
    float t2 = (bb.max.x - origin.x)*dirfrac.x;
    float t3 = (bb.min.y - origin.y)*dirfrac.y;
    float t4 = (bb.max.y - origin.y)*dirfrac.y;
    float t5 = (bb.min.z - origin.z)*dirfrac.z;
    float t6 = (bb.max.z - origin.z)*dirfrac.z;

    float tmin = max(max(min(t1, t2), min(t3, t4)), min(t5, t6));
    float tmax = min(min(max(t1, t2), max(t3, t4)), max(t5, t6));

    // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
    if (tmax < 0)
    {
        t = tmax;
        return false;
    }

    // if tmin > tmax, ray doesn't intersect AABB
    if (tmin > tmax)
    {
        t = tmax;
        return false;
    }

    t = tmin;
    return true;
}

bool Ray::intersectSphere(const Sphere &s, float &t1, float &t2) const{
    vec3 L = origin-s.pos;
    float a = glm::dot(direction,direction);
    float b = 2*glm::dot(direction,( L));
    float c = glm::dot(L,L) - s.r*s.r;
    float D = b*b + (-4.0f)*a*c;

    // If ray can not intersect then stop
    if (D < 0)
        return false;

    if(D==0){
        t1 = t2 = - 0.5 * b / a;
    }else{
        t1 = -0.5 * (b + sqrt(D)) / a ;
        t2 =  -0.5 * (b - sqrt(D)) / a;
    }
    if (t1 > t2) std::swap(t1, t2);

    return true;
}

bool Ray::intersectTriangle(const Triangle &tri, float &out, bool &back) const{
#define EPSILON 0.000001
    vec3 e1, e2;  //Edge1, Edge2
    vec3 P, Q, T;
    float det, inv_det, u, v;
    float t;

    //Find vectors for two edges sharing V1
    e1 = tri.b - tri.a;
    e2 = tri.c-tri.a;

    //culling
    vec3 n = glm::cross(e1,e2);
    back = glm::dot(direction,n)>0;

    //Begin calculating determinant - also used to calculate u parameter
    P = glm::cross( direction, e2);
    //if determinant is near zero, ray lies in plane of triangle
    det = glm::dot(e1, P);

    //NOT CULLING
    if(det > -EPSILON && det < EPSILON) return 0;
    inv_det = 1.f / det;

    //calculate distance from V1 to ray origin
    T=origin-tri.a;

    //Calculate u parameter and test bound
    u = glm::dot(T, P) * inv_det;
    //The intersection lies outside of the triangle
    if(u < 0.f || u > 1.f) return 0;

    //Prepare to test v parameter
    Q = glm::cross( T, e1);

    //Calculate V parameter and test bound
    v = glm::dot(direction, Q) * inv_det;
    //The intersection lies outside of the triangle
    if(v < 0.f || u + v  > 1.f) return 0;

    t = glm::dot(e2, Q) * inv_det;

    if(t > EPSILON) { //ray intersection
        out = t;
        return 1;
    }

    // No hit, no win
    return 0;
}

bool Ray::intersectPlane(const Plane &p, float &t) const
{
#define EPSILON 0.000001

    float denom = glm::dot(p.normal, direction);

    if (glm::abs(denom) > EPSILON)
    {
        t = glm::dot(p.point - origin, p.normal) / denom;
        if (t >= 0){
            return true;
        }
    }
    return false;
}

std::ostream& operator<<(std::ostream& os, const Ray& r)
{
    std::cout<<"Ray: ("<<r.origin.x<<","<<r.origin.y<<","<<r.origin.z<<")";
    std::cout<<" ("<<r.direction.x<<","<<r.direction.y<<","<<r.direction.z<<")";
    return os;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <windows.h>

using namespace std;

class Game{
public:
    void Maps(){
        char Map[10][10] = {
                {"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"}
        };

        for(row = 0; row < 10; ++row)
        {
            for(cal = 0; col < 10; ++col)
            {
                cout << Map[row][col];
            }
        }

    }
};

int main() {
    Game GP;
    GP.Maps();

    return 0;
}
<commit_msg>I wanted to finish it but im also done!<commit_after>#include <iostream>
#include <windows.h>

using namespace std;

class Game{
public:
    void Maps(){
        char* currentMap;
        char Map[10][10] = {
                {"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"},
                {"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"}
        };
        int playerRow = 2;
        int playerCol = 2;

        while(true){
            if(GetAsyncKeyState(VK_UP))
                playerRow -= 1;
            if(GetAsyncKeyState(VK_DOWN))
                playerRow += 1;
            if(GetAsyncKeyState(VK_RIGHT))
                playerCol -= 1;
            if(GetAsyncKeyState(VK_LEFT))
                playerCol += 1;

            for(row = 0; row < 10; ++row)
            {
                for(cal = 0; col < 10; ++col)
                {
                    if(row == playerRow && col == playerCol)
                        cout << ">";
                    else
                        cout << currentMap[row][col];

                }
            }
        }

    }
};

int main() {
    Game GP;
    GP.Maps();

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>X86: Actually handle 16 bit mode modrm.<commit_after><|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwengine.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#ifdef RW_OPENGL
#include <GL/glew.h>
#include "rwgl3.h"
#include "rwgl3shader.h"

#include "rwgl3impl.h"

int renderpassfudge = 2;

namespace rw {
namespace gl3 {

#define MAX_LIGHTS

void
drawInst_simple(InstanceDataHeader *header, InstanceData *inst)
{
	flushCache();
	glDrawElements(header->primType, inst->numIndex,
	               GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
}

// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void
drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst)
{
	uint32 hasAlpha;
	int alphafunc, alpharef, gsalpharef;
	int zwrite;
	hasAlpha = getAlphaBlend();
	if(hasAlpha){
		zwrite = rw::GetRenderState(rw::ZWRITEENABLE);
		alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);
		if(zwrite){
			alpharef = rw::GetRenderState(rw::ALPHATESTREF);
			gsalpharef = rw::GetRenderState(rw::GSALPHATESTREF);

			SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
			SetRenderState(rw::ALPHATESTREF, gsalpharef);
			drawInst_simple(header, inst);
			SetRenderState(rw::ALPHATESTFUNC, rw::ALPHALESS);
			SetRenderState(rw::ZWRITEENABLE, 0);
			drawInst_simple(header, inst);
			SetRenderState(rw::ZWRITEENABLE, 1);
			SetRenderState(rw::ALPHATESTFUNC, alphafunc);
			SetRenderState(rw::ALPHATESTREF, alpharef);
		}else{
			SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAALWAYS);
			drawInst_simple(header, inst);
			SetRenderState(rw::ALPHATESTFUNC, alphafunc);
		}
	}else
		drawInst_simple(header, inst);
}

void
drawInst(InstanceDataHeader *header, InstanceData *inst)
{
if(getAlphaBlend() == renderpassfudge)
return;
	if(rw::GetRenderState(rw::GSALPHATEST))
		drawInst_GSemu(header, inst);
	else
		drawInst_simple(header, inst);
}

void
setAttribPointers(AttribDesc *attribDescs, int32 numAttribs)
{
	AttribDesc *a;
	for(a = attribDescs; a != &attribDescs[numAttribs]; a++){
		glEnableVertexAttribArray(a->index);
		glVertexAttribPointer(a->index, a->size, a->type, a->normalized,
		                      a->stride, (void*)(uint64)a->offset);
	}
}

void
disableAttribPointers(AttribDesc *attribDescs, int32 numAttribs)
{
	AttribDesc *a;
	for(a = attribDescs; a != &attribDescs[numAttribs]; a++)
		glDisableVertexAttribArray(a->index);
}

int32
lightingCB(Atomic *atomic)
{
	WorldLights lightData;
	Light *directionals[8];
	Light *locals[8];
	lightData.directionals = directionals;
	lightData.numDirectionals = 8;
	lightData.locals = locals;
	lightData.numLocals = 8;

	if(atomic->geometry->flags & rw::Geometry::LIGHT){
		((World*)engine->currentWorld)->enumerateLights(atomic, &lightData);
		if((atomic->geometry->flags & rw::Geometry::NORMALS) == 0){
			// Get rid of lights that need normals when we don't have any
			lightData.numDirectionals = 0;
			lightData.numLocals = 0;
		}
		return setLights(&lightData);
	}else{
		memset(&lightData, 0, sizeof(lightData));
		return setLights(&lightData);
	}
}

#define U(i) currentShader->uniformLocations[i]

void
defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
	Material *m;

	setWorldMatrix(atomic->getFrame()->getLTM());
	lightingCB(atomic);

#ifdef RW_GL_USE_VAOS
	glBindVertexArray(header->vao);
#else
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
	glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
	setAttribPointers(header->attribDesc, header->numAttribs);
#endif

	InstanceData *inst = header->inst;
	int32 n = header->numMeshes;

	defaultShader->use();

	while(n--){
		m = inst->material;

		setMaterial(m->color, m->surfaceProps);

		setTexture(0, m->texture);

		rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);

		drawInst(header, inst);
		inst++;
	}
#ifndef RW_GL_USE_VAOS
	disableAttribPointers(header->attribDesc, header->numAttribs);
#endif
}

}
}

#endif

<commit_msg>remove test code<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwengine.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#ifdef RW_OPENGL
#include <GL/glew.h>
#include "rwgl3.h"
#include "rwgl3shader.h"

#include "rwgl3impl.h"

namespace rw {
namespace gl3 {

#define MAX_LIGHTS

void
drawInst_simple(InstanceDataHeader *header, InstanceData *inst)
{
	flushCache();
	glDrawElements(header->primType, inst->numIndex,
	               GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
}

// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void
drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst)
{
	uint32 hasAlpha;
	int alphafunc, alpharef, gsalpharef;
	int zwrite;
	hasAlpha = getAlphaBlend();
	if(hasAlpha){
		zwrite = rw::GetRenderState(rw::ZWRITEENABLE);
		alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);
		if(zwrite){
			alpharef = rw::GetRenderState(rw::ALPHATESTREF);
			gsalpharef = rw::GetRenderState(rw::GSALPHATESTREF);

			SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
			SetRenderState(rw::ALPHATESTREF, gsalpharef);
			drawInst_simple(header, inst);
			SetRenderState(rw::ALPHATESTFUNC, rw::ALPHALESS);
			SetRenderState(rw::ZWRITEENABLE, 0);
			drawInst_simple(header, inst);
			SetRenderState(rw::ZWRITEENABLE, 1);
			SetRenderState(rw::ALPHATESTFUNC, alphafunc);
			SetRenderState(rw::ALPHATESTREF, alpharef);
		}else{
			SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAALWAYS);
			drawInst_simple(header, inst);
			SetRenderState(rw::ALPHATESTFUNC, alphafunc);
		}
	}else
		drawInst_simple(header, inst);
}

void
drawInst(InstanceDataHeader *header, InstanceData *inst)
{
	if(rw::GetRenderState(rw::GSALPHATEST))
		drawInst_GSemu(header, inst);
	else
		drawInst_simple(header, inst);
}

void
setAttribPointers(AttribDesc *attribDescs, int32 numAttribs)
{
	AttribDesc *a;
	for(a = attribDescs; a != &attribDescs[numAttribs]; a++){
		glEnableVertexAttribArray(a->index);
		glVertexAttribPointer(a->index, a->size, a->type, a->normalized,
		                      a->stride, (void*)(uint64)a->offset);
	}
}

void
disableAttribPointers(AttribDesc *attribDescs, int32 numAttribs)
{
	AttribDesc *a;
	for(a = attribDescs; a != &attribDescs[numAttribs]; a++)
		glDisableVertexAttribArray(a->index);
}

int32
lightingCB(Atomic *atomic)
{
	WorldLights lightData;
	Light *directionals[8];
	Light *locals[8];
	lightData.directionals = directionals;
	lightData.numDirectionals = 8;
	lightData.locals = locals;
	lightData.numLocals = 8;

	if(atomic->geometry->flags & rw::Geometry::LIGHT){
		((World*)engine->currentWorld)->enumerateLights(atomic, &lightData);
		if((atomic->geometry->flags & rw::Geometry::NORMALS) == 0){
			// Get rid of lights that need normals when we don't have any
			lightData.numDirectionals = 0;
			lightData.numLocals = 0;
		}
		return setLights(&lightData);
	}else{
		memset(&lightData, 0, sizeof(lightData));
		return setLights(&lightData);
	}
}

#define U(i) currentShader->uniformLocations[i]

void
defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
	Material *m;

	setWorldMatrix(atomic->getFrame()->getLTM());
	lightingCB(atomic);

#ifdef RW_GL_USE_VAOS
	glBindVertexArray(header->vao);
#else
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
	glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
	setAttribPointers(header->attribDesc, header->numAttribs);
#endif

	InstanceData *inst = header->inst;
	int32 n = header->numMeshes;

	defaultShader->use();

	while(n--){
		m = inst->material;

		setMaterial(m->color, m->surfaceProps);

		setTexture(0, m->texture);

		rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);

		drawInst(header, inst);
		inst++;
	}
#ifndef RW_GL_USE_VAOS
	disableAttribPointers(header->attribDesc, header->numAttribs);
#endif
}

}
}

#endif

<|endoftext|>


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

#include <algorithm>
#include <iomanip>

#include "AndNode.h"
#include "IdNode.h"
#include "NotNode.h"
#include "SyntacticException.h"
#include "OrNode.h"
#include "XorNode.h"

#include "BooleanParser.h"

BooleanTree::BooleanTree(const std::string& input_)
{
	input = std::make_unique<char[]>(input_.size()+1);
	std::strcpy(input.get(), input_.c_str());
	lexer = std::make_unique<Lexer>(input.get());
	toRPN();
}

void
BooleanTree::Parse()
{
	root = BuildTree();
	if (!stack_output.empty()) {
		Token token = stack_output.back();
		string msj = "'" + token.lexeme + "' not expected";
		throw SyntacticException(msj.c_str());
	}
}

std::unique_ptr<BaseNode>
BooleanTree::BuildTree()
{
	if (stack_output.size() == 1 || stack_output.back().type == TokenType::Id) {
		Token token = stack_output.back();
		stack_output.pop_back();
		string id = token.lexeme;
		return std::make_unique<IdNode>(id);
	}
	/* Error case */
	else if (stack_output.size() == 1 && stack_output.back().type != TokenType::Id) {
		Token token = stack_output.back();
		string msj = "'" + token.lexeme + "' not expected";
		throw SyntacticException(msj.c_str());
	} else {
		Token token = stack_output.back();
		stack_output.pop_back();
		switch(token.type) {
			case TokenType::Not	:
				return std::make_unique<NotNode>(BuildTree());
				break;
			case TokenType::Or:
				return std::make_unique<OrNode>(BuildTree(), BuildTree());
				break;
			case TokenType::And:
				return std::make_unique<AndNode>(BuildTree(), BuildTree());
				break;
			case TokenType::Xor:
				return std::make_unique<XorNode>(BuildTree(), BuildTree());
				break;
			default:
				// Silence compiler switch warning
				break;
		}
	}
	return nullptr;
}

/*
 * Convert to RPN (Reverse Polish notation)
 * with Dijkstra's Shunting-yard algorithm.
 */
void
BooleanTree::toRPN()
{
	currentToken = lexer->NextToken();

	while (currentToken.type != TokenType::EndOfFile) {

		switch (currentToken.type) {

			case TokenType::Id:
				stack_output.push_back(currentToken);
				break;

			case TokenType::LeftParenthesis:
				stack_operator.push_back(currentToken);
				break;

			case TokenType::RightParenthesis:
				while (true) {
					if (!stack_operator.empty()) {
							Token token_back = stack_operator.back();
						if (token_back.type != TokenType::LeftParenthesis) {
							stack_output.push_back(token_back);
							stack_operator.pop_back();
						} else {
							stack_operator.pop_back();
							break;
						}
					} else {
						string msj = ") was expected";
						throw SyntacticException(msj.c_str());
					}
				}
				break;
			case TokenType::Not:
			case TokenType::Or:
			case TokenType::And:
			case TokenType::Xor:
				while (!stack_operator.empty() && precedence(currentToken.type) >= precedence(stack_operator.back().type)) {
					Token token_back = stack_operator.back();
					stack_operator.pop_back();
					stack_output.push_back(token_back);
				}
				stack_operator.push_back(currentToken);
				break;

			case TokenType::EndOfFile:
				break;
		}
		currentToken = lexer->NextToken();
	}

	while (!stack_operator.empty()) {
		Token tb = stack_operator.back();
		stack_output.push_back(tb);
		stack_operator.pop_back();
	}
}

unsigned
BooleanTree::precedence(TokenType type)
{
	switch (type) {
		case TokenType::Not:
			return 0; break;
		case TokenType::And:
			return 1; break;
		case TokenType::Xor:
			return 2; break;
		case TokenType::Or:
			return 3; break;
		default: return 4;
	}
}

void
BooleanTree::PrintTree()
{
	postorder(root.get());
}

void
BooleanTree::postorder(BaseNode* p, int indent)
{
	if(p != nullptr) {
		switch(p->getType()) {
			case AndNodeType:
				if (dynamic_cast<AndNode*>(p)->getLeftNode()) {
					postorder(dynamic_cast<AndNode*>(p)->getLeftNode(), indent+4);
				}
				if (indent) {
					std::cout << std::setw(indent) << ' ';
				}
				cout<< "AND" << "\n ";
				if (dynamic_cast<AndNode*>(p)->getRightNode()) {
					postorder(dynamic_cast<AndNode*>(p)->getRightNode(), indent+4);
				}
				break;
			case OrNodeType:
				if (dynamic_cast<OrNode*>(p)->getLeftNode()) {
					postorder(dynamic_cast<OrNode*>(p)->getLeftNode(), indent+4);
				}
				if (indent) {
					std::cout << std::setw(indent) << ' ';
				}
				cout<< "OR" << "\n ";
				if (dynamic_cast<OrNode*>(p)->getRightNode()) {
					postorder(dynamic_cast<OrNode*>(p)->getRightNode(), indent+4);
				}
				break;
			case NotNodeType:
				if (dynamic_cast<NotNode*>(p)) {
					std::cout << std::setw(indent) << ' ';
					cout<< "NOT" << "\n ";
					postorder(dynamic_cast<NotNode*>(p)->getNode(), indent+4);
				}
				break;
			case XorNodeType:
				if (dynamic_cast<XorNode*>(p)->getLeftNode()) {
					postorder(dynamic_cast<XorNode*>(p)->getLeftNode(), indent+4);
				}
				if (indent) {
					std::cout << std::setw(indent) << ' ';
				}
				cout<< "XOR" << "\n ";
				if (dynamic_cast<XorNode*>(p)->getRightNode()) {
					postorder(dynamic_cast<XorNode*>(p)->getRightNode(), indent+4);
				}
				break;
			case IdNodeType:
				std::cout << std::setw(indent) << ' ';
				if (dynamic_cast<IdNode*>(p)) {
					cout<< dynamic_cast<IdNode*>(p)->getId() << "\n ";
				}
				break;
		}
	}
}
<commit_msg>cleanups<commit_after>/*
 * Copyright (C) 2016 deipi.com LLC and contributors.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include <algorithm>
#include <iomanip>

#include "AndNode.h"
#include "IdNode.h"
#include "NotNode.h"
#include "SyntacticException.h"
#include "OrNode.h"
#include "XorNode.h"

#include "BooleanParser.h"

BooleanTree::BooleanTree(const std::string& input_)
{
	input = std::make_unique<char[]>(input_.size()+1);
	std::strcpy(input.get(), input_.c_str());
	lexer = std::make_unique<Lexer>(input.get());
	toRPN();
}

void
BooleanTree::Parse()
{
	root = BuildTree();
	if (!stack_output.empty()) {
		Token token = stack_output.back();
		string msj = "'" + token.lexeme + "' not expected";
		throw SyntacticException(msj.c_str());
	}
}

std::unique_ptr<BaseNode>
BooleanTree::BuildTree()
{
	if (stack_output.size() == 1 || stack_output.back().type == TokenType::Id) {
		Token token = stack_output.back();
		stack_output.pop_back();
		string id = token.lexeme;
		return std::make_unique<IdNode>(id);
	}
	/* Error case */
	else if (stack_output.size() == 1 && stack_output.back().type != TokenType::Id) {
		Token token = stack_output.back();
		string msj = "'" + token.lexeme + "' not expected";
		throw SyntacticException(msj.c_str());
	} else {
		Token token = stack_output.back();
		stack_output.pop_back();
		switch(token.type) {
			case TokenType::Not	:
				return std::make_unique<NotNode>(BuildTree());
				break;
			case TokenType::Or:
				return std::make_unique<OrNode>(BuildTree(), BuildTree());
				break;
			case TokenType::And:
				return std::make_unique<AndNode>(BuildTree(), BuildTree());
				break;
			case TokenType::Xor:
				return std::make_unique<XorNode>(BuildTree(), BuildTree());
				break;
			default:
				// Silence compiler switch warning
				break;
		}
	}
	return nullptr;
}

/*
 * Convert to RPN (Reverse Polish notation)
 * with Dijkstra's Shunting-yard algorithm.
 */
void
BooleanTree::toRPN()
{
	currentToken = lexer->NextToken();

	while (currentToken.type != TokenType::EndOfFile) {

		switch (currentToken.type) {

			case TokenType::Id:
				stack_output.push_back(currentToken);
				break;

			case TokenType::LeftParenthesis:
				stack_operator.push_back(currentToken);
				break;

			case TokenType::RightParenthesis:
				while (true) {
					if (!stack_operator.empty()) {
							Token token_back = stack_operator.back();
						if (token_back.type != TokenType::LeftParenthesis) {
							stack_output.push_back(token_back);
							stack_operator.pop_back();
						} else {
							stack_operator.pop_back();
							break;
						}
					} else {
						string msj = ") was expected";
						throw SyntacticException(msj.c_str());
					}
				}
				break;
			case TokenType::Not:
			case TokenType::Or:
			case TokenType::And:
			case TokenType::Xor:
				while (!stack_operator.empty() && precedence(currentToken.type) >= precedence(stack_operator.back().type)) {
					Token token_back = stack_operator.back();
					stack_operator.pop_back();
					stack_output.push_back(token_back);
				}
				stack_operator.push_back(currentToken);
				break;

			case TokenType::EndOfFile:
				break;
		}
		currentToken = lexer->NextToken();
	}

	while (!stack_operator.empty()) {
		Token tb = stack_operator.back();
		stack_output.push_back(tb);
		stack_operator.pop_back();
	}
}

unsigned
BooleanTree::precedence(TokenType type)
{
	switch (type) {
		case TokenType::Not:
			return 0;
		case TokenType::And:
			return 1;
		case TokenType::Xor:
			return 2;
		case TokenType::Or:
			return 3;
		default: return 4;
	}
}

void
BooleanTree::PrintTree()
{
	postorder(root.get());
}

void
BooleanTree::postorder(BaseNode* p, int indent)
{
	if(p != nullptr) {
		switch(p->getType()) {
			case AndNodeType:
				if (dynamic_cast<AndNode*>(p)->getLeftNode()) {
					postorder(dynamic_cast<AndNode*>(p)->getLeftNode(), indent+4);
				}
				if (indent) {
					std::cout << std::setw(indent) << ' ';
				}
				cout<< "AND" << "\n ";
				if (dynamic_cast<AndNode*>(p)->getRightNode()) {
					postorder(dynamic_cast<AndNode*>(p)->getRightNode(), indent+4);
				}
				break;
			case OrNodeType:
				if (dynamic_cast<OrNode*>(p)->getLeftNode()) {
					postorder(dynamic_cast<OrNode*>(p)->getLeftNode(), indent+4);
				}
				if (indent) {
					std::cout << std::setw(indent) << ' ';
				}
				cout<< "OR" << "\n ";
				if (dynamic_cast<OrNode*>(p)->getRightNode()) {
					postorder(dynamic_cast<OrNode*>(p)->getRightNode(), indent+4);
				}
				break;
			case NotNodeType:
				if (dynamic_cast<NotNode*>(p)) {
					std::cout << std::setw(indent) << ' ';
					cout<< "NOT" << "\n ";
					postorder(dynamic_cast<NotNode*>(p)->getNode(), indent+4);
				}
				break;
			case XorNodeType:
				if (dynamic_cast<XorNode*>(p)->getLeftNode()) {
					postorder(dynamic_cast<XorNode*>(p)->getLeftNode(), indent+4);
				}
				if (indent) {
					std::cout << std::setw(indent) << ' ';
				}
				cout<< "XOR" << "\n ";
				if (dynamic_cast<XorNode*>(p)->getRightNode()) {
					postorder(dynamic_cast<XorNode*>(p)->getRightNode(), indent+4);
				}
				break;
			case IdNodeType:
				std::cout << std::setw(indent) << ' ';
				if (dynamic_cast<IdNode*>(p)) {
					cout<< dynamic_cast<IdNode*>(p)->getId() << "\n ";
				}
				break;
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Fix the System.arraycopy race condition.<commit_after><|endoftext|>


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

#include <memory>
#include <vector>
extern "C" {
#include <unistd.h>
#include <stdarg.h>
#include <sys/time.h>
#include "h2o/memory.h"
#include "h2o/version.h"
}
#include "h2olog.h"

#define POLL_TIMEOUT (1000)
#define PERF_BUFFER_PAGE_COUNT 256

static void usage(void)
{
    printf(R"(h2olog (h2o v%s)
Usage: h2olog -p PID
       h2olog quic -p PID
       h2olog quic -s response_header_name -p PID
Other options:
    -h Print this help and exit
    -d Print debugging information (-dd shows more)
    -r Run without dropping root privilege
    -w Path to write the output (default: stdout)
)",
           H2O_VERSION);
    return;
}

static void make_timestamp(char *buf, size_t buf_len)
{
    time_t t = time(NULL);
    struct tm tms;
    localtime_r(&t, &tms);
    const char *iso8601format = "%FT%TZ";
    strftime(buf, buf_len, iso8601format, &tms);
}

static void infof(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

static void infof(const char *fmt, ...)
{
    char buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);

    char timestamp[128];
    make_timestamp(timestamp, sizeof(timestamp));

    fprintf(stderr, "%s %s\n", timestamp, buf);
}

uint64_t h2o_tracer::time_milliseconds()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

void h2o_tracer::show_event_per_sec(time_t *t0)
{
    time_t t1 = time(NULL);
    int64_t d = t1 - *t0;
    if (d > 10) {
        uint64_t c = stats_.num_events / d;
        if (c > 0) {
            if (stats_.num_lost > 0) {
                infof("%20" PRIu64 " events/s (possibly lost %" PRIu64 " events)", c, stats_.num_lost);
                stats_.num_lost = 0;
            } else {
                infof("%20" PRIu64 " events/s", c);
            }
            stats_.num_events = 0;
        }
        *t0 = t1;
    }
}

static void show_process(pid_t pid)
{
    char cmdline[256];
    char proc_file[256];
    snprintf(proc_file, sizeof(proc_file), "/proc/%d/cmdline", pid);
    FILE *f = fopen(proc_file, "r");
    if (f == nullptr) {
        fprintf(stderr, "Error: failed to open %s: %s\n", proc_file, strerror(errno));
        exit(EXIT_FAILURE);
    }
    size_t nread = fread(cmdline, 1, sizeof(cmdline), f);
    fclose(f);
    if (nread == 0) {
        fprintf(stderr, "Error: failed to read from %s: %s\n", proc_file, strerror(errno));
        exit(EXIT_FAILURE);
    }
    nread--; // skip trailing nul
    for (size_t i = 0; i < nread; i++) {
        if (cmdline[i] == '\0') {
            cmdline[i] = ' ';
        }
    }
    infof("Attaching pid=%d (%s)", pid, cmdline);
}

static void drop_root_privilege(void)
{
    if (getuid() == 0) {
        const char *sudo_gid = getenv("SUDO_GID");
        if (sudo_gid == NULL) {
            fprintf(stderr, "Error: the SUDO_GID environment variable is not set\n");
            exit(EXIT_FAILURE);
        }
        errno = 0;
        gid_t gid = (gid_t)strtol(sudo_gid, NULL, 10);
        if (errno != 0) {
            fprintf(stderr, "Error: failed to parse SUDO_GID\n");
            exit(EXIT_FAILURE);
        }
        if (setgid(gid) != 0) {
            perror("Error: setgid(2) failed\n");
            exit(EXIT_FAILURE);
        }
        const char *sudo_uid = getenv("SUDO_UID");
        if (sudo_uid == NULL) {
            fprintf(stderr, "Error: the SUDO_UID environment variable is not set\n");
            exit(EXIT_FAILURE);
        }
        errno = 0;
        uid_t uid = (uid_t)strtol(sudo_uid, NULL, 10);
        if (errno != 0) {
            fprintf(stderr, "Error: failed to parse SUDO_UID\n");
            exit(EXIT_FAILURE);
        }
        if (setuid(uid) != 0) {
            perror("Error: setuid(2) failed\n");
            exit(EXIT_FAILURE);
        }
    }
}

static std::string join_str(const std::string &sep, const std::vector<std::string> &strs)
{
    std::string s;
    for (auto iter = strs.cbegin(); iter != strs.cend(); ++iter) {
        if (iter != strs.cbegin()) {
            s += sep;
        }
        s += *iter;
    }
    return s;
}

static std::string generate_header_filter_cflag(const std::vector<std::string> &tokens)
{
    std::vector<std::string> conditions;

    for (auto &token : tokens) {
        char buf[256];
        snprintf(buf, sizeof(buf), "/* %s */ (slen) == %zu", token.c_str(), token.size());
        std::vector<std::string> exprs = {buf};

        for (size_t i = 0; i < token.size(); ++i) {
            snprintf(buf, sizeof(buf), "(s)[%zu] == '%c'", i, token[i]);
            exprs.push_back(buf);
        }
        conditions.push_back("(" + join_str(" && ", exprs) + ")");
    }

    std::string cflag("-DCHECK_ALLOWED_RES_HEADER_NAME(s,slen)=(");
    cflag += join_str(" || ", conditions);
    cflag += ")";
    return cflag;
}

static std::string make_pid_cflag(const char *macro_name, pid_t pid)
{
    char buf[256];
    snprintf(buf, sizeof(buf), "-D%s=%d", macro_name, pid);
    return std::string(buf);
}

static void event_cb(void *context, void *data, int len)
{
    h2o_tracer *tracer = (h2o_tracer *)context;
    tracer->handle_event(data, len);
}

static void lost_cb(void *context, uint64_t lost)
{
    h2o_tracer *tracer = (h2o_tracer *)context;
    tracer->handle_lost(lost);
}

int main(int argc, char **argv)
{
    std::unique_ptr<h2o_tracer> tracer;
    if (argc > 1 && strcmp(argv[1], "quic") == 0) {
        tracer.reset(create_quic_tracer());
        --argc;
        ++argv;
    } else {
        tracer.reset(create_http_tracer());
    }

    int debug = 0;
    int preserve_root = 0;
    FILE *outfp = stdout;
    std::vector<std::string> event_type_filters;
    std::vector<std::string> response_header_filters;
    int c;
    pid_t h2o_pid = -1;
    while ((c = getopt(argc, argv, "hdrp:t:s:w:")) != -1) {
        switch (c) {
        case 'p':
            h2o_pid = atoi(optarg);
            break;
        case 't':
            event_type_filters.push_back(optarg);
            break;
        case 's':
            response_header_filters.push_back(optarg);
            break;
        case 'w':
            if ((outfp = fopen(optarg, "w")) == nullptr) {
                fprintf(stderr, "Error: failed to open %s: %s", optarg, strerror(errno));
                exit(EXIT_FAILURE);
            }
            break;
        case 'd':
            debug++;
            break;
        case 'r':
            preserve_root = 1;
            break;
        case 'h':
            usage();
            exit(EXIT_SUCCESS);
        default:
            usage();
            exit(EXIT_FAILURE);
        }
    }

    if (argc > optind) {
        fprintf(stderr, "Error: too many aruments\n");
        usage();
        exit(EXIT_FAILURE);
    }

    if (h2o_pid == -1) {
        fprintf(stderr, "Error: -p option is missing\n");
        usage();
        exit(EXIT_FAILURE);
    }

    if (geteuid() != 0) {
        fprintf(stderr, "Error: root privilege is required\n");
        exit(EXIT_FAILURE);
    }

    tracer->init(outfp);

    std::vector<std::string> cflags({
        make_pid_cflag("H2OLOG_H2O_PID", h2o_pid),
    });

    if (!response_header_filters.empty()) {
        cflags.push_back(generate_header_filter_cflag(response_header_filters));
    }

    if (debug >= 2) {
        fprintf(stderr, "cflags=");
        for (size_t i = 0; i < cflags.size(); i++) {
            if (i > 0) {
                fprintf(stderr, " ");
            }
            fprintf(stderr, "%s", cflags[i].c_str());
        }
        fprintf(stderr, "\n");
        fprintf(stderr, "<BPF>\n%s\n</BPF>\n", tracer->bpf_text().c_str());
    }

    ebpf::BPF *bpf = new ebpf::BPF();
    std::vector<ebpf::USDT> probes = tracer->init_usdt_probes(h2o_pid);

    ebpf::StatusTuple ret = bpf->init(tracer->bpf_text(), cflags, probes);
    if (ret.code() != 0) {
        fprintf(stderr, "Error: init: %s\n", ret.msg().c_str());
        return EXIT_FAILURE;
    }

    bpf->attach_tracepoint("sched:sched_process_exit", "trace_sched_process_exit");

    for (auto &probe : probes) {
        ret = bpf->attach_usdt(probe);
        if (ret.code() != 0) {
            fprintf(stderr, "Error: attach_usdt: %s\n", ret.msg().c_str());
            return EXIT_FAILURE;
        }
    }

    ret = bpf->open_perf_buffer("events", event_cb, lost_cb, tracer.get(), PERF_BUFFER_PAGE_COUNT);
    if (ret.code() != 0) {
        fprintf(stderr, "Error: open_perf_buffer: %s\n", ret.msg().c_str());
        return EXIT_FAILURE;
    }

    if (debug) {
        show_process(h2o_pid);
    }
    if (!preserve_root) {
        drop_root_privilege();
    }

    ebpf::BPFPerfBuffer *perf_buffer = bpf->get_perf_buffer("events");
    if (perf_buffer) {
        time_t t0 = time(NULL);

        while (true) {
            perf_buffer->poll(POLL_TIMEOUT);
            tracer->flush();

            if (debug) {
                tracer->show_event_per_sec(&t0);
            }
        }
    }

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

#include <memory>
#include <vector>
extern "C" {
#include <unistd.h>
#include <stdarg.h>
#include <sys/time.h>
#include "h2o/memory.h"
#include "h2o/version.h"
}
#include "h2olog.h"

#define POLL_TIMEOUT (1000)
#define PERF_BUFFER_PAGE_COUNT 256

static void usage(void)
{
    printf(R"(h2olog (h2o v%s)
Usage: h2olog -p PID
       h2olog quic -p PID
       h2olog quic -s response_header_name -p PID
Other options:
    -h Print this help and exit
    -d Print debugging information (-dd shows more)
    -r Run without dropping root privilege
    -w Path to write the output (default: stdout)
)",
           H2O_VERSION);
    return;
}

static void make_timestamp(char *buf, size_t buf_len)
{
    time_t t = time(NULL);
    struct tm tms;
    localtime_r(&t, &tms);
    const char *iso8601format = "%FT%TZ";
    strftime(buf, buf_len, iso8601format, &tms);
}

static void infof(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

static void infof(const char *fmt, ...)
{
    char buf[1024];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);

    char timestamp[128];
    make_timestamp(timestamp, sizeof(timestamp));

    fprintf(stderr, "%s %s\n", timestamp, buf);
}

uint64_t h2o_tracer::time_milliseconds()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

void h2o_tracer::show_event_per_sec(time_t *t0)
{
    time_t t1 = time(NULL);
    int64_t d = t1 - *t0;
    if (d > 10) {
        uint64_t c = stats_.num_events / d;
        if (c > 0) {
            if (stats_.num_lost > 0) {
                infof("%20" PRIu64 " events/s (possibly lost %" PRIu64 " events)", c, stats_.num_lost);
                stats_.num_lost = 0;
            } else {
                infof("%20" PRIu64 " events/s", c);
            }
            stats_.num_events = 0;
        }
        *t0 = t1;
    }
}

static void show_process(pid_t pid)
{
    char cmdline[256];
    char proc_file[256];
    snprintf(proc_file, sizeof(proc_file), "/proc/%d/cmdline", pid);
    FILE *f = fopen(proc_file, "r");
    if (f == nullptr) {
        fprintf(stderr, "Error: failed to open %s: %s\n", proc_file, strerror(errno));
        exit(EXIT_FAILURE);
    }
    size_t nread = fread(cmdline, 1, sizeof(cmdline), f);
    fclose(f);
    if (nread == 0) {
        fprintf(stderr, "Error: failed to read from %s: %s\n", proc_file, strerror(errno));
        exit(EXIT_FAILURE);
    }
    nread--; // skip trailing nul
    for (size_t i = 0; i < nread; i++) {
        if (cmdline[i] == '\0') {
            cmdline[i] = ' ';
        }
    }
    infof("Attaching pid=%d (%s)", pid, cmdline);
}

static void drop_root_privilege(void)
{
    if (getuid() == 0) {
        const char *sudo_gid = getenv("SUDO_GID");
        if (sudo_gid == NULL) {
            fprintf(stderr, "Error: the SUDO_GID environment variable is not set\n");
            exit(EXIT_FAILURE);
        }
        errno = 0;
        gid_t gid = (gid_t)strtol(sudo_gid, NULL, 10);
        if (errno != 0) {
            fprintf(stderr, "Error: failed to parse SUDO_GID\n");
            exit(EXIT_FAILURE);
        }
        if (setgid(gid) != 0) {
            perror("Error: setgid(2) failed");
            exit(EXIT_FAILURE);
        }
        const char *sudo_uid = getenv("SUDO_UID");
        if (sudo_uid == NULL) {
            fprintf(stderr, "Error: the SUDO_UID environment variable is not set\n");
            exit(EXIT_FAILURE);
        }
        errno = 0;
        uid_t uid = (uid_t)strtol(sudo_uid, NULL, 10);
        if (errno != 0) {
            fprintf(stderr, "Error: failed to parse SUDO_UID\n");
            exit(EXIT_FAILURE);
        }
        if (setuid(uid) != 0) {
            perror("Error: setuid(2) failed\n");
            exit(EXIT_FAILURE);
        }
    }
}

static std::string join_str(const std::string &sep, const std::vector<std::string> &strs)
{
    std::string s;
    for (auto iter = strs.cbegin(); iter != strs.cend(); ++iter) {
        if (iter != strs.cbegin()) {
            s += sep;
        }
        s += *iter;
    }
    return s;
}

static std::string generate_header_filter_cflag(const std::vector<std::string> &tokens)
{
    std::vector<std::string> conditions;

    for (auto &token : tokens) {
        char buf[256];
        snprintf(buf, sizeof(buf), "/* %s */ (slen) == %zu", token.c_str(), token.size());
        std::vector<std::string> exprs = {buf};

        for (size_t i = 0; i < token.size(); ++i) {
            snprintf(buf, sizeof(buf), "(s)[%zu] == '%c'", i, token[i]);
            exprs.push_back(buf);
        }
        conditions.push_back("(" + join_str(" && ", exprs) + ")");
    }

    std::string cflag("-DCHECK_ALLOWED_RES_HEADER_NAME(s,slen)=(");
    cflag += join_str(" || ", conditions);
    cflag += ")";
    return cflag;
}

static std::string make_pid_cflag(const char *macro_name, pid_t pid)
{
    char buf[256];
    snprintf(buf, sizeof(buf), "-D%s=%d", macro_name, pid);
    return std::string(buf);
}

static void event_cb(void *context, void *data, int len)
{
    h2o_tracer *tracer = (h2o_tracer *)context;
    tracer->handle_event(data, len);
}

static void lost_cb(void *context, uint64_t lost)
{
    h2o_tracer *tracer = (h2o_tracer *)context;
    tracer->handle_lost(lost);
}

int main(int argc, char **argv)
{
    std::unique_ptr<h2o_tracer> tracer;
    if (argc > 1 && strcmp(argv[1], "quic") == 0) {
        tracer.reset(create_quic_tracer());
        --argc;
        ++argv;
    } else {
        tracer.reset(create_http_tracer());
    }

    int debug = 0;
    int preserve_root = 0;
    FILE *outfp = stdout;
    std::vector<std::string> event_type_filters;
    std::vector<std::string> response_header_filters;
    int c;
    pid_t h2o_pid = -1;
    while ((c = getopt(argc, argv, "hdrp:t:s:w:")) != -1) {
        switch (c) {
        case 'p':
            h2o_pid = atoi(optarg);
            break;
        case 't':
            event_type_filters.push_back(optarg);
            break;
        case 's':
            response_header_filters.push_back(optarg);
            break;
        case 'w':
            if ((outfp = fopen(optarg, "w")) == nullptr) {
                fprintf(stderr, "Error: failed to open %s: %s", optarg, strerror(errno));
                exit(EXIT_FAILURE);
            }
            break;
        case 'd':
            debug++;
            break;
        case 'r':
            preserve_root = 1;
            break;
        case 'h':
            usage();
            exit(EXIT_SUCCESS);
        default:
            usage();
            exit(EXIT_FAILURE);
        }
    }

    if (argc > optind) {
        fprintf(stderr, "Error: too many aruments\n");
        usage();
        exit(EXIT_FAILURE);
    }

    if (h2o_pid == -1) {
        fprintf(stderr, "Error: -p option is missing\n");
        usage();
        exit(EXIT_FAILURE);
    }

    if (geteuid() != 0) {
        fprintf(stderr, "Error: root privilege is required\n");
        exit(EXIT_FAILURE);
    }

    tracer->init(outfp);

    std::vector<std::string> cflags({
        make_pid_cflag("H2OLOG_H2O_PID", h2o_pid),
    });

    if (!response_header_filters.empty()) {
        cflags.push_back(generate_header_filter_cflag(response_header_filters));
    }

    if (debug >= 2) {
        fprintf(stderr, "cflags=");
        for (size_t i = 0; i < cflags.size(); i++) {
            if (i > 0) {
                fprintf(stderr, " ");
            }
            fprintf(stderr, "%s", cflags[i].c_str());
        }
        fprintf(stderr, "\n");
        fprintf(stderr, "<BPF>\n%s\n</BPF>\n", tracer->bpf_text().c_str());
    }

    ebpf::BPF *bpf = new ebpf::BPF();
    std::vector<ebpf::USDT> probes = tracer->init_usdt_probes(h2o_pid);

    ebpf::StatusTuple ret = bpf->init(tracer->bpf_text(), cflags, probes);
    if (ret.code() != 0) {
        fprintf(stderr, "Error: init: %s\n", ret.msg().c_str());
        return EXIT_FAILURE;
    }

    bpf->attach_tracepoint("sched:sched_process_exit", "trace_sched_process_exit");

    for (auto &probe : probes) {
        ret = bpf->attach_usdt(probe);
        if (ret.code() != 0) {
            fprintf(stderr, "Error: attach_usdt: %s\n", ret.msg().c_str());
            return EXIT_FAILURE;
        }
    }

    ret = bpf->open_perf_buffer("events", event_cb, lost_cb, tracer.get(), PERF_BUFFER_PAGE_COUNT);
    if (ret.code() != 0) {
        fprintf(stderr, "Error: open_perf_buffer: %s\n", ret.msg().c_str());
        return EXIT_FAILURE;
    }

    if (debug) {
        show_process(h2o_pid);
    }
    if (!preserve_root) {
        drop_root_privilege();
    }

    ebpf::BPFPerfBuffer *perf_buffer = bpf->get_perf_buffer("events");
    if (perf_buffer) {
        time_t t0 = time(NULL);

        while (true) {
            perf_buffer->poll(POLL_TIMEOUT);
            tracer->flush();

            if (debug) {
                tracer->show_event_per_sec(&t0);
            }
        }
    }

    fprintf(stderr, "Error: failed to get_perf_buffer()\n");
    return EXIT_FAILURE;
}
<|endoftext|>


<commit_before><commit_msg>mode_RPiHQ_mean.cpp: remove mask function<commit_after><|endoftext|>


<commit_before><commit_msg>added assertion<commit_after><|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
  *
  * Condor Software Copyright Notice
  * Copyright (C) 1990-2006, Condor Team, Computer Sciences Department,
  * University of Wisconsin-Madison, WI.
  *
  * This source code is covered by the Condor Public License, which can
  * be found in the accompanying LICENSE.TXT file, or online at
  * www.condorproject.org.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
  * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
  * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
  * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
  * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
  * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
  * RIGHT.
  *
  ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_classad.h"
#include "condor_string.h"
#include "condor_attributes.h"
#include "basename.h"
#include "directory.h"
#include "basename.h"
#include "build_job_env.h"

#define X509_USER_PROXY "X509_USER_PROXY"

StringMap build_job_env(const ClassAd & ad, bool using_file_transfer)
{
	StringMap results(1,MyStringHash,updateDuplicateKeys);// rejectDuplicateKeys?

	MyString Iwd;
	if( ! ad.LookupString(ATTR_JOB_IWD, Iwd) ) {
		ASSERT(0);
		dprintf(D_ALWAYS, "Job ClassAd lacks required attribute %s.  Job's environment may be incorrect.\n", ATTR_JOB_IWD);
		return results;
	}

	MyString X509Path;
	if(ad.LookupString(ATTR_X509_USER_PROXY, X509Path)) {
		if(using_file_transfer) {
			// The X509 proxy was put into the IWD, effectively flattening
			// any relative or absolute paths it might have.  So chomp it down.
			// (Don't try to do this in one line; the old string might be deleted
			// before the copy.)
			MyString tmp = condor_basename(X509Path.Value());
			X509Path = tmp;
		}
		if( ! fullpath(X509Path.Value()) ) {
			// It's not a full path, so glob on the IWD onto the front
			char * newpath = dircat(Iwd.Value(), X509Path.Value());
			X509Path = newpath;
			delete [] newpath; // dircat returnned newed memory.

		}
		results.insert(X509_USER_PROXY, X509Path.Value());
	}

	return results;
}

#if 0
static int Insert(ClassAd & ad, const char * lhs, const char * rhs) {
	MyString s;
	s.sprintf("%s=\"%s\"",lhs,rhs);
	return ad.Insert(s.Value());
}

int main() {
	ClassAd ad;
	Insert(ad,ATTR_JOB_IWD,"/path/to/iwd");
	Insert(ad,ATTR_X509_USER_PROXY,"/path/bob");
	StringMap sm = build_job_env(ad);

	sm.startIterations();
	MyString key,value;
	while(sm.iterate(key,value)) {
		printf("%s=%s\n",key.Value(), value.Value());
	}

	return 0;
}
#endif
<commit_msg>add missing include<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
  *
  * Condor Software Copyright Notice
  * Copyright (C) 1990-2006, Condor Team, Computer Sciences Department,
  * University of Wisconsin-Madison, WI.
  *
  * This source code is covered by the Condor Public License, which can
  * be found in the accompanying LICENSE.TXT file, or online at
  * www.condorproject.org.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * AND THE UNIVERSITY OF WISCONSIN-MADISON "AS IS" AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY, OF SATISFACTORY QUALITY, AND FITNESS
  * FOR A PARTICULAR PURPOSE OR USE ARE DISCLAIMED. THE COPYRIGHT
  * HOLDERS AND CONTRIBUTORS AND THE UNIVERSITY OF WISCONSIN-MADISON
  * MAKE NO MAKE NO REPRESENTATION THAT THE SOFTWARE, MODIFICATIONS,
  * ENHANCEMENTS OR DERIVATIVE WORKS THEREOF, WILL NOT INFRINGE ANY
  * PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET OR OTHER PROPRIETARY
  * RIGHT.
  *
  ****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_classad.h"
#include "condor_string.h"
#include "condor_attributes.h"
#include "basename.h"
#include "directory.h"
#include "basename.h"
#include "build_job_env.h"
#include "HashTable.h"

#define X509_USER_PROXY "X509_USER_PROXY"

StringMap build_job_env(const ClassAd & ad, bool using_file_transfer)
{
	StringMap results(1,MyStringHash,updateDuplicateKeys);// rejectDuplicateKeys?

	MyString Iwd;
	if( ! ad.LookupString(ATTR_JOB_IWD, Iwd) ) {
		ASSERT(0);
		dprintf(D_ALWAYS, "Job ClassAd lacks required attribute %s.  Job's environment may be incorrect.\n", ATTR_JOB_IWD);
		return results;
	}

	MyString X509Path;
	if(ad.LookupString(ATTR_X509_USER_PROXY, X509Path)) {
		if(using_file_transfer) {
			// The X509 proxy was put into the IWD, effectively flattening
			// any relative or absolute paths it might have.  So chomp it down.
			// (Don't try to do this in one line; the old string might be deleted
			// before the copy.)
			MyString tmp = condor_basename(X509Path.Value());
			X509Path = tmp;
		}
		if( ! fullpath(X509Path.Value()) ) {
			// It's not a full path, so glob on the IWD onto the front
			char * newpath = dircat(Iwd.Value(), X509Path.Value());
			X509Path = newpath;
			delete [] newpath; // dircat returnned newed memory.

		}
		results.insert(X509_USER_PROXY, X509Path.Value());
	}

	return results;
}

#if 0
static int Insert(ClassAd & ad, const char * lhs, const char * rhs) {
	MyString s;
	s.sprintf("%s=\"%s\"",lhs,rhs);
	return ad.Insert(s.Value());
}

int main() {
	ClassAd ad;
	Insert(ad,ATTR_JOB_IWD,"/path/to/iwd");
	Insert(ad,ATTR_X509_USER_PROXY,"/path/bob");
	StringMap sm = build_job_env(ad);

	sm.startIterations();
	MyString key,value;
	while(sm.iterate(key,value)) {
		printf("%s=%s\n",key.Value(), value.Value());
	}

	return 0;
}
#endif
<|endoftext|>


<commit_before>#include "File.h"
#include "Exception.h"

/////////////////////////////////////////////////////////////////////////////
// System-specific functions
/////////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
#include <Windows.h>
#include <io.h>
#include <FileAPI.h>

bool joedb::File::lock_file()
{
 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
 return LockFile(hFile, 0, 0, 1, 0) == TRUE;
}

void joedb::File::sync()
{
 _commit(_fileno(file));
}

#else
#include <sys/file.h>
#include <unistd.h>

bool joedb::File::lock_file()
{
 return flock(fileno(file), LOCK_EX | LOCK_NB) == 0;
}

void joedb::File::sync()
{
 fsync(fileno(file));
}

#endif

/////////////////////////////////////////////////////////////////////////////
bool joedb::File::try_open(const char *file_name, Open_Mode new_mode)
/////////////////////////////////////////////////////////////////////////////
{
 static const char *mode_string[3] = {"rb", "r+b", "w+b"};
 mode = new_mode;
 file = std::fopen(file_name, mode_string[static_cast<size_t>(mode)]);
 return file != 0;
}

/////////////////////////////////////////////////////////////////////////////
joedb::File::File(const char *file_name, Open_Mode new_mode)
/////////////////////////////////////////////////////////////////////////////
{
 if (new_mode == Open_Mode::write_existing_or_create_new)
 {
  try_open(file_name, Open_Mode::write_existing) ||
  try_open(file_name, Open_Mode::create_new);
 }
 else if (new_mode == Open_Mode::create_new)
 {
  if (try_open(file_name, Open_Mode::read_existing))
  {
   close_file();
   throw Exception("File already exists: " + std::string(file_name));
  }
  else
   try_open(file_name, Open_Mode::create_new);
 }
 else
  try_open(file_name, new_mode);

 if (!file)
  throw Exception("Cannot open file: " + std::string(file_name));

 if ((mode == Open_Mode::write_existing ||
      mode == Open_Mode::create_new) && !lock_file())
 {
  close_file();
  throw Exception("File locked: " + std::string(file_name));
 }

 std::setvbuf(file, 0, _IONBF, 0);
}

/////////////////////////////////////////////////////////////////////////////
size_t joedb::File::read_buffer()
/////////////////////////////////////////////////////////////////////////////
{
 return std::fread(buffer, 1, buffer_size, file);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::File::write_buffer()
/////////////////////////////////////////////////////////////////////////////
{
 const size_t written = std::fwrite(buffer, 1, write_buffer_index, file);
 if (written != write_buffer_index)
  throw Exception("Error writing file");
}

/////////////////////////////////////////////////////////////////////////////
int joedb::File::seek(size_t offset)
/////////////////////////////////////////////////////////////////////////////
{
 return std::fseek(file, long(offset), SEEK_SET);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::File::close_file()
/////////////////////////////////////////////////////////////////////////////
{
 if (file)
 {
  flush();
  fclose(file);
  file = 0;
 }
}

/////////////////////////////////////////////////////////////////////////////
int64_t joedb::File::get_size() const
/////////////////////////////////////////////////////////////////////////////
{
 const long current_tell = std::ftell(file);
 std::fseek(file, 0, SEEK_END);
 const int64_t result = std::ftell(file);
 std::fseek(file, current_tell, SEEK_SET);
 return result;
}

/////////////////////////////////////////////////////////////////////////////
joedb::File::~File()
/////////////////////////////////////////////////////////////////////////////
{
 close_file();
}
<commit_msg>Dummy file lock and sync for Nintendo Switch<commit_after>#include "File.h"
#include "Exception.h"

/////////////////////////////////////////////////////////////////////////////
// System-specific functions
/////////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
#include <Windows.h>
#include <io.h>
#include <stdio.h>
#include <FileAPI.h>

bool joedb::File::lock_file()
{
 HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
 return LockFile(hFile, 0, 0, 1, 0) == TRUE;
}

void joedb::File::sync()
{
 _commit(_fileno(file));
}

#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include <sys/file.h>
#include <unistd.h>

bool joedb::File::lock_file()
{
 return flock(fileno(file), LOCK_EX | LOCK_NB) == 0;
}

void joedb::File::sync()
{
 fsync(fileno(file));
}

#else
#pragma message("warning: unknown system: no lock, no sync")

bool joedb::File::lock_file()
{
 return true;
}

void joedb::File::sync()
{
}

#endif

/////////////////////////////////////////////////////////////////////////////
bool joedb::File::try_open(const char *file_name, Open_Mode new_mode)
/////////////////////////////////////////////////////////////////////////////
{
 static const char *mode_string[3] = {"rb", "r+b", "w+b"};
 mode = new_mode;
 file = std::fopen(file_name, mode_string[static_cast<size_t>(mode)]);
 return file != 0;
}

/////////////////////////////////////////////////////////////////////////////
joedb::File::File(const char *file_name, Open_Mode new_mode)
/////////////////////////////////////////////////////////////////////////////
{
 if (new_mode == Open_Mode::write_existing_or_create_new)
 {
  try_open(file_name, Open_Mode::write_existing) ||
  try_open(file_name, Open_Mode::create_new);
 }
 else if (new_mode == Open_Mode::create_new)
 {
  if (try_open(file_name, Open_Mode::read_existing))
  {
   close_file();
   throw Exception("File already exists: " + std::string(file_name));
  }
  else
   try_open(file_name, Open_Mode::create_new);
 }
 else
  try_open(file_name, new_mode);

 if (!file)
  throw Exception("Cannot open file: " + std::string(file_name));

 if ((mode == Open_Mode::write_existing ||
      mode == Open_Mode::create_new) && !lock_file())
 {
  close_file();
  throw Exception("File locked: " + std::string(file_name));
 }

 std::setvbuf(file, 0, _IONBF, 0);
}

/////////////////////////////////////////////////////////////////////////////
size_t joedb::File::read_buffer()
/////////////////////////////////////////////////////////////////////////////
{
 return std::fread(buffer, 1, buffer_size, file);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::File::write_buffer()
/////////////////////////////////////////////////////////////////////////////
{
 const size_t written = std::fwrite(buffer, 1, write_buffer_index, file);
 if (written != write_buffer_index)
  throw Exception("Error writing file");
}

/////////////////////////////////////////////////////////////////////////////
int joedb::File::seek(size_t offset)
/////////////////////////////////////////////////////////////////////////////
{
 return std::fseek(file, long(offset), SEEK_SET);
}

/////////////////////////////////////////////////////////////////////////////
void joedb::File::close_file()
/////////////////////////////////////////////////////////////////////////////
{
 if (file)
 {
  flush();
  fclose(file);
  file = 0;
 }
}

/////////////////////////////////////////////////////////////////////////////
int64_t joedb::File::get_size() const
/////////////////////////////////////////////////////////////////////////////
{
 const long current_tell = std::ftell(file);
 std::fseek(file, 0, SEEK_END);
 const int64_t result = std::ftell(file);
 std::fseek(file, current_tell, SEEK_SET);
 return result;
}

/////////////////////////////////////////////////////////////////////////////
joedb::File::~File()
/////////////////////////////////////////////////////////////////////////////
{
 close_file();
}
<|endoftext|>