<commit_before>#![feature(asm)]

use std::Box;
use std::{io, rand};
use std::ptr;
use std::syscall::sys_fork;

macro_rules! readln {
    () => {
        {
            let mut line = String::new();
            match io::stdin().read_line(&mut line) {
                Ok(_) => Some(line.trim().to_string()),
                Err(_) => None
            }
        }
    };
}

fn console_title(title: &str){

}

#[no_mangle]
pub fn main() {
    console_title("Test");

    println!("Type help for a command list");
    while let Some(line) = readln!() {
        let args: Vec<String> = line.split(' ').map(|arg| arg.to_string()).collect();

        if let Some(a_command) = args.get(0) {
            println!("# {}", line);
            let console_commands = ["panic",
                                    "ls",
                                    "ptr_write",
                                    "box_write",
                                    "reboot",
                                    "shutdown",
                                    "fork"];

            match &a_command[..] {
                command if command == console_commands[0] =>
                    panic!("Test panic"),
                command if command == console_commands[1] => {
                    // TODO: import std::fs functions into libredox
                    //fs::read_dir("/").unwrap().map(|dir| println!("{}", dir));
                }
                command if command == console_commands[2] => {
                    let a_ptr = rand() as *mut u8;
                    unsafe { ptr::write(a_ptr, rand() as u8); }
                }
                command if command == console_commands[3] => {
                    let mut a_box = Box::new(rand() as u8);
                    unsafe { ptr::write(Box::into_raw(a_box), rand() as u8); }
                }
                command if command == console_commands[4] => {
                    unsafe {
                        let mut good: u8 = 2;
                        while good & 2 == 2 {
                            asm!("in al, dx" : "={al}"(good) : "{dx}"(0x64) : : "intel", "volatile");
                        }
                        asm!("out dx, al" : : "{dx}"(0x64), "{al}"(0xFE) : : "intel", "volatile");
                        loop {
                            asm!("cli" : : : : "intel", "volatile");
                            asm!("hlt" : : : : "intel", "volatile");
                        }
                    }
                }
                command if command == console_commands[5] => {
                    unsafe {
                        loop {
                            asm!("cli" : : : : "intel", "volatile");
                            asm!("hlt" : : : : "intel", "volatile");
                        }
                    }
                }
                command if command == console_commands[6] => {
                    unsafe {
                        if sys_fork() == 0 {
                            println!("Parent from fork");
                        }else {
                            println!("Child from fork");
                        }
                    }
                }
                _ => println!("Commands: {}", console_commands.join(" ")),
            }
        }
    }
}
<commit_msg>Add leak test for test.rs<commit_after>#![feature(asm)]

use std::Box;
use std::{io, rand};
use std::ptr;
use std::syscall::sys_fork;

macro_rules! readln {
    () => {
        {
            let mut line = String::new();
            match io::stdin().read_line(&mut line) {
                Ok(_) => Some(line.trim().to_string()),
                Err(_) => None
            }
        }
    };
}

fn console_title(title: &str){

}

