<commit_before>// Learning.

use term::Term;
use stroke::Stroke;
use words::{LearnWord, Words};

use std::io::Write;

pub struct Learn {
    words: Words,
    term: Term,
}

impl Learn {
    pub fn new(words: Words, term: Term) -> Learn {
        Learn {
            words: words,
            term: term,
        }
    }

    // Consume the learner, returning the wordset contained in it.
    pub fn into_words(self) -> Words {
        self.words
    }

    pub fn run(&mut self) {
        loop {
            // TODO: Check for things that have expired we need to learn.

            let mut word = match self.words.get_learned() {
                None => {
                    match self.words.get_unlearned() {
                        None => {
                            println!("No more words to learn\r");
                            return;
                        },
                        Some(word) => word,
                    }
                }
                Some(word) => word,
            };

            let status = self.single(&mut word);

            // Return the word.
            self.words.push_word(word);

            if status == Status::Stopped {
                break;
            }
        }
    }

    // Learn a single word, updating its timing information based on how well it was learned.
    fn single(&mut self, word: &mut LearnWord) -> Status {
        let counts = self.words.get_counts();

        writeln!(self.term, "\r\nActive: {}, Later: {}, Unlearned: {}, Interval {}\r",
                 counts.active, counts.later, counts.unlearned,
                 humanize_time(word.interval)).unwrap();
        for b in &counts.buckets {
            writeln!(self.term, "  {:-4}: {:4} {}\r", b.name, b.count,
                     stars(65, b.count, counts.active + counts.later)).unwrap();
        }
        writeln!(self.term, "\r").unwrap();
        self.term.flush().unwrap();

        let mut state = Single::new(&mut self.term, word);
        state.run()
    }
}

// Format an interval (in seconds) in terms of nicer units.
fn humanize_time(interval: f64) -> String {
    let mut val = interval;
    for unit in UNITS {
        if val < unit.div {
            return format!("{:.1} {}", val, unit.name);
        }
        val /= unit.div;
    }
    // Out of bounds, return the unmodified time.
    format!("{:.1} seconds", interval)
}

struct UnitEntry {
    name: &'static str,
    div: f64,
}

static UNITS: &'static [UnitEntry] = &[
    UnitEntry{ name: "seconds", div: 60.0 },
    UnitEntry{ name: "minutes", div: 60.0 },
    UnitEntry{ name: "hours", div: 24.0 },
    UnitEntry{ name: "days", div: 365.0 },
    UnitEntry{ name: "months", div: 12.0 },
    UnitEntry{ name: "years", div: 1.0e6 },
];

// Print a line of stars resembling a histogram bar.  `len` is the number of stars to use, a is the
// number in question, and total is the expected total.
fn stars(len: usize, value: usize, total: usize) -> String {
    let mut buf = String::new();
    buf.push('|');
    let thresh = value as f64 / total as f64 * len as f64;
    for i in 0 .. len {
        if (i as f64) < thresh {
            buf.push('*');
        } else {
            buf.push(' ');
        };
    }
    buf.push('|');
    buf
}

struct Single<'t, 'w> {
    term: &'t mut Term,
    word: &'w mut LearnWord,
    user: Vec<Stroke>,
    errors: u32,
}

impl<'t, 'w> Single<'t, 'w> {
    fn new<'tt, 'ww>(term: &'tt mut Term, word: &'ww mut LearnWord) -> Single<'tt, 'ww> {
        Single {
            term: term,
            word: word,
            user: vec![],
            errors: 0,
        }
    }

    fn prompt(&mut self) {
        write!(self.term, "\r\x1b[J{:20}: {}{}",
               self.word.english,
               if self.word.strokes == self.user {
                   if self.errors == 0 { '✓' } else { '✗' }
               } else { ' ' },
               slashed(&self.user)).unwrap();
        if self.errors > 0 {
            write!(self.term, "  ({})", slashed(&self.word.strokes)).unwrap();
        }
        self.term.flush().unwrap();
    }

    fn run(&mut self) -> Status {
        let mut result = Status::Continue;
        loop {
            self.prompt();
            if self.word.strokes == self.user {
                break;
            }

            let stroke = match self.term.read_stroke().unwrap() {
                None => { result = Status::Stopped; break; }
                Some(st) => st,
            };
            if stroke.is_star() {
                self.user.pop();
            } else {
                self.user.push(stroke);
                let pos = self.user.len();
                if pos > self.word.strokes.len() ||
                    self.user[pos-1] != self.word.strokes[pos-1]
                {
                    self.errors += 1;
                }
            }
        }

        if self.errors > 0 {
            self.word.incorrect();
        } else {
            self.word.correct();
        }

        writeln!(self.term, "\r").unwrap();
        self.term.flush().unwrap();
        result
    }
}

// Generate a slash separated version of the given stroke list.
fn slashed(strokes: &[Stroke]) -> String {
    let mut buf = vec![];
    let mut first = true;

    for st in strokes {
        if !first {
            buf.push(b'/');
        }
        first = false;
        write!(&mut buf, "{}", st).unwrap();
    }
    String::from_utf8(buf).unwrap()
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Status {
    Continue,
    Stopped,
}
<commit_msg>Don't update intervals when exiting<commit_after>// Learning.

use term::Term;
use stroke::Stroke;
use words::{LearnWord, Words};

use std::io::Write;

pub struct Learn {
    words: Words,
    term: Term,
}

impl Learn {
    pub fn new(words: Words, term: Term) -> Learn {
        Learn {
            words: words,
            term: term,
        }
    }

    // Consume the learner, returning the wordset contained in it.
    pub fn into_words(self) -> Words {
        self.words
    }

    pub fn run(&mut self) {
        loop {
            // TODO: Check for things that have expired we need to learn.

            let mut word = match self.words.get_learned() {
                None => {
                    match self.words.get_unlearned() {
                        None => {
                            println!("No more words to learn\r");
                            return;
                        },
                        Some(word) => word,
                    }
                }
                Some(word) => word,
            };

            let status = self.single(&mut word);

            // Return the word.
            self.words.push_word(word);

            if status == Status::Stopped {
                break;
            }
        }
    }

    // Learn a single word, updating its timing information based on how well it was learned.
    fn single(&mut self, word: &mut LearnWord) -> Status {
        let counts = self.words.get_counts();

        writeln!(self.term, "\r\nActive: {}, Later: {}, Unlearned: {}, Interval {}\r",
                 counts.active, counts.later, counts.unlearned,
                 humanize_time(word.interval)).unwrap();
        for b in &counts.buckets {
            writeln!(self.term, "  {:-4}: {:4} {}\r", b.name, b.count,
                     stars(65, b.count, counts.active + counts.later)).unwrap();
        }
        writeln!(self.term, "\r").unwrap();
        self.term.flush().unwrap();

        let mut state = Single::new(&mut self.term, word);
        state.run()
    }
}

// Format an interval (in seconds) in terms of nicer units.
fn humanize_time(interval: f64) -> String {
    let mut val = interval;
    for unit in UNITS {
        if val < unit.div {
            return format!("{:.1} {}", val, unit.name);
        }
        val /= unit.div;
    }
    // Out of bounds, return the unmodified time.
    format!("{:.1} seconds", interval)
}

struct UnitEntry {
    name: &'static str,
    div: f64,
}

static UNITS: &'static [UnitEntry] = &[
    UnitEntry{ name: "seconds", div: 60.0 },
    UnitEntry{ name: "minutes", div: 60.0 },
    UnitEntry{ name: "hours", div: 24.0 },
    UnitEntry{ name: "days", div: 365.0 },
    UnitEntry{ name: "months", div: 12.0 },
    UnitEntry{ name: "years", div: 1.0e6 },
];

// Print a line of stars resembling a histogram bar.  `len` is the number of stars to use, a is the
// number in question, and total is the expected total.
fn stars(len: usize, value: usize, total: usize) -> String {
    let mut buf = String::new();
    buf.push('|');
    let thresh = value as f64 / total as f64 * len as f64;
    for i in 0 .. len {
        if (i as f64) < thresh {
            buf.push('*');
        } else {
            buf.push(' ');
        };
    }
    buf.push('|');
    buf
}

struct Single<'t, 'w> {
    term: &'t mut Term,
    word: &'w mut LearnWord,
    user: Vec<Stroke>,
    errors: u32,
}

impl<'t, 'w> Single<'t, 'w> {
    fn new<'tt, 'ww>(term: &'tt mut Term, word: &'ww mut LearnWord) -> Single<'tt, 'ww> {
        Single {
            term: term,
            word: word,
            user: vec![],
            errors: 0,
        }
    }

    fn prompt(&mut self) {
        write!(self.term, "\r\x1b[J{:20}: {}{}",
               self.word.english,
               if self.word.strokes == self.user {
                   if self.errors == 0 { '✓' } else { '✗' }
               } else { ' ' },
               slashed(&self.user)).unwrap();
        if self.errors > 0 {
            write!(self.term, "  ({})", slashed(&self.word.strokes)).unwrap();
        }
        self.term.flush().unwrap();
    }

    fn run(&mut self) -> Status {
        let mut result = Status::Continue;
        loop {
            self.prompt();
            if self.word.strokes == self.user {
                break;
            }

            let stroke = match self.term.read_stroke().unwrap() {
                None => { result = Status::Stopped; break; }
                Some(st) => st,
            };
            if stroke.is_star() {
                self.user.pop();
            } else {
                self.user.push(stroke);
                let pos = self.user.len();
                if pos > self.word.strokes.len() ||
                    self.user[pos-1] != self.word.strokes[pos-1]
                {
                    self.errors += 1;
                }
            }
        }

        if result == Status::Continue {
            if self.errors > 0 {
                self.word.incorrect();
            } else {
                self.word.correct();
            }

            writeln!(self.term, "\r\nNew interval {}\r", humanize_time(self.word.interval)).unwrap();
        } else {
            writeln!(self.term, "\r").unwrap();
        }
        self.term.flush().unwrap();
        result
    }
}

