<commit_before>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use phf::PhfMap;

use std::mem::replace;
use std::fmt::{Show, Formatter, FormatError};

static static_atom_map: PhfMap<&'static str, uint> = static_atom_map!();
static static_atom_array: &'static [&'static str] = static_atom_array!();

// Assume that a string which can be interned always is.
// FIXME: Revisit this assumption when we have dynamic interning.
/// Interned string.
///
/// Don't pattern-match this directly! Use the `atom!()` pattern macro.
#[deriving(Clone, PartialEq, Eq)]
pub enum Atom {
    Static(uint),
    // dynamic interning goes here
    Owned(String),
}

impl Atom {
    pub fn from_str(s: &str) -> Atom {
        match static_atom_map.find_equiv(&s) {
            Some(&k) => Static(k),
            None => Owned(s.to_string()),
        }
    }

    pub fn from_buf(s: String) -> Atom {
        match static_atom_map.find_equiv(&s.as_slice()) {
            Some(&k) => Static(k),
            None => Owned(s),
        }
    }

    /// Like `Atom::from_buf(replace(s, String::new()))` but avoids
    /// allocating a new `String` when the string is interned --
    /// just truncates the old one.
    pub fn take_from_buf(s: &mut String) -> Atom {
        match static_atom_map.find_equiv(&s.as_slice()) {
            Some(&k) => {
                s.truncate(0);
                Static(k)
            }
            None => {
                Owned(replace(s, String::new()))
            }
        }
    }

    #[inline(always)]
    fn fast_partial_eq(&self, other: &Atom) -> Option<bool> {
        match (self, other) {
            (&Static(x), &Static(y)) => Some(x == y),
            _ => None,
        }
    }
}

fn get_static(i: uint) -> &'static str {
    *static_atom_array.get(i).expect("bad static atom")
}

impl Str for Atom {
    fn as_slice<'t>(&'t self) -> &'t str {
        match *self {
            Static(i) => get_static(i),
            Owned(ref s) => s.as_slice(),
        }
    }
}

impl StrAllocating for Atom {
    fn into_string(self) -> String {
        match self {
            Static(i) => get_static(i).to_string(),
            Owned(s) => s.into_string(),
        }
    }

    fn into_owned(self) -> String {
        match self {
            Static(i) => get_static(i).to_string(),
            Owned(s) => s,
        }
    }
}

impl PartialOrd for Atom {
    fn partial_cmp(&self, other: &Atom) -> Option<Ordering> {
        match self.fast_partial_eq(other) {
            Some(true) => Some(Equal),
            _ => self.as_slice().partial_cmp(&other.as_slice()),
        }
    }
}

impl Ord for Atom {
    fn cmp(&self, other: &Atom) -> Ordering {
        match self.fast_partial_eq(other) {
            Some(true) => Equal,
            _ => self.as_slice().cmp(&other.as_slice()),
        }
    }
}

impl Show for Atom {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        try!("atom!(".fmt(fmt));
        try!(self.as_slice().fmt(fmt));
        ")".fmt(fmt)
    }
}

#[cfg(test)]
#[allow(non_snake_case_functions)]
mod test {
    use super::{Atom, get_static, Static, Owned};

    #[test]
    fn interned() {
        match Atom::from_str("body") {
            Static(i) => assert_eq!(get_static(i), "body"),
            _ => fail!("wrong interning"),
        }
    }

    #[test]
    fn not_interned() {
        match Atom::from_str("asdfghjk") {
            Owned(b) => assert_eq!(b.as_slice(), "asdfghjk"),
            _ => fail!("wrong interning"),
        }
    }

    #[test]
    fn as_slice() {
        assert_eq!(Atom::from_str("").as_slice(), "");
        assert_eq!(Atom::from_str("body").as_slice(), "body");
        assert_eq!(Atom::from_str("asdfghjk").as_slice(), "asdfghjk");
    }

    #[test]
    fn into_string() {
        assert_eq!(Atom::from_str("").into_string(), "".to_string());
        assert_eq!(Atom::from_str("body").into_string(), "body".to_string());
        assert_eq!(Atom::from_str("asdfghjk").into_string(), "asdfghjk".to_string());
    }

    #[test]
    fn to_string() {
        assert_eq!(Atom::from_str("").to_string(), "".to_string());
        assert_eq!(Atom::from_str("body").to_string(), "body".to_string());
        assert_eq!(Atom::from_str("asdfghjk").to_string(), "asdfghjk".to_string());
    }

    #[test]
    fn take_from_buf_interned() {
        let mut b = "body".to_string();
        let a = Atom::take_from_buf(&mut b);
        assert_eq!(a, Atom::from_str("body"));
        assert_eq!(b, String::new());
    }

    #[test]
    fn take_from_buf_not_interned() {
        let mut b = "asdfghjk".to_string();
        let a = Atom::take_from_buf(&mut b);
        assert_eq!(a, Atom::from_str("asdfghjk"));
        assert_eq!(b, String::new());
    }

    #[test]
    fn ord() {
        fn check(x: &str, y: &str) {
            assert_eq!(x < y, Atom::from_str(x) < Atom::from_str(y));
            assert_eq!(x.cmp(&y), Atom::from_str(x).cmp(&Atom::from_str(y)));
        }

        check("a", "body");
        check("asdf", "body");
        check("zasdf", "body");
        check("z", "body");

        check("a", "bbbbb");
        check("asdf", "bbbbb");
        check("zasdf", "bbbbb");
        check("z", "bbbbb");
    }

    #[test]
    fn atom_macro() {
        assert_eq!(atom!(body), Atom::from_str("body"));
        assert_eq!(atom!("body"), Atom::from_str("body"));
        assert_eq!(atom!("font-weight"), Atom::from_str("font-weight"));
    }

    #[test]
    fn match_atom() {
        assert_eq!(2u, match Atom::from_str("head") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });

        assert_eq!(3u, match Atom::from_str("body") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });

        assert_eq!(3u, match Atom::from_str("zzzzzz") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });
    }
}
<commit_msg>Change Show for Atom so to_string() is consistent with as_slice()<commit_after>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use phf::PhfMap;

use std::mem::replace;
use std::fmt::{Show, Formatter, FormatError};

static static_atom_map: PhfMap<&'static str, uint> = static_atom_map!();
static static_atom_array: &'static [&'static str] = static_atom_array!();

// Assume that a string which can be interned always is.
// FIXME: Revisit this assumption when we have dynamic interning.
/// Interned string.
///
/// Don't pattern-match this directly! Use the `atom!()` pattern macro.
#[deriving(Clone, PartialEq, Eq)]
pub enum Atom {
    Static(uint),
    // dynamic interning goes here
    Owned(String),
}

impl Atom {
    pub fn from_str(s: &str) -> Atom {
        match static_atom_map.find_equiv(&s) {
            Some(&k) => Static(k),
            None => Owned(s.to_string()),
        }
    }

    pub fn from_buf(s: String) -> Atom {
        match static_atom_map.find_equiv(&s.as_slice()) {
            Some(&k) => Static(k),
            None => Owned(s),
        }
    }

    /// Like `Atom::from_buf(replace(s, String::new()))` but avoids
    /// allocating a new `String` when the string is interned --
    /// just truncates the old one.
    pub fn take_from_buf(s: &mut String) -> Atom {
        match static_atom_map.find_equiv(&s.as_slice()) {
            Some(&k) => {
                s.truncate(0);
                Static(k)
            }
            None => {
                Owned(replace(s, String::new()))
            }
        }
    }

    #[inline(always)]
    fn fast_partial_eq(&self, other: &Atom) -> Option<bool> {
        match (self, other) {
            (&Static(x), &Static(y)) => Some(x == y),
            _ => None,
        }
    }
}

fn get_static(i: uint) -> &'static str {
    *static_atom_array.get(i).expect("bad static atom")
}