#[no_mangle]
pub fn main() {
    console_title("Test");

    println!("Type help for a command list");
    while let Some(line) = readln!() {
        let args: Vec<String> = line.split(' ').map(|arg| arg.to_string()).collect();

        if let Some(a_command) = args.get(0) {
            println!("# {}", line);
            let console_commands = ["panic",
                                    "ls",
                                    "ptr_write",
                                    "box_write",
                                    "reboot",
                                    "shutdown",
                                    "fork",
                                    "leak_test"];

            match &a_command[..] {
                command if command == console_commands[0] =>
                    panic!("Test panic"),
                command if command == console_commands[1] => {
                    // TODO: import std::fs functions into libredox
                    //fs::read_dir("/").unwrap().map(|dir| println!("{}", dir));
                }
                command if command == console_commands[2] => {
                    let a_ptr = rand() as *mut u8;
                    unsafe { ptr::write(a_ptr, rand() as u8); }
                }
                command if command == console_commands[3] => {
                    let mut a_box = Box::new(rand() as u8);
                    unsafe { ptr::write(Box::into_raw(a_box), rand() as u8); }
                }
                command if command == console_commands[4] => {
                    unsafe {
                        let mut good: u8 = 2;
                        while good & 2 == 2 {
                            asm!("in al, dx" : "={al}"(good) : "{dx}"(0x64) : : "intel", "volatile");
                        }
                        asm!("out dx, al" : : "{dx}"(0x64), "{al}"(0xFE) : : "intel", "volatile");
                        loop {
                            asm!("cli" : : : : "intel", "volatile");
                            asm!("hlt" : : : : "intel", "volatile");
                        }
                    }
                }
                command if command == console_commands[5] => {
                    unsafe {
                        loop {
                            asm!("cli" : : : : "intel", "volatile");
                            asm!("hlt" : : : : "intel", "volatile");
                        }
                    }
                }
                command if command == console_commands[6] => {
                    unsafe {
                        if sys_fork() == 0 {
                            println!("Parent from fork");
                        } else {
                            println!("Child from fork");
                        }
                    }
                }
                command if command == console_commands[7] => {
                    let mut stack_it: Vec<Box<u8>> = Vec::new();
                    loop {
                        stack_it.push(Box::new(rand() as u8))
                    }
                }
                _ => println!("Commands: {}", console_commands.join(" ")),
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>add snapshot to the repo<commit_after>use std::collections::{HashMap, HashSet};
use std::io::{Read, Seek, Write};

#[cfg(feature = "zstd")]
use zstd::block::{compress, decompress};

use super::*;

/// A snapshot of the state required to quickly restart
/// the `PageCache` and `SegmentAccountant`.
/// TODO consider splitting `Snapshot` into separate
/// snapshots for PC, SA, Materializer.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Snapshot<R> {
    /// the last lsn included in the `Snapshot`
    pub max_lsn: Lsn,
    /// the last lid included in the `Snapshot`
    pub last_lid: LogID,
    /// the highest allocated pid
    pub max_pid: PageID,
    /// the mapping from pages to (lsn, lid)
    pub pt: HashMap<PageID, PageState>,
    /// replaced pages per segment index
    pub replacements: HashMap<SegmentID, HashSet<(PageID, Lsn)>>,
    /// the free pids
    pub free: HashSet<PageID>,
    /// the `Materializer`-specific recovered state
    pub recovery: Option<R>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum PageState {
    Present(Vec<(Lsn, LogID)>),
    Allocated(Lsn, LogID),
    Free(Lsn, LogID),
}

impl PageState {
    fn push(&mut self, item: (Lsn, LogID)) {
        match self {
            &mut PageState::Present(ref mut items) => items.push(item),
            &mut PageState::Allocated(_, _) => {
                *self = PageState::Present(vec![item])
            }
            &mut PageState::Free(_, _) => {
                panic!("pushed items to a PageState::Free")
            }
        }
    }

    /// Iterate over the (lsn, lid) pairs that hold this page's state.
    pub fn iter(&self) -> Box<Iterator<Item = (Lsn, LogID)>> {
        match self {
            &PageState::Present(ref items) => Box::new(
                items.clone().into_iter(),
            ),
            &PageState::Allocated(lsn, lid) |
            &PageState::Free(lsn, lid) => {
                Box::new(vec![(lsn, lid)].into_iter())
            }
        }
    }
}

impl<R> Default for Snapshot<R> {
    fn default() -> Snapshot<R> {
        Snapshot {
            max_lsn: 0,
            last_lid: 0,
            max_pid: 0,
            pt: HashMap::new(),
            replacements: HashMap::new(),
            free: HashSet::new(),
            recovery: None,
        }
    }
}

impl<R> Snapshot<R> {
    fn apply<P>(
        &mut self,
        materializer: &Materializer<PageFrag = P, Recovery = R>,
        lsn: Lsn,
        log_id: LogID,
        bytes: &[u8],
        io_buf_size: usize,
    )
        where P: 'static
                     + Debug
                     + Clone
                     + Serialize
                     + DeserializeOwned
                     + Send
                     + Sync,
              R: Debug + Clone + Serialize + DeserializeOwned + Send
    {
        // unwrapping this because it's already passed the crc check
        // in the log iterator
        trace!("trying to deserialize buf for lid {} lsn {}", log_id, lsn);
        let deserialization = deserialize::<LoggedUpdate<P>>(&*bytes);

        if let Err(e) = deserialization {
            error!(
                "failed to deserialize buffer for item in log: lsn {} \
                    lid {}: {:?}",
                lsn,
                log_id,
                e
            );
            return;
        }

        let prepend = deserialization.unwrap();
        let pid = prepend.pid;

        if pid >= self.max_pid {
            self.max_pid = pid + 1;
        }

        let replaced_at_idx = log_id as SegmentID / io_buf_size;

        match prepend.update {
            Update::Append(partial_page) => {
                // Because we rewrite pages over time, we may have relocated
                // a page's initial Compact to a later segment. We should skip
                // over pages here unless we've encountered a Compact for them.
                if let Some(lids) = self.pt.get_mut(&pid) {
                    trace!(
                        "append of pid {} at lid {} lsn {}",
                        pid,
                        log_id,
                        lsn
                    );

                    if let Some(r) = materializer.recover(&partial_page) {
                        self.recovery = Some(r);
                    }

                    lids.push((lsn, log_id));
                }
                self.free.remove(&pid);
            }
            Update::Compact(partial_page) => {
                trace!("compact of pid {} at lid {} lsn {}", pid, log_id, lsn);
                if let Some(r) = materializer.recover(&partial_page) {
                    self.recovery = Some(r);
                }

                self.replace_pid(pid, replaced_at_idx, lsn, io_buf_size);
                self.pt.insert(pid, PageState::Present(vec![(lsn, log_id)]));
                self.free.remove(&pid);
            }
            Update::Allocate => {
                trace!(
                    "allocate  of pid {} at lid {} lsn {}",
                    pid,
                    log_id,
                    lsn
                );
                self.replace_pid(pid, replaced_at_idx, lsn, io_buf_size);
                self.pt.insert(pid, PageState::Allocated(lsn, log_id));
                self.free.remove(&pid);
            }
            Update::Free => {
                trace!("free of pid {} at lid {} lsn {}", pid, log_id, lsn);
                self.replace_pid(pid, replaced_at_idx, lsn, io_buf_size);
                self.pt.insert(pid, PageState::Free(lsn, log_id));
                self.free.insert(pid);
            }
        }
    }

    fn replace_pid(
        &mut self,
        pid: PageID,
        replaced_at_idx: usize,
        replaced_at_lsn: Lsn,
        io_buf_size: usize,
    ) {
        match self.pt.remove(&pid) {
            Some(PageState::Present(coords)) => {
                for (_lsn, lid) in coords {
                    let idx = lid as SegmentID / io_buf_size;
                    if replaced_at_idx == idx {
                        return;
                    }
                    let entry =
                        self.replacements.entry(idx).or_insert(HashSet::new());
                    entry.insert((pid, replaced_at_lsn));
                }
            }
            Some(PageState::Allocated(_lsn, lid)) |
            Some(PageState::Free(_lsn, lid)) => {

                let idx = lid as SegmentID / io_buf_size;
                if replaced_at_idx == idx {
                    return;
                }
                let entry =
                    self.replacements.entry(idx).or_insert(HashSet::new());
                entry.insert((pid, replaced_at_lsn));
            }
            None => {}
        }
    }
}

pub(super) fn advance_snapshot<PM, P, R>(
    iter: LogIter,
    mut snapshot: Snapshot<R>,
    config: &FinalConfig,
) -> Snapshot<R>
    where PM: Materializer<Recovery = R, PageFrag = P>,
          P: 'static
                 + Debug
                 + Clone
                 + Serialize
                 + DeserializeOwned
                 + Send
                 + Sync,
          R: Debug + Clone + Serialize + DeserializeOwned + Send
{
    let start = clock();

    trace!("building on top of old snapshot: {:?}", snapshot);

    let materializer = PM::new(&snapshot.recovery);

    let io_buf_size = config.get_io_buf_size();

    for (lsn, log_id, bytes) in iter {
        let segment_idx = log_id as SegmentID / io_buf_size;

        trace!(
            "in advance_snapshot looking at item with lsn {} lid {}",
            lsn,
            log_id
        );

        if lsn <= snapshot.max_lsn {
            // don't process already-processed Lsn's. max_lsn is for the last
            // item ALREADY INCLUDED lsn in the snapshot.
            trace!(
                "continuing in advance_snapshot, lsn {} log_id {} max_lsn {}",
                lsn,
                log_id,
                snapshot.max_lsn
            );
            continue;
        }

        assert!(lsn > snapshot.max_lsn);
        snapshot.max_lsn = lsn;
        snapshot.last_lid = log_id;

        // invalidate any removed pids
        snapshot.replacements.remove(&segment_idx);

        if !PM::is_null() {
            snapshot.apply(&materializer, lsn, log_id, &*bytes, io_buf_size);
        }
    }

    write_snapshot(config, &snapshot);

    trace!("generated new snapshot: {:?}", snapshot);

    M.advance_snapshot.measure(clock() - start);

    snapshot
}

/// Read a `Snapshot` or generate a default, then advance it to
/// the tip of the data file, if present.
pub fn read_snapshot_or_default<PM, P, R>(config: &FinalConfig) -> Snapshot<R>
    where PM: Materializer<Recovery = R, PageFrag = P>,
          P: 'static
                 + Debug
                 + Clone
                 + Serialize
                 + DeserializeOwned
                 + Send
                 + Sync,
          R: Debug + Clone + Serialize + DeserializeOwned + Send
{
    let last_snap = read_snapshot(config).unwrap_or_else(Snapshot::default);

    let log_iter = raw_segment_iter_from(last_snap.max_lsn, config);

    advance_snapshot::<PM, P, R>(log_iter, last_snap, config)
}

/// Read a `Snapshot` from disk.
fn read_snapshot<R>(config: &FinalConfig) -> Option<Snapshot<R>>
    where R: Debug + Clone + Serialize + DeserializeOwned + Send
{
    let mut candidates = config.get_snapshot_files();
    if candidates.is_empty() {
        info!("no previous snapshot found");
        return None;
    }

    candidates.sort();

    let path = candidates.pop().unwrap();

    let mut f = std::fs::OpenOptions::new().read(true).open(&path).unwrap();
    if f.metadata().unwrap().len() <= 16 {
        warn!("empty/corrupt snapshot file found");
        return None;
    }

    let mut buf = vec![];
    f.read_to_end(&mut buf).unwrap();
    let len = buf.len();
    buf.split_off(len - 16);

    let mut len_expected_bytes = [0u8; 8];
    f.seek(std::io::SeekFrom::End(-16)).unwrap();
    f.read_exact(&mut len_expected_bytes).unwrap();

    let mut crc_expected_bytes = [0u8; 8];
    f.seek(std::io::SeekFrom::End(-8)).unwrap();
    f.read_exact(&mut crc_expected_bytes).unwrap();
    let crc_expected: u64 = unsafe { std::mem::transmute(crc_expected_bytes) };

    let crc_actual = crc64(&*buf);

    if crc_expected != crc_actual {
        error!("crc for snapshot file {:?} failed!", path);
        return None;
    }

    #[cfg(feature = "zstd")]
    let bytes = if config.get_use_compression() {
        let len_expected: u64 =
            unsafe { std::mem::transmute(len_expected_bytes) };
        decompress(&*buf, len_expected as usize).unwrap()
    } else {
        buf
    };

    #[cfg(not(feature = "zstd"))]
    let bytes = buf;

    deserialize::<Snapshot<R>>(&*bytes).ok()
}

pub fn write_snapshot<R>(config: &FinalConfig, snapshot: &Snapshot<R>)
    where R: Debug + Clone + Serialize + DeserializeOwned + Send
{
    let raw_bytes = serialize(&snapshot, Infinite).unwrap();
    let decompressed_len = raw_bytes.len();

    #[cfg(feature = "zstd")]
    let bytes = if config.get_use_compression() {
        compress(&*raw_bytes, config.get_zstd_compression_factor()).unwrap()
    } else {
        raw_bytes
    };

    #[cfg(not(feature = "zstd"))]
    let bytes = raw_bytes;

    let crc64: [u8; 8] = unsafe { std::mem::transmute(crc64(&*bytes)) };
    let len_bytes: [u8; 8] =
        unsafe { std::mem::transmute(decompressed_len as u64) };

    let path_1_suffix = format!(".snap.{:016X}.in___motion", snapshot.max_lsn);

    let mut path_1 = config.snapshot_prefix();
    path_1.push(path_1_suffix);

    let path_2_suffix = format!(".snap.{:016X}", snapshot.max_lsn);

    let mut path_2 = config.snapshot_prefix();
    path_2.push(path_2_suffix);

    let mut f = std::fs::OpenOptions::new()
        .write(true)
        .create(true)
        .open(&path_1)
        .unwrap();

    // write the snapshot bytes, followed by a crc64 checksum at the end
    f.write_all(&*bytes).unwrap();
    f.write_all(&len_bytes).unwrap();
    f.write_all(&crc64).unwrap();
    f.sync_all().unwrap();
    drop(f);

    trace!("wrote snapshot to {}", path_1.to_string_lossy());

    std::fs::rename(path_1, &path_2).expect("failed to write snapshot");

    trace!("renamed snapshot to {}", path_2.to_string_lossy());

    // clean up any old snapshots
    let candidates = config.get_snapshot_files();
    for path in candidates {
        let path_str = path.file_name().unwrap().to_str().unwrap();
        if !path_2.to_string_lossy().ends_with(&*path_str) {
            debug!("removing old snapshot file {:?}", path);

            if let Err(_e) = std::fs::remove_file(&path) {
                warn!(
                    "failed to remove old snapshot file, maybe snapshot race? {}",
                    _e
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 LinkerFlavor;
use super::{LinkArgs, Target, TargetOptions};
use super::emscripten_base::{cmd};

pub fn target() -> Result<Target, String> {
    let mut post_link_args = LinkArgs::new();
    post_link_args.insert(LinkerFlavor::Gcc,
                          vec!["-s".to_string(),
                               "BINARYEN=1".to_string(),
                               "-s".to_string(),
                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);

    let opts = TargetOptions {
        linker: cmd("emcc"),
        ar: cmd("emar"),

        dynamic_linking: false,
        executables: true,
        // Today emcc emits two files - a .js file to bootstrap and
        // possibly interpret the wasm, and a .wasm file
        exe_suffix: ".js".to_string(),
        linker_is_gnu: true,
        allow_asm: false,
        obj_is_bitcode: true,
        is_like_emscripten: true,
        max_atomic_width: Some(32),
        post_link_args: post_link_args,
        target_family: Some("unix".to_string()),
        .. Default::default()
    };
    Ok(Target {
        llvm_target: "asmjs-unknown-emscripten".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_os: "emscripten".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
        arch: "wasm32".to_string(),
        linker_flavor: LinkerFlavor::Em,
        options: opts,
    })
}
<commit_msg>Compile WASM as WASM instead of asm.js<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 LinkerFlavor;
use super::{LinkArgs, Target, TargetOptions};
use super::emscripten_base::{cmd};

pub fn target() -> Result<Target, String> {
    let mut post_link_args = LinkArgs::new();
    post_link_args.insert(LinkerFlavor::Em,
                          vec!["-s".to_string(),
                               "BINARYEN=1".to_string(),
                               "-s".to_string(),
                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);

    let opts = TargetOptions {
        linker: cmd("emcc"),
        ar: cmd("emar"),

        dynamic_linking: false,
        executables: true,
        // Today emcc emits two files - a .js file to bootstrap and
        // possibly interpret the wasm, and a .wasm file
        exe_suffix: ".js".to_string(),
        linker_is_gnu: true,
        allow_asm: false,
        obj_is_bitcode: true,
        is_like_emscripten: true,
        max_atomic_width: Some(32),
        post_link_args: post_link_args,
        target_family: Some("unix".to_string()),
        .. Default::default()
    };
    Ok(Target {
        llvm_target: "asmjs-unknown-emscripten".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_os: "emscripten".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
        arch: "wasm32".to_string(),
        linker_flavor: LinkerFlavor::Em,
        options: opts,
    })
}
<|endoftext|>


<commit_before><commit_msg>Adds wip integration tests.<commit_after>use std::env;
use std::process::Command;

#[derive(Debug)]
pub struct NiceOutput {
    pub status: i32,
    pub stdout: String,
    pub stderr: String,
}

fn run(args: Vec<&str>) -> NiceOutput {
    let mut directory = env::current_exe().unwrap();
            directory.pop(); // chop off exe name but leave "debug"
    let name = format!("to{}", env::consts::EXE_SUFFIX);
    let binary = directory.join(&name);

    let mut command = Command::new(binary);
            command.args(&args);
    let output = command.output().unwrap();

    return NiceOutput {
        status: output.status.code().unwrap(),
        stdout: String::from_utf8(output.stdout).unwrap(),
        stderr: String::from_utf8(output.stderr).unwrap(),
    };
}

#[test]
fn smoke_test() {
    let result = run(vec!["-h"]);
    assert_eq!(result.status, 0);
}
<|endoftext|>


<commit_before>//! IO

use {fmt, str};
use string::String;
use vec::{IntoIter, Vec};
pub use system::error::Error;
use system::syscall::{sys_read, sys_write};

pub mod prelude;

pub type Result<T> = ::core::result::Result<T, Error>;

/// Types you can read
pub trait Read {
    /// Read a file to a buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

    /// Read the file to the end
    fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    vec.push_all(&bytes[0..count]);
                    read += count;
                }
            }
        }
    }

    /// Read the file to a string
    fn read_to_string(&mut self, string: &mut String) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    string.push_str(unsafe { &str::from_utf8_unchecked(&bytes[0..count]) });
                    read += count;
                }
            }
        }
    }

    /// Return an iterator of the bytes
    fn bytes(&mut self) -> IntoIter<u8> {
        // TODO: This is only a temporary implementation. Make this read one byte at a time.
        let mut buf = Vec::new();
        let _ = self.read_to_end(&mut buf);

        buf.into_iter()
    }
}

/// Types you can write
pub trait Write {
    /// Write to the file
    fn write(&mut self, buf: &[u8]) -> Result<usize>;

    /// Write a format to the file
    fn write_fmt(&mut self, args: fmt::Arguments) -> Result<()> {
        match self.write(fmt::format(args).as_bytes()) {
            Ok(_) => Ok(()),
            Err(err) => Err(err),
        }
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

/// Seek Location
pub enum SeekFrom {
    /// The start point
    Start(u64),
    /// The current point
    Current(i64),
    /// The end point
    End(i64),
}

pub trait Seek {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
}

pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64> where R: Read, W: Write {
    let mut copied = 0;
    loop {
        let mut bytes = [0; 4096];
        match reader.read(&mut bytes) {
            Ok(0) => return Ok(copied),
            Err(err) => return Err(err),
            Ok(count) => match writer.write(&bytes[0 .. count]){
                Ok(0) => return Ok(copied),
                Err(err) => return Err(err),
                Ok(count) => copied += count as u64
            }
        }
    }
}

/// Standard Input
pub struct Stdin;

/// Create a standard input
pub fn stdin() -> Stdin {
    Stdin
}

impl Stdin {
    pub fn read_line(&mut self, string: &mut String) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    string.push_str(unsafe { &str::from_utf8_unchecked(&bytes[0..count]) });
                    read += count;
                }
            }
        }
    }
}

/// Read implementation for standard input
impl Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        Error::demux(unsafe { sys_read(0, buf.as_mut_ptr(), buf.len()) })
    }
}