// Generate a slash separated version of the given stroke list.
fn slashed(strokes: &[Stroke]) -> String {
    let mut buf = vec![];
    let mut first = true;

    for st in strokes {
        if !first {
            buf.push(b'/');
        }
        first = false;
        write!(&mut buf, "{}", st).unwrap();
    }
    String::from_utf8(buf).unwrap()
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Status {
    Continue,
    Stopped,
}
<|endoftext|>


<commit_before>use token;
use peekable_string_iterator as peek;

/// The Lexer struct represents a lexer that tokenizes
/// the string input.
pub struct Lexer<'a> {
    iter: peek::PeekableStringIterator<'a>,
    sign: Option<char>,
    pub ast: Vec<token::Token>,
    pub errors: Vec<String>
}

impl<'a> Lexer<'a> {
    pub fn new(input: &str) -> Lexer {
        let mut l = Lexer {
            ast: Vec::new(),
            errors: vec![],
            iter: peek::PeekableStringIterator::new(input),
            sign: None
        };
        l.lex();
        l
    }

    fn lex(&mut self) {
        self.consume_input();
    }

    // Recursively consume the input
    fn consume_input(&mut self) {
        // Should we skip advancing if a sub method has done it for us?
        let mut skip_advance = false;

        // Peek the next character
        let peeked: Option<char> = match self.iter.peek() {
            Some(&c) => Some(c),
            None => None
        };

        // Decide what to do
        match peeked {
            Some(c) if c.is_whitespace() => {
                // Reset the sign
                self.sign = None;

                self.ast.push(token::Token::Whitespace);
            },
            Some(c) if c.is_numeric() => {
                // Grab the number (allowing for possible decimals)
                let number = self.consume_number();
                // Add a numeric token to the list of tokens
                match number.parse() {
                    Ok(val) => {
                        self.ast.push(token::Token::DecimalNumber(val));
                    },
                    Err(e) => self.errors.push(format!("FATAL: {}", e))
                }
                skip_advance = true;
            },
            Some(c) if c == '+' || c == '-' => {
                // Add the operator and advance the iterator
                self.ast.push(token::Token::Operator(c, token::LEFT_ASSOCIATIVE, 2));
            },
            Some(c) if c == '*' || c == '/' => {
                // Add the operator and advance the iterator
                self.ast.push(token::Token::Operator(c, token::LEFT_ASSOCIATIVE, 3));
            },
            Some(c) if c == '(' => self.ast.push(token::Token::LeftParenthesis),
            Some(c) if c == ')' => self.ast.push(token::Token::RightParenthesis),
            Some(c) if c == '^' => self.ast.push(token::Token::Operator(c, token::RIGHT_ASSOCIATIVE, 4)),
            Some(c) => self.errors.push(format!("Unknown identifier: {}", c)),
            None => return
        }
        // Advance the iterator and continue consuming the input
        if !skip_advance {
            self.iter.advance();
        }
        self.consume_input();
    }

    // Consumes the iterator until it reaches the end of a number
    fn consume_number(&mut self) -> String {
        // If the last operator was a sign ... prefix the number with it
        let last_op = self.ast.last().cloned();
        match last_op {
            Some(token::Token::Operator(o, _, _)) => {
                if o == '+' || o == '-' {
                    // Pop the operator and set our sign
                    self.ast.pop();
                    self.sign = Some(o);
                }
            },
            _ => ()
        }

        let mut chars = vec![self.sign.unwrap_or('+')];

        // Reset the sign
        self.sign = None;

        // Loop over every character until we reach a non-numeric one
        loop {
            match self.iter.peek() {
                Some(c) if c.is_numeric() || *c == '.' => chars.push(*c),
                Some(c) if !c.is_numeric() => break,
                //Some(c) => println!("Peeking at: {}", c),
                None => break,
                _ => break
            }
            self.iter.advance();
        }

        // Return out number as a String
        chars.into_iter().collect()
    }
}

<commit_msg>Moved the sign deciphering to its own method<commit_after>use token;
use peekable_string_iterator as peek;

/// The Lexer struct represents a lexer that tokenizes
/// the string input.
pub struct Lexer<'a> {
    iter: peek::PeekableStringIterator<'a>,
    sign: Option<char>,
    pub ast: Vec<token::Token>,
    pub errors: Vec<String>
}

impl<'a> Lexer<'a> {
    pub fn new(input: &str) -> Lexer {
        let mut l = Lexer {
            ast: Vec::new(),
            errors: vec![],
            iter: peek::PeekableStringIterator::new(input),
            sign: None
        };
        l.lex();
        l
    }

    fn lex(&mut self) {
        self.consume_input();
    }

    // Recursively consume the input
    fn consume_input(&mut self) {
        // Should we skip advancing if a sub method has done it for us?
        let mut skip_advance = false;

        // Peek the next character
        let peeked: Option<char> = match self.iter.peek() {
            Some(&c) => Some(c),
            None => None
        };

        // Decide what to do
        match peeked {
            Some(c) if c.is_whitespace() => {
                // Reset the sign
                self.sign = None;

                self.ast.push(token::Token::Whitespace);
            },
            Some(c) if c.is_numeric() => {
                // Grab the number (allowing for possible decimals)
                let number = self.consume_number();
                // Add a numeric token to the list of tokens
                match number.parse() {
                    Ok(val) => {
                        self.ast.push(token::Token::DecimalNumber(val));
                    },
                    Err(e) => self.errors.push(format!("FATAL: {}", e))
                }
                skip_advance = true;
            },
            Some(c) if c == '+' || c == '-' => {
                // Add the operator and advance the iterator
                self.ast.push(token::Token::Operator(c, token::LEFT_ASSOCIATIVE, 2));
            },
            Some(c) if c == '*' || c == '/' => {
                // Add the operator and advance the iterator
                self.ast.push(token::Token::Operator(c, token::LEFT_ASSOCIATIVE, 3));
            },
            Some(c) if c == '(' => self.ast.push(token::Token::LeftParenthesis),
            Some(c) if c == ')' => self.ast.push(token::Token::RightParenthesis),
            Some(c) if c == '^' => self.ast.push(token::Token::Operator(c, token::RIGHT_ASSOCIATIVE, 4)),
            Some(c) => self.errors.push(format!("Unknown identifier: {}", c)),
            None => return
        }
        // Advance the iterator and continue consuming the input
        if !skip_advance {
            self.iter.advance();
        }
        self.consume_input();
    }

    // Consumes the iterator until it reaches the end of a number
    fn consume_number(&mut self) -> String {
        // Decipher the sign of the number we want to consume
        self.decipher_sign();

        // Initialize our number with the given sign
        let mut chars = vec![self.sign.unwrap_or('+')];

        // Reset the sign
        self.sign = None;

        // Loop over every character until we reach a non-numeric one
        loop {
            match self.iter.peek() {
                Some(c) if c.is_numeric() || *c == '.' => chars.push(*c),
                Some(c) if !c.is_numeric() => break,
                //Some(c) => println!("Peeking at: {}", c),
                None => break,
                _ => break
            }
            self.iter.advance();
        }

        // Return out number as a String
        chars.into_iter().collect()
    }

    fn decipher_sign(&mut self) {
        // If the last operator was a sign ... set the sign
        let last_op = self.ast.last().cloned();
        match last_op {
            Some(token::Token::Operator(o, _, _)) => {
                if o == '+' || o == '-' {
                    // Pop the operator (because its not an operator .. its indicating the numbers'
                    // sign) and store our sign
                    self.ast.pop();
                    self.sign = Some(o);
                }
            },
            _ => ()
        }
    }
}

<|endoftext|>


<commit_before>#[cfg(not(target_os = "linux"))]
use std::io::ErrorKind;
use std::io::{self, Error};

/// An active AX.25 network interface, e.g. "ax0"
pub struct NetDev {
    pub name: String,
    pub ifindex: i32,
}

/// An open socket for sending and receiving AX.25 frames
pub struct Ax25RawSocket {
    #[cfg(target_os = "linux")]
    fd: i32,
}

#[cfg(target_os = "linux")]
impl Ax25RawSocket {
    /// Create a new socket for sending and receiving raw AX.25 frames. This requires root or CAP_NET_ADMIN.
    pub fn new() -> io::Result<Ax25RawSocket> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_new()
        }
        #[cfg(not(target_os = "linux"))]
        {
            Err(Error::new(ErrorKind::NotFound, "only supported on linux"))
        }
    }

    /// Close an open AX.25 socket.
    pub fn close(&mut self) -> io::Result<()> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_close(self)
        }
        #[cfg(not(target_os = "linux"))]
        {
            Err(Error::new(ErrorKind::NotFound, "only supported on linux"))
        }
    }

    /// Find all AX.25 interfaces on the system
    pub fn list_ax25_interfaces(&self) -> io::Result<Vec<NetDev>> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_list_ax25_interfaces(self)
        }
        #[cfg(not(target_os = "linux"))]
        {
            Ok(Vec::new())
        }
    }

    /// Send a frame to a particular interface, specified by its index
    pub fn send_frame(&self, frame: &[u8], ifindex: i32) -> io::Result<()> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_send_frame(self, frame, ifindex)
        }
        #[cfg(not(target_os = "linux"))]
        {
            Err(Error::new(
                ErrorKind::NotConnected,
                "only supported on linux",
            ))
        }
    }

    /// Block to receive an incoming AX.25 frame from any interface
    pub fn receive_frame(&self) -> io::Result<Vec<u8>> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_receive_frame(self)
        }
        #[cfg(not(target_os = "linux"))]
        {
            Err(Error::new(
                ErrorKind::NotConnected,
                "only supported on linux",
            ))
        }
    }
}

/// Keeps all the linux interface-specific code in one place
#[cfg(target_os = "linux")]
mod sys {
    use super::*;
    use libc::{c_char, c_int, c_ulong};
    use libc::{
        c_void, close, recvfrom, sendto, sockaddr_ll, socket, socklen_t, AF_AX25, AF_PACKET,
        SOCK_RAW,
    };
    use std::fs::File;
    use std::io::{BufRead, BufReader};
    use std::mem;

