<commit_before>//! \file
//! ClientConnectedState class implementation

#include "MainState.h"
#include <sstream>

MainStateEnum ClientConnectedState::LocalUpdate()
{
	if (InputHandler::InputTime == 0)
	{
		if (Index == 0)
		{
			if (InputHandler::LastInput == Down)
			{
				Index = 1;
			}
			else if (InputHandler::LastInput == Left)
			{
				if (SelectedCharacter == PacMan)
				{
					SelectedCharacter = Clyde;
				}
				else
				{
					SelectedCharacter = (Character)(SelectedCharacter - 1);
				}
			}
			else if (InputHandler::LastInput == Right)
			{
				if (SelectedCharacter == Clyde)
				{
					SelectedCharacter = PacMan;
				}
				else
				{
					SelectedCharacter = (Character)(SelectedCharacter + 1);
				}
			}
		}
		else
		{
			if (InputHandler::LastInput == Up)
			{
				Ready = false;
				std::vector<char> data_s(PlayerNotReady_size);
				NetworkManager::Send(NetworkManager::PlayerNotReady, data_s, 0);
				Index = 0;
			}
			else if (InputHandler::LastInput == Right)
			{
				Ready = true;
				std::vector<char> data_s(PlayerReady_size);
				data_s[PlayerReady_Character] = SelectedCharacter;
				NetworkManager::Send(
						NetworkManager::PlayerReady, data_s, 0);
			}
			else if (InputHandler::LastInput == Left)
			{
				Ready = false;
				std::vector<char> data_s(PlayerNotReady_size);
				NetworkManager::Send(NetworkManager::PlayerNotReady, data_s, 0);
			}
		}
	}

	if (NetworkManager::CurrentConnections[0].Lag > NetworkTimeout)
	{
		return Join;
	}

	// ping server
	std::vector<char> data_s(PingServer_size);
	NetworkManager::Send(NetworkManager::PingServer, data_s, 0);

	return ClientConnected;
}