impl Str for Atom {
    fn as_slice<'t>(&'t self) -> &'t str {
        match *self {
            Static(i) => get_static(i),
            Owned(ref s) => s.as_slice(),
        }
    }
}

impl StrAllocating for Atom {
    fn into_string(self) -> String {
        match self {
            Static(i) => get_static(i).to_string(),
            Owned(s) => s.into_string(),
        }
    }

    fn into_owned(self) -> String {
        match self {
            Static(i) => get_static(i).to_string(),
            Owned(s) => s,
        }
    }
}

impl PartialOrd for Atom {
    fn partial_cmp(&self, other: &Atom) -> Option<Ordering> {
        match self.fast_partial_eq(other) {
            Some(true) => Some(Equal),
            _ => self.as_slice().partial_cmp(&other.as_slice()),
        }
    }
}

impl Ord for Atom {
    fn cmp(&self, other: &Atom) -> Ordering {
        match self.fast_partial_eq(other) {
            Some(true) => Equal,
            _ => self.as_slice().cmp(&other.as_slice()),
        }
    }
}

impl Show for Atom {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        self.as_slice().fmt(fmt)
    }
}

#[cfg(test)]
#[allow(non_snake_case_functions)]
mod test {
    use super::{Atom, get_static, Static, Owned};

    #[test]
    fn interned() {
        match Atom::from_str("body") {
            Static(i) => assert_eq!(get_static(i), "body"),
            _ => fail!("wrong interning"),
        }
    }

    #[test]
    fn not_interned() {
        match Atom::from_str("asdfghjk") {
            Owned(b) => assert_eq!(b.as_slice(), "asdfghjk"),
            _ => fail!("wrong interning"),
        }
    }

    #[test]
    fn as_slice() {
        assert_eq!(Atom::from_str("").as_slice(), "");
        assert_eq!(Atom::from_str("body").as_slice(), "body");
        assert_eq!(Atom::from_str("asdfghjk").as_slice(), "asdfghjk");
    }

    #[test]
    fn into_string() {
        assert_eq!(Atom::from_str("").into_string(), "".to_string());
        assert_eq!(Atom::from_str("body").into_string(), "body".to_string());
        assert_eq!(Atom::from_str("asdfghjk").into_string(), "asdfghjk".to_string());
    }

    #[test]
    fn to_string() {
        assert_eq!(Atom::from_str("").to_string(), "".to_string());
        assert_eq!(Atom::from_str("body").to_string(), "body".to_string());
        assert_eq!(Atom::from_str("asdfghjk").to_string(), "asdfghjk".to_string());
    }

    #[test]
    fn take_from_buf_interned() {
        let mut b = "body".to_string();
        let a = Atom::take_from_buf(&mut b);
        assert_eq!(a, Atom::from_str("body"));
        assert_eq!(b, String::new());
    }

    #[test]
    fn take_from_buf_not_interned() {
        let mut b = "asdfghjk".to_string();
        let a = Atom::take_from_buf(&mut b);
        assert_eq!(a, Atom::from_str("asdfghjk"));
        assert_eq!(b, String::new());
    }

    #[test]
    fn ord() {
        fn check(x: &str, y: &str) {
            assert_eq!(x < y, Atom::from_str(x) < Atom::from_str(y));
            assert_eq!(x.cmp(&y), Atom::from_str(x).cmp(&Atom::from_str(y)));
        }

        check("a", "body");
        check("asdf", "body");
        check("zasdf", "body");
        check("z", "body");

        check("a", "bbbbb");
        check("asdf", "bbbbb");
        check("zasdf", "bbbbb");
        check("z", "bbbbb");
    }

    #[test]
    fn atom_macro() {
        assert_eq!(atom!(body), Atom::from_str("body"));
        assert_eq!(atom!("body"), Atom::from_str("body"));
        assert_eq!(atom!("font-weight"), Atom::from_str("font-weight"));
    }

    #[test]
    fn match_atom() {
        assert_eq!(2u, match Atom::from_str("head") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });

        assert_eq!(3u, match Atom::from_str("body") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });

        assert_eq!(3u, match Atom::from_str("zzzzzz") {
            atom!(br) => 1u,
            atom!(html) | atom!(head) => 2u,
            _ => 3u,
        });
    }
}
<|endoftext|>


<commit_before>use buffer;
use buffer::Buffer;
use std::old_io::IoError;

pub struct Workspace {
    path: Path,
    buffers: Vec<Buffer>,
    current_buffer_index: Option<usize>,
}

impl Workspace {
    pub fn open_file(&mut self, path: Path) -> Option<IoError> {
        match buffer::from_file(path) {
            Ok(b) => {
                self.buffers.push(b);
                self.current_buffer_index = Some(self.buffers.len()-1);
            },
            Err(e) => return Some(e),
        }

        None
    }

    pub fn current_buffer(&self) -> Option<&Buffer> {
        match self.current_buffer_index {
            Some(index) => Some(&self.buffers[index]),
            None => None,
        }
    }
}

pub fn new(path: Path) -> Workspace {
    Workspace{ path: path, buffers: Vec::new(), current_buffer_index: None }
}

#[cfg(test)]
mod tests {
    use super::new;

    #[test]
    fn open_file_adds_and_selects_a_properly_initialized_buffer() {
        let mut workspace = new(Path::new("tests/sample"));
        let file_path = Path::new("tests/sample/file");
        workspace.open_file(file_path);

        assert_eq!(workspace.buffers.len(), 1);
        assert_eq!(workspace.current_buffer().unwrap().data(), "it works!\n");
    }

    #[test]
    fn current_buffer_returns_none_when_there_are_no_buffers() {
        let mut workspace = new(Path::new("tests/sample"));
        assert!(workspace.current_buffer().is_none());
    }

    #[test]
    fn current_buffer_returns_one_when_there_are_buffers() {
        let mut workspace = new(Path::new("tests/sample"));
        let file_path = Path::new("tests/sample/file");
        workspace.open_file(file_path);
        assert!(workspace.current_buffer().is_some());
    }
}
<commit_msg>Replace open_file with add_buffer.<commit_after>use buffer;
use buffer::Buffer;
use std::old_io::IoError;

pub struct Workspace {
    path: Path,
    buffers: Vec<Buffer>,
    current_buffer_index: Option<usize>,
}

impl Workspace {
    pub fn add_buffer(&mut self, buf: Buffer) {
        self.buffers.push(buf);
        self.current_buffer_index = Some(self.buffers.len()-1);
    }

    pub fn current_buffer(&self) -> Option<&Buffer> {
        match self.current_buffer_index {
            Some(index) => Some(&self.buffers[index]),
            None => None,
        }
    }
}

pub fn new(path: Path) -> Workspace {
    Workspace{ path: path, buffers: Vec::new(), current_buffer_index: None }
}

#[cfg(test)]
mod tests {
    use super::new;
    use buffer;

    #[test]
    fn add_buffer_adds_and_selects_the_passed_buffer() {
        let mut workspace = new(Path::new("tests/sample"));
        let buf = buffer::from_file(Path::new("tests/sample/file")).unwrap();
        workspace.add_buffer(buf);

        assert_eq!(workspace.buffers.len(), 1);
        assert_eq!(workspace.current_buffer().unwrap().data(), "it works!\n");
    }

    #[test]
    fn current_buffer_returns_none_when_there_are_no_buffers() {
        let mut workspace = new(Path::new("tests/sample"));
        assert!(workspace.current_buffer().is_none());
    }

    #[test]
    fn current_buffer_returns_one_when_there_are_buffers() {
        let mut workspace = new(Path::new("tests/sample"));
        let buf = buffer::from_file(Path::new("tests/sample/file")).unwrap();
        workspace.add_buffer(buf);
        assert!(workspace.current_buffer().is_some());
    }
}
<|endoftext|>