    const ETH_P_AX25: u16 = 0x0002; // from if_ether.h for SOCK_RAW
    const SIOCGIFHWADDR: c_ulong = 0x8927; // from sockios.h in the linux kernel
    const SIOCGIFINDEX: c_ulong = 0x8933;

    pub fn socket_new() -> io::Result<Ax25RawSocket> {
        match unsafe { socket(AF_PACKET, SOCK_RAW, ETH_P_AX25.to_be() as i32) } {
            -1 => Err(Error::last_os_error()),
            fd => Ok(Ax25RawSocket { fd }),
        }
    }

    pub fn socket_close(socket: &mut Ax25RawSocket) -> io::Result<()> {
        match unsafe { close(socket.fd) } {
            -1 => Err(Error::last_os_error()),
            _ => Ok(()),
        }
    }

    pub fn socket_list_ax25_interfaces(socket: &Ax25RawSocket) -> io::Result<Vec<NetDev>> {
        let dev_file = File::open("/proc/net/dev")?;
        let mut devices: Vec<NetDev> = Vec::new();
        let reader = BufReader::new(dev_file);
        let lines = reader.lines();
        for l in lines.skip(2) {
            if let Ok(line) = l {
                let device_name = line.trim().split(':').next().unwrap();
                if let Some(net_dev) = get_ax25_netdev(&device_name, socket.fd) {
                    devices.push(net_dev);
                }
            }
        }
        Ok(devices)
    }

    pub fn socket_send_frame(socket: &Ax25RawSocket, frame: &[u8], ifindex: i32) -> io::Result<()> {
        // The Linux interface demands a single null byte prefix on the actual packet
        let mut prefixed_frame: Vec<u8> = Vec::with_capacity(frame.len() + 1);
        prefixed_frame.push(0);
        prefixed_frame.extend(frame.iter().cloned());

        let sa = sockaddr_ll {
            sll_family: AF_PACKET as u16,
            sll_protocol: ETH_P_AX25.to_be(),
            sll_ifindex: ifindex,
            sll_hatype: 0,
            sll_pkttype: 0,
            sll_halen: 0,
            sll_addr: [0; 8],
        };

        match unsafe {
            let sa_ptr = &sa as *const libc::sockaddr_ll as *const libc::sockaddr;
            sendto(
                socket.fd,
                prefixed_frame.as_ptr() as *const c_void,
                prefixed_frame.len(),
                0,
                sa_ptr,
                mem::size_of_val(&sa) as socklen_t,
            )
        } {
            -1 => Err(Error::last_os_error()),
            _ => Ok(()),
        }
    }

    pub fn socket_receive_frame(socket: &Ax25RawSocket) -> io::Result<Vec<u8>> {
        let mut buf: [u8; 1024] = [0; 1024];
        // Not sure we need the address but it might come in handy someday
        let mut addr_struct: sockaddr_ll = unsafe { mem::zeroed() };
        let len: usize;
        unsafe {
            let sa_ptr = &mut addr_struct as *mut libc::sockaddr_ll as *mut libc::sockaddr;
            let mut sa_in_sz: socklen_t = mem::size_of::<sockaddr_ll>() as socklen_t;
            len = match recvfrom(
                socket.fd,
                buf.as_mut_ptr() as *mut c_void,
                buf.len(),
                0,
                sa_ptr,
                &mut sa_in_sz,
            ) {
                -1 => return Err(Error::last_os_error()),
                len => len as usize,
            };
        }
        let valid_buf = &buf[0..len];

        // In practice AF_PACKET gives us one leading one null byte
        // These are unhelpful so we will skip all leading null bytes
        let filtered: Vec<u8> = valid_buf.iter().skip_while(|&c| *c == 0).cloned().collect();
        Ok(filtered)
    }

    fn get_ax25_netdev(name: &str, fd: i32) -> Option<NetDev> {
        let mut req = ifreq::default();
        let if_name = name.to_owned();
        for (d, s) in req.ifr_name.iter_mut().zip(if_name.as_bytes()) {
            *d = *s as c_char;
        }

        if unsafe { ioctl(fd, SIOCGIFHWADDR, &mut req) } == -1 {
            return None;
        }
        if req.data.address_family() as i32 != AF_AX25 {
            return None;
        }
        let hw_addr = match req.data.ax25_address() {
            Some(addr) => addr,
            None => return None,
        };

        if unsafe { ioctl(fd, SIOCGIFINDEX, &mut req) } == -1 {
            return None;
        }
        let ifindex = req.data.ifindex();

        Some(NetDev {
            name: hw_addr,
            ifindex,
        })
    }

    extern "C" {
        fn ioctl(fd: c_int, request: c_ulong, ifreq: *mut ifreq) -> c_int;
    }

    #[repr(C)]
    struct ifreq {
        ifr_name: [c_char; 16],
        data: ifreq_union,
    }

    impl Default for ifreq {
        fn default() -> ifreq {
            ifreq {
                ifr_name: [0; 16],
                data: ifreq_union::default(),
            }
        }
    }

    #[repr(C)]
    struct ifreq_union {
        data: [u8; 24],
    }

    impl Default for ifreq_union {
        fn default() -> ifreq_union {
            ifreq_union { data: [0; 24] }
        }
    }

    impl ifreq_union {
        fn ifindex(&self) -> c_int {
            c_int::from_be(
                ((self.data[0] as c_int) << 24)
                    + ((self.data[1] as c_int) << 16)
                    + ((self.data[2] as c_int) << 8)
                    + (self.data[3] as c_int),
            )
        }

        fn address_family(&self) -> u16 {
            u16::from_be(((self.data[0] as u16) << 8) + (self.data[1] as u16))
        }

        fn ax25_address(&self) -> Option<String> {
            let mut addr_utf8: Vec<u8> = self.data[2..8]
                .iter()
                .rev()
                .map(|&c| c >> 1)
                .skip_while(|&c| c == 0)
                .collect::<Vec<u8>>();
            addr_utf8.reverse();
            let ssid = (self.data[8] >> 1) & 0x0f;
            if let Ok(addr) = String::from_utf8(addr_utf8) {
                return Some(format!("{}-{}", addr, ssid));
            }
            None
        }
    }
}
<commit_msg>Missed a cfg<commit_after>#[cfg(not(target_os = "linux"))]
use std::io::ErrorKind;
use std::io::{self, Error};

/// An active AX.25 network interface, e.g. "ax0"
pub struct NetDev {
    pub name: String,
    pub ifindex: i32,
}

/// An open socket for sending and receiving AX.25 frames
pub struct Ax25RawSocket {
    #[cfg(target_os = "linux")]
    fd: i32,
}

impl Ax25RawSocket {
    /// Create a new socket for sending and receiving raw AX.25 frames. This requires root or CAP_NET_ADMIN.
    pub fn new() -> io::Result<Ax25RawSocket> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_new()
        }
        #[cfg(not(target_os = "linux"))]
        {
            Err(Error::new(ErrorKind::NotFound, "only supported on linux"))
        }
    }

    /// Close an open AX.25 socket.
    pub fn close(&mut self) -> io::Result<()> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_close(self)
        }
        #[cfg(not(target_os = "linux"))]
        {
            Err(Error::new(ErrorKind::NotFound, "only supported on linux"))
        }
    }

    /// Find all AX.25 interfaces on the system
    pub fn list_ax25_interfaces(&self) -> io::Result<Vec<NetDev>> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_list_ax25_interfaces(self)
        }
        #[cfg(not(target_os = "linux"))]
        {
            Ok(Vec::new())
        }
    }

    /// Send a frame to a particular interface, specified by its index
    pub fn send_frame(&self, frame: &[u8], ifindex: i32) -> io::Result<()> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_send_frame(self, frame, ifindex)
        }
        #[cfg(not(target_os = "linux"))]
        {
            Err(Error::new(
                ErrorKind::NotConnected,
                "only supported on linux",
            ))
        }
    }

    /// Block to receive an incoming AX.25 frame from any interface
    pub fn receive_frame(&self) -> io::Result<Vec<u8>> {
        #[cfg(target_os = "linux")]
        {
            sys::socket_receive_frame(self)
        }
        #[cfg(not(target_os = "linux"))]
        {
            Err(Error::new(
                ErrorKind::NotConnected,
                "only supported on linux",
            ))
        }
    }
}

/// Keeps all the linux interface-specific code in one place
#[cfg(target_os = "linux")]
mod sys {
    use super::*;
    use libc::{c_char, c_int, c_ulong};
    use libc::{
        c_void, close, recvfrom, sendto, sockaddr_ll, socket, socklen_t, AF_AX25, AF_PACKET,
        SOCK_RAW,
    };
    use std::fs::File;
    use std::io::{BufRead, BufReader};
    use std::mem;

    const ETH_P_AX25: u16 = 0x0002; // from if_ether.h for SOCK_RAW
    const SIOCGIFHWADDR: c_ulong = 0x8927; // from sockios.h in the linux kernel
    const SIOCGIFINDEX: c_ulong = 0x8933;

    pub fn socket_new() -> io::Result<Ax25RawSocket> {
        match unsafe { socket(AF_PACKET, SOCK_RAW, ETH_P_AX25.to_be() as i32) } {
            -1 => Err(Error::last_os_error()),
            fd => Ok(Ax25RawSocket { fd }),
        }
    }

    pub fn socket_close(socket: &mut Ax25RawSocket) -> io::Result<()> {
        match unsafe { close(socket.fd) } {
            -1 => Err(Error::last_os_error()),
            _ => Ok(()),
        }
    }

    pub fn socket_list_ax25_interfaces(socket: &Ax25RawSocket) -> io::Result<Vec<NetDev>> {
        let dev_file = File::open("/proc/net/dev")?;
        let mut devices: Vec<NetDev> = Vec::new();
        let reader = BufReader::new(dev_file);
        let lines = reader.lines();
        for l in lines.skip(2) {
            if let Ok(line) = l {
                let device_name = line.trim().split(':').next().unwrap();
                if let Some(net_dev) = get_ax25_netdev(&device_name, socket.fd) {
                    devices.push(net_dev);
                }
            }
        }
        Ok(devices)
    }