/// Standard Output
pub struct Stdout;

/// Create a standard output
pub fn stdout() -> Stdout {
    Stdout
}

/// Write implementation for standard output
impl Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        Error::demux(unsafe { sys_write(1, buf.as_ptr(), buf.len()) })
    }
}

/// Standard Error
pub struct Stderr;

/// Create a standard error
pub fn stderr() -> Stderr {
    Stderr
}

/// Write implementation for standard error
impl Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        Error::demux(unsafe { sys_write(2, buf.as_ptr(), buf.len()) })
    }
}

#[allow(unused_must_use)]
pub fn _print(args: fmt::Arguments) {
    stdout().write_fmt(args);
}
<commit_msg>Compatibility with libstd's Bytes iterator<commit_after>//! IO

use {fmt, str};
use string::String;
use vec::Vec;
pub use system::error::Error;
use system::syscall::{sys_read, sys_write};

pub mod prelude;

pub type Result<T> = ::core::result::Result<T, Error>;

pub struct Bytes<R: Read> {
    reader: R,
}

impl<R: Read> Iterator for Bytes<R> {
    type Item = Result<u8>;

    fn next(&mut self) -> Option<Result<u8>> {
        let mut byte = [4];
        if let Ok(1) = self.reader.read(&mut byte) {
            if byte[0] == 4 {
                None
            } else {
                Some(Ok(byte[0]))
            }
        } else {
            None
        }
    }
}

/// Types you can read
pub trait Read {
    /// Read a file to a buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

    /// Read the file to the end
    fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    vec.push_all(&bytes[0..count]);
                    read += count;
                }
            }
        }
    }

    /// Read the file to a string
    fn read_to_string(&mut self, string: &mut String) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    string.push_str(unsafe { &str::from_utf8_unchecked(&bytes[0..count]) });
                    read += count;
                }
            }
        }
    }

    /// Return an iterator of the bytes
    fn bytes(self) -> Bytes<Self> where Self: Sized {
        Bytes {
            reader: self,
        }
    }
}

/// Types you can write
pub trait Write {
    /// Write to the file
    fn write(&mut self, buf: &[u8]) -> Result<usize>;

    /// Write a format to the file
    fn write_fmt(&mut self, args: fmt::Arguments) -> Result<()> {
        match self.write(fmt::format(args).as_bytes()) {
            Ok(_) => Ok(()),
            Err(err) => Err(err),
        }
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

/// Seek Location
pub enum SeekFrom {
    /// The start point
    Start(u64),
    /// The current point
    Current(i64),
    /// The end point
    End(i64),
}

pub trait Seek {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
}

pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64> where R: Read, W: Write {
    let mut copied = 0;
    loop {
        let mut bytes = [0; 4096];
        match reader.read(&mut bytes) {
            Ok(0) => return Ok(copied),
            Err(err) => return Err(err),
            Ok(count) => match writer.write(&bytes[0 .. count]){
                Ok(0) => return Ok(copied),
                Err(err) => return Err(err),
                Ok(count) => copied += count as u64
            }
        }
    }
}

/// Standard Input
pub struct Stdin;

/// Create a standard input
pub fn stdin() -> Stdin {
    Stdin
}

impl Stdin {
    pub fn read_line(&mut self, string: &mut String) -> Result<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 4096];
            match self.read(&mut bytes) {
                Ok(0) => return Ok(read),
                Err(err) => return Err(err),
                Ok(count) => {
                    string.push_str(unsafe { &str::from_utf8_unchecked(&bytes[0..count]) });
                    read += count;
                }
            }
        }
    }
}

/// Read implementation for standard input
impl Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        Error::demux(unsafe { sys_read(0, buf.as_mut_ptr(), buf.len()) })
    }
}

/// Standard Output
pub struct Stdout;

/// Create a standard output
pub fn stdout() -> Stdout {
    Stdout
}

/// Write implementation for standard output
impl Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        Error::demux(unsafe { sys_write(1, buf.as_ptr(), buf.len()) })
    }
}

/// Standard Error
pub struct Stderr;

/// Create a standard error
pub fn stderr() -> Stderr {
    Stderr
}

/// Write implementation for standard error
impl Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        Error::demux(unsafe { sys_write(2, buf.as_ptr(), buf.len()) })
    }
}

#[allow(unused_must_use)]
pub fn _print(args: fmt::Arguments) {
    stdout().write_fmt(args);
}
<|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::InheritTypes::{DocumentFragmentDerived, NodeCast};
use dom::bindings::codegen::Bindings::DocumentFragmentBinding;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::Fallible;
use dom::document::Document;
use dom::element::Element;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlcollection::HTMLCollection;
use dom::node::{DocumentFragmentNodeTypeId, Node, window_from_node};
use dom::window::{Window, WindowMethods};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct DocumentFragment {
    pub node: Node,
}

impl DocumentFragmentDerived for EventTarget {
    fn is_documentfragment(&self) -> bool {
        self.type_id == NodeTargetTypeId(DocumentFragmentNodeTypeId)
    }
}

impl DocumentFragment {
    /// Creates a new DocumentFragment.
    pub fn new_inherited(document: &JSRef<Document>) -> DocumentFragment {
        DocumentFragment {
            node: Node::new_inherited(DocumentFragmentNodeTypeId, document),
        }
    }

    pub fn new(document: &JSRef<Document>) -> Temporary<DocumentFragment> {
        let node = DocumentFragment::new_inherited(document);
        Node::reflect_node(box node, document, DocumentFragmentBinding::Wrap)
    }