<commit_before>//! Densely numbered entity references as mapping keys.
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::slice;
use std::vec::Vec;
use {EntityRef, Iter, IterMut, Keys};

/// A primary mapping `K -> V` allocating dense entity references.
///
/// The `PrimaryMap` data structure uses the dense index space to implement a map with a vector.
///
/// A primary map contains the main definition of an entity, and it can be used to allocate new
/// entity references with the `push` method.
///
/// There should only be a single `PrimaryMap` instance for a given `EntityRef` type, otherwise
/// conflicting references will be created. Using unknown keys for indexing will cause a panic.
///
/// Note that `PrimaryMap` doesn't implement `Deref` or `DerefMut`, which would allow
/// `&PrimaryMap<K, V>` to convert to `&[V]`. One of the main advantages of `PrimaryMap` is
/// that it only allows indexing with the distinct `EntityRef` key type, so converting to a
/// plain slice would make it easier to use incorrectly.
#[derive(Debug, Clone)]
pub struct PrimaryMap<K, V>
where
    K: EntityRef,
{
    elems: Vec<V>,
    unused: PhantomData<K>,
}

impl<K, V> PrimaryMap<K, V>
where
    K: EntityRef,
{
    /// Create a new empty map.
    pub fn new() -> Self {
        Self {
            elems: Vec::new(),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Get the element at `k` if it exists, mutable version.
    pub fn get_mut(&mut self, k: K) -> Option<&mut V> {
        self.elems.get_mut(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys::with_len(self.elems.len())
    }

    /// Iterate over all the values in this map.
    pub fn values(&self) -> slice::Iter<V> {
        self.elems.iter()
    }

    /// Iterate over all the values in this map, mutable edition.
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.elems.iter_mut()
    }

    /// Iterate over all the keys and values in this map.
    pub fn iter(&self) -> Iter<K, V> {
        Iter::new(self.elems.iter())
    }

    /// Iterate over all the keys and values in this map, mutable edition.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        IterMut::new(self.elems.iter_mut())
    }

    /// Remove all entries from this map.
    pub fn clear(&mut self) {
        self.elems.clear()
    }

    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Append `v` to the mapping, assigning a new key which is returned.
    pub fn push(&mut self, v: V) -> K {
        let k = self.next_key();
        self.elems.push(v);
        k
    }

    /// Returns the last element that was inserted in the map.
    pub fn last(&self) -> Option<&V> {
        self.elems.last()
    }
}

/// Immutable indexing into an `PrimaryMap`.
/// The indexed value must be in the map.
impl<K, V> Index<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into an `PrimaryMap`.
impl<K, V> IndexMut<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

impl<'a, K, V> IntoIterator for &'a PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.elems.iter())
    }
}

impl<'a, K, V> IntoIterator for &'a mut PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut::new(self.elems.iter_mut())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let m = PrimaryMap::<E, isize>::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        assert!(!m.is_valid(r1));
    }

    #[test]
    fn push() {
        let mut m = PrimaryMap::new();
        let k0: E = m.push(12);
        let k1 = m.push(33);

        assert_eq!(m[k0], 12);
        assert_eq!(m[k1], 33);

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [k0, k1]);
    }

    #[test]
    fn iter() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for (key, value) in &m {
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for (key_mut, value_mut) in m.iter_mut() {
            assert_eq!(key_mut.index(), i);
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn iter_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for (key, value) in m.iter().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }

        i = 2;
        for (key, value) in m.iter_mut().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
    }
    #[test]
    fn keys() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for key in m.keys() {
            assert_eq!(key.index(), i);
            i += 1;
        }
    }

    #[test]
    fn keys_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for key in m.keys().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
        }
    }

    #[test]
    fn values() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for value in m.values() {
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for value_mut in m.values_mut() {
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn values_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for value in m.values().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
        i = 2;
        for value_mut in m.values_mut().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
        }
    }
}
<commit_msg>Implement `reserve` and `reserve_exact` for `PrimaryMap`.<commit_after>//! Densely numbered entity references as mapping keys.
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::slice;
use std::vec::Vec;
use {EntityRef, Iter, IterMut, Keys};

/// A primary mapping `K -> V` allocating dense entity references.
///
/// The `PrimaryMap` data structure uses the dense index space to implement a map with a vector.
///
/// A primary map contains the main definition of an entity, and it can be used to allocate new
/// entity references with the `push` method.
///
/// There should only be a single `PrimaryMap` instance for a given `EntityRef` type, otherwise
/// conflicting references will be created. Using unknown keys for indexing will cause a panic.
///
/// Note that `PrimaryMap` doesn't implement `Deref` or `DerefMut`, which would allow
/// `&PrimaryMap<K, V>` to convert to `&[V]`. One of the main advantages of `PrimaryMap` is
/// that it only allows indexing with the distinct `EntityRef` key type, so converting to a
/// plain slice would make it easier to use incorrectly.
#[derive(Debug, Clone)]
pub struct PrimaryMap<K, V>
where
    K: EntityRef,
{
    elems: Vec<V>,
    unused: PhantomData<K>,
}

impl<K, V> PrimaryMap<K, V>
where
    K: EntityRef,
{
    /// Create a new empty map.
    pub fn new() -> Self {
        Self {
            elems: Vec::new(),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Get the element at `k` if it exists, mutable version.
    pub fn get_mut(&mut self, k: K) -> Option<&mut V> {
        self.elems.get_mut(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys::with_len(self.elems.len())
    }

    /// Iterate over all the values in this map.
    pub fn values(&self) -> slice::Iter<V> {
        self.elems.iter()
    }

    /// Iterate over all the values in this map, mutable edition.
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.elems.iter_mut()
    }

    /// Iterate over all the keys and values in this map.
    pub fn iter(&self) -> Iter<K, V> {
        Iter::new(self.elems.iter())
    }

    /// Iterate over all the keys and values in this map, mutable edition.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        IterMut::new(self.elems.iter_mut())
    }

    /// Remove all entries from this map.
    pub fn clear(&mut self) {
        self.elems.clear()
    }

    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Append `v` to the mapping, assigning a new key which is returned.
    pub fn push(&mut self, v: V) -> K {
        let k = self.next_key();
        self.elems.push(v);
        k
    }

    /// Returns the last element that was inserted in the map.
    pub fn last(&self) -> Option<&V> {
        self.elems.last()
    }

    /// Reserves capacity for at least `additional` more elements to be inserted.
    pub fn reserve(&mut self, additional: usize) {
        self.elems.reserve(additional)
    }

    /// Reserves the minimum capacity for exactly `additional` more elements to be inserted.
    pub fn reserve_exact(&mut self, additional: usize) {
        self.elems.reserve_exact(additional)
    }
}

/// Immutable indexing into an `PrimaryMap`.
/// The indexed value must be in the map.
impl<K, V> Index<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into an `PrimaryMap`.
impl<K, V> IndexMut<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

impl<'a, K, V> IntoIterator for &'a PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.elems.iter())
    }
}

impl<'a, K, V> IntoIterator for &'a mut PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut::new(self.elems.iter_mut())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let m = PrimaryMap::<E, isize>::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        assert!(!m.is_valid(r1));
    }

    #[test]
    fn push() {
        let mut m = PrimaryMap::new();
        let k0: E = m.push(12);
        let k1 = m.push(33);

        assert_eq!(m[k0], 12);
        assert_eq!(m[k1], 33);

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [k0, k1]);
    }

    #[test]
    fn iter() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for (key, value) in &m {
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for (key_mut, value_mut) in m.iter_mut() {
            assert_eq!(key_mut.index(), i);
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn iter_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for (key, value) in m.iter().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }

        i = 2;
        for (key, value) in m.iter_mut().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
    }
    #[test]
    fn keys() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for key in m.keys() {
            assert_eq!(key.index(), i);
            i += 1;
        }
    }

    #[test]
    fn keys_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for key in m.keys().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
        }
    }

    #[test]
    fn values() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for value in m.values() {
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for value_mut in m.values_mut() {
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn values_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for value in m.values().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
        i = 2;
        for value_mut in m.values_mut().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
        }
    }
}
<|endoftext|>