    pub fn socket_send_frame(socket: &Ax25RawSocket, frame: &[u8], ifindex: i32) -> io::Result<()> {
        // The Linux interface demands a single null byte prefix on the actual packet
        let mut prefixed_frame: Vec<u8> = Vec::with_capacity(frame.len() + 1);
        prefixed_frame.push(0);
        prefixed_frame.extend(frame.iter().cloned());

        let sa = sockaddr_ll {
            sll_family: AF_PACKET as u16,
            sll_protocol: ETH_P_AX25.to_be(),
            sll_ifindex: ifindex,
            sll_hatype: 0,
            sll_pkttype: 0,
            sll_halen: 0,
            sll_addr: [0; 8],
        };

        match unsafe {
            let sa_ptr = &sa as *const libc::sockaddr_ll as *const libc::sockaddr;
            sendto(
                socket.fd,
                prefixed_frame.as_ptr() as *const c_void,
                prefixed_frame.len(),
                0,
                sa_ptr,
                mem::size_of_val(&sa) as socklen_t,
            )
        } {
            -1 => Err(Error::last_os_error()),
            _ => Ok(()),
        }
    }

    pub fn socket_receive_frame(socket: &Ax25RawSocket) -> io::Result<Vec<u8>> {
        let mut buf: [u8; 1024] = [0; 1024];
        // Not sure we need the address but it might come in handy someday
        let mut addr_struct: sockaddr_ll = unsafe { mem::zeroed() };
        let len: usize;
        unsafe {
            let sa_ptr = &mut addr_struct as *mut libc::sockaddr_ll as *mut libc::sockaddr;
            let mut sa_in_sz: socklen_t = mem::size_of::<sockaddr_ll>() as socklen_t;
            len = match recvfrom(
                socket.fd,
                buf.as_mut_ptr() as *mut c_void,
                buf.len(),
                0,
                sa_ptr,
                &mut sa_in_sz,
            ) {
                -1 => return Err(Error::last_os_error()),
                len => len as usize,
            };
        }
        let valid_buf = &buf[0..len];

        // In practice AF_PACKET gives us one leading one null byte
        // These are unhelpful so we will skip all leading null bytes
        let filtered: Vec<u8> = valid_buf.iter().skip_while(|&c| *c == 0).cloned().collect();
        Ok(filtered)
    }

    fn get_ax25_netdev(name: &str, fd: i32) -> Option<NetDev> {
        let mut req = ifreq::default();
        let if_name = name.to_owned();
        for (d, s) in req.ifr_name.iter_mut().zip(if_name.as_bytes()) {
            *d = *s as c_char;
        }

        if unsafe { ioctl(fd, SIOCGIFHWADDR, &mut req) } == -1 {
            return None;
        }
        if req.data.address_family() as i32 != AF_AX25 {
            return None;
        }
        let hw_addr = match req.data.ax25_address() {
            Some(addr) => addr,
            None => return None,
        };

        if unsafe { ioctl(fd, SIOCGIFINDEX, &mut req) } == -1 {
            return None;
        }
        let ifindex = req.data.ifindex();

        Some(NetDev {
            name: hw_addr,
            ifindex,
        })
    }

    extern "C" {
        fn ioctl(fd: c_int, request: c_ulong, ifreq: *mut ifreq) -> c_int;
    }

    #[repr(C)]
    struct ifreq {
        ifr_name: [c_char; 16],
        data: ifreq_union,
    }

    impl Default for ifreq {
        fn default() -> ifreq {
            ifreq {
                ifr_name: [0; 16],
                data: ifreq_union::default(),
            }
        }
    }

    #[repr(C)]
    struct ifreq_union {
        data: [u8; 24],
    }

    impl Default for ifreq_union {
        fn default() -> ifreq_union {
            ifreq_union { data: [0; 24] }
        }
    }

    impl ifreq_union {
        fn ifindex(&self) -> c_int {
            c_int::from_be(
                ((self.data[0] as c_int) << 24)
                    + ((self.data[1] as c_int) << 16)
                    + ((self.data[2] as c_int) << 8)
                    + (self.data[3] as c_int),
            )
        }

        fn address_family(&self) -> u16 {
            u16::from_be(((self.data[0] as u16) << 8) + (self.data[1] as u16))
        }

        fn ax25_address(&self) -> Option<String> {
            let mut addr_utf8: Vec<u8> = self.data[2..8]
                .iter()
                .rev()
                .map(|&c| c >> 1)
                .skip_while(|&c| c == 0)
                .collect::<Vec<u8>>();
            addr_utf8.reverse();
            let ssid = (self.data[8] >> 1) & 0x0f;
            if let Ok(addr) = String::from_utf8(addr_utf8) {
                return Some(format!("{}-{}", addr, ssid));
            }
            None
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate sync;

#[cfg(test)]
extern crate test;

use std::{cmp, str, fmt, rt, option, io};
use rand::{task_rng, Rng};
use sync::{Arc, Future};

#[cfg(test)]
use test::Bencher;

static LIVE_CELL: char = '@';
static DEAD_CELL: char = '.';

fn main() {
  let mut brd = Board::new(65, 248).random();
  let mut timer = io::Timer::new().unwrap();

  let periodic = timer.periodic(64);
  loop {
    println!("\x1b[H\x1b[2J{}", brd);
    periodic.recv();
    brd = brd.parallel_next_generation();
  }
}

#[deriving(Eq, Clone)]
struct Board {
  board: Vec<bool>,
  survive: Vec<uint>,
  born: Vec<uint>,
  rows: uint,
  cols: uint
}

impl Board {
  fn new(rows: uint, cols: uint) -> Board {
    let born = vec![3];
    let survive = vec![2, 3];

    Board::new_with_custom_rules(rows, cols, born, survive)
  }

  fn new_with_custom_rules(rows: uint, cols: uint, born: Vec<uint>, survive: Vec<uint>) -> Board {
    let new_board = Vec::from_elem(rows * cols, false);

    Board { board  : new_board,
            born   : born,
            survive: survive,
            rows   : rows,
            cols   : cols }
  }

  fn len(&self) -> uint {
    self.rows * self.cols
  }

  fn next_board(&self, new_board: Vec<bool>) -> Board {
    assert!(new_board.len() == self.len());

    Board { board  : new_board,
            born   : self.born.clone(),
            survive: self.survive.clone(),
            rows   : self.rows,
            cols   : self.cols }
  }

  fn random(&self) -> Board {
    let board = task_rng().gen_vec(self.len());

    self.next_board(board)
  }

  fn next_generation(&self) -> Board {
    let new_brd = Vec::from_fn(self.len(), |cell| self.successor_cell(cell));

    self.next_board(new_brd)
  }

  fn parallel_next_generation(&self) -> Board {
    let length = self.len();
    let num_tasks = cmp::min(rt::default_sched_threads(), length);
    let shared_brd = Arc::new(self.clone());
    let all_tasks: Vec<uint> = range(0, length).collect();
    let tasks: Vec<&[uint]> = all_tasks.as_slice().chunks(length / num_tasks).collect();

    fn future_batch(task_brd: Arc<Board>, task: ~[uint]) -> Future<Vec<bool>> {
      Future::spawn(proc()
        task.iter().map(|&idx| task_brd.successor_cell(idx)).collect()
      )
    }

    let future_batches: Vec<Future<Vec<bool>>> = tasks.move_iter().map(|task| {
      future_batch(shared_brd.clone(), task.to_owned())
    }).collect();

    let mut new_brd: Vec<bool> = Vec::with_capacity(length);

    for b in future_batches.move_iter() {
      new_brd.push_all_move(b.unwrap());
    }

    self.next_board(new_brd)
  }

  fn cell_live(&self, x: uint, y: uint) -> bool {
    !(x >= self.cols || y >= self.rows) && *self.board.get(y * self.cols + x)
  }

  fn living_neighbors(&self, x: uint, y: uint) -> uint {
    let neighbors = [
      self.cell_live(x-1, y-1), self.cell_live(x, y-1), self.cell_live(x+1, y-1),
      self.cell_live(x-1, y+0),                         self.cell_live(x+1, y+0),
      self.cell_live(x-1, y+1), self.cell_live(x, y+1), self.cell_live(x+1, y+1),
    ];
    neighbors.iter().count(|&x| x)
  }

  fn successor_cell(&self, cell:uint) -> bool {
    self.successor(cell % self.cols, cell / self.cols)
  }

  fn successor(&self, x:uint, y:uint) -> bool {
    let neighbors = self.living_neighbors(x, y);
    if self.cell_live(x, y) {
      self.survive.contains(&neighbors)
    } else {
      self.born.contains(&neighbors)
    }
  }

  fn from_str(string: &str) -> Option<Board> {
    let rows: Vec<&str> = string.split_terminator('\n').collect();
    let (row_cnt, col_cnt) = (rows.get(0).len(), rows.len());

    if rows.iter().any(|x| x.len() != row_cnt) { return None; };

    let brd = option::collect(
      rows.concat().chars().map(|c| match c {
        LIVE_CELL => Some(true),
        DEAD_CELL => Some(false),
        _         => None
      })
    );

    match brd {
      Some(board) => Some(Board::new(row_cnt, col_cnt).next_board(board)),
      None        => None
    }
  }
}

impl fmt::Show for Board {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

    fn row_to_str(row: &[bool]) -> ~str {
      let chars: Vec<char> = row.iter().map(|&cell|
        if cell {LIVE_CELL} else {DEAD_CELL}
      ).collect();
      str::from_chars(chars.as_slice())
    }

    let rows: Vec<~str> = self.board.as_slice().chunks(self.cols).map(|row|
      row_to_str(row)
    ).collect();

    write!(f.buf, "{}", rows.connect("\n"))
  }
}

#[cfg(test)]
static test_boards: [&'static str, ..3] = [
  ".@.\n.@@\n.@@",
  "...\n@@@\n...",
  ".@.\n.@.\n.@."
];

#[cfg(test)]
fn testing_board(n: uint) -> Board {
  Board::from_str(test_boards[n]).unwrap()
}

#[test]
fn test_board_str_conversion() {
  assert_eq!(testing_board(0).to_str(), test_boards[0].to_owned());
}

#[test]
fn test_cell_live() {
  let brd = testing_board(0);
  assert!(!brd.cell_live(0, 0));
  assert!(brd.cell_live(2, 2));
}

#[test]
fn test_live_count() {
  let brd = testing_board(0);
  assert_eq!(brd.living_neighbors(0, 0), 2);
  assert_eq!(brd.living_neighbors(2, 2), 3);
}

#[test]
fn test_next_generation() {
  assert_eq!(testing_board(1).next_generation(), testing_board(2));
}

#[test]
fn test_parallel_next_generation() {
  assert_eq!(testing_board(1).parallel_next_generation(), testing_board(2));
}

#[bench]
fn bench_random(b: &mut Bencher) {
  let brd = Board::new(200,200);
  b.iter(|| brd.random());
}

#[bench]
fn bench_hundred_generations(b: &mut Bencher) {
  let mut brd = Board::new(200,200).random();
  b.iter(||
    for _ in range(0,100) { brd = brd.next_generation() }
  );
}

#[bench]
fn bench_hundred_parallel_generations(b: &mut Bencher) {
  let mut brd = Board::new(200,200).random();
  b.iter(||
    for _ in range(0,100) { brd = brd.parallel_next_generation() }
  );
}
<commit_msg>reduce bench iterations<commit_after>extern crate rand;
extern crate sync;

#[cfg(test)]
extern crate test;

use std::{cmp, str, fmt, rt, option, io};
use rand::{task_rng, Rng};
use sync::{Arc, Future};

#[cfg(test)]
use test::Bencher;

static LIVE_CELL: char = '@';
static DEAD_CELL: char = '.';

fn main() {
  let mut brd = Board::new(65, 248).random();
  let mut timer = io::Timer::new().unwrap();

  let periodic = timer.periodic(64);
  loop {
    println!("\x1b[H\x1b[2J{}", brd);
    periodic.recv();
    brd = brd.parallel_next_generation();
  }
}

#[deriving(Eq, Clone)]
struct Board {
  board: Vec<bool>,
  survive: Vec<uint>,
  born: Vec<uint>,
  rows: uint,
  cols: uint
}

impl Board {
  fn new(rows: uint, cols: uint) -> Board {
    let born = vec![3];
    let survive = vec![2, 3];

    Board::new_with_custom_rules(rows, cols, born, survive)
  }