    pub fn Constructor(owner: &JSRef<Window>) -> Fallible<Temporary<DocumentFragment>> {
        let document = owner.Document();
        let document = document.root();

        Ok(DocumentFragment::new(&document.root_ref()))
    }
}

pub trait DocumentFragmentMethods {
    fn Children(&self) -> Temporary<HTMLCollection>;
    fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
}

impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> {
    fn Children(&self) -> Temporary<HTMLCollection> {
        let window = window_from_node(self).root();
        HTMLCollection::children(&window.root_ref(), NodeCast::from_ref(self))
    }

    fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> {
        Ok(None)
    }
}
<commit_msg>Implement querySelector for DocumentFragment<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::InheritTypes::{DocumentFragmentDerived, NodeCast};
use dom::bindings::codegen::Bindings::DocumentFragmentBinding;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::Fallible;
use dom::document::Document;
use dom::element::Element;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlcollection::HTMLCollection;
use dom::node::{DocumentFragmentNodeTypeId, Node, NodeHelpers, window_from_node};
use dom::window::{Window, WindowMethods};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct DocumentFragment {
    pub node: Node,
}

impl DocumentFragmentDerived for EventTarget {
    fn is_documentfragment(&self) -> bool {
        self.type_id == NodeTargetTypeId(DocumentFragmentNodeTypeId)
    }
}

impl DocumentFragment {
    /// Creates a new DocumentFragment.
    pub fn new_inherited(document: &JSRef<Document>) -> DocumentFragment {
        DocumentFragment {
            node: Node::new_inherited(DocumentFragmentNodeTypeId, document),
        }
    }

    pub fn new(document: &JSRef<Document>) -> Temporary<DocumentFragment> {
        let node = DocumentFragment::new_inherited(document);
        Node::reflect_node(box node, document, DocumentFragmentBinding::Wrap)
    }

    pub fn Constructor(owner: &JSRef<Window>) -> Fallible<Temporary<DocumentFragment>> {
        let document = owner.Document();
        let document = document.root();

        Ok(DocumentFragment::new(&document.root_ref()))
    }
}

pub trait DocumentFragmentMethods {
    fn Children(&self) -> Temporary<HTMLCollection>;
    fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>>;
}

impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> {
    // http://dom.spec.whatwg.org/#dom-parentnode-children
    fn Children(&self) -> Temporary<HTMLCollection> {
        let window = window_from_node(self).root();
        HTMLCollection::children(&window.root_ref(), NodeCast::from_ref(self))
    }

    // http://dom.spec.whatwg.org/#dom-parentnode-queryselector
    fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> {
        let root: &JSRef<Node> = NodeCast::from_ref(self);
        root.query_selector(selectors)
    }
}
<|endoftext|>


<commit_before><commit_msg>Added helper to create Vec with a given sizewq<commit_after>use super::operation::DeleteOperation;
use std::sync::{Arc, RwLock};
use std::mem;
use std::ops::DerefMut;

#[derive(Clone, Default)]
struct DeleteQueue {
    writer: Arc<RwLock<Vec<DeleteOperation>>>,
    next_block: Option<NextBlock>,
}

impl DeleteQueue {

    pub fn new() -> Arc<DeleteQueue> {
        let mut delete_queue = Arc::new(DeleteQueue::default());
        delete_queue.next_block = Some(
            NextBlock::from(delete_queue)
        );
        delete_queue
    }

    pub fn cursor(&self) -> Cursor {

        Cursor {
            current_block: Arc<Block>,
            pos: 0,
        }
    }

    pub fn push(&self, delete_operation: DeleteOperation) {
        let mut write_lock = self.writer
            .write()
            .expect("Failed to acquire write lock on delete queue writer")
            .push(delete_operation);
    }

    fn flush(&self) -> Option<Vec<DeleteOperation>> {
        let mut write_lock = self
            .writer
            .write()
            .expect("Failed to acquire write lock on delete queue writer");
        if write_lock.is_empty() {
            return None;
        }
        Some(mem::replace(write_lock.deref_mut(), vec!()))
    }
}

enum InnerNextBlock {
    Writer(Arc<DeleteQueue>),
    Closed(Arc<Block>),
    Terminated,
}

struct NextBlock(RwLock<InnerNextBlock>);

impl From<Arc<DeleteQueue>> for NextBlock {
    fn from(writer_arc: Arc<DeleteQueue>) -> NextBlock {
        NextBlock(RwLock::new(InnerNextBlock::Writer(writer_arc)))
    }
}

impl NextBlock {
    pub fn next_block(&self) -> Option<Arc<Block>> {
        {
            let next_read_lock = self.0
                .read()
                .expect("Failed to acquire write lock in delete queue");
            match *next_read_lock {
                InnerNextBlock::Terminated => {
                    return None;
                }
                InnerNextBlock::Closed(ref block) => {
                    return Some(block.clone());
                }
                _ => {}
            }
        }
        let delete_operations;
        let writer_arc;
        {
            let mut next_write_lock = self.0
                .write()
                .expect("Failed to acquire write lock in delete queue");
            match *next_write_lock {
                InnerNextBlock::Terminated => {
                    return None;
                }
                InnerNextBlock::Closed(ref block) => {
                    return Some(block.clone());
                }
                InnerNextBlock::Writer(ref writer) => {
                    match writer.flush() {
                        Some(flushed_delete_operations) => {
                            delete_operations = flushed_delete_operations;
                        }
                        None => {
                            return None;
                        }
                    }
                    writer_arc = writer.clone();
                }
            }
            let next_block = Arc::new(Block {
                operations: Arc::new(delete_operations),
                next: NextBlock::from(writer_arc),
            });
            *next_write_lock.deref_mut() = InnerNextBlock::Closed(next_block.clone()); // TODO fix
            return Some(next_block)
        }
    }
}

struct Block {
    operations: Arc<Vec<DeleteOperation>>,
    next: NextBlock,
}

#[derive(Clone)]
struct Cursor {
    current_block: Arc<Block>,
    pos: usize,
}

impl Cursor {
    fn next<'a>(&'a mut self) -> Option<&'a DeleteOperation> {
        if self.pos >= self.current_block.operations.len() {
            // we have consumed our operations entirely.
            // let's ask our writer if he has more for us.
            // self.go_next_block();
            match self.current_block.next.next_block() {
                Some(block) => {
                    self.current_block = block;
                    self.pos = 0;
                }
                None => {
                    return None;
                }
            }
        }
        let operation = &self.current_block.operations[self.pos];
        self.pos += 1;
        return Some(operation);
    }
}

#[cfg(test)]
mod tests {

    use super::{DeleteQueue, DeleteOperation};
    use schema::{Term, Field};

    #[test]
    fn test_deletequeue() {
        let delete_queue = DeleteQueue::new();

        let make_op = |i: usize| {
            let field = Field(1u8);
            DeleteOperation {
                opstamp: i as u64,
                term: Term::from_field_u32(field, i as u32)
            }
        };

        delete_queue.push(make_op(1));
        delete_queue.push(make_op(2));

        let snapshot = delete_queue.cursor();
        {
            let mut operations_it = snapshot.clone();
            assert_eq!(operations_it.next().unwrap().opstamp, 1);
            assert_eq!(operations_it.next().unwrap().opstamp, 2);
            assert!(operations_it.next().is_none());
        }
        {
            let mut operations_it = snapshot.clone();
            assert_eq!(operations_it.next().unwrap().opstamp, 1);
            assert_eq!(operations_it.next().unwrap().opstamp, 2);
            assert!(operations_it.next().is_none());
        }

        // // operations does not own a lock on the queue.
        // delete_queue.push(make_op(3));
        // let snapshot2 = delete_queue.snapshot();
        // {
        //     // operations is not affected by
        //     // the push that occurs after.
        //     let mut operations_it = snapshot.iter();
        //     let mut operations2_it = snapshot2.iter();
        //     assert_eq!(operations_it.next().unwrap().opstamp, 1);
        //     assert_eq!(operations2_it.next().unwrap().opstamp, 1);
        //     assert_eq!(operations_it.next().unwrap().opstamp, 2);
        //     assert_eq!(operations2_it.next().unwrap().opstamp, 2);
        //     assert!(operations_it.next().is_none());
        //     assert_eq!(operations2_it.next().unwrap().opstamp, 3);
        //     assert!(operations2_it.next().is_none());
        // }
    }
}<|endoftext|>


<commit_before><commit_msg>Adds Rust solution for #005<commit_after><|endoftext|>


<commit_before><commit_msg>Wednesday Algorithms.<commit_after><|endoftext|>


<commit_before>use alloc::boxed::Box;

use core::cmp;

use common::event::{KeyEvent, MouseEvent};

use drivers::pio::*;

use schemes::KScheme;

/// PS2
pub struct Ps2 {
    /// The data
    data: Pio8,
    /// The command
    cmd: Pio8,
    /// Left shift?
    lshift: bool,
    /// Right shift?
    rshift: bool,
    /// Caps lock?
    caps_lock: bool,
    /// Caps lock toggle
    caps_lock_toggle: bool,
    /// The mouse packet
    mouse_packet: [u8; 4],
    /// Mouse packet index
    mouse_i: usize,
    /// Mouse point x
    mouse_x: isize,
    /// Mouse point y
    mouse_y: isize,
    /// Layout for keyboard
    layout: usize,
}

impl Ps2 {
    /// Create new PS2 data
    pub fn new() -> Box<Self> {
        let mut module = box Ps2 {
            data: Pio8::new(0x60),
            cmd: Pio8::new(0x64),
            lshift: false,
            rshift: false,
            caps_lock: false,
            caps_lock_toggle: false,
            mouse_packet: [0; 4],
            mouse_i: 0,
            mouse_x: 0,
            mouse_y: 0,
            layout: 0,
        };

        unsafe {
            module.keyboard_init();
            module.mouse_init();
        }

        module
    }