<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use std::io::signal::{Listener, Interrupt};
use std::libc;
use std::num;
use extra::getopts;

struct Shell {
    cmd_prompt: ~str,
    cmd_history: ~[~str]
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
	    cmd_history: ~[]
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
	    self.cmd_history.push(cmd_line.clone());
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

	    let mut mod_prog = program.clone();
	    let prog_length = mod_prog.len();
	    if mod_prog.slice_from(prog_length - 1) == "&" {
	       mod_prog = mod_prog.slice_to(prog_length - 1);
	    }

            match mod_prog {
                ""      =>  { continue; }
                "exit"  =>  { return; }
                _       =>  { self.run_pipes(cmd_line); }
            }
        }
    }

    fn run_pipes(&mut self, cmd_line: &str) {
       let progs: ~[~str] =
       	       	      cmd_line.split('|').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();
       let mut channels: ~[std::os::Pipe] = ~[];
       for _ in range(0, progs.len()) {
       	   channels.push(std::os::pipe());
       }
       for i in range(0, progs.len()) {
       	   let mut in_chan = libc::STDIN_FILENO;
	   let mut out_chan = libc::STDOUT_FILENO;
	   if i == 0 {
	      out_chan = channels[i].out;
	   }
       	   if i > 0 {
	      in_chan = channels[i-1].input;
	      out_chan = channels[i].out;
	   }
	   if i == progs.len() - 1 {
	      out_chan = libc::STDOUT_FILENO;
	   }
	   self.run_cmdline(progs[i].trim().clone(), in_chan, out_chan);
       }
    }

    fn run_cmdline(&mut self, cmd_line: &str, in_chan: libc::c_int, out_chan: libc::c_int) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();
        if argv.len() > 0 {
	   let program: ~str = argv.remove(0);
	   let mut mod_prog = program.clone();
	   if mod_prog == ~"grep" {
	      if argv.len() > 0 {
	      	 let mut matching = argv.pop();
		 if matching.slice_to(1) == "\"" && matching.slice_from(matching.len() - 1) == "\"" {
		    matching = matching.slice_to(matching.len() - 1).to_owned();
		    matching = matching.slice_from(1).to_owned();
	      	 }
		 argv.push(matching);
	      }
	   }
	   let mut background = false;
	   if argv.len() == 0 {
	      let prog_length = mod_prog.len();
	      if mod_prog.slice_from(prog_length - 1) == "&" {
	      	 mod_prog = mod_prog.slice_to(prog_length - 1).trim().to_owned();
	       	 background = true;
	      }
	   }
	   else {
	      let mut last_arg = argv[argv.len() - 1].clone();
	      if last_arg == ~"&" {
	      	 argv.pop();
		 background = true;
	      }
	      else {
	      	   let arg_length = last_arg.len();
	      	   if last_arg.slice_from(arg_length - 1) == "&" {
	      	      last_arg = last_arg.slice_to(arg_length - 1).to_owned();
		      argv.pop();
		      argv.push(last_arg);
		      background = true;
	      	   }
	      }
	   }

	   // Handle IO redirection
	   let mut input: libc::c_int = in_chan;
	   let mut output: libc::c_int = out_chan;
	   let argv_length = argv.len();
	   for i in range(0, argv_length) {
	       if i >= argv.len() {
	       	  break;
	       }
	       if argv[i] == ~"<" {
	       	  argv.remove(i);
	       	  if i >= argv.len() {
		     println!("No file specified for input.")
		     return;
		  }
		  else {
		       unsafe{
			let in_file_name = argv.remove(i);
		       	let mode = "r".to_c_str().unwrap();
			let file_path = Path::new(in_file_name.clone());
			if file_path.exists() {
			   let name_in_str = in_file_name.clone().to_c_str().unwrap();
			   let in_file = libc::fopen(name_in_str, mode);
		       	   input = libc::fileno(in_file);
			}
			else {
			   println!("Input file does not exists!");
			   return;
			}
		       }
		  }
	       }
	       if i >= argv.len() {
	       	  break;
	       }
	       if argv[i] == ~">" {
	       	  argv.remove(i);
		  if i >= argv.len() {
		     println!("No file specified for output.")
		     return;
		  }
		  else {
		       unsafe {
		       	 let out_file_name = argv.remove(i).to_c_str().unwrap();
		       	 let mode = "w".to_c_str().unwrap();
		       	 let out_file = libc::fopen(out_file_name, mode);
		       	 output = libc::fileno(out_file);
		       }
		     if output == -1 {
		     	println!("Invalid file for output.");
			return;
		     }
		  }
	       }
	   }

	   if background {
	      let prog = mod_prog.clone();
	      let arguments = argv.clone();
	      let fin_chan = input.clone();
	      let fout_chan = output.clone();
	      let err_chan = libc::STDERR_FILENO;
	      if self.cmd_exists(prog) {
	      	 do spawn {
		    let proc_run_opt = run::Process::new(prog, arguments, run::ProcessOptions {
		    		  			  	     env: None,
								     dir: None,
								     in_fd: Some(fin_chan),
								     out_fd: Some(fout_chan),
								     err_fd: Some(err_chan)
		    		  			  	     });
		    let mut proc_run = proc_run_opt.unwrap();
		    let mut listener = Listener::new();
		    listener.register(Interrupt);
		    proc_run.finish();
		    if fin_chan != 0 {
		       std::os::close(fin_chan);
		    }
		    if fout_chan != 1 {
		       std::os::close(fout_chan);
		    }
		 }
	      }
	      else {
	      	 println!("{:s}: command not found", prog);
	      }
	   }
	   else {
	   	self.run_cmd(program, argv, input, output);
	   }
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str], input_chan: libc::c_int, output_chan: libc::c_int) {
        if self.cmd_exists(program) {
	    if program == "cd" {
	       if argv.len() > 1 {
	       	  println!("Usage: cd <directory>!");
	       }
	       else if argv.len() == 0 {
	       	  let tar_path = std::os::homedir().unwrap();
		  os::change_dir(&tar_path);
	       }
	       else {
	       	  let tar_path = Path::new(argv[0].clone());
		  match os::change_dir(&tar_path) {
		  	true => { return; }
			false => { println!("No such directory!"); }
		  }
	       }
	    }
	    else {
            	  let proc_run_opt = run::Process::new(program, argv, run::ProcessOptions {
		    		  			  	     env: None,
								     dir: None,
								     in_fd: Some(input_chan),
								     out_fd: Some(output_chan),
								     err_fd: Some(libc::STDERR_FILENO)
		    		  			  	     });
		  let mut proc_run = proc_run_opt.unwrap();
		  let mut listener = Listener::new();
		  listener.register(Interrupt);
		  proc_run.finish();
		  if input_chan != 0 {
		     std::os::close(input_chan);
		  }
		  if output_chan != 1 {
		     std::os::close(output_chan);
		  }
            }
        }
	else if program == "history" {
	     for i in range(0, self.cmd_history.len()) {
	     	 println!(" {:u} {:s}", i+1, self.cmd_history[i]);
	     }
	     let mut stdin = BufferedReader::new(stdin());
	     loop {
	     	  println!("Enter the next command you want to run (-1 to quit): ");
	     	  let input_no_str = stdin.read_line().unwrap_or(~"-1");
		  let input_no = from_str::<int>(input_no_str.slice_to(input_no_str.len() - 1)).unwrap();
		  if input_no == -1 {
		     break;
		  }
		  else if input_no < num::from_uint(self.cmd_history.len()).unwrap() {
		     let retrieved_cmd = self.cmd_history[input_no - 1].clone();
		     self.cmd_history.push(retrieved_cmd.clone());
		     self.run_pipes(retrieved_cmd);
		     break;
		  }
		  else {
		      println!("Invalid index for command!");
		  }
	     }
	}
	else {
            println!("{:s}: command not found", program);
        }
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line, libc::STDIN_FILENO, libc::STDOUT_FILENO),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>deleted special handling for grep<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use std::io::signal::{Listener, Interrupt};
use std::libc;
use std::num;
use extra::getopts;