  fn new_with_custom_rules(rows: uint, cols: uint, born: Vec<uint>, survive: Vec<uint>) -> Board {
    let new_board = Vec::from_elem(rows * cols, false);

    Board { board  : new_board,
            born   : born,
            survive: survive,
            rows   : rows,
            cols   : cols }
  }

  fn len(&self) -> uint {
    self.rows * self.cols
  }

  fn next_board(&self, new_board: Vec<bool>) -> Board {
    assert!(new_board.len() == self.len());

    Board { board  : new_board,
            born   : self.born.clone(),
            survive: self.survive.clone(),
            rows   : self.rows,
            cols   : self.cols }
  }

  fn random(&self) -> Board {
    let board = task_rng().gen_vec(self.len());

    self.next_board(board)
  }

  fn next_generation(&self) -> Board {
    let new_brd = Vec::from_fn(self.len(), |cell| self.successor_cell(cell));

    self.next_board(new_brd)
  }

  fn parallel_next_generation(&self) -> Board {
    let length = self.len();
    let num_tasks = cmp::min(rt::default_sched_threads(), length);
    let shared_brd = Arc::new(self.clone());
    let all_tasks: Vec<uint> = range(0, length).collect();
    let tasks: Vec<&[uint]> = all_tasks.as_slice().chunks(length / num_tasks).collect();

    fn future_batch(task_brd: Arc<Board>, task: ~[uint]) -> Future<Vec<bool>> {
      Future::spawn(proc()
        task.iter().map(|&idx| task_brd.successor_cell(idx)).collect()
      )
    }

    let future_batches: Vec<Future<Vec<bool>>> = tasks.move_iter().map(|task| {
      future_batch(shared_brd.clone(), task.to_owned())
    }).collect();

    let mut new_brd: Vec<bool> = Vec::with_capacity(length);

    for b in future_batches.move_iter() {
      new_brd.push_all_move(b.unwrap());
    }

    self.next_board(new_brd)
  }

  fn cell_live(&self, x: uint, y: uint) -> bool {
    !(x >= self.cols || y >= self.rows) && *self.board.get(y * self.cols + x)
  }

  fn living_neighbors(&self, x: uint, y: uint) -> uint {
    let neighbors = [
      self.cell_live(x-1, y-1), self.cell_live(x, y-1), self.cell_live(x+1, y-1),
      self.cell_live(x-1, y+0),                         self.cell_live(x+1, y+0),
      self.cell_live(x-1, y+1), self.cell_live(x, y+1), self.cell_live(x+1, y+1),
    ];
    neighbors.iter().count(|&x| x)
  }

  fn successor_cell(&self, cell:uint) -> bool {
    self.successor(cell % self.cols, cell / self.cols)
  }

  fn successor(&self, x:uint, y:uint) -> bool {
    let neighbors = self.living_neighbors(x, y);
    if self.cell_live(x, y) {
      self.survive.contains(&neighbors)
    } else {
      self.born.contains(&neighbors)
    }
  }

  fn from_str(string: &str) -> Option<Board> {
    let rows: Vec<&str> = string.split_terminator('\n').collect();
    let (row_cnt, col_cnt) = (rows.get(0).len(), rows.len());

    if rows.iter().any(|x| x.len() != row_cnt) { return None; };

    let brd = option::collect(
      rows.concat().chars().map(|c| match c {
        LIVE_CELL => Some(true),
        DEAD_CELL => Some(false),
        _         => None
      })
    );

    match brd {
      Some(board) => Some(Board::new(row_cnt, col_cnt).next_board(board)),
      None        => None
    }
  }
}

impl fmt::Show for Board {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

    fn row_to_str(row: &[bool]) -> ~str {
      let chars: Vec<char> = row.iter().map(|&cell|
        if cell {LIVE_CELL} else {DEAD_CELL}
      ).collect();
      str::from_chars(chars.as_slice())
    }

    let rows: Vec<~str> = self.board.as_slice().chunks(self.cols).map(|row|
      row_to_str(row)
    ).collect();