    unsafe fn wait0(&self) {
        while (self.cmd.read() & 1) == 0 {}
    }

    unsafe fn wait1(&self) {
        while (self.cmd.read() & 2) == 2 {}
    }

    unsafe fn keyboard_init(&mut self) {
        while (self.cmd.read() & 0x1) == 1 {
            self.data.read();
        }

        self.wait1();
        self.cmd.write(0x20);
        self.wait0();
        let flags = (self.data.read() & 0b00110111) | 1 | 0b10000;
        self.wait1();
        self.cmd.write(0x60);
        self.wait1();
        self.data.write(flags);

        // Set Defaults
        self.wait1();
        self.data.write(0xF6);
        self.wait0();
        self.data.read();

        // Set LEDS
        self.wait1();
        self.data.write(0xED);
        self.wait0();
        self.data.read();

        self.wait1();
        self.data.write(0);
        self.wait0();
        self.data.read();

        // Set Scancode Map:
        self.wait1();
        self.data.write(0xF0);
        self.wait0();
        self.data.read();

        self.wait1();
        self.data.write(1);
        self.wait0();
        self.data.read();
    }

    /// Keyboard interrupt
    pub fn keyboard_interrupt(&mut self) -> Option<KeyEvent> {
        let scancode = unsafe { self.data.read() };

        if scancode == 0 {
            return None;
        } else if scancode == 0x2A {
            self.lshift = true;
        } else if scancode == 0xAA {
            self.lshift = false;
        } else if scancode == 0x36 {
            self.rshift = true;
        } else if scancode == 0xB6 {
            self.rshift = false;
        } else if scancode == 0x3A {
            if !self.caps_lock {
                self.caps_lock = true;
                self.caps_lock_toggle = true;
            } else {
                self.caps_lock_toggle = false;
            }
        } else if scancode == 0xBA {
            if self.caps_lock && !self.caps_lock_toggle {
                self.caps_lock = false;
            }
        }

        let shift;
        if self.caps_lock {
            shift = !(self.lshift || self.rshift);
        } else {
            shift = self.lshift || self.rshift;
        }

        return Some(KeyEvent {
            character: char_for_scancode(scancode & 0x7F, shift, self.layout),
            scancode: scancode & 0x7F,
            pressed: scancode < 0x80,
        });
    }

    unsafe fn mouse_cmd(&mut self, byte: u8) -> u8 {
        self.wait1();
        self.cmd.write(0xD4);
        self.wait1();
        self.data.write(byte);

        self.wait0();
        self.data.read()
    }

    /// Initialize mouse
    pub unsafe fn mouse_init(&mut self) {
        // The Init Dance
        self.wait1();
        self.cmd.write(0xA8);

        self.wait1();
        self.cmd.write(0x20);
        self.wait0();
        let status = self.data.read() | 2;
        self.wait1();
        self.cmd.write(0x60);
        self.wait1();
        self.data.write(status);

        // Set defaults
        self.mouse_cmd(0xF6);

        // Enable Streaming
        self.mouse_cmd(0xF4);
    }

    /// Mouse interrupt
    pub fn mouse_interrupt(&mut self) -> Option<MouseEvent> {
        let byte = unsafe { self.data.read() };
        if self.mouse_i == 0 {
            if byte & 0x8 == 0x8 {
                self.mouse_packet[0] = byte;
                self.mouse_i += 1;
            }
        } else if self.mouse_i == 1 {
            self.mouse_packet[1] = byte;

            self.mouse_i += 1;
        } else {
            self.mouse_packet[2] = byte;

            let left_button = (self.mouse_packet[0] & 1) == 1;
            let right_button = (self.mouse_packet[0] & 2) == 2;
            let middle_button = (self.mouse_packet[0] & 4) == 4;

            let x;
            if (self.mouse_packet[0] & 0x40) != 0x40 && self.mouse_packet[1] != 0 {
                x = self.mouse_packet[1] as isize -
                    (((self.mouse_packet[0] as isize) << 4) & 0x100);
            } else {
                x = 0;
            }

            let y;
            if (self.mouse_packet[0] & 0x80) != 0x80 && self.mouse_packet[2] != 0 {
                y = (((self.mouse_packet[0] as isize) << 3) & 0x100) -
                    self.mouse_packet[2] as isize;
            } else {
                y = 0;
            }

            unsafe {
                self.mouse_x = cmp::max(0,
                                        cmp::min((*::console).display.width as isize,
                                                 self.mouse_x + x));
                self.mouse_y = cmp::max(0,
                                        cmp::min((*::console).display.height as isize,
                                                 self.mouse_y + y));
            }

            self.mouse_i = 0;

            return Some(MouseEvent {
                x: self.mouse_x,
                y: self.mouse_y,
                left_button: left_button,
                right_button: right_button,
                middle_button: middle_button,
            });
        }

        return None;
    }

    /// Function to change the layout of the keyboard
    pub fn change_layout(&mut self, layout: usize) {
        self.layout = layout;
    }

}

impl KScheme for Ps2 {
    fn on_irq(&mut self, irq: u8) {
        if irq == 0x1 || irq == 0xC {
            self.on_poll();
        }
    }

    fn on_poll(&mut self) {
        loop {
            let status = unsafe { self.cmd.read() };
            if status & 0x21 == 1 {
                if let Some(key_event) = self.keyboard_interrupt() {
                    key_event.trigger();
                }
            } else if status & 0x21 == 0x21 {
                if let Some(mouse_event) = self.mouse_interrupt() {
                    mouse_event.trigger();
                }
            } else {
                break;
            }
        }
    }
}

/// Function to return the character associated with the scancode, and the layout
fn char_for_scancode(scancode: u8, shift: bool, layout: usize) -> char {
    if scancode >= 58 {
        '\x00'
    }
    let character =
        match layout {
            0 => SCANCODES_EN[scancode as usize],
            1 => SCANCODES_FR[scancode as usize],
        };
    if shift {
        character = characters[1]
    } else {
        character = characters[scancode as usize][0]
    }
}

static SCANCODES: [[char; 2]; 58] = [['\0', '\0'],
                                     ['\x1B', '\x1B'],
                                     ['1', '!'],
                                     ['2', '@'],
                                     ['3', '#'],
                                     ['4', '$'],
                                     ['5', '%'],
                                     ['6', '^'],
                                     ['7', '&'],
                                     ['8', '*'],
                                     ['9', '('],
                                     ['0', ')'],
                                     ['-', '_'],
                                     ['=', '+'],
                                     ['\0', '\0'],
                                     ['\t', '\t'],
                                     ['q', 'Q'],
                                     ['w', 'W'],
                                     ['e', 'E'],
                                     ['r', 'R'],
                                     ['t', 'T'],
                                     ['y', 'Y'],
                                     ['u', 'U'],
                                     ['i', 'I'],
                                     ['o', 'O'],
                                     ['p', 'P'],
                                     ['[', '{'],
                                     [']', '}'],
                                     ['\n', '\n'],
                                     ['\0', '\0'],
                                     ['a', 'A'],
                                     ['s', 'S'],
                                     ['d', 'D'],
                                     ['f', 'F'],
                                     ['g', 'G'],
                                     ['h', 'H'],
                                     ['j', 'J'],
                                     ['k', 'K'],
                                     ['l', 'L'],
                                     [';', ':'],
                                     ['\'', '"'],
                                     ['`', '~'],
                                     ['\0', '\0'],
                                     ['\\', '|'],
                                     ['z', 'Z'],
                                     ['x', 'X'],
                                     ['c', 'C'],
                                     ['v', 'V'],
                                     ['b', 'B'],
                                     ['n', 'N'],
                                     ['m', 'M'],
                                     [',', '<'],
                                     ['.', '>'],
                                     ['/', '?'],
                                     ['\0', '\0'],
                                     ['\0', '\0'],
                                     ['\0', '\0'],
                                     [' ', ' ']];

 static SCANCODES_FR: [[char; 2]; 58] = [['\0', '\0'],
                                      ['\x1B', '\x1B'],
                                      ['1', '&'],
                                      ['2', 'é'],
                                      ['3', '"'],
                                      ['4', '\''],
                                      ['5', '('],
                                      ['6', '-'],
                                      ['7', 'è'],
                                      ['8', '_'],
                                      ['9', 'ç'],
                                      ['0', 'à'],
                                      ['-', ')'],
                                      ['=', '='],
                                      ['\0', '\0'],
                                      ['\t', '\t'],
                                      ['a', 'A'],
                                      ['z', 'Z'],
                                      ['e', 'E'],
                                      ['r', 'R'],
                                      ['t', 'T'],
                                      ['y', 'Y'],
                                      ['u', 'U'],
                                      ['i', 'I'],
                                      ['o', 'O'],
                                      ['p', 'P'],
                                      ['^', '¨'],
                                      ['$', '£'],
                                      ['\n', '\n'],
                                      ['\0', '\0'],
                                      ['q', 'Q'],
                                      ['s', 'S'],
                                      ['d', 'D'],
                                      ['f', 'F'],
                                      ['g', 'G'],
                                      ['h', 'H'],
                                      ['j', 'J'],
                                      ['k', 'K'],
                                      ['l', 'L'],
                                      ['m', 'M'],
                                      ['ù', '%'],
                                      ['*', 'µ'],
                                      ['\0', '\0'],
                                      ['<', '>'],
                                      ['w', 'W'],
                                      ['x', 'X'],
                                      ['c', 'C'],
                                      ['v', 'V'],
                                      ['b', 'B'],
                                      ['n', 'N'],
                                      [',', '?'],
                                      [';', '.'],
                                      [':', '/'],
                                      ['!', '§'],
                                      ['\0', '\0'],
                                      ['\0', '\0'],
                                      ['\0', '\0'],
                                      [' ', ' ']];