struct Shell {
    cmd_prompt: ~str,
    cmd_history: ~[~str]
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
	    cmd_history: ~[]
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
	    self.cmd_history.push(cmd_line.clone());
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

	    let mut mod_prog = program.clone();
	    let prog_length = mod_prog.len();
	    if mod_prog.slice_from(prog_length - 1) == "&" {
	       mod_prog = mod_prog.slice_to(prog_length - 1);
	    }

            match mod_prog {
                ""      =>  { continue; }
                "exit"  =>  { return; }
                _       =>  { self.run_pipes(cmd_line); }
            }
        }
    }

    fn run_pipes(&mut self, cmd_line: &str) {
       let progs: ~[~str] =
       	       	      cmd_line.split('|').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();
       let mut channels: ~[std::os::Pipe] = ~[];
       for _ in range(0, progs.len()) {
       	   channels.push(std::os::pipe());
       }
       for i in range(0, progs.len()) {
       	   let mut in_chan = libc::STDIN_FILENO;
	   let mut out_chan = libc::STDOUT_FILENO;
	   if i == 0 {
	      out_chan = channels[i].out;
	   }
       	   if i > 0 {
	      in_chan = channels[i-1].input;
	      out_chan = channels[i].out;
	   }
	   if i == progs.len() - 1 {
	      out_chan = libc::STDOUT_FILENO;
	   }
	   self.run_cmdline(progs[i].trim().clone(), in_chan, out_chan);
       }
    }

    fn run_cmdline(&mut self, cmd_line: &str, in_chan: libc::c_int, out_chan: libc::c_int) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();
        if argv.len() > 0 {
	   let program: ~str = argv.remove(0);
	   let mut mod_prog = program.clone();
	   /*
	   if mod_prog == ~"grep" {
	      if argv.len() > 0 {
	      	 let mut matching = argv.pop();
		 if matching.slice_to(1) == "\"" && matching.slice_from(matching.len() - 1) == "\"" {
		    matching = matching.slice_to(matching.len() - 1).to_owned();
		    matching = matching.slice_from(1).to_owned();
	      	 }
		 argv.push(matching);
	      }
	   }
	   */
	   let mut background = false;
	   if argv.len() == 0 {
	      let prog_length = mod_prog.len();
	      if mod_prog.slice_from(prog_length - 1) == "&" {
	      	 mod_prog = mod_prog.slice_to(prog_length - 1).trim().to_owned();
	       	 background = true;
	      }
	   }
	   else {
	      let mut last_arg = argv[argv.len() - 1].clone();
	      if last_arg == ~"&" {
	      	 argv.pop();
		 background = true;
	      }
	      else {
	      	   let arg_length = last_arg.len();
	      	   if last_arg.slice_from(arg_length - 1) == "&" {
	      	      last_arg = last_arg.slice_to(arg_length - 1).to_owned();
		      argv.pop();
		      argv.push(last_arg);
		      background = true;
	      	   }
	      }
	   }

	   // Handle IO redirection
	   let mut input: libc::c_int = in_chan;
	   let mut output: libc::c_int = out_chan;
	   let argv_length = argv.len();
	   for i in range(0, argv_length) {
	       if i >= argv.len() {
	       	  break;
	       }
	       if argv[i] == ~"<" {
	       	  argv.remove(i);
	       	  if i >= argv.len() {
		     println!("No file specified for input.")
		     return;
		  }
		  else {
		       unsafe{
			let in_file_name = argv.remove(i);
		       	let mode = "r".to_c_str().unwrap();
			let file_path = Path::new(in_file_name.clone());
			if file_path.exists() {
			   let name_in_str = in_file_name.clone().to_c_str().unwrap();
			   let in_file = libc::fopen(name_in_str, mode);
		       	   input = libc::fileno(in_file);
			}
			else {
			   println!("Input file does not exists!");
			   return;
			}
		       }
		  }
	       }
	       if i >= argv.len() {
	       	  break;
	       }
	       if argv[i] == ~">" {
	       	  argv.remove(i);
		  if i >= argv.len() {
		     println!("No file specified for output.")
		     return;
		  }
		  else {
		       unsafe {
		       	 let out_file_name = argv.remove(i).to_c_str().unwrap();
		       	 let mode = "w".to_c_str().unwrap();
		       	 let out_file = libc::fopen(out_file_name, mode);
		       	 output = libc::fileno(out_file);
		       }
		     if output == -1 {
		     	println!("Invalid file for output.");
			return;
		     }
		  }
	       }
	   }

	   if background {
	      let prog = mod_prog.clone();
	      let arguments = argv.clone();
	      let fin_chan = input.clone();
	      let fout_chan = output.clone();
	      let err_chan = libc::STDERR_FILENO;
	      if self.cmd_exists(prog) {
	      	 do spawn {
		    let proc_run_opt = run::Process::new(prog, arguments, run::ProcessOptions {
		    		  			  	     env: None,
								     dir: None,
								     in_fd: Some(fin_chan),
								     out_fd: Some(fout_chan),
								     err_fd: Some(err_chan)
		    		  			  	     });
		    let mut proc_run = proc_run_opt.unwrap();
		    let mut listener = Listener::new();
		    listener.register(Interrupt);
		    proc_run.finish();
		    if fin_chan != 0 {
		       std::os::close(fin_chan);
		    }
		    if fout_chan != 1 {
		       std::os::close(fout_chan);
		    }
		 }
	      }
	      else {
	      	 println!("{:s}: command not found", prog);
	      }
	   }
	   else {
	   	self.run_cmd(program, argv, input, output);
	   }
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str], input_chan: libc::c_int, output_chan: libc::c_int) {
        if self.cmd_exists(program) {
	    if program == "cd" {
	       if argv.len() > 1 {
	       	  println!("Usage: cd <directory>!");
	       }
	       else if argv.len() == 0 {
	       	  let tar_path = std::os::homedir().unwrap();
		  os::change_dir(&tar_path);
	       }
	       else {
	       	  let tar_path = Path::new(argv[0].clone());
		  match os::change_dir(&tar_path) {
		  	true => { return; }
			false => { println!("No such directory!"); }
		  }
	       }
	    }
	    else {
            	  let proc_run_opt = run::Process::new(program, argv, run::ProcessOptions {
		    		  			  	     env: None,
								     dir: None,
								     in_fd: Some(input_chan),
								     out_fd: Some(output_chan),
								     err_fd: Some(libc::STDERR_FILENO)
		    		  			  	     });
		  let mut proc_run = proc_run_opt.unwrap();
		  let mut listener = Listener::new();
		  listener.register(Interrupt);
		  proc_run.finish();
		  if input_chan != 0 {
		     std::os::close(input_chan);
		  }
		  if output_chan != 1 {
		     std::os::close(output_chan);
		  }
            }
        }
	else if program == "history" {
	     for i in range(0, self.cmd_history.len()) {
	     	 println!(" {:u} {:s}", i+1, self.cmd_history[i]);
	     }
	     let mut stdin = BufferedReader::new(stdin());
	     loop {
	     	  println!("Enter the next command you want to run (-1 to quit): ");
	     	  let input_no_str = stdin.read_line().unwrap_or(~"-1");
		  let input_no = from_str::<int>(input_no_str.slice_to(input_no_str.len() - 1)).unwrap();
		  if input_no == -1 {
		     break;
		  }
		  else if input_no < num::from_uint(self.cmd_history.len()).unwrap() {
		     let retrieved_cmd = self.cmd_history[input_no - 1].clone();
		     self.cmd_history.push(retrieved_cmd.clone());
		     self.run_pipes(retrieved_cmd);
		     break;
		  }
		  else {
		      println!("Invalid index for command!");
		  }
	     }
	}
	else {
            println!("{:s}: command not found", program);
        }
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line, libc::STDIN_FILENO, libc::STDOUT_FILENO),
        None           => Shell::new("gash > ").run()
    }
}
<|endoftext|>