    write!(f.buf, "{}", rows.connect("\n"))
  }
}

#[cfg(test)]
static test_boards: [&'static str, ..3] = [
  ".@.\n.@@\n.@@",
  "...\n@@@\n...",
  ".@.\n.@.\n.@."
];

#[cfg(test)]
fn testing_board(n: uint) -> Board {
  Board::from_str(test_boards[n]).unwrap()
}

#[test]
fn test_board_str_conversion() {
  assert_eq!(testing_board(0).to_str(), test_boards[0].to_owned());
}

#[test]
fn test_cell_live() {
  let brd = testing_board(0);
  assert!(!brd.cell_live(0, 0));
  assert!(brd.cell_live(2, 2));
}

#[test]
fn test_live_count() {
  let brd = testing_board(0);
  assert_eq!(brd.living_neighbors(0, 0), 2);
  assert_eq!(brd.living_neighbors(2, 2), 3);
}

#[test]
fn test_next_generation() {
  assert_eq!(testing_board(1).next_generation(), testing_board(2));
}

#[test]
fn test_parallel_next_generation() {
  assert_eq!(testing_board(1).parallel_next_generation(), testing_board(2));
}

#[bench]
fn bench_random(b: &mut Bencher) {
  let brd = Board::new(200,200);
  b.iter(|| brd.random());
}

#[bench]
fn bench_ten_generations(b: &mut Bencher) {
  let mut brd = Board::new(200,200).random();
  b.iter(||
    for _ in range(0,10) { brd = brd.next_generation() }
  );
}

#[bench]
fn bench_ten_parallel_generations(b: &mut Bencher) {
  let mut brd = Board::new(200,200).random();
  b.iter(||
    for _ in range(0,10) { brd = brd.parallel_next_generation() }
  );
}
<|endoftext|>


<commit_before>
import std::vec;
import std::vec::plus_option;
import syntax::ast::*;
import util::ppaux::fn_ident_to_string;
import std::option::*;
import syntax::walk;
import syntax::visit;
import walk::walk_crate;
import walk::walk_fn;
import walk::ast_visitor;
import aux::cinit;
import aux::ninit;
import aux::npred;
import aux::cpred;
import aux::constraint;
import aux::fn_info;
import aux::crate_ctxt;
import aux::num_constraints;
import aux::constr_map;
import aux::expr_to_constr;
import aux::constraints_expr;
import aux::node_id_to_def_strict;
import std::map::new_int_hash;
import util::common::new_def_hash;
import syntax::codemap::span;
import syntax::ast::respan;

type ctxt = rec(@mutable vec[aux::constr] cs, ty::ctxt tcx);

fn collect_local(&@local loc, &ctxt cx, &visit::vt[ctxt] v) {
    log "collect_local: pushing " + loc.node.ident;
    vec::push(*cx.cs,
              respan(loc.span, rec(id=loc.node.id, c=ninit(loc.node.ident))));
    visit::visit_local(loc, cx, v);
}

fn collect_pred(&@expr e, &ctxt cx, &visit::vt[ctxt] v) {
    alt (e.node) {
        case (expr_check(_, ?ch)) {
            vec::push(*cx.cs, expr_to_constr(cx.tcx, ch));
        }
        case (expr_if_check(?ex, _, _)) {
            vec::push(*cx.cs, expr_to_constr(cx.tcx, ex));
        }
        // If it's a call, generate appropriate instances of the
        // call's constraints.
        case (expr_call(?operator, ?operands)) {
            // FIXME: Remove this vec->ivec conversion.
            auto operands_ivec = ~[];
            for (@expr opd in operands) { operands_ivec += ~[opd]; }

            for (@ty::constr_def c in constraints_expr(cx.tcx, operator)) {
                let aux::constr ct = respan(c.span,
                      rec(id=c.node.id._1,
                          c=aux::substitute_constr_args(cx.tcx,
                                                        operands_ivec, c)));
                vec::push(*cx.cs, ct);
            }
        }
        case (_) { }
    }
    // visit subexpressions
    visit::visit_expr(e, cx, v);
}

fn do_nothing(&_fn f, &vec[ty_param] tp, &span sp, &fn_ident i,
              node_id iid, &ctxt cx, &visit::vt[ctxt] v) {
}

fn find_locals(&ty::ctxt tcx, &_fn f, &vec[ty_param] tps,
               &span sp, &fn_ident i, node_id id)
    -> ctxt {
    let ctxt cx = rec(cs=@mutable vec::alloc(0u), tcx=tcx);
    auto visitor = visit::default_visitor[ctxt]();

    visitor =
        @rec(visit_local=collect_local,
             visit_expr=collect_pred,
             visit_fn=do_nothing
             with *visitor);
    visit::visit_fn(f, tps, sp, i, id, cx, visit::vtor(visitor));
    ret cx;
}

fn add_constraint(&ty::ctxt tcx, aux::constr c, uint next, constr_map tbl) ->
   uint {
    log aux::constraint_to_str(tcx, c) + " |-> " + std::uint::str(next);
    alt (c.node.c) {
        case (ninit(?i)) { tbl.insert(c.node.id, cinit(next, c.span, i)); }
        case (npred(?p, ?args)) {
            alt (tbl.find(c.node.id)) {
                case (some(?ct)) {
                    alt (ct) {
                        case (cinit(_, _, _)) {
                            tcx.sess.bug("add_constraint: same def_id used" +
                                             " as a variable and a pred");
                        }
                        case (cpred(_, ?pds)) {
                            *pds += ~[respan(c.span,
                                             rec(args=args, bit_num=next))];
                        }
                    }
                }
                case (none) {
                    tbl.insert(c.node.id,
                               cpred(p,
                                     @mutable ~[respan(c.span,
                                                       rec(args=args,
                                                           bit_num=next))]));
                }
            }
        }
    }
    ret next + 1u;
}

/* builds a table mapping each local var defined in f
   to a bit number in the precondition/postcondition vectors */
fn mk_fn_info(&crate_ctxt ccx, &_fn f, &vec[ty_param] tp,
              &span f_sp, &fn_ident f_name,
              node_id id) {
    auto res_map = @new_int_hash[constraint]();
    let uint next = 0u;

    let ctxt cx = find_locals(ccx.tcx, f, tp, f_sp, f_name, id);
    /* now we have to add bit nums for both the constraints
       and the variables... */

    for (aux::constr c in { *cx.cs }) {
        next = add_constraint(cx.tcx, c, next, res_map);
    }
    /* add a pseudo-entry for the function's return value
       we can safely use the function's name itself for this purpose */

    auto name = fn_ident_to_string(id, f_name);
    add_constraint(cx.tcx, respan(f_sp, rec(id=id, c=ninit(name))), next,
                   res_map);
    let @mutable node_id[] v = @mutable ~[];
    auto rslt =
        rec(constrs=res_map,
            num_constraints=vec::len(*cx.cs) + 1u,
            cf=f.decl.cf,
            used_vars=v);
    ccx.fm.insert(id, rslt);
    log name + " has " + std::uint::str(num_constraints(rslt)) +
        " constraints";
}

/* initializes the global fn_info_map (mapping each function ID, including
   nested locally defined functions, onto a mapping from local variable name
   to bit number) */
fn mk_f_to_fn_info(&crate_ctxt ccx, @crate c) {
    let ast_visitor vars_visitor = walk::default_visitor();
    vars_visitor =
        rec(visit_fn_pre=bind mk_fn_info(ccx, _, _, _, _, _)
            with vars_visitor);
    walk_crate(vars_visitor, *c);
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>rustc: Move middle::tstate::collect_locals over to interior vectors<commit_after>
import std::ivec;
import std::vec;
import syntax::ast::*;
import util::ppaux::fn_ident_to_string;
import std::option::*;
import syntax::walk;
import syntax::visit;
import walk::walk_crate;
import walk::walk_fn;
import walk::ast_visitor;
import aux::cinit;
import aux::ninit;
import aux::npred;
import aux::cpred;
import aux::constraint;
import aux::fn_info;
import aux::crate_ctxt;
import aux::num_constraints;
import aux::constr_map;
import aux::expr_to_constr;
import aux::constraints_expr;
import aux::node_id_to_def_strict;
import std::map::new_int_hash;
import util::common::new_def_hash;
import syntax::codemap::span;
import syntax::ast::respan;

type ctxt = rec(@mutable (aux::constr[]) cs, ty::ctxt tcx);

fn collect_local(&@local loc, &ctxt cx, &visit::vt[ctxt] v) {
    log "collect_local: pushing " + loc.node.ident;
    *cx.cs += ~[respan(loc.span, rec(id=loc.node.id,
                                     c=ninit(loc.node.ident)))];
    visit::visit_local(loc, cx, v);
}

fn collect_pred(&@expr e, &ctxt cx, &visit::vt[ctxt] v) {
    alt (e.node) {
        case (expr_check(_, ?ch)) {
            *cx.cs += ~[expr_to_constr(cx.tcx, ch)];
        }
        case (expr_if_check(?ex, _, _)) {
            *cx.cs += ~[expr_to_constr(cx.tcx, ex)];
        }
        // If it's a call, generate appropriate instances of the
        // call's constraints.
        case (expr_call(?operator, ?operands)) {
            // FIXME: Remove this vec->ivec conversion.
            auto operands_ivec = ~[];
            for (@expr opd in operands) { operands_ivec += ~[opd]; }

            for (@ty::constr_def c in constraints_expr(cx.tcx, operator)) {
                let aux::constr ct = respan(c.span,
                      rec(id=c.node.id._1,
                          c=aux::substitute_constr_args(cx.tcx,
                                                        operands_ivec, c)));
                *cx.cs += ~[ct];
            }
        }
        case (_) { }
    }
    // visit subexpressions
    visit::visit_expr(e, cx, v);
}

fn do_nothing(&_fn f, &vec[ty_param] tp, &span sp, &fn_ident i,
              node_id iid, &ctxt cx, &visit::vt[ctxt] v) {
}

fn find_locals(&ty::ctxt tcx, &_fn f, &vec[ty_param] tps,
               &span sp, &fn_ident i, node_id id)
    -> ctxt {
    let ctxt cx = rec(cs=@mutable ~[], tcx=tcx);
    auto visitor = visit::default_visitor[ctxt]();

    visitor =
        @rec(visit_local=collect_local,
             visit_expr=collect_pred,
             visit_fn=do_nothing
             with *visitor);
    visit::visit_fn(f, tps, sp, i, id, cx, visit::vtor(visitor));
    ret cx;
}

fn add_constraint(&ty::ctxt tcx, aux::constr c, uint next, constr_map tbl) ->
   uint {
    log aux::constraint_to_str(tcx, c) + " |-> " + std::uint::str(next);
    alt (c.node.c) {
        case (ninit(?i)) { tbl.insert(c.node.id, cinit(next, c.span, i)); }
        case (npred(?p, ?args)) {
            alt (tbl.find(c.node.id)) {
                case (some(?ct)) {
                    alt (ct) {
                        case (cinit(_, _, _)) {
                            tcx.sess.bug("add_constraint: same def_id used" +
                                             " as a variable and a pred");
                        }
                        case (cpred(_, ?pds)) {
                            *pds += ~[respan(c.span,
                                             rec(args=args, bit_num=next))];
                        }
                    }
                }
                case (none) {
                    tbl.insert(c.node.id,
                               cpred(p,
                                     @mutable ~[respan(c.span,
                                                       rec(args=args,
                                                           bit_num=next))]));
                }
            }
        }
    }
    ret next + 1u;
}

/* builds a table mapping each local var defined in f
   to a bit number in the precondition/postcondition vectors */
fn mk_fn_info(&crate_ctxt ccx, &_fn f, &vec[ty_param] tp,
              &span f_sp, &fn_ident f_name,
              node_id id) {
    auto res_map = @new_int_hash[constraint]();
    let uint next = 0u;

    let ctxt cx = find_locals(ccx.tcx, f, tp, f_sp, f_name, id);
    /* now we have to add bit nums for both the constraints
       and the variables... */

    for (aux::constr c in { *cx.cs }) {
        next = add_constraint(cx.tcx, c, next, res_map);
    }
    /* add a pseudo-entry for the function's return value
       we can safely use the function's name itself for this purpose */

    auto name = fn_ident_to_string(id, f_name);
    add_constraint(cx.tcx, respan(f_sp, rec(id=id, c=ninit(name))), next,
                   res_map);
    let @mutable node_id[] v = @mutable ~[];
    auto rslt =
        rec(constrs=res_map,
            num_constraints=ivec::len(*cx.cs) + 1u,
            cf=f.decl.cf,
            used_vars=v);
    ccx.fm.insert(id, rslt);
    log name + " has " + std::uint::str(num_constraints(rslt)) +
        " constraints";
}

/* initializes the global fn_info_map (mapping each function ID, including
   nested locally defined functions, onto a mapping from local variable name
   to bit number) */
fn mk_f_to_fn_info(&crate_ctxt ccx, @crate c) {
    let ast_visitor vars_visitor = walk::default_visitor();
    vars_visitor =
        rec(visit_fn_pre=bind mk_fn_info(ccx, _, _, _, _, _)
            with vars_visitor);
    walk_crate(vars_visitor, *c);
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::HTMLElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLElementDerived;
use dom::bindings::js::JS;
use dom::bindings::error::{ErrorResult, Fallible};
use dom::document::Document;
use dom::element::{Element, ElementTypeId, HTMLElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::node::{Node, ElementNodeTypeId};
use js::jsapi::JSContext;
use js::jsval::{JSVal, NullValue};
use servo_util::namespace;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLElement {
    element: Element
}

impl HTMLElementDerived for EventTarget {
    fn is_htmlelement(&self) -> bool {
        match self.type_id {
            NodeTargetTypeId(ElementNodeTypeId(_)) => true,
            _ => false
        }
    }
}

impl HTMLElement {
    pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, document: JS<Document>) -> HTMLElement {
        HTMLElement {
            element: Element::new_inherited(type_id, tag_name, namespace::HTML, document)
        }
    }

    pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLElement> {
        let element = HTMLElement::new_inherited(HTMLElementTypeId, localName, document.clone());
        Node::reflect_node(~element, document, HTMLElementBinding::Wrap)
    }
}

impl HTMLElement {
    pub fn Title(&self) -> DOMString {
        ~""
    }

    pub fn SetTitle(&mut self, _title: DOMString) {
    }

    pub fn Lang(&self) -> DOMString {
        ~""
    }

    pub fn SetLang(&mut self, _lang: DOMString) {
    }

    pub fn Dir(&self) -> DOMString {
        ~""
    }

    pub fn SetDir(&mut self, _dir: DOMString) -> ErrorResult {
        Ok(())
    }

    pub fn GetItemValue(&self, _cx: *JSContext) -> Fallible<JSVal> {
        Ok(NullValue())
    }

    pub fn SetItemValue(&mut self, _cx: *JSContext, _val: JSVal) -> ErrorResult {
        Ok(())
    }

    pub fn Hidden(&self) -> bool {
        false
    }

    pub fn SetHidden(&mut self, _hidden: bool) -> ErrorResult {
        Ok(())
    }

    pub fn Click(&self) {
    }

    pub fn TabIndex(&self) -> i32 {
        0
    }

    pub fn SetTabIndex(&mut self, _index: i32) -> ErrorResult {
        Ok(())
    }

    pub fn Focus(&self) -> ErrorResult {
        Ok(())
    }

    pub fn Blur(&self) -> ErrorResult {
        Ok(())
    }

    pub fn AccessKey(&self) -> DOMString {
        ~""
    }

    pub fn SetAccessKey(&self, _key: DOMString) -> ErrorResult {
        Ok(())
    }

    pub fn AccessKeyLabel(&self) -> DOMString {
        ~""
    }

    pub fn Draggable(&self) -> bool {
        false
    }

    pub fn SetDraggable(&mut self, _draggable: bool) -> ErrorResult {
        Ok(())
    }

    pub fn ContentEditable(&self) -> DOMString {
        ~""
    }

    pub fn SetContentEditable(&mut self, _val: DOMString) -> ErrorResult {
        Ok(())
    }

    pub fn IsContentEditable(&self) -> bool {
        false
    }

    pub fn Spellcheck(&self) -> bool {
        false
    }

    pub fn SetSpellcheck(&self, _val: bool) -> ErrorResult {
        Ok(())
    }

    pub fn GetOffsetParent(&self) -> Option<JS<Element>> {
        None
    }

    pub fn OffsetTop(&self) -> i32 {
        0
    }

    pub fn OffsetLeft(&self) -> i32 {
        0
    }

    pub fn OffsetWidth(&self) -> i32 {
        0
    }

    pub fn OffsetHeight(&self) -> i32 {
        0
    }
}
<commit_msg>Fix HTMLElementDerived::is_htmlelement to take non-HTML elements into account.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::HTMLElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLElementDerived;
use dom::bindings::js::JS;
use dom::bindings::error::{ErrorResult, Fallible};
use dom::document::Document;
use dom::element::{Element, ElementTypeId, HTMLElementTypeId};
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::node::{Node, ElementNodeTypeId};
use js::jsapi::JSContext;
use js::jsval::{JSVal, NullValue};
use servo_util::namespace;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLElement {
    element: Element
}

impl HTMLElementDerived for EventTarget {
    fn is_htmlelement(&self) -> bool {
        match self.type_id {
            NodeTargetTypeId(ElementNodeTypeId(ElementTypeId)) => false,
            NodeTargetTypeId(ElementNodeTypeId(_)) => true,
            _ => false
        }
    }
}

impl HTMLElement {
    pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, document: JS<Document>) -> HTMLElement {
        HTMLElement {
            element: Element::new_inherited(type_id, tag_name, namespace::HTML, document)
        }
    }

    pub fn new(localName: DOMString, document: &JS<Document>) -> JS<HTMLElement> {
        let element = HTMLElement::new_inherited(HTMLElementTypeId, localName, document.clone());
        Node::reflect_node(~element, document, HTMLElementBinding::Wrap)
    }
}

impl HTMLElement {
    pub fn Title(&self) -> DOMString {
        ~""
    }

    pub fn SetTitle(&mut self, _title: DOMString) {
    }

    pub fn Lang(&self) -> DOMString {
        ~""
    }

    pub fn SetLang(&mut self, _lang: DOMString) {
    }

    pub fn Dir(&self) -> DOMString {
        ~""
    }

    pub fn SetDir(&mut self, _dir: DOMString) -> ErrorResult {
        Ok(())
    }

    pub fn GetItemValue(&self, _cx: *JSContext) -> Fallible<JSVal> {
        Ok(NullValue())
    }

    pub fn SetItemValue(&mut self, _cx: *JSContext, _val: JSVal) -> ErrorResult {
        Ok(())
    }

    pub fn Hidden(&self) -> bool {
        false
    }

    pub fn SetHidden(&mut self, _hidden: bool) -> ErrorResult {
        Ok(())
    }

    pub fn Click(&self) {
    }

    pub fn TabIndex(&self) -> i32 {
        0
    }

    pub fn SetTabIndex(&mut self, _index: i32) -> ErrorResult {
        Ok(())
    }

    pub fn Focus(&self) -> ErrorResult {
        Ok(())
    }

    pub fn Blur(&self) -> ErrorResult {
        Ok(())
    }

    pub fn AccessKey(&self) -> DOMString {
        ~""
    }

    pub fn SetAccessKey(&self, _key: DOMString) -> ErrorResult {
        Ok(())
    }

    pub fn AccessKeyLabel(&self) -> DOMString {
        ~""
    }

    pub fn Draggable(&self) -> bool {
        false
    }

    pub fn SetDraggable(&mut self, _draggable: bool) -> ErrorResult {
        Ok(())
    }

    pub fn ContentEditable(&self) -> DOMString {
        ~""
    }

    pub fn SetContentEditable(&mut self, _val: DOMString) -> ErrorResult {
        Ok(())
    }

    pub fn IsContentEditable(&self) -> bool {
        false
    }

    pub fn Spellcheck(&self) -> bool {
        false
    }

    pub fn SetSpellcheck(&self, _val: bool) -> ErrorResult {
        Ok(())
    }

    pub fn GetOffsetParent(&self) -> Option<JS<Element>> {
        None
    }

    pub fn OffsetTop(&self) -> i32 {
        0
    }

    pub fn OffsetLeft(&self) -> i32 {
        0
    }

    pub fn OffsetWidth(&self) -> i32 {
        0
    }

    pub fn OffsetHeight(&self) -> i32 {
        0
    }
}
<|endoftext|>


<commit_before>#![crate_id(name="shuf", vers="1.0.0", author="Arcterus")]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#![feature(macro_rules)]

extern crate getopts;
extern crate libc;

use std::cmp;
use std::from_str::from_str;
use std::io;
use std::io::IoResult;
use std::iter::{range_inclusive, RangeInclusive};
use std::rand;
use std::uint;

#[path = "../common/util.rs"]
mod util;

enum Mode {
    Default,
    Echo,
    InputRange(RangeInclusive<uint>)
}

static NAME: &'static str = "shuf";
static VERSION: &'static str = "0.0.1";

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0).clone();