<commit_msg>SCANCODES has been renamed by SCANCODES_FR<commit_after>use alloc::boxed::Box;

use core::cmp;

use common::event::{KeyEvent, MouseEvent};

use drivers::pio::*;

use schemes::KScheme;

/// PS2
pub struct Ps2 {
    /// The data
    data: Pio8,
    /// The command
    cmd: Pio8,
    /// Left shift?
    lshift: bool,
    /// Right shift?
    rshift: bool,
    /// Caps lock?
    caps_lock: bool,
    /// Caps lock toggle
    caps_lock_toggle: bool,
    /// The mouse packet
    mouse_packet: [u8; 4],
    /// Mouse packet index
    mouse_i: usize,
    /// Mouse point x
    mouse_x: isize,
    /// Mouse point y
    mouse_y: isize,
    /// Layout for keyboard
    layout: usize,
}

impl Ps2 {
    /// Create new PS2 data
    pub fn new() -> Box<Self> {
        let mut module = box Ps2 {
            data: Pio8::new(0x60),
            cmd: Pio8::new(0x64),
            lshift: false,
            rshift: false,
            caps_lock: false,
            caps_lock_toggle: false,
            mouse_packet: [0; 4],
            mouse_i: 0,
            mouse_x: 0,
            mouse_y: 0,
            layout: 0,
        };

        unsafe {
            module.keyboard_init();
            module.mouse_init();
        }

        module
    }

    unsafe fn wait0(&self) {
        while (self.cmd.read() & 1) == 0 {}
    }

    unsafe fn wait1(&self) {
        while (self.cmd.read() & 2) == 2 {}
    }

    unsafe fn keyboard_init(&mut self) {
        while (self.cmd.read() & 0x1) == 1 {
            self.data.read();
        }

        self.wait1();
        self.cmd.write(0x20);
        self.wait0();
        let flags = (self.data.read() & 0b00110111) | 1 | 0b10000;
        self.wait1();
        self.cmd.write(0x60);
        self.wait1();
        self.data.write(flags);

        // Set Defaults
        self.wait1();
        self.data.write(0xF6);
        self.wait0();
        self.data.read();

        // Set LEDS
        self.wait1();
        self.data.write(0xED);
        self.wait0();
        self.data.read();

        self.wait1();
        self.data.write(0);
        self.wait0();
        self.data.read();

        // Set Scancode Map:
        self.wait1();
        self.data.write(0xF0);
        self.wait0();
        self.data.read();

        self.wait1();
        self.data.write(1);
        self.wait0();
        self.data.read();
    }

    /// Keyboard interrupt
    pub fn keyboard_interrupt(&mut self) -> Option<KeyEvent> {
        let scancode = unsafe { self.data.read() };

        if scancode == 0 {
            return None;
        } else if scancode == 0x2A {
            self.lshift = true;
        } else if scancode == 0xAA {
            self.lshift = false;
        } else if scancode == 0x36 {
            self.rshift = true;
        } else if scancode == 0xB6 {
            self.rshift = false;
        } else if scancode == 0x3A {
            if !self.caps_lock {
                self.caps_lock = true;
                self.caps_lock_toggle = true;
            } else {
                self.caps_lock_toggle = false;
            }
        } else if scancode == 0xBA {
            if self.caps_lock && !self.caps_lock_toggle {
                self.caps_lock = false;
            }
        }

        let shift;
        if self.caps_lock {
            shift = !(self.lshift || self.rshift);
        } else {
            shift = self.lshift || self.rshift;
        }

        return Some(KeyEvent {
            character: char_for_scancode(scancode & 0x7F, shift, self.layout),
            scancode: scancode & 0x7F,
            pressed: scancode < 0x80,
        });
    }

    unsafe fn mouse_cmd(&mut self, byte: u8) -> u8 {
        self.wait1();
        self.cmd.write(0xD4);
        self.wait1();
        self.data.write(byte);

        self.wait0();
        self.data.read()
    }

    /// Initialize mouse
    pub unsafe fn mouse_init(&mut self) {
        // The Init Dance
        self.wait1();
        self.cmd.write(0xA8);

        self.wait1();
        self.cmd.write(0x20);
        self.wait0();
        let status = self.data.read() | 2;
        self.wait1();
        self.cmd.write(0x60);
        self.wait1();
        self.data.write(status);

        // Set defaults
        self.mouse_cmd(0xF6);

        // Enable Streaming
        self.mouse_cmd(0xF4);
    }

    /// Mouse interrupt
    pub fn mouse_interrupt(&mut self) -> Option<MouseEvent> {
        let byte = unsafe { self.data.read() };
        if self.mouse_i == 0 {
            if byte & 0x8 == 0x8 {
                self.mouse_packet[0] = byte;
                self.mouse_i += 1;
            }
        } else if self.mouse_i == 1 {
            self.mouse_packet[1] = byte;

            self.mouse_i += 1;
        } else {
            self.mouse_packet[2] = byte;

            let left_button = (self.mouse_packet[0] & 1) == 1;
            let right_button = (self.mouse_packet[0] & 2) == 2;
            let middle_button = (self.mouse_packet[0] & 4) == 4;

            let x;
            if (self.mouse_packet[0] & 0x40) != 0x40 && self.mouse_packet[1] != 0 {
                x = self.mouse_packet[1] as isize -
                    (((self.mouse_packet[0] as isize) << 4) & 0x100);
            } else {
                x = 0;
            }

            let y;
            if (self.mouse_packet[0] & 0x80) != 0x80 && self.mouse_packet[2] != 0 {
                y = (((self.mouse_packet[0] as isize) << 3) & 0x100) -
                    self.mouse_packet[2] as isize;
            } else {
                y = 0;
            }

            unsafe {
                self.mouse_x = cmp::max(0,
                                        cmp::min((*::console).display.width as isize,
                                                 self.mouse_x + x));
                self.mouse_y = cmp::max(0,
                                        cmp::min((*::console).display.height as isize,
                                                 self.mouse_y + y));
            }

            self.mouse_i = 0;

            return Some(MouseEvent {
                x: self.mouse_x,
                y: self.mouse_y,
                left_button: left_button,
                right_button: right_button,
                middle_button: middle_button,
            });
        }

        return None;
    }

    /// Function to change the layout of the keyboard
    pub fn change_layout(&mut self, layout: usize) {
        self.layout = layout;
    }

}

impl KScheme for Ps2 {
    fn on_irq(&mut self, irq: u8) {
        if irq == 0x1 || irq == 0xC {
            self.on_poll();
        }
    }

    fn on_poll(&mut self) {
        loop {
            let status = unsafe { self.cmd.read() };
            if status & 0x21 == 1 {
                if let Some(key_event) = self.keyboard_interrupt() {
                    key_event.trigger();
                }
            } else if status & 0x21 == 0x21 {
                if let Some(mouse_event) = self.mouse_interrupt() {
                    mouse_event.trigger();
                }
            } else {
                break;
            }
        }
    }
}

/// Function to return the character associated with the scancode, and the layout
fn char_for_scancode(scancode: u8, shift: bool, layout: usize) -> char {
    if scancode >= 58 {
        '\x00'
    }
    let character =
        match layout {
            0 => SCANCODES_EN[scancode as usize],
            1 => SCANCODES_FR[scancode as usize],
        };
    if shift {
        character = characters[1]
    } else {
        character = characters[scancode as usize][0]
    }
}

static SCANCODES_EN: [[char; 2]; 58] = [['\0', '\0'],
                                     ['\x1B', '\x1B'],
                                     ['1', '!'],
                                     ['2', '@'],
                                     ['3', '#'],
                                     ['4', '$'],
                                     ['5', '%'],
                                     ['6', '^'],
                                     ['7', '&'],
                                     ['8', '*'],
                                     ['9', '('],
                                     ['0', ')'],
                                     ['-', '_'],
                                     ['=', '+'],
                                     ['\0', '\0'],
                                     ['\t', '\t'],
                                     ['q', 'Q'],
                                     ['w', 'W'],
                                     ['e', 'E'],
                                     ['r', 'R'],
                                     ['t', 'T'],
                                     ['y', 'Y'],
                                     ['u', 'U'],
                                     ['i', 'I'],
                                     ['o', 'O'],
                                     ['p', 'P'],
                                     ['[', '{'],
                                     [']', '}'],
                                     ['\n', '\n'],
                                     ['\0', '\0'],
                                     ['a', 'A'],
                                     ['s', 'S'],
                                     ['d', 'D'],
                                     ['f', 'F'],
                                     ['g', 'G'],
                                     ['h', 'H'],
                                     ['j', 'J'],
                                     ['k', 'K'],
                                     ['l', 'L'],
                                     [';', ':'],
                                     ['\'', '"'],
                                     ['`', '~'],
                                     ['\0', '\0'],
                                     ['\\', '|'],
                                     ['z', 'Z'],
                                     ['x', 'X'],
                                     ['c', 'C'],
                                     ['v', 'V'],
                                     ['b', 'B'],
                                     ['n', 'N'],
                                     ['m', 'M'],
                                     [',', '<'],
                                     ['.', '>'],
                                     ['/', '?'],
                                     ['\0', '\0'],
                                     ['\0', '\0'],
                                     ['\0', '\0'],
                                     [' ', ' ']];

 static SCANCODES_FR: [[char; 2]; 58] = [['\0', '\0'],
                                      ['\x1B', '\x1B'],
                                      ['1', '&'],
                                      ['2', 'é'],
                                      ['3', '"'],
                                      ['4', '\''],
                                      ['5', '('],
                                      ['6', '-'],
                                      ['7', 'è'],
                                      ['8', '_'],
                                      ['9', 'ç'],
                                      ['0', 'à'],
                                      ['-', ')'],
                                      ['=', '='],
                                      ['\0', '\0'],
                                      ['\t', '\t'],
                                      ['a', 'A'],
                                      ['z', 'Z'],
                                      ['e', 'E'],
                                      ['r', 'R'],
                                      ['t', 'T'],
                                      ['y', 'Y'],
                                      ['u', 'U'],
                                      ['i', 'I'],
                                      ['o', 'O'],
                                      ['p', 'P'],
                                      ['^', '¨'],
                                      ['$', '£'],
                                      ['\n', '\n'],
                                      ['\0', '\0'],
                                      ['q', 'Q'],
                                      ['s', 'S'],
                                      ['d', 'D'],
                                      ['f', 'F'],
                                      ['g', 'G'],
                                      ['h', 'H'],
                                      ['j', 'J'],
                                      ['k', 'K'],
                                      ['l', 'L'],
                                      ['m', 'M'],
                                      ['ù', '%'],
                                      ['*', 'µ'],
                                      ['\0', '\0'],
                                      ['<', '>'],
                                      ['w', 'W'],
                                      ['x', 'X'],
                                      ['c', 'C'],
                                      ['v', 'V'],
                                      ['b', 'B'],
                                      ['n', 'N'],
                                      [',', '?'],
                                      [';', '.'],
                                      [':', '/'],
                                      ['!', '§'],
                                      ['\0', '\0'],
                                      ['\0', '\0'],
                                      ['\0', '\0'],
                                      [' ', ' ']];