MainStateEnum ClientConnectedState::ProcessPacket(NetworkManager::MessageType mtype,
		std::vector<char> &data_r, unsigned int id)
{
	if (id == 0)
	{
		NetworkManager::CurrentConnections[0].Lag = 0;
		if (mtype == NetworkManager::PingClient)
		{
			// No action needed
		}
		else if (mtype == NetworkManager::ConfirmClient)
		{
			PlayerNumber =
				data_r[ConfirmClient_PlayerNumber];
		}
		else if (mtype == NetworkManager::DisconnectClient)
		{
			return Join;
		}
		else if (mtype == NetworkManager::StartGame)
		{
			unsigned char count = data_r[StartGame_PlayerCount];
			unsigned char field = data_r[StartGame_Field];

			/// \TODO Add field selection
			Field gameField("../stage1.txt");
			Renderer::LoadField(&gameField, "../spritesheet.png");

			std::vector<Player *> players;
			for (unsigned int i = 0; i < count; i++)
			{
				Character c = (Character)data_r[StartGame_Character + i];
				if (c == PacMan)
				{
					players.push_back(new Pacman(PacmanSprite,
								Position(
									14 * TILE_SIZE,
									23 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Left));
				}
				else if (c == Blinky)
				{
					players.push_back(new Ghost(GhostSprites[0],
								Position(
									14 * TILE_SIZE,
									11 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Left));
				}
				else if (c == Inky)
				{
					players.push_back(new Ghost(GhostSprites[2],
								Position(
									12 * TILE_SIZE,
									14 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Up));
				}
				else if (c == Pinky)
				{
					players.push_back(new Ghost(GhostSprites[1],
								Position(
									14 * TILE_SIZE,
									14 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Down));
				}
				else if (c == Clyde)
				{
					players.push_back(new Ghost(GhostSprites[3],
								Position(
									16 * TILE_SIZE,
									14 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Up));
				}
			}
			StartingGame = new Game(gameField, players);
			return Gameplay;
		}
	}

	return ClientConnected;
}

void ClientConnectedState::Render() const
{
	std::ostringstream ss;
	ss << "You are Player ";
	ss << PlayerNumber + 1;
	std::string str = ss.str();
	Renderer::DrawText(0, str, 24, 60, 100);
	Character c = SelectedCharacter;
	bool ready = Ready;
	unsigned int index = Index;

	if (c == PacMan)
	{
		Renderer::DrawText(0, "< Pac-Man >", 18, 60, 140);
	}
	else if (c == Blinky)
	{
		Renderer::DrawText(0, "< Blinky >", 18, 60, 140);
	}
	else if (c == Inky)
	{
		Renderer::DrawText(0, "< Inky >", 18, 60, 140);
	}
	else if (c == Pinky)
	{
		Renderer::DrawText(0, "< Pinky >", 18, 60, 140);
	}
	else if (c == Clyde)
	{
		Renderer::DrawText(0, "< Clyde >", 18, 60, 140);
	}

	if (ready)
	{
		Renderer::DrawText(0, "< Ready!", 18, 60, 180);
	}
	else
	{
		Renderer::DrawText(0, "  Ready? >", 18, 60, 180);
	}
	Renderer::DrawText(0, ">", 18, 20, 140 + 40 * index);
}
<commit_msg>Show sprites in character selection<commit_after>//! \file
//! ClientConnectedState class implementation

#include "MainState.h"
#include <sstream>

MainStateEnum ClientConnectedState::LocalUpdate()
{
	if (InputHandler::InputTime == 0)
	{
		if (Index == 0)
		{
			if (InputHandler::LastInput == Down)
			{
				Index = 1;
			}
			else if (InputHandler::LastInput == Left)
			{
				if (SelectedCharacter == PacMan)
				{
					SelectedCharacter = Clyde;
				}
				else
				{
					SelectedCharacter = (Character)(SelectedCharacter - 1);
				}
			}
			else if (InputHandler::LastInput == Right)
			{
				if (SelectedCharacter == Clyde)
				{
					SelectedCharacter = PacMan;
				}
				else
				{
					SelectedCharacter = (Character)(SelectedCharacter + 1);
				}
			}
		}
		else
		{
			if (InputHandler::LastInput == Up)
			{
				Ready = false;
				std::vector<char> data_s(PlayerNotReady_size);
				NetworkManager::Send(NetworkManager::PlayerNotReady, data_s, 0);
				Index = 0;
			}
			else if (InputHandler::LastInput == Right)
			{
				Ready = true;
				std::vector<char> data_s(PlayerReady_size);
				data_s[PlayerReady_Character] = SelectedCharacter;
				NetworkManager::Send(
						NetworkManager::PlayerReady, data_s, 0);
			}
			else if (InputHandler::LastInput == Left)
			{
				Ready = false;
				std::vector<char> data_s(PlayerNotReady_size);
				NetworkManager::Send(NetworkManager::PlayerNotReady, data_s, 0);
			}
		}
	}

	if (NetworkManager::CurrentConnections[0].Lag > NetworkTimeout)
	{
		return Join;
	}

	// ping server
	std::vector<char> data_s(PingServer_size);
	NetworkManager::Send(NetworkManager::PingServer, data_s, 0);

	return ClientConnected;
}

MainStateEnum ClientConnectedState::ProcessPacket(NetworkManager::MessageType mtype,
		std::vector<char> &data_r, unsigned int id)
{
	if (id == 0)
	{
		NetworkManager::CurrentConnections[0].Lag = 0;
		if (mtype == NetworkManager::PingClient)
		{
			// No action needed
		}
		else if (mtype == NetworkManager::ConfirmClient)
		{
			PlayerNumber =
				data_r[ConfirmClient_PlayerNumber];
		}
		else if (mtype == NetworkManager::DisconnectClient)
		{
			return Join;
		}
		else if (mtype == NetworkManager::StartGame)
		{
			unsigned char count = data_r[StartGame_PlayerCount];
			unsigned char field = data_r[StartGame_Field];

			/// \TODO Add field selection
			Field gameField("../stage1.txt");
			Renderer::LoadField(&gameField, "../spritesheet.png");

			std::vector<Player *> players;
			for (unsigned int i = 0; i < count; i++)
			{
				Character c = (Character)data_r[StartGame_Character + i];
				if (c == PacMan)
				{
					players.push_back(new Pacman(PacmanSprite,
								Position(
									14 * TILE_SIZE,
									23 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Left));
				}
				else if (c == Blinky)
				{
					players.push_back(new Ghost(GhostSprites[0],
								Position(
									14 * TILE_SIZE,
									11 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Left));
				}
				else if (c == Inky)
				{
					players.push_back(new Ghost(GhostSprites[2],
								Position(
									12 * TILE_SIZE,
									14 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Up));
				}
				else if (c == Pinky)
				{
					players.push_back(new Ghost(GhostSprites[1],
								Position(
									14 * TILE_SIZE,
									14 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Down));
				}
				else if (c == Clyde)
				{
					players.push_back(new Ghost(GhostSprites[3],
								Position(
									16 * TILE_SIZE,
									14 * TILE_SIZE + (TILE_SIZE - 1) / 2),
								Up));
				}
			}
			StartingGame = new Game(gameField, players);
			return Gameplay;
		}
	}

	return ClientConnected;
}

void ClientConnectedState::Render() const
{
	std::ostringstream ss;
	ss << "You are Player ";
	ss << PlayerNumber + 1;
	std::string str = ss.str();
	Renderer::DrawText(0, str, 24, 60, 100);
	Character c = SelectedCharacter;
	bool ready = Ready;
	unsigned int index = Index;

	if (c == PacMan)
	{
		Renderer::DrawText(0, "< Pac-Man    >", 18, 60, 140);
		Renderer::DrawSprite(
				PacmanSprite,
				9 * TILE_SIZE, 5 * TILE_SIZE,
				0.f, true,
				0, 4);
	}
	else if (c == Blinky)
	{
		Renderer::DrawText(0, "< Blinky     >", 18, 60, 140);
		Renderer::DrawSprite(
				GhostSprites[0],
				9 * TILE_SIZE, 5 * TILE_SIZE,
				0.f, false,
				0, 0);
	}
	else if (c == Inky)
	{
		Renderer::DrawText(0, "< Inky       >", 18, 60, 140);
		Renderer::DrawSprite(
				GhostSprites[2],
				9 * TILE_SIZE, 5 * TILE_SIZE,
				0.f, false,
				0, 0);
	}
	else if (c == Pinky)
	{
		Renderer::DrawText(0, "< Pinky      >", 18, 60, 140);
		Renderer::DrawSprite(
				GhostSprites[1],
				9 * TILE_SIZE, 5 * TILE_SIZE,
				0.f, false,
				0, 0);
	}
	else if (c == Clyde)
	{
		Renderer::DrawText(0, "< Clyde      >", 18, 60, 140);
		Renderer::DrawSprite(
				GhostSprites[3],
				9 * TILE_SIZE, 5 * TILE_SIZE,
				0.f, false,
				0, 0);
	}

	if (ready)
	{
		Renderer::DrawText(0, "< Ready!", 18, 60, 180);
	}
	else
	{
		Renderer::DrawText(0, "  Ready? >", 18, 60, 180);
	}
	Renderer::DrawText(0, ">", 18, 20, 140 + 40 * index);
}
<|endoftext|>


<commit_before>/* The libMesh Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

/* 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 */

 //
Miscellaneous Example 6 - Meshing with LibMesh's TetGen and Triangle Interfaces

 //
 // LibMesh provides interfaces to both Triangle and TetGen for generating
 // Delaunay triangulations and tetrahedralizations in two and three dimensions
 // (respectively).

// Local header files
#include "libmesh/elem.h"
#include "libmesh/face_tri3.h"
#include "libmesh/mesh.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/mesh_tetgen_interface.h"
#include "libmesh/mesh_triangle_holes.h"
#include "libmesh/mesh_triangle_interface.h"
#include "libmesh/node.h"
#include "libmesh/serial_mesh.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

// Major functions called by main
void triangulate_domain(const Parallel::Communicator& comm);
void tetrahedralize_domain(const Parallel::Communicator& comm);

// Helper routine for tetrahedralize_domain().  Adds the points and elements
// of a convex hull generated by TetGen to the input mesh
void add_cube_convex_hull_to_mesh(MeshBase& mesh, Point lower_limit, Point upper_limit);

// Begin the main program.
int main (int argc, char** argv)
{
  // Initialize libMesh and any dependent libaries, like in example 2.
  LibMeshInit init (argc, argv);

  libmesh_example_assert(2 <= LIBMESH_DIM, "2D support");

  std::cout << "Triangulating an L-shaped domain with holes" << std::endl;

  // 1.) 2D triangulation of L-shaped domain with three holes of different shape
  triangulate_domain(init.communicator());

  libmesh_example_assert(3 <= LIBMESH_DIM, "3D support");

  std::cout << "Tetrahedralizing a prismatic domain with a hole" << std::endl;

  // 2.) 3D tetrahedralization of rectangular domain with hole.
  tetrahedralize_domain(init.communicator());

  return 0;
}

void triangulate_domain(const Parallel::Communicator& comm)
{
#ifdef LIBMESH_HAVE_TRIANGLE
  // Use typedefs for slightly less typing.
  typedef TriangleInterface::Hole Hole;
  typedef TriangleInterface::PolygonHole PolygonHole;
  typedef TriangleInterface::ArbitraryHole ArbitraryHole;

  // Libmesh mesh that will eventually be created.
  Mesh mesh(comm, 2);

  // The points which make up the L-shape:
  mesh.add_point(Point( 0. ,  0.));
  mesh.add_point(Point( 0. , -1.));
  mesh.add_point(Point(-1. , -1.));
  mesh.add_point(Point(-1. ,  1.));
  mesh.add_point(Point( 1. ,  1.));
  mesh.add_point(Point( 1. ,  0.));

  // Declare the TriangleInterface object.  This is where
  // we can set parameters of the triangulation and where the
  // actual triangulate function lives.
  TriangleInterface t(mesh);

  // Customize the variables for the triangulation
  t.desired_area()       = .01;

  // A Planar Straight Line Graph (PSLG) is essentially a list
  // of segments which have to exist in the final triangulation.
  // For an L-shaped domain, Triangle will compute the convex
  // hull of boundary points if we do not specify the PSLG.
  // The PSLG algorithm is also required for triangulating domains
  // containing holes
  t.triangulation_type() = TriangleInterface::PSLG;

  // Turn on/off Laplacian mesh smoothing after generation.
  // By default this is on.
  t.smooth_after_generating() = true;

  // Define holes...

  // hole_1 is a circle (discretized by 50 points)
  PolygonHole hole_1(Point(-0.5,  0.5), // center
		     0.25,              // radius
		     50);               // n. points

  // hole_2 is itself a triangle
  PolygonHole hole_2(Point(0.5, 0.5),   // center
		     0.1,               // radius
		     3);                // n. points

  // hole_3 is an ellipse of 100 points which we define here
  Point ellipse_center(-0.5,  -0.5);
  const unsigned int n_ellipse_points=100;
  std::vector<Point> ellipse_points(n_ellipse_points);
  const Real
    dtheta = 2*libMesh::pi / static_cast<Real>(n_ellipse_points),
    a = .1,
    b = .2;

  for (unsigned int i=0; i<n_ellipse_points; ++i)
    ellipse_points[i]= Point(ellipse_center(0)+a*cos(i*dtheta),
			     ellipse_center(1)+b*sin(i*dtheta));

  ArbitraryHole hole_3(ellipse_center, ellipse_points);

  // Create the vector of Hole*'s ...
  std::vector<Hole*> holes;
  holes.push_back(&hole_1);
  holes.push_back(&hole_2);
  holes.push_back(&hole_3);

  // ... and attach it to the triangulator object
  t.attach_hole_list(&holes);

  // Triangulate!
  t.triangulate();

  // Write the result to file
  mesh.write("delaunay_l_shaped_hole.e");

#endif // LIBMESH_HAVE_TRIANGLE
}

void tetrahedralize_domain(const Parallel::Communicator& comm)
{
#ifdef LIBMESH_HAVE_TETGEN
  // The algorithm is broken up into several steps:
  // 1.) A convex hull is constructed for a rectangular hole.
  // 2.) A convex hull is constructed for the domain exterior.
  // 3.) Neighbor information is updated so TetGen knows there is a convex hull
  // 4.) A vector of hole points is created.
  // 5.) The domain is tetrahedralized, the mesh is written out, etc.

  // The mesh we will eventually generate
  SerialMesh mesh(3,comm);

  // Lower and Upper bounding box limits for a rectangular hole within the unit cube.
  Point hole_lower_limit(0.2, 0.2, 0.4);
  Point hole_upper_limit(0.8, 0.8, 0.6);

  // 1.) Construct a convex hull for the hole
  add_cube_convex_hull_to_mesh(mesh, hole_lower_limit, hole_upper_limit);

  // 2.) Generate elements comprising the outer boundary of the domain.
  add_cube_convex_hull_to_mesh(mesh, Point(0.,0.,0.), Point(1., 1., 1.));

  // 3.) Update neighbor information so that TetGen can verify there is a convex hull.
  mesh.find_neighbors();

  // 4.) Set up vector of hole points
  std::vector<Point> hole(1);
  hole[0] = Point( 0.5*(hole_lower_limit + hole_upper_limit) );

  // 5.) Set parameters and tetrahedralize the domain

  // 0 means "use TetGen default value"
  Real quality_constraint = 2.0;

  // The volume constraint determines the max-allowed tetrahedral
  // volume in the Mesh.  TetGen will split cells which are larger than
  // this size
  Real volume_constraint = 0.001;

  // Construct the Delaunay tetrahedralization
  TetGenMeshInterface t(mesh);
  t.triangulate_conformingDelaunayMesh_carvehole(hole,
						 quality_constraint,
						 volume_constraint);

  // Find neighbors, etc in preparation for writing out the Mesh
  mesh.prepare_for_use();

  // Finally, write out the result
  mesh.write("hole_3D.e");
#endif // LIBMESH_HAVE_TETGEN
}

void add_cube_convex_hull_to_mesh(MeshBase& mesh, Point lower_limit, Point upper_limit)
{
#ifdef LIBMESH_HAVE_TETGEN
  SerialMesh cube_mesh(3,mesh.communicator());

  unsigned n_elem = 1;

  MeshTools::Generation::build_cube(cube_mesh,
				    n_elem,n_elem,n_elem, // n. elements in each direction
				    lower_limit(0), upper_limit(0),
				    lower_limit(1), upper_limit(1),
				    lower_limit(2), upper_limit(2),
				    HEX8);

  // The pointset_convexhull() algorithm will ignore the Hex8s
  // in the Mesh, and just construct the triangulation
  // of the convex hull.
  TetGenMeshInterface t(cube_mesh);
  t.pointset_convexhull();

  // Now add all nodes from the boundary of the cube_mesh to the input mesh.

  // Map from "node id in cube_mesh" -> "node id in mesh".  Initially inserted
  // with a dummy value, later to be assigned a value by the input mesh.
  std::map<unsigned,unsigned> node_id_map;
  typedef std::map<unsigned,unsigned>::iterator iterator;

  {
    MeshBase::element_iterator it = cube_mesh.elements_begin();
    const MeshBase::element_iterator end = cube_mesh.elements_end();
    for ( ; it != end; ++it)
      {
	Elem* elem = *it;

	for (unsigned s=0; s<elem->n_sides(); ++s)
	  if (elem->neighbor(s) == NULL)
	    {
	      // Add the node IDs of this side to the set
	      AutoPtr<Elem> side = elem->side(s);

	      for (unsigned n=0; n<side->n_nodes(); ++n)
		node_id_map.insert( std::make_pair(side->node(n), /*dummy_value=*/0) );
	    }
      }
  }

  // For each node in the map, insert it into the input mesh and keep
  // track of the ID assigned.
  for (iterator it=node_id_map.begin(); it != node_id_map.end(); ++it)
    {
      // Id of the node in the cube mesh
      unsigned id = (*it).first;

      // Pointer to node in the cube mesh
      Node* old_node = cube_mesh.node_ptr(id);

      // Add geometric point to input mesh
      Node* new_node = mesh.add_point ( *old_node );

      // Track ID value of new_node in map
      (*it).second = new_node->id();
    }

  // With the points added and the map data structure in place, we are
  // ready to add each TRI3 element of the cube_mesh to the input Mesh
  // with proper node assignments
  {
    MeshBase::element_iterator       el     = cube_mesh.elements_begin();
    const MeshBase::element_iterator end_el = cube_mesh.elements_end();

    for (; el != end_el; ++el)
      {
	Elem* old_elem = *el;

	if (old_elem->type() == TRI3)
	  {
	    Elem* new_elem = mesh.add_elem(new Tri3);

	    // Assign nodes in new elements.  Since this is an example,
	    // we'll do it in several steps.
	    for (unsigned i=0; i<old_elem->n_nodes(); ++i)
	      {
		// Locate old node ID in the map
		iterator it = node_id_map.find(old_elem->node(i));

		// Check for not found
		if (it == node_id_map.end())
		  {
		    libMesh::err << "Node id " << old_elem->node(i) << " not found in map!" << std::endl;
		    libmesh_error();
		  }

		// Mapping to node ID in input mesh
		unsigned new_node_id = (*it).second;

		// Node pointer assigned from input mesh
		new_elem->set_node(i) = mesh.node_ptr(new_node_id);
	      }
	  }
      }
  }
#endif // LIBMESH_HAVE_TETGEN
}
<commit_msg>Missed a couple Mesh creations in previous commit<commit_after>/* The libMesh Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

/* 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 */

 //
Miscellaneous Example 6 - Meshing with LibMesh's TetGen and Triangle Interfaces

 //
 // LibMesh provides interfaces to both Triangle and TetGen for generating
 // Delaunay triangulations and tetrahedralizations in two and three dimensions
 // (respectively).

// Local header files
#include "libmesh/elem.h"
#include "libmesh/face_tri3.h"
#include "libmesh/mesh.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/mesh_tetgen_interface.h"
#include "libmesh/mesh_triangle_holes.h"
#include "libmesh/mesh_triangle_interface.h"
#include "libmesh/node.h"
#include "libmesh/serial_mesh.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

// Major functions called by main
void triangulate_domain(const Parallel::Communicator& comm);
void tetrahedralize_domain(const Parallel::Communicator& comm);

// Helper routine for tetrahedralize_domain().  Adds the points and elements
// of a convex hull generated by TetGen to the input mesh
void add_cube_convex_hull_to_mesh(MeshBase& mesh, Point lower_limit, Point upper_limit);

// Begin the main program.
int main (int argc, char** argv)
{
  // Initialize libMesh and any dependent libaries, like in example 2.
  LibMeshInit init (argc, argv);

  libmesh_example_assert(2 <= LIBMESH_DIM, "2D support");

  std::cout << "Triangulating an L-shaped domain with holes" << std::endl;

  // 1.) 2D triangulation of L-shaped domain with three holes of different shape
  triangulate_domain(init.communicator());

  libmesh_example_assert(3 <= LIBMESH_DIM, "3D support");

  std::cout << "Tetrahedralizing a prismatic domain with a hole" << std::endl;

  // 2.) 3D tetrahedralization of rectangular domain with hole.
  tetrahedralize_domain(init.communicator());

  return 0;
}

void triangulate_domain(const Parallel::Communicator& comm)
{
#ifdef LIBMESH_HAVE_TRIANGLE
  // Use typedefs for slightly less typing.
  typedef TriangleInterface::Hole Hole;
  typedef TriangleInterface::PolygonHole PolygonHole;
  typedef TriangleInterface::ArbitraryHole ArbitraryHole;

  // Libmesh mesh that will eventually be created.
  Mesh mesh(comm, 2);

  // The points which make up the L-shape:
  mesh.add_point(Point( 0. ,  0.));
  mesh.add_point(Point( 0. , -1.));
  mesh.add_point(Point(-1. , -1.));
  mesh.add_point(Point(-1. ,  1.));
  mesh.add_point(Point( 1. ,  1.));
  mesh.add_point(Point( 1. ,  0.));

  // Declare the TriangleInterface object.  This is where
  // we can set parameters of the triangulation and where the
  // actual triangulate function lives.
  TriangleInterface t(mesh);

  // Customize the variables for the triangulation
  t.desired_area()       = .01;

  // A Planar Straight Line Graph (PSLG) is essentially a list
  // of segments which have to exist in the final triangulation.
  // For an L-shaped domain, Triangle will compute the convex
  // hull of boundary points if we do not specify the PSLG.
  // The PSLG algorithm is also required for triangulating domains
  // containing holes
  t.triangulation_type() = TriangleInterface::PSLG;

  // Turn on/off Laplacian mesh smoothing after generation.
  // By default this is on.
  t.smooth_after_generating() = true;

  // Define holes...

  // hole_1 is a circle (discretized by 50 points)
  PolygonHole hole_1(Point(-0.5,  0.5), // center
		     0.25,              // radius
		     50);               // n. points

  // hole_2 is itself a triangle
  PolygonHole hole_2(Point(0.5, 0.5),   // center
		     0.1,               // radius
		     3);                // n. points

  // hole_3 is an ellipse of 100 points which we define here
  Point ellipse_center(-0.5,  -0.5);
  const unsigned int n_ellipse_points=100;
  std::vector<Point> ellipse_points(n_ellipse_points);
  const Real
    dtheta = 2*libMesh::pi / static_cast<Real>(n_ellipse_points),
    a = .1,
    b = .2;

  for (unsigned int i=0; i<n_ellipse_points; ++i)
    ellipse_points[i]= Point(ellipse_center(0)+a*cos(i*dtheta),
			     ellipse_center(1)+b*sin(i*dtheta));

  ArbitraryHole hole_3(ellipse_center, ellipse_points);

  // Create the vector of Hole*'s ...
  std::vector<Hole*> holes;
  holes.push_back(&hole_1);
  holes.push_back(&hole_2);
  holes.push_back(&hole_3);

  // ... and attach it to the triangulator object
  t.attach_hole_list(&holes);

  // Triangulate!
  t.triangulate();

  // Write the result to file
  mesh.write("delaunay_l_shaped_hole.e");

#endif // LIBMESH_HAVE_TRIANGLE
}

void tetrahedralize_domain(const Parallel::Communicator& comm)
{
#ifdef LIBMESH_HAVE_TETGEN
  // The algorithm is broken up into several steps:
  // 1.) A convex hull is constructed for a rectangular hole.
  // 2.) A convex hull is constructed for the domain exterior.
  // 3.) Neighbor information is updated so TetGen knows there is a convex hull
  // 4.) A vector of hole points is created.
  // 5.) The domain is tetrahedralized, the mesh is written out, etc.

  // The mesh we will eventually generate
  SerialMesh mesh(comm,3);

  // Lower and Upper bounding box limits for a rectangular hole within the unit cube.
  Point hole_lower_limit(0.2, 0.2, 0.4);
  Point hole_upper_limit(0.8, 0.8, 0.6);

  // 1.) Construct a convex hull for the hole
  add_cube_convex_hull_to_mesh(mesh, hole_lower_limit, hole_upper_limit);

  // 2.) Generate elements comprising the outer boundary of the domain.
  add_cube_convex_hull_to_mesh(mesh, Point(0.,0.,0.), Point(1., 1., 1.));

  // 3.) Update neighbor information so that TetGen can verify there is a convex hull.
  mesh.find_neighbors();

  // 4.) Set up vector of hole points
  std::vector<Point> hole(1);
  hole[0] = Point( 0.5*(hole_lower_limit + hole_upper_limit) );

  // 5.) Set parameters and tetrahedralize the domain

  // 0 means "use TetGen default value"
  Real quality_constraint = 2.0;

  // The volume constraint determines the max-allowed tetrahedral
  // volume in the Mesh.  TetGen will split cells which are larger than
  // this size
  Real volume_constraint = 0.001;

  // Construct the Delaunay tetrahedralization
  TetGenMeshInterface t(mesh);
  t.triangulate_conformingDelaunayMesh_carvehole(hole,
						 quality_constraint,
						 volume_constraint);

  // Find neighbors, etc in preparation for writing out the Mesh
  mesh.prepare_for_use();

  // Finally, write out the result
  mesh.write("hole_3D.e");
#endif // LIBMESH_HAVE_TETGEN
}

void add_cube_convex_hull_to_mesh(MeshBase& mesh, Point lower_limit, Point upper_limit)
{
#ifdef LIBMESH_HAVE_TETGEN
  SerialMesh cube_mesh(mesh.communicator(),3);

  unsigned n_elem = 1;

  MeshTools::Generation::build_cube(cube_mesh,
				    n_elem,n_elem,n_elem, // n. elements in each direction
				    lower_limit(0), upper_limit(0),
				    lower_limit(1), upper_limit(1),
				    lower_limit(2), upper_limit(2),
				    HEX8);

  // The pointset_convexhull() algorithm will ignore the Hex8s
  // in the Mesh, and just construct the triangulation
  // of the convex hull.
  TetGenMeshInterface t(cube_mesh);
  t.pointset_convexhull();

  // Now add all nodes from the boundary of the cube_mesh to the input mesh.

  // Map from "node id in cube_mesh" -> "node id in mesh".  Initially inserted
  // with a dummy value, later to be assigned a value by the input mesh.
  std::map<unsigned,unsigned> node_id_map;
  typedef std::map<unsigned,unsigned>::iterator iterator;

  {
    MeshBase::element_iterator it = cube_mesh.elements_begin();
    const MeshBase::element_iterator end = cube_mesh.elements_end();
    for ( ; it != end; ++it)
      {
	Elem* elem = *it;

	for (unsigned s=0; s<elem->n_sides(); ++s)
	  if (elem->neighbor(s) == NULL)
	    {
	      // Add the node IDs of this side to the set
	      AutoPtr<Elem> side = elem->side(s);

	      for (unsigned n=0; n<side->n_nodes(); ++n)
		node_id_map.insert( std::make_pair(side->node(n), /*dummy_value=*/0) );
	    }
      }
  }

  // For each node in the map, insert it into the input mesh and keep
  // track of the ID assigned.
  for (iterator it=node_id_map.begin(); it != node_id_map.end(); ++it)
    {
      // Id of the node in the cube mesh
      unsigned id = (*it).first;

      // Pointer to node in the cube mesh
      Node* old_node = cube_mesh.node_ptr(id);

      // Add geometric point to input mesh
      Node* new_node = mesh.add_point ( *old_node );

      // Track ID value of new_node in map
      (*it).second = new_node->id();
    }

  // With the points added and the map data structure in place, we are
  // ready to add each TRI3 element of the cube_mesh to the input Mesh
  // with proper node assignments
  {
    MeshBase::element_iterator       el     = cube_mesh.elements_begin();
    const MeshBase::element_iterator end_el = cube_mesh.elements_end();

    for (; el != end_el; ++el)
      {
	Elem* old_elem = *el;

	if (old_elem->type() == TRI3)
	  {
	    Elem* new_elem = mesh.add_elem(new Tri3);

	    // Assign nodes in new elements.  Since this is an example,
	    // we'll do it in several steps.
	    for (unsigned i=0; i<old_elem->n_nodes(); ++i)
	      {
		// Locate old node ID in the map
		iterator it = node_id_map.find(old_elem->node(i));

		// Check for not found
		if (it == node_id_map.end())
		  {
		    libMesh::err << "Node id " << old_elem->node(i) << " not found in map!" << std::endl;
		    libmesh_error();
		  }

		// Mapping to node ID in input mesh
		unsigned new_node_id = (*it).second;

		// Node pointer assigned from input mesh
		new_elem->set_node(i) = mesh.node_ptr(new_node_id);
	      }
	  }
      }
  }
#endif // LIBMESH_HAVE_TETGEN
}
<|endoftext|>


<commit_before>/* rbOOmit: An implementation of the Certified Reduced Basis method. */
/* Copyright (C) 2009, 2010 David J. Knezevic */
/*     This file is part of rbOOmit. */

/* rbOOmit 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. */

/* rbOOmit 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 */

//
Reduced Basis Example 1 - Certified Reduced Basis Method

// In this example problem we use the Certified Reduced Basis method
// to solve a steady convection-diffusion problem on the unit square.
// The reduced basis method relies on an expansion of the PDE in the
// form \sum_q=1^Q_a theta_a^q(\mu) * a^q(u,v) = \sum_q=1^Q_f theta_f^q(\mu) f^q(v)
// where theta_a, theta_f are parameter dependent functions and
// a^q, f^q are parameter independent operators (\mu denotes a parameter).

// We first attach the parameter dependent functions and paramater
// independent operators to the RBSystem. Then in Offline mode, a
// reduced basis space is generated and written out to the directory
// "offline_data". In Online mode, the reduced basis data in "offline_data"
// is read in and used to solve the reduced problem for the parameters
// specified in reduced_basis_ex1.in.

// We also attach four outputs to the system which are averages over certain
// subregions of the domain. In Online mode, we print out the values of these
// outputs as well as rigorous error bounds with respect to the output
// associated with the "truth" finite element discretization.

// C++ include files that we need
#include <iostream>
#include <algorithm>
#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
#include <cmath>
#include <set>

// Basic include file needed for the mesh functionality.
#include "libmesh/libmesh.h"
#include "libmesh/mesh.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/exodusII_io.h"
#include "libmesh/equation_systems.h"
#include "libmesh/dof_map.h"
#include "libmesh/getpot.h"
#include "libmesh/elem.h"

// local includes
#include "rb_classes.h"
#include "assembly.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

#if !defined(LIBMESH_HAVE_XDR)
  // We need XDR support to write out reduced bases
  libmesh_example_assert(false, "--enable-xdr");
#elif defined(LIBMESH_DEFAULT_SINGLE_PRECISION)
  // XDR binary support requires double precision
  libmesh_example_assert(false, "--disable-singleprecision");
#endif
  // FIXME: This example currently segfaults with Trilinos?
  libmesh_example_assert(libMesh::default_solver_package() == PETSC_SOLVERS, "--enable-petsc");

  // Skip this 2D example if libMesh was compiled as 1D-only.
  libmesh_example_assert(2 <= LIBMESH_DIM, "2D support");

  // Parse the input file (reduced_basis_ex1.in) using GetPot
  std::string parameters_filename = "reduced_basis_ex1.in";
  GetPot infile(parameters_filename);

  unsigned int n_elem = infile("n_elem", 1);       // Determines the number of elements in the "truth" mesh
  const unsigned int dim = 2;                      // The number of spatial dimensions

  bool store_basis_functions = infile("store_basis_functions", true); // Do we write the RB basis functions to disk?

  // Read the "online_mode" flag from the command line
  GetPot command_line (argc, argv);
  int online_mode = 0;
  if ( command_line.search(1, "-online_mode") )
    online_mode = command_line.next(online_mode);

  // Build a mesh on the default MPI communicator.
  Mesh mesh (init.comm(), dim);
  MeshTools::Generation::build_square (mesh,
                                       n_elem, n_elem,
                                       0., 1.,
                                       0., 1.,
                                       QUAD4);

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);

  // We override RBConstruction with SimpleRBConstruction in order to
  // specialize a few functions for this particular problem.
  SimpleRBConstruction & rb_con =
    equation_systems.add_system<SimpleRBConstruction> ("RBConvectionDiffusion");

  // Initialize the data structures for the equation system.
  equation_systems.init ();

  // Print out some information about the "truth" discretization
  equation_systems.print_info();
  mesh.print_info();

  // Build a new RBEvaluation object which will be used to perform
  // Reduced Basis calculations. This is required in both the
  // "Offline" and "Online" stages.
  SimpleRBEvaluation rb_eval(mesh.comm());

  // We need to give the RBConstruction object a pointer to
  // our RBEvaluation object
  rb_con.set_rb_evaluation(rb_eval);

  if(!online_mode) // Perform the Offline stage of the RB method
    {
      // Read in the data that defines this problem from the specified text file
      rb_con.process_parameters_file(parameters_filename);

      // Print out info that describes the current setup of rb_con
      rb_con.print_info();

      // Prepare rb_con for the Construction stage of the RB method.
      // This sets up the necessary data structures and performs
      // initial assembly of the "truth" affine expansion of the PDE.
      rb_con.initialize_rb_construction();

      // Compute the reduced basis space by computing "snapshots", i.e.
      // "truth" solves, at well-chosen parameter values and employing
      // these snapshots as basis functions.
      rb_con.train_reduced_basis();

      // Write out the data that will subsequently be required for the Evaluation stage
      rb_con.get_rb_evaluation().write_offline_data_to_files();

      // If requested, write out the RB basis functions for visualization purposes
      if(store_basis_functions)
        {
          // Write out the basis functions
          rb_con.get_rb_evaluation().write_out_basis_functions(rb_con);
        }

      // Basis functions should be orthonormal, so
      // print out the inner products to check this
      rb_con.print_basis_function_orthogonality();
    }
  else // Perform the Online stage of the RB method
    {
      // Read in the reduced basis data
      rb_eval.read_offline_data_from_files();

      // Read in online_N and initialize online parameters
      unsigned int online_N = infile("online_N",1);
      Real online_x_vel = infile("online_x_vel", 0.);
      Real online_y_vel = infile("online_y_vel", 0.);
      RBParameters online_mu;
      online_mu.set_value("x_vel", online_x_vel);
      online_mu.set_value("y_vel", online_y_vel);
      rb_eval.set_parameters(online_mu);
      rb_eval.print_parameters();

      // Now do the Online solve using the precomputed reduced basis
      rb_eval.rb_solve(online_N);

      // Print out outputs as well as the corresponding output error bounds.
      std::cout << "output 1, value = " << rb_eval.RB_outputs[0]
                << ", bound = " << rb_eval.RB_output_error_bounds[0]
                << std::endl;
      std::cout << "output 2, value = " << rb_eval.RB_outputs[1]
                << ", bound = " << rb_eval.RB_output_error_bounds[1]
                << std::endl;
      std::cout << "output 3, value = " << rb_eval.RB_outputs[2]
                << ", bound = " << rb_eval.RB_output_error_bounds[2]
                << std::endl;
      std::cout << "output 4, value = " << rb_eval.RB_outputs[3]
                << ", bound = " << rb_eval.RB_output_error_bounds[3]
                << std::endl << std::endl;

      if(store_basis_functions)
        {
          // Read in the basis functions
          rb_eval.read_in_basis_functions(rb_con);

          // Plot the solution
          rb_con.load_rb_solution();
#ifdef LIBMESH_HAVE_EXODUS_API
          ExodusII_IO(mesh).write_equation_systems ("RB_sol.e",equation_systems);
#endif

          // Plot the first basis function that was generated from the train_reduced_basis
          // call in the Offline stage
          rb_con.load_basis_function(0);
#ifdef LIBMESH_HAVE_EXODUS_API
          ExodusII_IO(mesh).write_equation_systems ("bf0.e",equation_systems);
#endif
        }
    }

  return 0;
}
<commit_msg>reduced_basis_ex1 works with Eigen sparse linear solvers.<commit_after>/* rbOOmit: An implementation of the Certified Reduced Basis method. */
/* Copyright (C) 2009, 2010 David J. Knezevic */
/*     This file is part of rbOOmit. */

/* rbOOmit 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. */

/* rbOOmit 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 */

//
Reduced Basis Example 1 - Certified Reduced Basis Method

// In this example problem we use the Certified Reduced Basis method
// to solve a steady convection-diffusion problem on the unit square.
// The reduced basis method relies on an expansion of the PDE in the
// form \sum_q=1^Q_a theta_a^q(\mu) * a^q(u,v) = \sum_q=1^Q_f theta_f^q(\mu) f^q(v)
// where theta_a, theta_f are parameter dependent functions and
// a^q, f^q are parameter independent operators (\mu denotes a parameter).

// We first attach the parameter dependent functions and paramater
// independent operators to the RBSystem. Then in Offline mode, a
// reduced basis space is generated and written out to the directory
// "offline_data". In Online mode, the reduced basis data in "offline_data"
// is read in and used to solve the reduced problem for the parameters
// specified in reduced_basis_ex1.in.

// We also attach four outputs to the system which are averages over certain
// subregions of the domain. In Online mode, we print out the values of these
// outputs as well as rigorous error bounds with respect to the output
// associated with the "truth" finite element discretization.

// C++ include files that we need
#include <iostream>
#include <algorithm>
#include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
#include <cmath>
#include <set>

// Basic include file needed for the mesh functionality.
#include "libmesh/libmesh.h"
#include "libmesh/mesh.h"
#include "libmesh/mesh_generation.h"
#include "libmesh/exodusII_io.h"
#include "libmesh/equation_systems.h"
#include "libmesh/dof_map.h"
#include "libmesh/getpot.h"
#include "libmesh/elem.h"

// local includes
#include "rb_classes.h"
#include "assembly.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  LibMeshInit init (argc, argv);

#if !defined(LIBMESH_HAVE_XDR)
  // We need XDR support to write out reduced bases
  libmesh_example_assert(false, "--enable-xdr");
#elif defined(LIBMESH_DEFAULT_SINGLE_PRECISION)
  // XDR binary support requires double precision
  libmesh_example_assert(false, "--disable-singleprecision");
#endif
  // FIXME: This example currently segfaults with Trilinos?  It works
  // with PETSc and Eigen sparse linear solvers though.
  libmesh_example_assert(libMesh::default_solver_package() != TRILINOS_SOLVERS, "--enable-petsc");

  // Skip this 2D example if libMesh was compiled as 1D-only.
  libmesh_example_assert(2 <= LIBMESH_DIM, "2D support");

  // Parse the input file (reduced_basis_ex1.in) using GetPot
  std::string parameters_filename = "reduced_basis_ex1.in";
  GetPot infile(parameters_filename);

  unsigned int n_elem = infile("n_elem", 1);       // Determines the number of elements in the "truth" mesh
  const unsigned int dim = 2;                      // The number of spatial dimensions

  bool store_basis_functions = infile("store_basis_functions", true); // Do we write the RB basis functions to disk?

  // Read the "online_mode" flag from the command line
  GetPot command_line (argc, argv);
  int online_mode = 0;
  if ( command_line.search(1, "-online_mode") )
    online_mode = command_line.next(online_mode);

  // Build a mesh on the default MPI communicator.
  Mesh mesh (init.comm(), dim);
  MeshTools::Generation::build_square (mesh,
                                       n_elem, n_elem,
                                       0., 1.,
                                       0., 1.,
                                       QUAD4);

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);

  // We override RBConstruction with SimpleRBConstruction in order to
  // specialize a few functions for this particular problem.
  SimpleRBConstruction & rb_con =
    equation_systems.add_system<SimpleRBConstruction> ("RBConvectionDiffusion");

  // Initialize the data structures for the equation system.
  equation_systems.init ();

  // Print out some information about the "truth" discretization
  equation_systems.print_info();
  mesh.print_info();

  // Build a new RBEvaluation object which will be used to perform
  // Reduced Basis calculations. This is required in both the
  // "Offline" and "Online" stages.
  SimpleRBEvaluation rb_eval(mesh.comm());

  // We need to give the RBConstruction object a pointer to
  // our RBEvaluation object
  rb_con.set_rb_evaluation(rb_eval);

  if(!online_mode) // Perform the Offline stage of the RB method
    {
      // Read in the data that defines this problem from the specified text file
      rb_con.process_parameters_file(parameters_filename);

      // Print out info that describes the current setup of rb_con
      rb_con.print_info();

      // Prepare rb_con for the Construction stage of the RB method.
      // This sets up the necessary data structures and performs
      // initial assembly of the "truth" affine expansion of the PDE.
      rb_con.initialize_rb_construction();

      // Compute the reduced basis space by computing "snapshots", i.e.
      // "truth" solves, at well-chosen parameter values and employing
      // these snapshots as basis functions.
      rb_con.train_reduced_basis();

      // Write out the data that will subsequently be required for the Evaluation stage
      rb_con.get_rb_evaluation().write_offline_data_to_files();

      // If requested, write out the RB basis functions for visualization purposes
      if(store_basis_functions)
        {
          // Write out the basis functions
          rb_con.get_rb_evaluation().write_out_basis_functions(rb_con);
        }

      // Basis functions should be orthonormal, so
      // print out the inner products to check this
      rb_con.print_basis_function_orthogonality();
    }
  else // Perform the Online stage of the RB method
    {
      // Read in the reduced basis data
      rb_eval.read_offline_data_from_files();

      // Read in online_N and initialize online parameters
      unsigned int online_N = infile("online_N",1);
      Real online_x_vel = infile("online_x_vel", 0.);
      Real online_y_vel = infile("online_y_vel", 0.);
      RBParameters online_mu;
      online_mu.set_value("x_vel", online_x_vel);
      online_mu.set_value("y_vel", online_y_vel);
      rb_eval.set_parameters(online_mu);
      rb_eval.print_parameters();

      // Now do the Online solve using the precomputed reduced basis
      rb_eval.rb_solve(online_N);

      // Print out outputs as well as the corresponding output error bounds.
      std::cout << "output 1, value = " << rb_eval.RB_outputs[0]
                << ", bound = " << rb_eval.RB_output_error_bounds[0]
                << std::endl;
      std::cout << "output 2, value = " << rb_eval.RB_outputs[1]
                << ", bound = " << rb_eval.RB_output_error_bounds[1]
                << std::endl;
      std::cout << "output 3, value = " << rb_eval.RB_outputs[2]
                << ", bound = " << rb_eval.RB_output_error_bounds[2]
                << std::endl;
      std::cout << "output 4, value = " << rb_eval.RB_outputs[3]
                << ", bound = " << rb_eval.RB_output_error_bounds[3]
                << std::endl << std::endl;

      if(store_basis_functions)
        {
          // Read in the basis functions
          rb_eval.read_in_basis_functions(rb_con);

          // Plot the solution
          rb_con.load_rb_solution();
#ifdef LIBMESH_HAVE_EXODUS_API
          ExodusII_IO(mesh).write_equation_systems ("RB_sol.e",equation_systems);
#endif

          // Plot the first basis function that was generated from the train_reduced_basis
          // call in the Offline stage
          rb_con.load_basis_function(0);
#ifdef LIBMESH_HAVE_EXODUS_API
          ExodusII_IO(mesh).write_equation_systems ("bf0.e",equation_systems);
#endif
        }
    }

  return 0;
}
<|endoftext|>


<commit_before>//C++ libs
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>

//C libs
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

const string cmd_delimiter = ";|&#";

void splice_input(queue<string> &cmds, queue<char> &conns, const string &input);
bool run_command(string &input, char &conn);
void tokenize(vector<char*> &comms, string &input);
void trim_lead_and_trail(string &str);

int main()
{
  string input;
  char logic;
  queue<string> commands;
  queue<char> connectors;
  bool running = true;

  char *hostname = new char[20];

  if(gethostname(hostname, 20) == -1)
  {
    perror("Error with getting hostname!");
  }

  //Continue prompting
  while(1)
  {
    cout << getlogin() << "@" << hostname << "$ ";

    getline(cin, input);
    splice_input(commands, connectors, input);

    //After getting input from the user begin dequeing
    //until the queue of commands is empty or logic
    //returns to stop running
    while(!commands.empty() && running)
    {
      //Get command from queue
      input = commands.front();
      commands.pop();
      //Get connector from queue
      if(!connectors.empty())
      {
        logic = connectors.front();
        connectors.pop();
      }

      //Check if input is exit
      //And begin handling command
      if(input.find("exit") == string::npos)
        running = run_command(input, logic);
      else
        exit(1);

      //Clear queues
      if(!running)
      {
        connectors = queue<char>();
        commands = queue<string>();
      }
    }
    //Reset running
    running = true;
  }

  return 0;
}

//Splits the commands and connectors into seperate queues.
void splice_input(queue<string> &cmds, queue<char> &conns, const string &input)
{
  int pos = 0;
  char logic;
  string new_cmd;
  string parse = input;

  while(pos != -1)
  {
    pos = parse.find_first_of(cmd_delimiter);
    new_cmd = parse.substr(0, pos);
    logic = parse[pos];

    trim_lead_and_trail(new_cmd);

    if(logic == '&' || logic == '|')
    {
      if(parse[pos + 1] == logic)
        cmds.push(new_cmd);
      parse.erase(0, pos + 2);
    }
    else if(logic == ';')
    {
      if(parse[pos + 1] == logic)
        cmds.push(new_cmd);
      parse.erase(0, pos + 1);
    }
    else
      cmds.push(new_cmd);

    if(logic == '#')
      return;

    conns.push(logic);
  }
}

bool run_command(string &input, char &conn)
{
  int pid = fork();
  vector<char*> tokens;
  int status = 0;

  if(pid == -1)
  {
    perror("Error with fork()");
    exit(1);
  }
  else if(pid == 0)
  {
    tokenize(tokens, input);
    char **cmds = &tokens[0];
    execvp(cmds[0], cmds);
    perror("Execvp failed!");
    exit(1);
  }
  else
  {
    wait(&status);

    //Deallocating memory
    for( size_t i = 0; i < tokens.size(); i++  )
      delete tokens[i];

    //Cleaning up vector
    tokens.clear();

    //Checking if the connector was AND
    if(conn == '&')
    {
      //If the previous cmd failed stop running
      if(status > 0)
        return false;
    }

    //Checking if the connector was OR
    if(conn == '|')
    {
      //No need to continue running since first cmd was true
      if(status <= 0)
        return false;
    }
  }

  //Continue getting commands
  return true;
}

void tokenize(vector<char*> &comms, string &input)
{
  string convert;
  string tokenizer = input;
  size_t pos = 0;

  trim_lead_and_trail(tokenizer);

  while(pos != string::npos )
  {
    pos = tokenizer.find(' ');
    convert = pos == string::npos ? tokenizer \
                                  : tokenizer.substr(0, pos);

    trim_lead_and_trail(convert);

    if(!convert.empty())
    {
      char *tmp = new char[convert.length() + 1];
      strcpy(tmp, convert.c_str());
      comms.push_back(tmp);
      tokenizer.erase(0, pos + 1);
    }
  }

  comms.push_back(NULL);

  return;
}

void trim_lead_and_trail(string &str)
{
  str.erase(str.begin(), std::find_if(str.begin(), str.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
  str.erase(std::find_if(str.rbegin(), str.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), str.end());
}

<commit_msg>Fixed bug introduced from previous patch<commit_after>//C++ libs
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>

//C libs
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

const string cmd_delimiter = ";|&#";

void splice_input(queue<string> &cmds, queue<char> &conns, const string &input);
bool run_command(string &input, char &conn);
void tokenize(vector<char*> &comms, string &input);
void trim_lead_and_trail(string &str);

int main()
{
  string input;
  char logic;
  queue<string> commands;
  queue<char> connectors;
  bool running = true;

  char *hostname = new char[20];

  if(gethostname(hostname, 20) == -1)
  {
    perror("Error with getting hostname!");
  }

  //Continue prompting
  while(1)
  {
    cout << getlogin() << "@" << hostname << "$ ";

    getline(cin, input);
    splice_input(commands, connectors, input);

    //After getting input from the user begin dequeing
    //until the queue of commands is empty or logic
    //returns to stop running
    while(!commands.empty() && running)
    {
      //Get command from queue
      input = commands.front();
      commands.pop();
      //Get connector from queue
      if(!connectors.empty())
      {
        logic = connectors.front();
        connectors.pop();
      }

      //Check if input is exit
      //And begin handling command
      if(input.find("exit") == string::npos)
        running = run_command(input, logic);
      else
        exit(1);

      //Clear queues
      if(!running)
      {
        connectors = queue<char>();
        commands = queue<string>();
      }
    }
    //Reset running
    running = true;
  }

  return 0;
}

//Splits the commands and connectors into seperate queues.
void splice_input(queue<string> &cmds, queue<char> &conns, const string &input)
{
  int pos = 0;
  char logic;
  string new_cmd;
  string parse = input;

  while(pos != -1)
  {
    pos = parse.find_first_of(cmd_delimiter);
    new_cmd = parse.substr(0, pos);
    logic = parse[pos];

    trim_lead_and_trail(new_cmd);

    if(logic == '&' || logic == '|')
    {
      if(parse[pos + 1] == logic)
        cmds.push(new_cmd);
      parse.erase(0, pos + 2);
    }
    else if(logic == ';')
    {
      cmds.push(new_cmd);
      parse.erase(0, pos + 1);
    }
    else
      cmds.push(new_cmd);

    if(logic == '#')
      return;

    conns.push(logic);
  }
}

bool run_command(string &input, char &conn)
{
  int pid = fork();
  vector<char*> tokens;
  int status = 0;

  if(pid == -1)
  {
    perror("Error with fork()");
    exit(1);
  }
  else if(pid == 0)
  {
    tokenize(tokens, input);
    char **cmds = &tokens[0];
    execvp(cmds[0], cmds);
    perror("Execvp failed!");
    exit(1);
  }
  else
  {
    wait(&status);

    //Deallocating memory
    for( size_t i = 0; i < tokens.size(); i++  )
      delete tokens[i];

    //Cleaning up vector
    tokens.clear();

    //Checking if the connector was AND
    if(conn == '&')
    {
      //If the previous cmd failed stop running
      if(status > 0)
        return false;
    }

    //Checking if the connector was OR
    if(conn == '|')
    {
      //No need to continue running since first cmd was true
      if(status <= 0)
        return false;
    }
  }

  //Continue getting commands
  return true;
}

void tokenize(vector<char*> &comms, string &input)
{
  string convert;
  string tokenizer = input;
  size_t pos = 0;

  trim_lead_and_trail(tokenizer);

  while(pos != string::npos )
  {
    pos = tokenizer.find(' ');
    convert = pos == string::npos ? tokenizer \
                                  : tokenizer.substr(0, pos);

    trim_lead_and_trail(convert);

    if(!convert.empty())
    {
      char *tmp = new char[convert.length() + 1];
      strcpy(tmp, convert.c_str());
      comms.push_back(tmp);
      tokenizer.erase(0, pos + 1);
    }
  }

  comms.push_back(NULL);

  return;
}

void trim_lead_and_trail(string &str)
{
  str.erase(str.begin(), std::find_if(str.begin(), str.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
  str.erase(std::find_if(str.rbegin(), str.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), str.end());
}

<|endoftext|>


<commit_before>#include <algorithm>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <vector>
#include <pwd.h>

const std::multimap<std::string, int> DEFINED_OPS = { std::make_pair("&", 2),
                                                      std::make_pair("|", 2),
                                                      std::make_pair(";", 1) };

const std::vector<std::string> IMPLEMENTED_OPS{ "&&", "||", ";" };

// handles what to do with finalized input state
void Execute(std::list<std::string> &input);

// assumes an operator in the first position of the input list
// extracts and pops it for determination of shell command flow
bool UseOperator(std::list<std::string> &input, bool prevcommandstate);

// used when an UseOperator returns false ie asdf && ls
// the first command is false and && must force a properly inputted second
// command
// to not execute. the command is extracted from the input list and nothing
// is done with it.
void DumpCommand(std::list<std::string> &input);

// assumes non operator in first position of the list
// tokens are extracted from the list until an operator or the end of
// the list is reached. the command is forked and execvp'd
bool UseCommand(std::list<std::string> &input);

// helper function that searched through global const IMPLEMENTED_OPS
// checks inputted string to see if it matches any within the vector
bool ContainsImplementedOp(std::string token);

// Returns true on >1 operators occuring back to back
// e.g. "&&&&&", ";;", etc.
bool FoundRepeat(const std::list<std::string> &input);

// assumes all like-operators have been merged together
// this finds 'strings' of operators that are too long
// rebuilds a std pair from the global const map DEFINED_OPS
// uses it as param to string::find on each element of the input list
// if its found that means it CONTAINS the operator. checking if it
// doesn't equal at this point means it's using operator symbols of an
// incorrect type.
bool InvalidRepeatOp(const std::list<std::string> &input,
                     std::pair<std::string, int> op);

// helper function that calls RebuildOps with each element of global const
// DEFINED_OPS as 2nd parameter (the single instances of & | ;)
void CombineDefinedOps(std::list<std::string> &input);

// unused check for unimplemented operators
bool UnimplementedOp(const std::list<std::string> &input, std::string op);

// uses unix calls to get username and hostname
// returns 'shellish' formatted str ie usrname@host:~$
std::string UserHostInfo();

// output username@hostname$ and wait for command input
std::string Prompt();

// separates string by delimeters into vector elements
// if # is found it excludes it and anything beyond in the string
std::list<std::string> Split(const std::string &input);

// debugging inputlist outputter
void Output(std::list<std::string> &input);

// takes the input list and an operator character and merges all repeating
// instances of that character within the list
// operators in shell can use the same symbol a different amount of times to
// represent different things
// ie bitwise & vs and &&
// the delimiter method I used to separate the arguments in the first place only
// had single character delimiting available
// since the function is general it will:
// avoid having to create new handcrafted parses when more features have to be
// added
// make bug checking general and simple (is & implemented? is &&& implemented?
// if not theyre bugs)
void RebuildOps(std::list<std::string> &input, std::string op);

// does a search in input list for a known operator and checks if the next
// element is also
// a known operator.
bool FoundAdjOp(std::list<std::string> &input);

int main() {
  while (true) {
    auto cmd = Prompt();
    auto input = Split(cmd);
    CombineDefinedOps(input);
    Execute(input);
  }
}
std::string UserHostInfo() {
  auto userinfo = getpwuid(getuid());
  if (errno != 0) {
    perror("error in getpwuid");
    exit(1);
  }
  std::string login(userinfo->pw_name);

  char *rawhost = new char[100];
  auto status = gethostname(rawhost, 100);
  if (status == -1) {
    perror("gethostname failed");
  }

  std::string hostname(rawhost);
  delete[] rawhost;

  char *rawpwd = get_current_dir_name();
  if (rawpwd == NULL) {
    perror("get_current_dir_name returned NULL");
    exit(1);
  }
  std::string pwd(rawpwd);
  delete rawpwd;

  // handles /home/username -> ~/ shortcut
  std::string target = userinfo->pw_dir;
  if (pwd.find(target) == 0) {
    pwd.erase(0, target.size());
    pwd = "~" + pwd;
  }
  return login + "@" + hostname + ":" + pwd + "$ ";
}
std::string Prompt() {
  std::cout << "->" << UserHostInfo();
  std::string input;
  std::getline(std::cin, input);
  return input;
}
std::list<std::string> Split(const std::string &input) {
  using namespace boost;
  using namespace std;
  list<string> input_split;
  char_separator<char> sep(" ", "#&|;");
  typedef tokenizer<char_separator<char> > tokener;

  tokener tokens(input, sep);

  // complexity increases if I handle # as bash does.
  for (const auto &t : tokens) {
    if (t == "#")
      break;
    input_split.push_back(t);
  }
  return input_split;
}
void Output(std::list<std::string> &input) {
  using namespace std;
  for (const auto &e : input)
    cout << e << endl;
}
void RebuildOps(std::list<std::string> &input, std::string op) {
  using namespace std;
  auto front = input.begin();
  auto back = input.end();
  while (front != back) {
    auto element = find(front, back, op);
    int count = 0;
    while (element != back) {
      if (*element == op) {
        element = input.erase(element);
        count++;
      } else {
        break;
      }
    }
    std::string tempstr = "";
    while (count--) {
      tempstr += op;
    }
    if (!tempstr.empty())
      front = input.insert(element, tempstr);
    front++;
  }
}
void CombineDefinedOps(std::list<std::string> &input) {
  for (const auto &op : DEFINED_OPS) {
    RebuildOps(input, op.first);
  }
}
bool FoundRepeat(const std::list<std::string> &input) {
  using namespace std;
  for (const auto &op : DEFINED_OPS) {
    if (InvalidRepeatOp(input, op)) {
      cout << "Invalid '" << op.first << "' usage found" << endl
           << "known operator used an invalid amount of consecutive" << endl
           << "times: e.g. '&&&' -> '&&' ?" << endl;
      return true;
    }
  }
  return false;
}
bool InvalidRepeatOp(const std::list<std::string> &input,
                     std::pair<std::string, int> pair) {
  std::string rebuilt_op = "";
  auto op_size = pair.second;
  while (op_size--) {
    rebuilt_op += pair.first;
  }
  auto front = input.begin();
  auto back = input.end();
  while (front != back) {
    auto itr = std::find_if(front, back, [&](std::string elem) {
      if (elem.find(rebuilt_op) == std::string::npos)
        return false;
      else
        return true;
    });
    if (itr == back)
      return false;

    else if (*itr != rebuilt_op)
      break;
    else {
      front = itr;
      front++;
    }
  }
  return true;
}
bool UnimplementedOp(const std::list<std::string> &input, std::string op) {
  using namespace std;
  auto itr = find(input.begin(), input.end(), op);
  if (itr == input.end()) {
    cout << "operator '" << op << "' is unimplemented" << endl;
    return false;
  }
  return true;
}
bool UseCommand(std::list<std::string> &input) {
  using namespace std;

  // Take list of strings, make copies of their c_strs, and put into vector
  // a vector of char* can be used as char** if used as such
  vector<char *> vectorcommand;
  while (!input.empty() && !ContainsImplementedOp(input.front())) {
    string transferstr = input.front();
    input.pop_front();
    char *cstrcopy = new char[transferstr.size() + 1];
    memcpy(cstrcopy, transferstr.c_str(), transferstr.size() + 1);
    cstrcopy[transferstr.size()] = 0;
    vectorcommand.push_back(cstrcopy);
  }
  vectorcommand.push_back(NULL);

  char **rawcommand = &vectorcommand[0];
  int exitvalue = 0;
  auto pid = fork();
  if (pid == -1) {
    perror("Error on fork");
    exit(1);
  }
  // child state
  else if (pid == 0) {
    execvp(rawcommand[0], rawcommand);
    if (errno != 0) {
      perror("Error in execvp. Likely a nonexisting command?");
      exit(1);
    }
    for (size_t i = 0; i < vectorcommand.size(); i++)
      delete[] rawcommand[i];
  }
  // parent
  else {
    int status;
    auto wait_val = wait(&status);
    if (wait_val == -1) {
      perror("Error on waiting for child process to finish");
      exit(1);
    }
    exitvalue = WEXITSTATUS(status);
    for (size_t i = 0; i < vectorcommand.size(); i++)
      delete[] rawcommand[i];
  }

  if (exitvalue == 0)
    return true;
  else
    return false;
}
bool ContainsImplementedOp(std::string token) {
  auto match = find(IMPLEMENTED_OPS.begin(), IMPLEMENTED_OPS.end(), token);
  if (match != IMPLEMENTED_OPS.end())
    return true;
  return false;
}
bool UseOperator(std::list<std::string> &input, bool prevcommandstate) {
  using namespace std;
  if (input.empty())
    return false;
  string op = input.front();
  input.pop_front();
  if (prevcommandstate == true) {
    if (op == ";")
      return true;
    else if (op == "&&")
      return true;
    else if (op == "||")
      return false;
  } else {
    if (op == ";")
      return true;
    else if (op == "&&")
      return false;
    else if (op == "||")
      return true;
  }
  // proper input ensures we never get down here, so im killing warning message
  // fixing this 'properly' would make it annoying to add more operators later
  cout << "what in god's name" << endl;
  return false;
}
void Execute(std::list<std::string> &input) {
  if (input.empty() || FoundRepeat(input) || FoundAdjOp(input))
    return;
  bool cmdstate = true;
  while (!input.empty()) {
    if (input.front() == "exit")
      exit(0);
    if (cmdstate)
      cmdstate = UseCommand(input);
    else
      DumpCommand(input);
    cmdstate = UseOperator(input, cmdstate);
  }
}
void DumpCommand(std::list<std::string> &input) {
  while (!input.empty() && !ContainsImplementedOp(input.front())) {
    input.pop_front();
  }
}
bool FoundAdjOp(std::list<std::string> &input) {
  using namespace std;
  for (const auto &op : IMPLEMENTED_OPS) {
    auto element = input.begin();
    auto front = input.begin();
    auto next = input.begin();

    auto back = input.end();
    while (element != input.end()) {
      element = find(front, back, op);
      if (element == input.end())
        continue;
      next = element;
      next++;
      if (next == input.end())
        continue;
      else if (find(IMPLEMENTED_OPS.begin(), IMPLEMENTED_OPS.end(), *next) !=
               IMPLEMENTED_OPS.end()) {
        cout << "Two operators are adjacent to each other e.g. '&&;' ?" << endl;
        return true;
      }
      front = next;
      front++;
    }
  }
  return false;
}
<commit_msg>> >> and < work<commit_after>#include <fcntl.h>
#include <algorithm>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <vector>
#include <pwd.h>

const std::multimap<std::string, int> DEFINED_OPS = { std::make_pair("&", 2),
                                                      std::make_pair("|", 2),
                                                      std::make_pair(";", 1),
                                                      std::make_pair("<", 1),
                                                      std::make_pair(">", 2) };

const std::vector<std::string> IMPLEMENTED_OPS{ "&&", "||", ";", "|", ">>", ">", "<" };

void PeekForRedirection(std::list<std::string> &input);
// handles what to do with finalized input state
void Execute(std::list<std::string> &input);

// assumes an operator in the first position of the input list
// extracts and pops it for determination of shell command flow
bool UseOperator(std::list<std::string> &input, bool prevcommandstate);

// used when an UseOperator returns false ie asdf && ls
// the first command is false and && must force a properly inputted second
// command
// to not execute. the command is extracted from the input list and nothing
// is done with it.
void DumpCommand(std::list<std::string> &input);

// assumes non operator in first position of the list
// tokens are extracted from the list until an operator or the end of
// the list is reached. the command is forked and execvp'd
bool UseCommand(std::list<std::string> &input);

// helper function that searched through global const IMPLEMENTED_OPS
// checks inputted string to see if it matches any within the vector
bool ContainsImplementedOp(std::string token);

// Returns true on >1 operators occuring back to back
// e.g. "&&&&&", ";;", etc.
bool FoundRepeat(const std::list<std::string> &input);

// assumes all like-operators have been merged together
// this finds 'strings' of operators that are too long
// rebuilds a std pair from the global const map DEFINED_OPS
// uses it as param to string::find on each element of the input list
// if its found that means it CONTAINS the operator. checking if it
// doesn't equal at this point means it's using operator symbols of an
// incorrect type.
bool InvalidRepeatOp(const std::list<std::string> &input,
                     std::pair<std::string, int> op);

// helper function that calls  with each element of global const
// DEFINED_OPS as 2nd parameter (the single instances of & | ;)
void CombineDefinedOps(std::list<std::string> &input);

// unused check for unimplemented operators
bool UnimplementedOp(const std::list<std::string> &input, std::string op);

// uses unix calls to get username and hostname
// returns 'shellish' formatted str ie usrname@host:~$
std::string UserHostInfo();

// output username@hostname$ and wait for command input
std::string Prompt();

// separates string by delimeters into vector elements
// if # is found it excludes it and anything beyond in the string
std::list<std::string> Split(const std::string &input);

// debugging inputlist outputter
void Output(std::list<std::string> &input);

// takes the input list and an operator character and merges all repeating
// instances of that character within the list
// operators in shell can use the same symbol a different amount of times to
// represent different things
// ie bitwise & vs and &&
// the delimiter method I used to separate the arguments in the first place only
// had single character delimiting available
// since the function is general it will:
// avoid having to create new handcrafted parses when more features have to be
// added
// make bug checking general and simple (is & implemented? is &&& implemented?
// if not theyre bugs)
void RebuildOps(std::list<std::string> &input, std::string op);

// does a search in input list for a known operator and checks if the next
// element is also
// a known operator.
bool FoundAdjOp(std::list<std::string> &input);

int main() {
  while (true) {
    auto cmd = Prompt();
    auto input = Split(cmd);
    CombineDefinedOps(input);
    Execute(input);
  }
}
std::string UserHostInfo() {
  auto userinfo = getpwuid(getuid());
  if (errno != 0) {
    perror("error in getpwuid");
    exit(1);
  }
  std::string login(userinfo->pw_name);

  char *rawhost = new char[100];
  auto status = gethostname(rawhost, 100);
  if (status == -1) {
    perror("gethostname failed");
  }

  std::string hostname(rawhost);
  delete[] rawhost;

  char *rawpwd = get_current_dir_name();
  if (rawpwd == NULL) {
    perror("get_current_dir_name returned NULL");
    exit(1);
  }
  std::string pwd(rawpwd);
  delete rawpwd;

  // handles /home/username -> ~/ shortcut
  std::string target = userinfo->pw_dir;
  if (pwd.find(target) == 0) {
    pwd.erase(0, target.size());
    pwd = "~" + pwd;
  }
  return login + "@" + hostname + ":" + pwd + "$ ";
}
std::string Prompt() {
  std::cout << "->" << UserHostInfo();
  std::string input;
  std::getline(std::cin, input);
  return input;
}
std::list<std::string> Split(const std::string &input) {
  using namespace boost;
  using namespace std;
  list<string> input_split;
  char_separator<char> sep(" ", "#&|;><");
  typedef tokenizer<char_separator<char> > tokener;

  tokener tokens(input, sep);

  // complexity increases if I handle # as bash does.
  for (const auto &t : tokens) {
    if (t == "#")
      break;
    input_split.push_back(t);
  }
  return input_split;
}
void Output(std::list<std::string> &input) {
  using namespace std;
  for (const auto &e : input)
    cout << e << endl;
}
void RebuildOps(std::list<std::string> &input, std::string op) {
  using namespace std;
  auto front = input.begin();
  auto back = input.end();
  while (front != back) {
    auto element = find(front, back, op);
    int count = 0;
    while (element != back) {
      if (*element == op) {
        element = input.erase(element);
        count++;
      } else {
        break;
      }
    }
    std::string tempstr = "";
    while (count--) {
      tempstr += op;
    }
    if (!tempstr.empty())
      front = input.insert(element, tempstr);
    front++;
  }
}
void CombineDefinedOps(std::list<std::string> &input) {
  for (const auto &op : DEFINED_OPS) {
    RebuildOps(input, op.first);
  }
}
bool FoundRepeat(const std::list<std::string> &input) {
  using namespace std;
  for (const auto &op : DEFINED_OPS) {
    if (InvalidRepeatOp(input, op)) {
      cout << "Invalid '" << op.first << "' usage found" << endl
           << "known operator used an invalid amount of consecutive" << endl
           << "times: e.g. '&&&' -> '&&' ?" << endl;
      return true;
    }
  }
  return false;
}
bool InvalidRepeatOp(const std::list<std::string> &input,
                     std::pair<std::string, int> pair) {
  std::string rebuilt_op = "";
  auto op_size = pair.second;
  while (op_size--) {
    rebuilt_op += pair.first;
  }
  auto front = input.begin();
  auto back = input.end();
  while (front != back) {
    auto itr = std::find_if(front, back, [&](std::string elem) {
      if (elem.find(rebuilt_op) == std::string::npos)
        return false;
      else
        return true;
    });
    if (itr == back)
      return false;

    else if (*itr != rebuilt_op)
      break;
    else {
      front = itr;
      front++;
    }
  }
  return true;
}
bool UnimplementedOp(const std::list<std::string> &input, std::string op) {
  using namespace std;
  auto itr = find(input.begin(), input.end(), op);
  if (itr == input.end()) {
    cout << "operator '" << op << "' is unimplemented" << endl;
    return false;
  }
  return true;
}
bool UseCommand(std::list<std::string> &input) {
  using namespace std;

  // Take list of strings, make copies of their c_strs, and put into vector
  // a vector of char* can be used as char** if used as such
  vector<char *> vectorcommand;
  while (!input.empty() && !ContainsImplementedOp(input.front())) {
    string transferstr = input.front();
    input.pop_front();
    char *cstrcopy = new char[transferstr.size() + 1];
    memcpy(cstrcopy, transferstr.c_str(), transferstr.size() + 1);
    cstrcopy[transferstr.size()] = 0;
    vectorcommand.push_back(cstrcopy);
  }
  vectorcommand.push_back(NULL);

  char **rawcommand = &vectorcommand[0];
  int exitvalue = 0;
  auto pid = fork();
  if (pid == -1) {
    perror("Error on fork");
    exit(1);
  }
  // child state
  else if (pid == 0) {
    //TODO search operators inplace of input vector?
    if (!input.empty()) {
      PeekForRedirection(input);
    }

    execvp(rawcommand[0], rawcommand);
    if (errno != 0) {
      perror("Error in execvp. Likely a nonexisting command?");
      exit(1);
    }
    for (size_t i = 0; i < vectorcommand.size(); i++)
      delete[] rawcommand[i];
  }
  // parent
  else {
    int status;
    auto wait_val = wait(&status);
    if (wait_val == -1) {
      perror("Error on waiting for child process to finish");
      exit(1);
    }
    exitvalue = WEXITSTATUS(status);
    for (size_t i = 0; i < vectorcommand.size(); i++)
      delete[] rawcommand[i];
  }
  if (exitvalue == 0)
    return true;
  else
    return false;
}
bool ContainsImplementedOp(std::string token) {
  auto match = find(IMPLEMENTED_OPS.begin(), IMPLEMENTED_OPS.end(), token);
  if (match != IMPLEMENTED_OPS.end())
    return true;
  return false;
}
bool UseOperator(std::list<std::string> &input, bool prevcommandstate) {
  using namespace std;
  if (input.empty())
    return false;
  string op = input.front();
  input.pop_front();
  if (prevcommandstate == true) {
    if (op == ";")
      return true;
    else if (op == "&&")
      return true;
    else if (op == "||")
      return false;
  } else {
    if (op == ";")
      return true;
    else if (op == "&&")
      return false;
    else if (op == "||")
      return true;
  }
  // proper input ensures we never get down here, so im killing warning message
  // fixing this 'properly' would make it annoying to add more operators later
  //TODO make that not wrong^
  return true;
}
void Execute(std::list<std::string> &input) {
  if (input.empty() || FoundRepeat(input) || FoundAdjOp(input))
    return;
  bool cmdstate = true;
  while (!input.empty()) {
    if (input.front() == "exit")
      exit(0);
    if (cmdstate) {
      cmdstate = UseCommand(input);
      }
    else
      DumpCommand(input);
    cmdstate = UseOperator(input, cmdstate);
  }
}
void DumpCommand(std::list<std::string> &input) {
  while (!input.empty() && !ContainsImplementedOp(input.front())) {
    input.pop_front();
  }
}
bool FoundAdjOp(std::list<std::string> &input) {
  using namespace std;
  for (const auto &op : IMPLEMENTED_OPS) {
    auto element = input.begin();
    auto front = input.begin();
    auto next = input.begin();

    auto back = input.end();
    while (element != input.end()) {
      element = find(front, back, op);
      if (element == input.end())
        continue;
      next = element;
      next++;
      if (next == input.end())
        continue;
      else if (find(IMPLEMENTED_OPS.begin(), IMPLEMENTED_OPS.end(), *next) !=
               IMPLEMENTED_OPS.end()) {
        cout << "Two operators are adjacent to each other e.g. '&&;' ?" << endl;
        return true;
      }
      front = next;
      front++;
    }
  }
  return false;
}
void PeekForRedirection(std::list<std::string> &input) {
  std::string op = input.front();
  input.pop_front();
  std::string target = input.front();
  input.pop_front();
  int fd = -1;
  if (op == ">") {
    fd = open(target.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);
    close(1);
    dup2(fd, 1);
  }
  else if (op == ">>") {
    fd = open(target.c_str(), O_RDWR | O_CREAT | O_APPEND, 0644);
    close(1);
    dup2(fd, 1);
  }
  else if (op == "<") {
    fd = open(target.c_str(), O_RDONLY, 0644);
    close(0);
    dup2(fd, 0);
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "KytheVFS.h"

#include "kythe/cxx/common/proto_conversions.h"

#include "llvm/Support/Path.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"

namespace kythe {

IndexVFS::IndexVFS(const std::string &working_directory,
                   const std::vector<proto::FileData> &virtual_files)
    : virtual_files_(virtual_files), working_directory_(working_directory) {
  assert(llvm::sys::path::is_absolute(working_directory) &&
         "Working directory must be absolute.");
  for (const auto &data : virtual_files_) {
    if (auto *record = FileRecordForPath(ToStringRef(data.info().path()),
                                         BehaviorOnMissing::kCreateFile,
                                         data.content().size())) {
      record->data = llvm::StringRef(data.content());
    }
  }
}

IndexVFS::~IndexVFS() {
  for (auto &entry : uid_to_record_map_) {
    delete entry.second;
  }
}

llvm::ErrorOr<clang::vfs::Status> IndexVFS::status(const llvm::Twine &path) {
  if (const auto *record =
          FileRecordForPath(path.str(), BehaviorOnMissing::kReturnError, 0)) {
    return record->status;
  }
  return make_error_code(llvm::errc::no_such_file_or_directory);
}

llvm::ErrorOr<std::unique_ptr<clang::vfs::File>> IndexVFS::openFileForRead(
    const llvm::Twine &path) {
  if (FileRecord *record =
          FileRecordForPath(path.str(), BehaviorOnMissing::kReturnError, 0)) {
    if (record->status.getType() == llvm::sys::fs::file_type::regular_file) {
      return std::unique_ptr<clang::vfs::File>(new File(record));
    }
  }
  return make_error_code(llvm::errc::no_such_file_or_directory);
}

clang::vfs::directory_iterator IndexVFS::dir_begin(
    const llvm::Twine &dir, std::error_code &error_code) {
  llvm_unreachable("unimplemented");
}

void IndexVFS::SetVName(const std::string &path, const proto::VName &vname) {
  if (FileRecord *record =
          FileRecordForPath(path, BehaviorOnMissing::kReturnError, 0)) {
    if (record->status.getType() == llvm::sys::fs::file_type::regular_file) {
      record->vname.CopyFrom(vname);
      record->has_vname = true;
    }
  }
}

bool IndexVFS::get_vname(const clang::FileEntry *entry,
                         proto::VName *merge_with) {
  auto record = uid_to_record_map_.find(entry->getUniqueID());
  if (record != uid_to_record_map_.end()) {
    if (record->second->status.getType() ==
            llvm::sys::fs::file_type::regular_file &&
        record->second->has_vname) {
      merge_with->CopyFrom(record->second->vname);
      return true;
    }
  }
  return false;
}

std::string IndexVFS::get_debug_uid_string(const llvm::sys::fs::UniqueID &uid) {
  auto record = uid_to_record_map_.find(uid);
  if (record != uid_to_record_map_.end()) {
    return record->second->status.getName();
  }
  return "uid(device: " + std::to_string(uid.getDevice()) + " file: " +
         std::to_string(uid.getFile()) + ")";
}

IndexVFS::FileRecord *IndexVFS::FileRecordForPathRoot(const llvm::Twine &path,
                                                      bool create_if_missing) {
  std::string path_str(path.str());
  bool is_absolute = true;
  auto root_name = llvm::sys::path::root_name(path_str);
  if (root_name.empty()) {
    root_name = llvm::sys::path::root_name(working_directory_);
    if (!root_name.empty()) {
      // This index comes from a filesystem with significant root names.
      is_absolute = false;
    }
  }
  auto root_dir = llvm::sys::path::root_directory(path_str);
  if (root_dir.empty()) {
    root_dir = llvm::sys::path::root_directory(working_directory_);
    is_absolute = false;
  }
  if (!is_absolute) {
    // This terminates: the working directory must be an absolute path.
    return FileRecordForPath(working_directory_,
                             create_if_missing
                                 ? BehaviorOnMissing::kCreateDirectory
                                 : BehaviorOnMissing::kReturnError,
                             0);
  }
  FileRecord *name_record = nullptr;
  auto name_found = root_name_to_root_map_.find(root_name);
  if (name_found != root_name_to_root_map_.end()) {
    name_record = name_found->second;
  } else if (!create_if_missing) {
    return nullptr;
  } else {
    name_record = new FileRecord(
        {clang::vfs::Status(
             root_name, root_name, clang::vfs::getNextVirtualUniqueID(),
             llvm::sys::TimeValue(), 0, 0, 0,
             llvm::sys::fs::file_type::directory_file, llvm::sys::fs::all_read),
         false, root_name});
    root_name_to_root_map_[root_name] = name_record;
    uid_to_record_map_[name_record->status.getUniqueID()] = name_record;
  }
  return AllocOrReturnFileRecord(name_record, create_if_missing, root_dir,
                                 llvm::sys::fs::file_type::directory_file, 0);
}

IndexVFS::FileRecord *IndexVFS::FileRecordForPath(const llvm::StringRef path,
                                                  BehaviorOnMissing behavior,
                                                  size_t size) {
  using namespace llvm::sys::path;
  std::vector<llvm::StringRef> path_components;
  int skip_count = 0;

  auto eventual_type = (behavior == BehaviorOnMissing::kCreateFile
                            ? llvm::sys::fs::file_type::regular_file
                            : llvm::sys::fs::file_type::directory_file);
  bool create_if_missing = (behavior != BehaviorOnMissing::kReturnError);
  size_t eventual_size =
      (behavior == BehaviorOnMissing::kCreateFile ? size : 0);

  for (auto node = llvm::sys::path::rbegin(path), node_end = rend(path);
       node != node_end; ++node) {
    if (*node == "..") {
      ++skip_count;
    } else if (*node != ".") {
      if (skip_count > 0) {
        --skip_count;
      } else {
        path_components.push_back(*node);
      }
    }
  }
  FileRecord *current_record = FileRecordForPathRoot(path, create_if_missing);
  for (auto node = path_components.crbegin(),
            node_end = path_components.crend();
       current_record != nullptr && node != node_end;) {
    llvm::StringRef label = *node;
    bool is_last = (++node == node_end);
    current_record = AllocOrReturnFileRecord(
        current_record, create_if_missing, label,
        is_last ? eventual_type : llvm::sys::fs::file_type::directory_file,
        is_last ? eventual_size : 0);
  }
  return current_record;
}

IndexVFS::FileRecord *IndexVFS::AllocOrReturnFileRecord(
    FileRecord *parent, bool create_if_missing, llvm::StringRef label,
    llvm::sys::fs::file_type type, size_t size) {
  assert(parent != nullptr);
  for (auto &record : parent->children) {
    if (record->label == label) {
      if (create_if_missing && (record->status.getSize() != size ||
                                record->status.getType() != type)) {
        fprintf(stderr, "Warning: path %s/%s: defined inconsistently (%d/%d)\n",
                parent->status.getName().str().c_str(), label.str().c_str(),
                type, record->status.getType());
        return nullptr;
      }
      return record;
    }
  }
  if (!create_if_missing) {
    return nullptr;
  }
  llvm::SmallString<1024> out_path(llvm::StringRef(parent->status.getName()));
  llvm::sys::path::append(out_path, label);
  FileRecord *new_record = new FileRecord{
      clang::vfs::Status(
          out_path, out_path, clang::vfs::getNextVirtualUniqueID(),
          llvm::sys::TimeValue(), 0, 0, size, type, llvm::sys::fs::all_read),
      false, label};
  parent->children.push_back(new_record);
  uid_to_record_map_[new_record->status.getUniqueID()] = new_record;
  return new_record;
}

}  // namespace kythe
<commit_msg>Make a conversion to StringRef explicit.<commit_after>/*
 * Copyright 2015 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "KytheVFS.h"

#include "kythe/cxx/common/proto_conversions.h"

#include "llvm/Support/Path.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"

namespace kythe {

IndexVFS::IndexVFS(const std::string &working_directory,
                   const std::vector<proto::FileData> &virtual_files)
    : virtual_files_(virtual_files), working_directory_(working_directory) {
  assert(llvm::sys::path::is_absolute(working_directory) &&
         "Working directory must be absolute.");
  for (const auto &data : virtual_files_) {
    if (auto *record = FileRecordForPath(ToStringRef(data.info().path()),
                                         BehaviorOnMissing::kCreateFile,
                                         data.content().size())) {
      record->data = llvm::StringRef(data.content().data(),
                                     data.content().size());
    }
  }
}

IndexVFS::~IndexVFS() {
  for (auto &entry : uid_to_record_map_) {
    delete entry.second;
  }
}

llvm::ErrorOr<clang::vfs::Status> IndexVFS::status(const llvm::Twine &path) {
  if (const auto *record =
          FileRecordForPath(path.str(), BehaviorOnMissing::kReturnError, 0)) {
    return record->status;
  }
  return make_error_code(llvm::errc::no_such_file_or_directory);
}

llvm::ErrorOr<std::unique_ptr<clang::vfs::File>> IndexVFS::openFileForRead(
    const llvm::Twine &path) {
  if (FileRecord *record =
          FileRecordForPath(path.str(), BehaviorOnMissing::kReturnError, 0)) {
    if (record->status.getType() == llvm::sys::fs::file_type::regular_file) {
      return std::unique_ptr<clang::vfs::File>(new File(record));
    }
  }
  return make_error_code(llvm::errc::no_such_file_or_directory);
}

clang::vfs::directory_iterator IndexVFS::dir_begin(
    const llvm::Twine &dir, std::error_code &error_code) {
  llvm_unreachable("unimplemented");
}

void IndexVFS::SetVName(const std::string &path, const proto::VName &vname) {
  if (FileRecord *record =
          FileRecordForPath(path, BehaviorOnMissing::kReturnError, 0)) {
    if (record->status.getType() == llvm::sys::fs::file_type::regular_file) {
      record->vname.CopyFrom(vname);
      record->has_vname = true;
    }
  }
}

bool IndexVFS::get_vname(const clang::FileEntry *entry,
                         proto::VName *merge_with) {
  auto record = uid_to_record_map_.find(entry->getUniqueID());
  if (record != uid_to_record_map_.end()) {
    if (record->second->status.getType() ==
            llvm::sys::fs::file_type::regular_file &&
        record->second->has_vname) {
      merge_with->CopyFrom(record->second->vname);
      return true;
    }
  }
  return false;
}

std::string IndexVFS::get_debug_uid_string(const llvm::sys::fs::UniqueID &uid) {
  auto record = uid_to_record_map_.find(uid);
  if (record != uid_to_record_map_.end()) {
    return record->second->status.getName();
  }
  return "uid(device: " + std::to_string(uid.getDevice()) + " file: " +
         std::to_string(uid.getFile()) + ")";
}

IndexVFS::FileRecord *IndexVFS::FileRecordForPathRoot(const llvm::Twine &path,
                                                      bool create_if_missing) {
  std::string path_str(path.str());
  bool is_absolute = true;
  auto root_name = llvm::sys::path::root_name(path_str);
  if (root_name.empty()) {
    root_name = llvm::sys::path::root_name(working_directory_);
    if (!root_name.empty()) {
      // This index comes from a filesystem with significant root names.
      is_absolute = false;
    }
  }
  auto root_dir = llvm::sys::path::root_directory(path_str);
  if (root_dir.empty()) {
    root_dir = llvm::sys::path::root_directory(working_directory_);
    is_absolute = false;
  }
  if (!is_absolute) {
    // This terminates: the working directory must be an absolute path.
    return FileRecordForPath(working_directory_,
                             create_if_missing
                                 ? BehaviorOnMissing::kCreateDirectory
                                 : BehaviorOnMissing::kReturnError,
                             0);
  }
  FileRecord *name_record = nullptr;
  auto name_found = root_name_to_root_map_.find(root_name);
  if (name_found != root_name_to_root_map_.end()) {
    name_record = name_found->second;
  } else if (!create_if_missing) {
    return nullptr;
  } else {
    name_record = new FileRecord(
        {clang::vfs::Status(
             root_name, root_name, clang::vfs::getNextVirtualUniqueID(),
             llvm::sys::TimeValue(), 0, 0, 0,
             llvm::sys::fs::file_type::directory_file, llvm::sys::fs::all_read),
         false, root_name});
    root_name_to_root_map_[root_name] = name_record;
    uid_to_record_map_[name_record->status.getUniqueID()] = name_record;
  }
  return AllocOrReturnFileRecord(name_record, create_if_missing, root_dir,
                                 llvm::sys::fs::file_type::directory_file, 0);
}

IndexVFS::FileRecord *IndexVFS::FileRecordForPath(const llvm::StringRef path,
                                                  BehaviorOnMissing behavior,
                                                  size_t size) {
  using namespace llvm::sys::path;
  std::vector<llvm::StringRef> path_components;
  int skip_count = 0;

  auto eventual_type = (behavior == BehaviorOnMissing::kCreateFile
                            ? llvm::sys::fs::file_type::regular_file
                            : llvm::sys::fs::file_type::directory_file);
  bool create_if_missing = (behavior != BehaviorOnMissing::kReturnError);
  size_t eventual_size =
      (behavior == BehaviorOnMissing::kCreateFile ? size : 0);

  for (auto node = llvm::sys::path::rbegin(path), node_end = rend(path);
       node != node_end; ++node) {
    if (*node == "..") {
      ++skip_count;
    } else if (*node != ".") {
      if (skip_count > 0) {
        --skip_count;
      } else {
        path_components.push_back(*node);
      }
    }
  }
  FileRecord *current_record = FileRecordForPathRoot(path, create_if_missing);
  for (auto node = path_components.crbegin(),
            node_end = path_components.crend();
       current_record != nullptr && node != node_end;) {
    llvm::StringRef label = *node;
    bool is_last = (++node == node_end);
    current_record = AllocOrReturnFileRecord(
        current_record, create_if_missing, label,
        is_last ? eventual_type : llvm::sys::fs::file_type::directory_file,
        is_last ? eventual_size : 0);
  }
  return current_record;
}

IndexVFS::FileRecord *IndexVFS::AllocOrReturnFileRecord(
    FileRecord *parent, bool create_if_missing, llvm::StringRef label,
    llvm::sys::fs::file_type type, size_t size) {
  assert(parent != nullptr);
  for (auto &record : parent->children) {
    if (record->label == label) {
      if (create_if_missing && (record->status.getSize() != size ||
                                record->status.getType() != type)) {
        fprintf(stderr, "Warning: path %s/%s: defined inconsistently (%d/%d)\n",
                parent->status.getName().str().c_str(), label.str().c_str(),
                type, record->status.getType());
        return nullptr;
      }
      return record;
    }
  }
  if (!create_if_missing) {
    return nullptr;
  }
  llvm::SmallString<1024> out_path(llvm::StringRef(parent->status.getName()));
  llvm::sys::path::append(out_path, label);
  FileRecord *new_record = new FileRecord{
      clang::vfs::Status(
          out_path, out_path, clang::vfs::getNextVirtualUniqueID(),
          llvm::sys::TimeValue(), 0, 0, size, type, llvm::sys::fs::all_read),
      false, label};
  parent->children.push_back(new_record);
  uid_to_record_map_[new_record->status.getUniqueID()] = new_record;
  return new_record;
}

}  // namespace kythe
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <string>
#include <memory>
#include <vector>
#include <sstream>
#include <boost/tokenizer.hpp>
std::string UserHostInfo();
void Prompt();
void Parse(const char** argslist);
std::vector<std::string> ParseDashArg(const std::string& dashlist);
bool ContainsHome(const std::string& pwd, const std::string& loginname);

int main() {
    std::string list = "ls";

    const char** test = new const char*[10];
    //execvp(list.c_str(), args);

}

//uses unix calls to get username and hostname
//returns 'shellish' formatted str ie U@H:
std::string UserHostInfo() {
    std::string loginname(getlogin());

    char* rawhost= new char[100];
    gethostname(rawhost,100);
    std::string hostname(rawhost);
    delete [] rawhost;

    std::string cwd(get_current_dir_name());
    if(ContainsHome)
        std::cout << "hey";
    return loginname+"@"+hostname+":"+cwd+"$ ";
}

bool ContainsHome(const std::string& pwd, const std::string& loginname) {
    std::string target = "/home/"+loginname+"/";
    if (pwd.find(target) == 0)
        return true;
    return false;
}

void ArgsFill(const char** argslist) {

}

void Prompt() {
    std::cout << UserHostInfo();
    std::string input;
    std::cin >> input;

}
std::vector<std::string> ParseDashArg(const std::string& dashlist) {

}
<commit_msg>fix tinkerings to make it build-- more formal from here on out<commit_after>#include <iostream>
#include <unistd.h>
#include <string>
#include <memory>
#include <vector>
#include <sstream>
#include <boost/tokenizer.hpp>
std::string UserHostInfo();
void Prompt();
bool ContainsHome(const std::string& pwd, const std::string& loginname);

int main() {

    std::cout << UserHostInfo();
    //execvp(list.c_str(), args);

}

//uses unix calls to get username and hostname
//returns 'shellish' formatted str ie U@H:
std::string UserHostInfo() {
    std::string loginname(getlogin());

    char* rawhost= new char[100];
    gethostname(rawhost,100);
    std::string hostname(rawhost);
    delete [] rawhost;

    std::string cwd(get_current_dir_name());
    if(ContainsHome(cwd, loginname))
        std::cout << "hey";
    return loginname+"@"+hostname+":"+cwd+"$ ";
}

bool ContainsHome(const std::string& pwd, const std::string& loginname) {
    std::string target = "/home/"+loginname+"/";
    if (pwd.find(target) == 0) {
                return true;
    }
    return false;
}

void Prompt() {
    std::cout << UserHostInfo();
    std::string input;
    std::cin >> input;

}
<|endoftext|>