    let opts = [
        getopts::optflag("e", "echo", "treat each ARG as an input line"),
        getopts::optopt("i", "input-range", "treat each number LO through HI as an input line", "LO-HI"),
        getopts::optopt("n", "head-count", "output at most COUNT lines", "COUNT"),
        getopts::optopt("o", "output", "write result to FILE instead of standard output", "FILE"),
        getopts::optopt("", "random-source", "get random bytes from FILE", "FILE"),
        getopts::optflag("r", "repeat", "output lines can be repeated"),
        getopts::optflag("z", "zero-terminated", "end lines with 0 byte, not newline"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "{}", f)
        }
    };
    if matches.opt_present("help") {
        println!("{name} v{version}

Usage:
  {prog} [OPTION]... [FILE]
  {prog} -e [OPTION]... [ARG]...
  {prog} -i LO-HI [OPTION]...\n
{usage}
With no FILE, or when FILE is -, read standard input.",
                 name = NAME, version = VERSION, prog = program,
                 usage = getopts::usage("Write a random permutation of the input lines to standard output.", opts));
    } else if matches.opt_present("version") {
        println!("{} v{}", NAME, VERSION);
    } else {
        let echo = matches.opt_present("echo");
        let mode = match matches.opt_str("input-range") {
            Some(range) => {
                if echo {
                    show_error!("cannot specify more than one mode");
                    return 1;
                }
                match parse_range(range) {
                    Ok(m) => InputRange(m),
                    Err((msg, code)) => {
                        show_error!("{}", msg);
                        return code;
                    }
                }
            }
            None => if echo { Echo } else { Default }
        };
        let repeat = matches.opt_present("repeat");
        let zero = matches.opt_present("zero-terminated");
        let count = match matches.opt_str("head-count") {
            Some(cnt) => match from_str::<uint>(cnt.as_slice()) {
                Some(val) => val,
                None => {
                    show_error!("'{}' is not a valid count", cnt);
                    return 1;
                }
            },
            None => uint::MAX
        };
        let output = matches.opt_str("output");
        let random = matches.opt_str("random-source");
        match shuf(matches.free, mode, repeat, zero, count, output, random) {
            Err(f) => {
                show_error!("{}", f);
                return 1;
            },
            _ => {}
        }
    }

    0
}