<|endoftext|>


<commit_before><commit_msg>Document the Error type.<commit_after><|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 driver::session::Session;
use middle::resolve;
use middle::ty;
use middle::typeck;
use util::ppaux;

use syntax::ast::*;
use syntax::codemap;
use syntax::{ast_util, ast_map};
use syntax::visit::Visitor;
use syntax::visit;

struct CheckCrateVisitor {
    sess: Session,
    ast_map: ast_map::map,
    def_map: resolve::DefMap,
    method_map: typeck::method_map,
    tcx: ty::ctxt,
}

impl Visitor<bool> for CheckCrateVisitor {
    fn visit_item(&mut self, i:@item, env:bool) {
        check_item(self, self.sess, self.ast_map, self.def_map, i, env);
    }
    fn visit_pat(&mut self, p:@Pat, env:bool) {
        check_pat(self, p, env);
    }
    fn visit_expr(&mut self, ex:@Expr, env:bool) {
        check_expr(self, self.sess, self.def_map, self.method_map,
                   self.tcx, ex, env);
    }
}

pub fn check_crate(sess: Session,
                   crate: &Crate,
                   ast_map: ast_map::map,
                   def_map: resolve::DefMap,
                   method_map: typeck::method_map,
                   tcx: ty::ctxt) {
    let mut v = CheckCrateVisitor {
        sess: sess,
        ast_map: ast_map,
        def_map: def_map,
        method_map: method_map,
        tcx: tcx,
    };
    visit::walk_crate(&mut v, crate, false);
    sess.abort_if_errors();
}

pub fn check_item(v: &mut CheckCrateVisitor,
                  sess: Session,
                  ast_map: ast_map::map,
                  def_map: resolve::DefMap,
                  it: @item,
                  _is_const: bool) {
    match it.node {
      item_static(_, _, ex) => {
        v.visit_expr(ex, true);
        check_item_recursion(sess, ast_map, def_map, it);
      }
      item_enum(ref enum_definition, _) => {
        for var in (*enum_definition).variants.iter() {
            for ex in var.node.disr_expr.iter() {
                v.visit_expr(*ex, true);
            }
        }
      }
      _ => visit::walk_item(v, it, false)
    }
}

pub fn check_pat(v: &mut CheckCrateVisitor, p: @Pat, _is_const: bool) {
    fn is_str(e: @Expr) -> bool {
        match e.node {
            ExprVstore(
                @Expr { node: ExprLit(@codemap::Spanned {
                    node: lit_str(_),
                    _}),
                       _ },
                ExprVstoreUniq
            ) => true,
            _ => false
        }
    }
    match p.node {
      // Let through plain ~-string literals here
      PatLit(a) => if !is_str(a) { v.visit_expr(a, true); },
      PatRange(a, b) => {
        if !is_str(a) { v.visit_expr(a, true); }
        if !is_str(b) { v.visit_expr(b, true); }
      }
      _ => visit::walk_pat(v, p, false)
    }
}

pub fn check_expr(v: &mut CheckCrateVisitor,
                  sess: Session,
                  def_map: resolve::DefMap,
                  method_map: typeck::method_map,
                  tcx: ty::ctxt,
                  e: @Expr,
                  is_const: bool) {
    if is_const {
        match e.node {
          ExprUnary(_, UnDeref, _) => { }
          ExprUnary(_, UnBox(_), _) | ExprUnary(_, UnUniq, _) => {
            sess.span_err(e.span,
                          "disallowed operator in constant expression");
            return;
          }
          ExprLit(@codemap::Spanned {node: lit_str(_), _}) => { }
          ExprBinary(*) | ExprUnary(*) => {
            if method_map.contains_key(&e.id) {
                sess.span_err(e.span, "user-defined operators are not \
                                       allowed in constant expressions");
            }
          }
          ExprLit(_) => (),
          ExprCast(_, _) => {
            let ety = ty::expr_ty(tcx, e);
            if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
                sess.span_err(e.span, ~"can not cast to `" +
                              ppaux::ty_to_str(tcx, ety) +
                              "` in a constant expression");
            }
          }
          ExprPath(ref pth) => {
            // NB: In the future you might wish to relax this slightly
            // to handle on-demand instantiation of functions via
            // foo::<bar> in a const. Currently that is only done on
            // a path in trans::callee that only works in block contexts.
            if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
                sess.span_err(
                    e.span, "paths in constants may only refer to \
                             items without type parameters");
            }
            match def_map.find(&e.id) {
              Some(&DefStatic(*)) |
              Some(&DefFn(_, _)) |
              Some(&DefVariant(_, _, _)) |
              Some(&DefStruct(_)) => { }

              Some(&def) => {
                debug!("(checking const) found bad def: %?", def);
                sess.span_err(
                    e.span,
                    "paths in constants may only refer to \
                     constants or functions");
              }
              None => {
                sess.span_bug(e.span, "unbound path in const?!");
              }
            }
          }
          ExprCall(callee, _, NoSugar) => {
            match def_map.find(&callee.id) {
                Some(&DefStruct(*)) => {}    // OK.
                Some(&DefVariant(*)) => {}    // OK.
                _ => {
                    sess.span_err(
                        e.span,
                        "function calls in constants are limited to \
                         struct and enum constructors");
                }
            }
          }
          ExprParen(e) => { check_expr(v, sess, def_map, method_map,
                                        tcx, e, is_const); }
          ExprVstore(_, ExprVstoreSlice) |
          ExprVec(_, MutImmutable) |
          ExprAddrOf(MutImmutable, _) |
          ExprField(*) |
          ExprIndex(*) |
          ExprTup(*) |
          ExprRepeat(*) |
          ExprStruct(*) => { }
          ExprAddrOf(*) => {
                sess.span_err(
                    e.span,
                    "borrowed pointers in constants may only refer to \
                     immutable values");
          }
          _ => {
            sess.span_err(e.span,
                          "constant contains unimplemented expression type");
            return;
          }
        }
    }
    match e.node {
        ExprLit(@codemap::Spanned {node: lit_int(v, t), _}) => {
            if (v as u64) > ast_util::int_ty_max(
                if t == ty_i { sess.targ_cfg.int_type } else { t }) {
                sess.span_err(e.span, "literal out of range for its type");
            }
        }
        ExprLit(@codemap::Spanned {node: lit_uint(v, t), _}) => {
            if v > ast_util::uint_ty_max(
                if t == ty_u { sess.targ_cfg.uint_type } else { t }) {
                sess.span_err(e.span, "literal out of range for its type");
            }
        }
        _ => ()
    }
    visit::walk_expr(v, e, is_const);
}

#[deriving(Clone)]
struct env {
    root_it: @item,
    sess: Session,
    ast_map: ast_map::map,
    def_map: resolve::DefMap,
    idstack: @mut ~[NodeId]
}

struct CheckItemRecursionVisitor;

// Make sure a const item doesn't recursively refer to itself
// FIXME: Should use the dependency graph when it's available (#1356)
pub fn check_item_recursion(sess: Session,
                            ast_map: ast_map::map,
                            def_map: resolve::DefMap,
                            it: @item) {
    let env = env {
        root_it: it,
        sess: sess,
        ast_map: ast_map,
        def_map: def_map,
        idstack: @mut ~[]
    };

    let mut visitor = CheckItemRecursionVisitor;
    visitor.visit_item(it, env);
}

impl Visitor<env> for CheckItemRecursionVisitor {
    fn visit_item(&mut self, it: @item, env: env) {
        if env.idstack.iter().any(|x| x == &(it.id)) {
            env.sess.span_fatal(env.root_it.span, "recursive constant");
        }
        env.idstack.push(it.id);
        visit::walk_item(self, it, env);
        env.idstack.pop();
    }

    fn visit_expr(&mut self, e: @Expr, env: env) {
        match e.node {
            ExprPath(*) => match env.def_map.find(&e.id) {
                Some(&DefStatic(def_id, _)) if ast_util::is_local(def_id) =>
                    match env.ast_map.get_copy(&def_id.node) {
                        ast_map::node_item(it, _) => {
                            self.visit_item(it, env);
                        }
                        _ => fail!("const not bound to an item")
                    },
                _ => ()
            },
            _ => ()
        }
        visit::walk_expr(self, e, env);
    }
}
<commit_msg>Fold env into CheckItemRecursionVisitor.<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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 driver::session::Session;
use middle::resolve;
use middle::ty;
use middle::typeck;
use util::ppaux;