<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use extra::getopts;

struct Shell {
    cmd_prompt: ~str,
    cmd_history: ~[~str],
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            cmd_history: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

            match program {
                ""          =>  { continue; }
                "exit"      =>  { return; }
                "cd"        =>  { self.run_cd(cmd_line); }
                "history"   =>  { self.run_history(cmd_line); }
                _           =>  { self.run_cmdline(cmd_line); }
            }

            self.cmd_history.push(program.to_owned());
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] = self.get_args(cmd_line);

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            run::process_status(program, argv);
        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    fn run_cd(&mut self, cmd_line: &str) {
        let argv: ~[~str] = self.get_args(cmd_line);
        let pathOpt: Option<Path> = match argv.len() {
            1   =>  { os::homedir() }
            0   =>  { os::homedir() }
            _   =>  { Some(Path::new(argv[1])) }
        };

        match pathOpt {
            Some(path)   =>  {
                if path.is_dir() {
                    os::change_dir(&path);
                } else {
                    println!("Error: {:s} is not a directory", path.as_str().unwrap());
                }
            }
            None        =>  {
                println!("Error: Invalid path");
            }
        };
    }

    fn run_history(&mut self, cmd_line: &str) {
        let argv: ~[~str] = self.get_args(cmd_line);
        if (argv.len() > 1) {
            println!("Error: history does not take options (sadly).");
        }
        else {
            let mut i = 1;
            for entry in self.cmd_history.iter() {
                println!("{:d} \t{:s}", i, entry.to_owned());
                i = i + 1;
            }
        }

    }

    fn get_args(&mut self, cmd_line: &str) -> ~[~str] {
        return cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>can run in background (yay functional programming)<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use extra::getopts;

struct Shell {
    cmd_prompt: ~str,
    cmd_history: ~[~str],
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            cmd_history: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let mut cmd_line: ~str = line.trim().to_owned();
            let mut background: bool = false;
            if cmd_line.char_len() > 0 {
                background = cmd_line.char_at(cmd_line.char_len() - 1) == '&';
                if background {
                    cmd_line = cmd_line.slice(0, cmd_line.char_len() - 1).trim().to_owned();
                }
            }

            let params = cmd_line.clone().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");

            match program {
                ""          =>  { continue; }
                "exit"      =>  { return; }
                "cd"        =>  { Shell::run_check_mode(background, Shell::run_cd(params)); }
                "history"   =>  { Shell::run_check_mode(background, Shell::run_history(params, self.cmd_history)); }
                _           =>  { Shell::run_check_mode(background, Shell::run_cmdline(params)); }
            }

            self.cmd_history.push(program.to_owned());
        }
    }

    fn run_check_mode(background: bool, f: proc()) {
        if background {
            spawn(proc() { f(); });
        } else {
            f();
        }
    }

    fn run_cmdline_single(cmd_line: &str) {
        (Shell::run_cmdline(cmd_line))();
    }

    fn run_cmdline(cmd_line: &str) -> proc() {
        let params = cmd_line.to_owned();
        return proc() {
            let mut argv: ~[~str] = Shell::get_args(params);

            if argv.len() > 0 {
                let program: ~str = argv.remove(0);
                Shell::run_cmd(program, argv);
            }
        };
    }

    fn run_cmd(program: &str, argv: &[~str]) {
        if Shell::cmd_exists(program) {
            run::process_status(program, argv);
        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn cmd_exists(cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    fn run_cd(cmd_line: &str) -> proc() {
        let params = cmd_line.to_owned();
        return proc() {
            let argv: ~[~str] = Shell::get_args(params);
            let pathOpt: Option<Path> = match argv.len() {
                1   =>  { os::homedir() }
                0   =>  { os::homedir() }
                _   =>  { Some(Path::new(argv[1])) }
            };

            match pathOpt {
                Some(path)   =>  {
                    if path.is_dir() {
                        os::change_dir(&path);
                    } else {
                        println!("Error: {:s} is not a directory", path.as_str().unwrap());
                    }
                }
                None        =>  {
                    println!("Error: Invalid path");
                }
            };
        };
    }

    fn run_history(cmd_line: &str, cmd_history: &[~str]) -> proc() {
        let history = cmd_history.to_owned();
        let params = cmd_line.to_owned();
        return proc() {
            let argv: ~[~str] = Shell::get_args(params);
            if (argv.len() > 1) {
                println!("Error: history does not take options (sadly).");
            }
            else {
                let mut i = 1;
                for entry in history.iter() {
                    println!("{:d} \t{:s}", i, entry.to_owned());
                    i = i + 1;
                }
            }
        };
    }

    fn get_args(cmd_line: &str) -> ~[~str] {
        return cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::run_cmdline_single(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<|endoftext|>


<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//
/*
Vikram Bhasin vb8nd and Justin Ingram jci5kb
*/

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use std::os::getcwd;
use extra::getopts;
use std::run::Process;
use std::run::ProcessOutput;
use std::run::ProcessOptions;
use std::option::{Option, None, Some};
use std::io::buffered::BufferedWriter;
use std::io::File;
use std::comm::Chan;
use std::io::signal::Listener;
use std::io::signal::{Interrupt};

struct Shell {
    cmd_prompt: ~str,
    hist: ~[~str],
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {

        Shell {
            cmd_prompt: prompt_str.to_owned(),
            hist: ~[],
        }
    }

    fn listen(&mut self, list: Listener) {
	spawn(proc() {
	    loop {
		match list.port.recv() {
		    Interrupt => { }
		    _ => { println("THERE WAS DERP"); }
		}
	    }
	});
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        let mut x = Listener::new();
	let reg = x.register(Interrupt);

	if reg {
	    self.listen(x);
	} else {
	    println("Failed to register listener");
	}

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            self.hist.push(line);
            match program {
                ""      =>  { continue; }
                "exit"  =>  { return; }
                "cd"	=>  { self.changeDir(cmd_line); }
                "history" =>{ self.history(); }
                _       =>  { self.run_cmdline(cmd_line); }
            }
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            //Let's process the argv

            let endopt = argv.pop_opt();
            let end = match endopt {
		Some(stringy) => { stringy }
		None => { ~"" }
            };

            if end.eq(&~"&") {
		// println("Start in a new process" + end);
		self.run_cmd(program, argv, true);
            } else {
		//println("No new process");
		if !end.eq(&~"") {
		    argv.push(end.to_owned());
		}
		self.run_cmd(program, argv, false);
            }

        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str], bg: bool) {
        if self.cmd_exists(program) {
	    // Old stuff

            //println("Run command hit");
            //println(program);

	    if !bg {
		run::process_status(program, argv);
	    } else {
		//let f = self.makefunky(program, argv);
		//let (recvp, recvc): (Port<~str>, Chan<~str>) = Chan::new();
		//spawn(expr(f(program, argv)));

		let x = program.clone().to_owned();
		let y = argv.clone().to_owned();

		spawn(proc() {
		    let mut whichprocop = ProcessOptions::new();
		    match(Process::new(x, y, whichprocop)) {
			Some(mut process) => {
			    process.finish();
			}
			None => { println("ERROR"); }
		    }
		});
	    }

        } else {
            println!("{:s}: command not found", program);
        }
    }
    /*
    fn makefunky(&mut self, program: &str, argv: &[~str]) -> (proc(&str, &[~str])) {
	proc(program: &str, argv: &[~str]) {

	    // whichprocop.dir = self.cwdopt.as_ref();

	    let mut whichproc = Process::new(program, argv, whichprocop);
	    let mut process = whichproc.unwrap();

	    let mut procout = process.finish_with_output();
	    println(std::str::from_utf8(procout.output));
	}
    }
    */

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    //Justin's function for cd
    fn changeDir(&mut self, cmd_line: &str) {
	let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 1 {
            let pstring: ~str = argv.remove(1);

            //println!("You want to change cwd to {:s}", pstring);

            let npath = Path::new(pstring);

            let mut cpath = getcwd();
            cpath.push(npath);

            if cpath.exists() {
		let mut cpathforopt = cpath.clone();
		std::os::change_dir(&cpath);
		// self.cwd = cpath;
            } else {
		println("Path does not exist!");
            }

        }

        let x = getcwd();

        match x.as_str() {
	    Some(path_str) => {println!("{:s}", path_str); }
	    None	=> {println("Path not representable as string!"); }
        }
    }

    fn history(&mut self) {
	let mut n :int = 1;
	for stringy in self.hist.iter() {
	    let x = stringy.clone();
	    print("[" + n.to_str() + "]" + ~"\t" + x);
	    n += 1;
	}
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {

    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>Many changes<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//
/*
Vikram Bhasin vb8nd and Justin Ingram jci5kb
*/

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use std::os::getcwd;
use extra::getopts;
use std::run::Process;
use std::run::ProcessOutput;
use std::run::ProcessOptions;
use std::option::{Option, None, Some};
use std::io::buffered::BufferedWriter;
use std::io::File;
use std::comm::Chan;
use std::io::signal::Listener;
use std::io::signal::{Interrupt};
use std::libc;

struct Shell {
    cmd_prompt: ~str,
    hist: ~[~str],
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {

        Shell {
            cmd_prompt: prompt_str.to_owned(),
            hist: ~[],
        }
    }

    fn listen(&mut self, list: Listener) {
	spawn(proc() {
	    loop {
		match list.port.recv() {
		    Interrupt => { }
		    _ => { println("THERE WAS DERP"); }
		}
	    }
	});
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        let mut x = Listener::new();
	let reg = x.register(Interrupt);

	if reg {
	    self.listen(x);
	} else {
	    println("Failed to register listener");
	}

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            self.hist.push(line);
            match program {
                ""      =>  { continue; }
                "exit"  =>  { return; }
                "cd"	=>  { self.changeDir(cmd_line); }
                "history" =>{ self.history(); }
                "gcowsay" => { self.cowsay(cmd_line); }
                _       =>  { self.run_cmdline(cmd_line); }
            }
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            //Let's process the argv

            let endopt = argv.pop_opt();
            let end = match endopt {
		Some(stringy) => { stringy }
		None => { ~"" }
            };

            if end.eq(&~"&") {
		// println("Start in a new process" + end);

		if argv.contains(&~">") {
		    println("Contains >");
		}

		self.run_cmd(program, argv, true);
            } else {
		//println("No new process");
		if !end.eq(&~"") {
		    argv.push(end.to_owned());
		}

		if argv.contains(&~">") {
		    //println("Contains >");
		    let mut found = false;
		    let mut filename = ~"";
		    let mut x = 0;
		    for stringy in argv.clone().move_iter() {
			if stringy.eq(&~">") {
			    break;
			}
			x += 1;
		    }
		    match argv.get_opt(x+1) {
			Some(text) => { filename = text.to_owned(); }
			None => {}
		    }
		    argv.remove(x+1);
		    argv.remove(x);
		    self.run_cmd_out(program, argv, filename, false);
		} else {
		    self.run_cmd(program, argv, false);
		}
            }
        }
    }

    fn run_cmd_out(&mut self, program: &str, argv: &[~str], filename: &str, bg: bool) {
        if self.cmd_exists(program) {
	    // Old stuff

            //println("Run command hit");
            //println(program);

	    if !bg {
		// run::process_status(program, argv);
		let mut whichprocop = ProcessOptions::new();
		unsafe {
		    whichprocop.out_fd = Some(libc::fileno(libc::fopen(filename.to_c_str().unwrap(), "w".to_c_str().unwrap())));
		}

	    } else {
		//let f = self.makefunky(program, argv);
		//let (recvp, recvc): (Port<~str>, Chan<~str>) = Chan::new();
		//spawn(expr(f(program, argv)));

		let x = program.clone().to_owned();
		let y = argv.clone().to_owned();

		spawn(proc() {
		    let mut whichprocop = ProcessOptions::new();
		    match(Process::new(x, y, whichprocop)) {
			Some(mut process) => {
			    process.finish();
			}
			None => { println("ERROR"); }
		    }
		});
	    }

        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str], bg: bool) {
        if self.cmd_exists(program) {
	    // Old stuff

            //println("Run command hit");
            //println(program);

	    if !bg {
		run::process_status(program, argv);
	    } else {
		//let f = self.makefunky(program, argv);
		//let (recvp, recvc): (Port<~str>, Chan<~str>) = Chan::new();
		//spawn(expr(f(program, argv)));

		let x = program.clone().to_owned();
		let y = argv.clone().to_owned();

		spawn(proc() {
		    let mut whichprocop = ProcessOptions::new();
		    match(Process::new(x, y, whichprocop)) {
			Some(mut process) => {
			    process.finish();
			}
			None => { println("ERROR"); }
		    }
		});
	    }

        } else {
            println!("{:s}: command not found", program);
        }
    }
    /*
    fn makefunky(&mut self, program: &str, argv: &[~str]) -> (proc(&str, &[~str])) {
	proc(program: &str, argv: &[~str]) {

	    // whichprocop.dir = self.cwdopt.as_ref();

	    let mut whichproc = Process::new(program, argv, whichprocop);
	    let mut process = whichproc.unwrap();

	    let mut procout = process.finish_with_output();
	    println(std::str::from_utf8(procout.output));
	}
    }
    */

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }

    //Justin's function for cd
    fn changeDir(&mut self, cmd_line: &str) {
	let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 1 {
            let pstring: ~str = argv.remove(1);

            //println!("You want to change cwd to {:s}", pstring);

            let npath = Path::new(pstring);

            let mut cpath = getcwd();
            cpath.push(npath);

            if cpath.exists() {
		let mut cpathforopt = cpath.clone();
		std::os::change_dir(&cpath);
		// self.cwd = cpath;
            } else {
		println("Path does not exist!");
            }

        }

        let x = getcwd();

        match x.as_str() {
	    Some(path_str) => {println!("{:s}", path_str); }
	    None	=> {println("Path not representable as string!"); }
        }
    }

    fn history(&mut self) {
	let mut n :int = 1;
	for stringy in self.hist.iter() {
	    let x = stringy.clone();
	    print("[" + n.to_str() + "]" + ~"\t" + x);
	    n += 1;
	}
    }

    fn cowsay(&mut self, cmd_line: &str) {
	let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();
	let mut stringer = ~"";

	if argv.len() > 1 {
	    argv.remove(0);
	}

	for stringy in argv.iter() {
	    stringer = stringer + ~" " + stringy.to_owned();
	}

	println(" _______");
	println("< " + stringer + " >");
	println(" -------");
	println("        \\   ^__^");
	println("         \\  (oo)\\_______");
	println("            (__)\\       )\\/\\");
	println("                ||----w |");
	println("                ||     ||");
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {

    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<|endoftext|>


<commit_before>use opengles;   // FIXME: Should only be for tests.
import glut::{check_loop, create_window, destroy_window, init, init_display_mode, swap_buffers};
import opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
import opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, NO_ERROR, STATIC_DRAW};
import opengles::gl2::{TRIANGLE_STRIP, VERTEX_SHADER, GLclampf, GLenum};
import opengles::gl2::{GLsizei, GLuint, attach_shader, bind_buffer};
import opengles::gl2::{buffer_data, create_program, clear, clear_color};
import opengles::gl2::{compile_shader, create_shader, draw_arrays};
import opengles::gl2::{enable_vertex_attrib_array, gen_buffers};
import opengles::gl2::{get_attrib_location, get_error, get_program_iv};
import opengles::gl2::{get_shader_info_log, get_shader_iv};
import opengles::gl2::{get_uniform_location, link_program, shader_source};
import opengles::gl2::{use_program, vertex_attrib_pointer_f32};

import comm::{chan, peek, port, recv, send};
import io::println;
import ptr::{addr_of, null};
import str::bytes;
import task::task_builder;
import vec::unsafe::to_ptr;

fn fragment_shader_source() -> ~str {
    ~"
    #ifdef GLES2
        precision mediump float;
    #endif

        void main(void) {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "
}

fn vertex_shader_source() -> ~str {
    ~"
        attribute vec3 aVertexPosition;

        /*uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;*/

        void main(void) {
            gl_Position = /*uPMatrix * uMVMatrix **/
                vec4(aVertexPosition, 1.0);
        }
    "
}

fn load_shader(source_str: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, ~[bytes(source_str)]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail ~"failed to compile shader with error";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(get_shader_info_log(shader_id));
        fail ~"failed to compile shader";
    }
    return shader_id;
}

class shader_program {
    let program: GLuint;
    let aVertexPosition: c_int;
    /*let uPMatrix: c_int;
    let uMVMatrix: c_int;*/

    new(program: GLuint) {
        self.program = program;
        self.aVertexPosition = get_attrib_location(program, ~"aVertexPosition");
        /*self.uPMatrix = get_uniform_location(program, "uPMatrix");
        self.uMVMatrix = get_uniform_location(program, "uMVMatrix");*/

        enable_vertex_attrib_array(self.aVertexPosition as GLuint);
    }
}

fn init_shaders() -> shader_program {
    let vertex_shader = load_shader(vertex_shader_source(), VERTEX_SHADER);
    let fragment_shader = load_shader(fragment_shader_source(),
                                      FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail ~"failed to initialize program";
    }

    use_program(program);

    return shader_program(program);
}

fn init_buffers() -> GLuint {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);
    let vertices = ~[
        0.0f32, 1.0f32, 0.0f32,
        1.0f32, 0.0f32, 0.0f32,
        0.0f32, 0.0f32, 0.0f32
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    return triangle_vertex_buffer;
}

fn draw_scene(shader_program: shader_program, vertex_buffer: GLuint) {
    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    vertex_attrib_pointer_f32(shader_program.aVertexPosition as GLuint,
                              3 as GLint, false, 0 as GLsizei, 0 as GLuint);
    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 3 as GLint);
}

fn display_callback() {
    let program = init_shaders();
    let vertex_buffer = init_buffers();
    draw_scene(program, vertex_buffer);

    swap_buffers();
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = task::task().sched_mode(task::platform_thread);

    let po: port<()> = port();
    let ch = chan(po);
    let _result_ch: chan<()> = builder.spawn_listener(|_port| {
        init();
        init_display_mode(0 as c_uint);
        let window = create_window(~"Rust GLUT");
        display_func(display_callback);

        let wakeup = port();
        let wakeup_chan = chan(wakeup);
        timer_func(1000, || send(wakeup_chan, ()));

        loop {
            check_loop();

            if peek(wakeup) {
                recv(wakeup);
                send(ch, ());
                destroy_window(window);
                break;
            }
        }
    });

    recv(po);
}

<commit_msg>Fix more breakage<commit_after>use opengles;   // FIXME: Should only be for tests.
import glut::{check_loop, create_window, destroy_window, init, init_display_mode, swap_buffers};
import opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
import opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, NO_ERROR, STATIC_DRAW};
import opengles::gl2::{TRIANGLE_STRIP, VERTEX_SHADER, GLclampf, GLenum};
import opengles::gl2::{GLsizei, GLuint, attach_shader, bind_buffer};
import opengles::gl2::{buffer_data, create_program, clear, clear_color};
import opengles::gl2::{compile_shader, create_shader, draw_arrays};
import opengles::gl2::{enable_vertex_attrib_array, gen_buffers};
import opengles::gl2::{get_attrib_location, get_error, get_program_iv};
import opengles::gl2::{get_shader_info_log, get_shader_iv};
import opengles::gl2::{get_uniform_location, link_program, shader_source};
import opengles::gl2::{use_program, vertex_attrib_pointer_f32};

import comm::{chan, peek, port, recv, send, Chan, Port};
import io::println;
import ptr::{addr_of, null};
import str::bytes;
import task::TaskBuilder;
import vec::unsafe::to_ptr;

fn fragment_shader_source() -> ~str {
    ~"
    #ifdef GLES2
        precision mediump float;
    #endif

        void main(void) {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "
}

fn vertex_shader_source() -> ~str {
    ~"
        attribute vec3 aVertexPosition;

        /*uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;*/

        void main(void) {
            gl_Position = /*uPMatrix * uMVMatrix **/
                vec4(aVertexPosition, 1.0);
        }
    "
}

fn load_shader(source_str: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, ~[bytes(source_str)]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail ~"failed to compile shader with error";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(get_shader_info_log(shader_id));
        fail ~"failed to compile shader";
    }
    return shader_id;
}

class shader_program {
    let program: GLuint;
    let aVertexPosition: c_int;
    /*let uPMatrix: c_int;
    let uMVMatrix: c_int;*/

    new(program: GLuint) {
        self.program = program;
        self.aVertexPosition = get_attrib_location(program, ~"aVertexPosition");
        /*self.uPMatrix = get_uniform_location(program, "uPMatrix");
        self.uMVMatrix = get_uniform_location(program, "uMVMatrix");*/

        enable_vertex_attrib_array(self.aVertexPosition as GLuint);
    }
}

fn init_shaders() -> shader_program {
    let vertex_shader = load_shader(vertex_shader_source(), VERTEX_SHADER);
    let fragment_shader = load_shader(fragment_shader_source(),
                                      FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail ~"failed to initialize program";
    }

    use_program(program);

    return shader_program(program);
}

fn init_buffers() -> GLuint {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);
    let vertices = ~[
        0.0f32, 1.0f32, 0.0f32,
        1.0f32, 0.0f32, 0.0f32,
        0.0f32, 0.0f32, 0.0f32
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    return triangle_vertex_buffer;
}

fn draw_scene(shader_program: shader_program, vertex_buffer: GLuint) {
    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    vertex_attrib_pointer_f32(shader_program.aVertexPosition as GLuint,
                              3 as GLint, false, 0 as GLsizei, 0 as GLuint);
    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 3 as GLint);
}

fn display_callback() {
    let program = init_shaders();
    let vertex_buffer = init_buffers();
    draw_scene(program, vertex_buffer);

    swap_buffers();
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = task::task().sched_mode(task::PlatformThread);

    let po: Port<()> = port();
    let ch = chan(po);
    let _result_ch: Chan<()> = builder.spawn_listener(|_port| {
        init();
        init_display_mode(0 as c_uint);
        let window = create_window(~"Rust GLUT");
        display_func(display_callback);

        let wakeup = port();
        let wakeup_chan = chan(wakeup);
        timer_func(1000, || send(wakeup_chan, ()));

        loop {
            check_loop();

            if peek(wakeup) {
                recv(wakeup);
                send(ch, ());
                destroy_window(window);
                break;
            }
        }
    });

    recv(po);
}

<|endoftext|>