fn shuf(input: Vec<String>, mode: Mode, repeat: bool, zero: bool, count: uint, output: Option<String>, random: Option<String>) -> IoResult<()> {
    match mode {
        Echo => shuf_lines(input, repeat, zero, count, output, random),
        InputRange(range) => shuf_lines(range.map(|num| num.to_str()).collect(), repeat, zero, count, output, random),
        Default => {
            let lines: Vec<String> = input.move_iter().flat_map(|filename| {
                let mut file = io::BufferedReader::new(crash_if_err!(1, io::File::open(&Path::new(filename.as_slice()))));
                let mut lines = vec!();
                for line in file.lines() {
                    let mut line = crash_if_err!(1, line);
                    line.pop_char();
                    lines.push(line);
                }
                lines.move_iter()
            }).collect();
            shuf_lines(lines, repeat, zero, count, output, random)
        }
    }
}

fn shuf_lines(mut lines: Vec<String>, repeat: bool, zero: bool, count: uint, outname: Option<String>, random: Option<String>) -> IoResult<()> {
    let mut output = match outname {
        Some(name) => box io::BufferedWriter::new(try!(io::File::create(&Path::new(name)))) as Box<Writer>,
        None => box io::stdout() as Box<Writer>
    };
    let mut rng = match random {
        Some(name) => box rand::reader::ReaderRng::new(try!(io::File::open(&Path::new(name)))) as Box<rand::Rng>,
        None => box rand::task_rng() as Box<rand::Rng>
    };
    let mut len = lines.len();
    let max = if repeat { count } else { cmp::min(count, len) };
    for _ in range(0, max) {
        let idx = rng.next_u32() as uint % len;
        try!(write!(output, "{}{}", lines.get(idx), if zero { '\0' } else { '\n' }));
        if !repeat {
            lines.remove(idx);
            len -= 1;
        }
    }
    Ok(())
}

fn parse_range(input_range: String) -> Result<RangeInclusive<uint>, (String, int)> {
    let split: Vec<&str> = input_range.as_slice().split('-').collect();
    if split.len() != 2 {
        Err(("invalid range format".to_string(), 1))
    } else {
        let begin = match from_str::<uint>(*split.get(0)) {
            Some(m) => m,
            None => return Err((format!("{} is not a valid number", split.get(0)), 1))
        };
        let end = match from_str::<uint>(*split.get(1)) {
            Some(m) => m,
            None => return Err((format!("{} is not a valid number", split.get(1)), 1))
        };
        Ok(range_inclusive(begin, end))
    }
}

<commit_msg>shuf: update for latest Rust<commit_after>#![crate_name = "shuf"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#![feature(macro_rules)]

extern crate getopts;
extern crate libc;

use std::cmp;
use std::from_str::from_str;
use std::io;
use std::io::IoResult;
use std::iter::{range_inclusive, RangeInclusive};
use std::rand;
use std::uint;

#[path = "../common/util.rs"]
mod util;

enum Mode {
    Default,
    Echo,
    InputRange(RangeInclusive<uint>)
}

static NAME: &'static str = "shuf";
static VERSION: &'static str = "0.0.1";

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0).clone();

    let opts = [
        getopts::optflag("e", "echo", "treat each ARG as an input line"),
        getopts::optopt("i", "input-range", "treat each number LO through HI as an input line", "LO-HI"),
        getopts::optopt("n", "head-count", "output at most COUNT lines", "COUNT"),
        getopts::optopt("o", "output", "write result to FILE instead of standard output", "FILE"),
        getopts::optopt("", "random-source", "get random bytes from FILE", "FILE"),
        getopts::optflag("r", "repeat", "output lines can be repeated"),
        getopts::optflag("z", "zero-terminated", "end lines with 0 byte, not newline"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "{}", f)
        }
    };
    if matches.opt_present("help") {
        println!("{name} v{version}

Usage:
  {prog} [OPTION]... [FILE]
  {prog} -e [OPTION]... [ARG]...
  {prog} -i LO-HI [OPTION]...\n
{usage}
With no FILE, or when FILE is -, read standard input.",
                 name = NAME, version = VERSION, prog = program,
                 usage = getopts::usage("Write a random permutation of the input lines to standard output.", opts));
    } else if matches.opt_present("version") {
        println!("{} v{}", NAME, VERSION);
    } else {
        let echo = matches.opt_present("echo");
        let mode = match matches.opt_str("input-range") {
            Some(range) => {
                if echo {
                    show_error!("cannot specify more than one mode");
                    return 1;
                }
                match parse_range(range) {
                    Ok(m) => InputRange(m),
                    Err((msg, code)) => {
                        show_error!("{}", msg);
                        return code;
                    }
                }
            }
            None => if echo { Echo } else { Default }
        };
        let repeat = matches.opt_present("repeat");
        let zero = matches.opt_present("zero-terminated");
        let count = match matches.opt_str("head-count") {
            Some(cnt) => match from_str::<uint>(cnt.as_slice()) {
                Some(val) => val,
                None => {
                    show_error!("'{}' is not a valid count", cnt);
                    return 1;
                }
            },
            None => uint::MAX
        };
        let output = matches.opt_str("output");
        let random = matches.opt_str("random-source");
        match shuf(matches.free, mode, repeat, zero, count, output, random) {
            Err(f) => {
                show_error!("{}", f);
                return 1;
            },
            _ => {}
        }
    }

    0
}

fn shuf(input: Vec<String>, mode: Mode, repeat: bool, zero: bool, count: uint, output: Option<String>, random: Option<String>) -> IoResult<()> {
    match mode {
        Echo => shuf_lines(input, repeat, zero, count, output, random),
        InputRange(range) => shuf_lines(range.map(|num| num.to_string()).collect(), repeat, zero, count, output, random),
        Default => {
            let lines: Vec<String> = input.move_iter().flat_map(|filename| {
                let mut file = io::BufferedReader::new(crash_if_err!(1, io::File::open(&Path::new(filename.as_slice()))));
                let mut lines = vec!();
                for line in file.lines() {
                    let mut line = crash_if_err!(1, line);
                    line.pop_char();
                    lines.push(line);
                }
                lines.move_iter()
            }).collect();
            shuf_lines(lines, repeat, zero, count, output, random)
        }
    }
}

fn shuf_lines(mut lines: Vec<String>, repeat: bool, zero: bool, count: uint, outname: Option<String>, random: Option<String>) -> IoResult<()> {
    let mut output = match outname {
        Some(name) => box io::BufferedWriter::new(try!(io::File::create(&Path::new(name)))) as Box<Writer>,
        None => box io::stdout() as Box<Writer>
    };
    let mut rng = match random {
        Some(name) => box rand::reader::ReaderRng::new(try!(io::File::open(&Path::new(name)))) as Box<rand::Rng>,
        None => box rand::task_rng() as Box<rand::Rng>
    };
    let mut len = lines.len();
    let max = if repeat { count } else { cmp::min(count, len) };
    for _ in range(0, max) {
        let idx = rng.next_u32() as uint % len;
        try!(write!(output, "{}{}", lines.get(idx), if zero { '\0' } else { '\n' }));
        if !repeat {
            lines.remove(idx);
            len -= 1;
        }
    }
    Ok(())
}

fn parse_range(input_range: String) -> Result<RangeInclusive<uint>, (String, int)> {
    let split: Vec<&str> = input_range.as_slice().split('-').collect();
    if split.len() != 2 {
        Err(("invalid range format".to_string(), 1))
    } else {
        let begin = match from_str::<uint>(*split.get(0)) {
            Some(m) => m,
            None => return Err((format!("{} is not a valid number", split.get(0)), 1))
        };
        let end = match from_str::<uint>(*split.get(1)) {
            Some(m) => m,
            None => return Err((format!("{} is not a valid number", split.get(1)), 1))
        };
        Ok(range_inclusive(begin, end))
    }
}

<|endoftext|>


<commit_before>// Build the library.

extern crate gcc;

use std::fs;
use std::io;
use std::path::Path;

fn main() {
    let mut conf = gcc::Config::new();

    conf.file("../boot/bootutil/src/loader.c");
    conf.file("../boot/bootutil/src/bootutil_misc.c");
    conf.file("csupport/run.c");
    conf.include("../boot/bootutil/include");
    conf.include("../zephyr/include");
    conf.debug(true);
    conf.compile("libbootutil.a");
    walk_dir("../boot").unwrap();
    walk_dir("csupport").unwrap();
    walk_dir("../zephyr").unwrap();
}

// Output the names of all files within a directory so that Cargo knows when to rebuild.
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
    for ent in fs::read_dir(path.as_ref())? {
        let ent = ent?;
        let p = ent.path();
        if p.is_dir() {
            walk_dir(p)?;
        } else {
            // Note that non-utf8 names will fail.
            let name = p.to_str().unwrap();
            if name.ends_with(".c") || name.ends_with(".h") {
                println!("cargo:rerun-if-changed={}", name);
            }
        }
    }

    Ok(())
}
<commit_msg>sim: Fix build paths for new directory layout<commit_after>// Build the library.

extern crate gcc;

use std::fs;
use std::io;
use std::path::Path;

fn main() {
    let mut conf = gcc::Config::new();

    conf.file("../boot/bootutil/src/loader.c");
    conf.file("../boot/bootutil/src/bootutil_misc.c");
    conf.file("csupport/run.c");
    conf.include("../boot/bootutil/include");
    conf.include("../boot/zephyr/include");
    conf.debug(true);
    conf.compile("libbootutil.a");
    walk_dir("../boot").unwrap();
    walk_dir("csupport").unwrap();
}

// Output the names of all files within a directory so that Cargo knows when to rebuild.
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
    for ent in fs::read_dir(path.as_ref())? {
        let ent = ent?;
        let p = ent.path();
        if p.is_dir() {
            walk_dir(p)?;
        } else {
            // Note that non-utf8 names will fail.
            let name = p.to_str().unwrap();
            if name.ends_with(".c") || name.ends_with(".h") {
                println!("cargo:rerun-if-changed={}", name);
            }
        }
    }

    Ok(())
}
<|endoftext|>