use syntax::ast::*;
use syntax::codemap;
use syntax::{ast_util, ast_map};
use syntax::visit::Visitor;
use syntax::visit;

struct CheckCrateVisitor {
    sess: Session,
    ast_map: ast_map::map,
    def_map: resolve::DefMap,
    method_map: typeck::method_map,
    tcx: ty::ctxt,
}

impl Visitor<bool> for CheckCrateVisitor {
    fn visit_item(&mut self, i:@item, env:bool) {
        check_item(self, self.sess, self.ast_map, self.def_map, i, env);
    }
    fn visit_pat(&mut self, p:@Pat, env:bool) {
        check_pat(self, p, env);
    }
    fn visit_expr(&mut self, ex:@Expr, env:bool) {
        check_expr(self, self.sess, self.def_map, self.method_map,
                   self.tcx, ex, env);
    }
}

pub fn check_crate(sess: Session,
                   crate: &Crate,
                   ast_map: ast_map::map,
                   def_map: resolve::DefMap,
                   method_map: typeck::method_map,
                   tcx: ty::ctxt) {
    let mut v = CheckCrateVisitor {
        sess: sess,
        ast_map: ast_map,
        def_map: def_map,
        method_map: method_map,
        tcx: tcx,
    };
    visit::walk_crate(&mut v, crate, false);
    sess.abort_if_errors();
}

pub fn check_item(v: &mut CheckCrateVisitor,
                  sess: Session,
                  ast_map: ast_map::map,
                  def_map: resolve::DefMap,
                  it: @item,
                  _is_const: bool) {
    match it.node {
      item_static(_, _, ex) => {
        v.visit_expr(ex, true);
        check_item_recursion(sess, ast_map, def_map, it);
      }
      item_enum(ref enum_definition, _) => {
        for var in (*enum_definition).variants.iter() {
            for ex in var.node.disr_expr.iter() {
                v.visit_expr(*ex, true);
            }
        }
      }
      _ => visit::walk_item(v, it, false)
    }
}

pub fn check_pat(v: &mut CheckCrateVisitor, p: @Pat, _is_const: bool) {
    fn is_str(e: @Expr) -> bool {
        match e.node {
            ExprVstore(
                @Expr { node: ExprLit(@codemap::Spanned {
                    node: lit_str(_),
                    _}),
                       _ },
                ExprVstoreUniq
            ) => true,
            _ => false
        }
    }
    match p.node {
      // Let through plain ~-string literals here
      PatLit(a) => if !is_str(a) { v.visit_expr(a, true); },
      PatRange(a, b) => {
        if !is_str(a) { v.visit_expr(a, true); }
        if !is_str(b) { v.visit_expr(b, true); }
      }
      _ => visit::walk_pat(v, p, false)
    }
}

pub fn check_expr(v: &mut CheckCrateVisitor,
                  sess: Session,
                  def_map: resolve::DefMap,
                  method_map: typeck::method_map,
                  tcx: ty::ctxt,
                  e: @Expr,
                  is_const: bool) {
    if is_const {
        match e.node {
          ExprUnary(_, UnDeref, _) => { }
          ExprUnary(_, UnBox(_), _) | ExprUnary(_, UnUniq, _) => {
            sess.span_err(e.span,
                          "disallowed operator in constant expression");
            return;
          }
          ExprLit(@codemap::Spanned {node: lit_str(_), _}) => { }
          ExprBinary(*) | ExprUnary(*) => {
            if method_map.contains_key(&e.id) {
                sess.span_err(e.span, "user-defined operators are not \
                                       allowed in constant expressions");
            }
          }
          ExprLit(_) => (),
          ExprCast(_, _) => {
            let ety = ty::expr_ty(tcx, e);
            if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
                sess.span_err(e.span, ~"can not cast to `" +
                              ppaux::ty_to_str(tcx, ety) +
                              "` in a constant expression");
            }
          }
          ExprPath(ref pth) => {
            // NB: In the future you might wish to relax this slightly
            // to handle on-demand instantiation of functions via
            // foo::<bar> in a const. Currently that is only done on
            // a path in trans::callee that only works in block contexts.
            if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
                sess.span_err(
                    e.span, "paths in constants may only refer to \
                             items without type parameters");
            }
            match def_map.find(&e.id) {
              Some(&DefStatic(*)) |
              Some(&DefFn(_, _)) |
              Some(&DefVariant(_, _, _)) |
              Some(&DefStruct(_)) => { }

              Some(&def) => {
                debug!("(checking const) found bad def: %?", def);
                sess.span_err(
                    e.span,
                    "paths in constants may only refer to \
                     constants or functions");
              }
              None => {
                sess.span_bug(e.span, "unbound path in const?!");
              }
            }
          }
          ExprCall(callee, _, NoSugar) => {
            match def_map.find(&callee.id) {
                Some(&DefStruct(*)) => {}    // OK.
                Some(&DefVariant(*)) => {}    // OK.
                _ => {
                    sess.span_err(
                        e.span,
                        "function calls in constants are limited to \
                         struct and enum constructors");
                }
            }
          }
          ExprParen(e) => { check_expr(v, sess, def_map, method_map,
                                        tcx, e, is_const); }
          ExprVstore(_, ExprVstoreSlice) |
          ExprVec(_, MutImmutable) |
          ExprAddrOf(MutImmutable, _) |
          ExprField(*) |
          ExprIndex(*) |
          ExprTup(*) |
          ExprRepeat(*) |
          ExprStruct(*) => { }
          ExprAddrOf(*) => {
                sess.span_err(
                    e.span,
                    "borrowed pointers in constants may only refer to \
                     immutable values");
          }
          _ => {
            sess.span_err(e.span,
                          "constant contains unimplemented expression type");
            return;
          }
        }
    }
    match e.node {
        ExprLit(@codemap::Spanned {node: lit_int(v, t), _}) => {
            if (v as u64) > ast_util::int_ty_max(
                if t == ty_i { sess.targ_cfg.int_type } else { t }) {
                sess.span_err(e.span, "literal out of range for its type");
            }
        }
        ExprLit(@codemap::Spanned {node: lit_uint(v, t), _}) => {
            if v > ast_util::uint_ty_max(
                if t == ty_u { sess.targ_cfg.uint_type } else { t }) {
                sess.span_err(e.span, "literal out of range for its type");
            }
        }
        _ => ()
    }
    visit::walk_expr(v, e, is_const);
}

#[deriving(Clone)]
struct env {
    root_it: @item,
    sess: Session,
    ast_map: ast_map::map,
    def_map: resolve::DefMap,
    idstack: @mut ~[NodeId]
}

struct CheckItemRecursionVisitor {
    env: env,
}

// Make sure a const item doesn't recursively refer to itself
// FIXME: Should use the dependency graph when it's available (#1356)
pub fn check_item_recursion(sess: Session,
                            ast_map: ast_map::map,
                            def_map: resolve::DefMap,
                            it: @item) {
    let env = env {
        root_it: it,
        sess: sess,
        ast_map: ast_map,
        def_map: def_map,
        idstack: @mut ~[]
    };

    let mut visitor = CheckItemRecursionVisitor { env: env };
    visitor.visit_item(it, ());
}

impl Visitor<()> for CheckItemRecursionVisitor {
    fn visit_item(&mut self, it: @item, _: ()) {
        if self.env.idstack.iter().any(|x| x == &(it.id)) {
            self.env.sess.span_fatal(self.env.root_it.span, "recursive constant");
        }
        self.env.idstack.push(it.id);
        visit::walk_item(self, it, ());
        self.env.idstack.pop();
    }

    fn visit_expr(&mut self, e: @Expr, _: ()) {
        match e.node {
            ExprPath(*) => match self.env.def_map.find(&e.id) {
                Some(&DefStatic(def_id, _)) if ast_util::is_local(def_id) =>
                    match self.env.ast_map.get_copy(&def_id.node) {
                        ast_map::node_item(it, _) => {
                            self.visit_item(it, ());
                        }
                        _ => fail!("const not bound to an item")
                    },
                _ => ()
            },
            _ => ()
        }
        visit::walk_expr(self, e, ());
    }
}
<|endoftext|>


<commit_before><commit_msg>implement kill command<commit_after>use std::fmt;

use protocol::command::CMD_KILL;
use protocol::message::{IrcMessage, RawMessage, ParseMessageError, ParseMessageErrorKind};

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct KillCommand<'a> {
    nickname: &'a str,
    msg: Option<&'a str>,
}

impl<'a> KillCommand<'a> {
    fn new(nickname: &'a str, msg: Option<&'a str>) -> KillCommand<'a> {
        KillCommand {
            nickname: nickname,
            msg: msg,
        }
    }

    pub fn nickname(&self) -> &'a str {
        self.nickname
    }

    pub fn message(&self) -> Option<&'a str> {
        self.msg
    }
}

impl<'a> fmt::Display for KillCommand<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{} {}", CMD_KILL, self.nickname));

        match self.msg {
            Some(m) => write!(f, " {}", m),
            None => Ok(()),
        }
    }
}

impl<'a> IrcMessage<'a> for KillCommand<'a> {
    fn from_raw(raw: &RawMessage<'a>) -> Result<KillCommand<'a>, ParseMessageError> {
        let mut params = raw.parameters();

        let (nick, msg) = match (params.next(), params.next()) {
            (Some(nick), Some(msg)) => (nick, Some(msg)),
            (Some(nick), None) => (nick, None),
            _ => {
                return Err(ParseMessageError::new(ParseMessageErrorKind::NeedMoreParams,
                                                  "KILL command needs at least 1 parameters"));
            }
        };

        Ok(KillCommand::new(nick, msg))
    }
}
<|endoftext|>