<commit_before><commit_msg>add example code<commit_after>#[feature(globs)];

extern mod glfw;
extern mod gl;

use std::cast;
use std::ptr;
use std::str;
use std::vec;
use std::libc;

use gl::types::*;

static vertex_shader_src : &'static str = r"
#version 110

attribute vec4 position;

varying vec2 texcoord;

void main() {
    gl_Position = position;
    texcoord = position.xy;
}
";

static fragment_shader_src : &'static str = r"
#version 110

varying vec2 texcoord;

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

#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn main() {
   glfw::set_error_callback(~ErrorContext);

   let window_width = 800;
   let window_height = 600;

    do glfw::start {
        let window = glfw::Window::create(window_width, window_height, "Hello, I am a window.", glfw::Windowed)
            .expect("Failed to create GLFW window.");

        //window.set_cursor_mode(glfw::CursorDisabled);
        window.make_context_current();

        gl::load_with(glfw::get_proc_address);

        let vs = compile_shader(vertex_shader_src.as_bytes(), gl::VERTEX_SHADER);
        let fs = compile_shader(fragment_shader_src.as_bytes(), gl::FRAGMENT_SHADER);
        let program = link_program(vs, fs);

        let mut vao = 0;
        let mut vbo = 0;

        let VERTEX_DATA : ~[GLfloat] = ~[
            -1.0, -1.0, 0.0, 1.0,
            1.0, -1.0, 0.0, 1.0,
            -1.0, 1.0, 0.0, 1.0,
            1.0, 1.0, 0.0, 1.0,
        ];

        unsafe {
            // Create Vertex Array Object
            gl::GenVertexArrays(1, &mut vao);
            gl::BindVertexArray(vao);

            // Create a Vertex Buffer Object and copy the vertex data to it
            gl::GenBuffers(1, &mut vbo);
            gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
            gl::BufferData(gl::ARRAY_BUFFER,
                           (VERTEX_DATA.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
                           cast::transmute(&VERTEX_DATA[0]),
                           gl::STATIC_DRAW);

            // Use shader program
            gl::UseProgram(program);

            // Specify the layout of the vertex data
            let vert_attr = "position".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
            gl::EnableVertexAttribArray(vert_attr as GLuint);
            gl::VertexAttribPointer(vert_attr as GLuint, 4, gl::FLOAT,
                                    gl::FALSE as GLboolean, 0, ptr::null());
        }

        check_gl();

        window.set_cursor_pos_callback(~CursorPosContext);
        window.set_key_callback(~KeyContext);

        while !window.should_close() {
            glfw::poll_events();

            gl::Viewport(0,0, window_width as GLint, window_height as GLint);

            gl::ClearColor(0.8, 0.3, 0.3, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
            gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4);

            window.swap_buffers();

            check_gl();
        }
    }
}

fn check_gl() {
    let err = gl::GetError();
    if (err != gl::NO_ERROR) {
        fail!("GL error");
    }
}

fn compile_shader(src: &[u8], ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        //transmute is used here because `as` causes ICE
        //wait a sec, is `src` null-terminated properly?
        gl::ShaderSource(shader, 1, std::cast::transmute(std::ptr::to_unsafe_ptr(&src.as_ptr())), ptr::null());
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), buf.as_mut_ptr() as *mut GLchar);
            fail!(str::raw::from_utf8(buf).to_owned());
        }
    }
    program
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
    fn call(&self, _: glfw::Error, description: ~str) {
        fail!("GLFW Error: {:s}", description);
    }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
    fn call(&self, _: &glfw::Window, _: f64, _: f64) {
    }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
    fn call(&self, window: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
        match (action, key) {
            (glfw::Press, glfw::KeyEscape) => window.set_should_close(true),
            _ => println!("unexpected key callback for action {:?} key {:?}", action, key)
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>an empy message<commit_after><|endoftext|>


<commit_before><commit_msg>Fix Spacing<commit_after><|endoftext|>


<commit_before><commit_msg>Use 'is_empty' in 'raindrops'.<commit_after><|endoftext|>


<commit_before>#![crate_name = "sort"]
#![allow(unstable)]

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

#![allow(dead_code)]

extern crate getopts;

use std::cmp::Ordering;
use std::io::{print, File, BufferedReader};
use std::io::stdio::stdin_raw;
use std::str::Chars;

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

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

static DECIMAL_PT: char = '.';
static THOUSANDS_SEP: char = ',';

pub fn uumain(args: Vec<String>) -> isize {
    let program = args[0].as_slice();
    let opts = [
        getopts::optflag("n", "numeric-sort", "compare according to string numerical value"),
        getopts::optflag("r", "reverse", "reverse the output"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f)
    };
    if matches.opt_present("help") {
        println!("Usage: {0} [OPTION]... [FILE]...", program);
        println!("Write the sorted concatenation of all FILE(s) to standard output.");
        println!("");
        print(getopts::usage("Mandatory arguments for long options are mandatory for short options too.", &opts).as_slice());
        println!("");
        println!("With no FILE, or when FILE is -, read standard input.");
        return 0;
    }

    if matches.opt_present("version") {
        println!("sort 1.0.0");
        return 0;
    }

    let numeric = matches.opt_present("numeric-sort");
    let reverse = matches.opt_present("reverse");

    let mut files = matches.free;
    if files.is_empty() {
        /* if no file, default to stdin */
        files.push("-".to_string());
    }

    exec(files, numeric, reverse);

    0
}

fn exec(files: Vec<String>, numeric: bool, reverse: bool) {
    for path in files.iter() {
        let (reader, _) = match open(path.as_slice()) {
            Some(x) => x,
            None => continue,
        };

        let mut buf_reader = BufferedReader::new(reader);
        let mut lines = Vec::new();

        for line in buf_reader.lines() {
            match line {
                Ok(n) => {
                    lines.push(n);
                },
                _ => break
            }
        }

        if numeric {
            lines.sort_by(frac_compare);
        } else {
            lines.sort();
        }

        let iter = lines.iter();
        if reverse {
            print_sorted(iter.rev());
        } else {
            print_sorted(iter)
        };
    }
}

fn skip_zeros(mut char_a: char, char_iter: &mut Chars, ret: Ordering) -> Ordering {
    char_a = match char_iter.next() { None => 0 as char, Some(t) => t };
    while char_a == '0' {
        char_a = match char_iter.next() { None => return Ordering::Equal, Some(t) => t };
    }
    if char_a.is_digit(10) { ret } else { Ordering::Equal }
}

/// Compares two decimal fractions as strings (n < 1)
/// This requires the strings to start with a decimal, otherwise it's treated as 0
fn frac_compare(a: &String, b: &String) -> Ordering {
    let a_chars = &mut a.as_slice().chars();
    let b_chars = &mut b.as_slice().chars();

    let mut char_a = match a_chars.next() { None => 0 as char, Some(t) => t };
    let mut char_b = match b_chars.next() { None => 0 as char, Some(t) => t };

    if char_a == DECIMAL_PT && char_b == DECIMAL_PT {
        while char_a == char_b {
            char_a = match a_chars.next() { None => 0 as char, Some(t) => t };
            char_b = match b_chars.next() { None => 0 as char, Some(t) => t };
            // hit the end at the same time, they are equal
            if !char_a.is_digit(10) {
                return Ordering::Equal;
            }
        }
        if char_a.is_digit(10) && char_b.is_digit(10) {
            (char_a as isize).cmp(&(char_b as isize))
        } else if char_a.is_digit(10) {
            skip_zeros(char_a, a_chars, Ordering::Greater)
        } else if char_b.is_digit(10) {
            skip_zeros(char_b, b_chars, Ordering::Less)
        } else { Ordering::Equal }
    } else if char_a == DECIMAL_PT {
        skip_zeros(char_a, a_chars, Ordering::Greater)
    } else if char_b == DECIMAL_PT {
        skip_zeros(char_b, b_chars, Ordering::Less)
    } else { Ordering::Equal }
}

#[inline(always)]
fn print_sorted<S, T: Iterator<Item=S>>(mut iter: T) where S: std::fmt::String {
    for line in iter {
        print!("{}", line);
    }
}

// from cat.rs
fn open<'a>(path: &str) -> Option<(Box<Reader + 'a>, bool)> {
    if path == "-" {
        let stdin = stdin_raw();
        let interactive = stdin.isatty();
        return Some((Box::new(stdin) as Box<Reader>, interactive));
    }

    match File::open(&std::path::Path::new(path)) {
        Ok(f) => Some((Box::new(f) as Box<Reader>, false)),
        Err(e) => {
            show_error!("sort: {0}: {1}", path, e.to_string());
            None
        },
    }
}

<commit_msg>sort: fix build<commit_after>#![crate_name = "sort"]
#![allow(unstable)]

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

#![allow(dead_code)]

extern crate getopts;

use std::cmp::Ordering;
use std::io::{print, File, BufferedReader};
use std::io::stdio::stdin_raw;
use std::str::Chars;

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

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

static DECIMAL_PT: char = '.';
static THOUSANDS_SEP: char = ',';

pub fn uumain(args: Vec<String>) -> isize {
    let program = args[0].as_slice();
    let opts = [
        getopts::optflag("n", "numeric-sort", "compare according to string numerical value"),
        getopts::optflag("r", "reverse", "reverse the output"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => crash!(1, "Invalid options\n{}", f)
    };
    if matches.opt_present("help") {
        println!("Usage: {0} [OPTION]... [FILE]...", program);
        println!("Write the sorted concatenation of all FILE(s) to standard output.");
        println!("");
        print(getopts::usage("Mandatory arguments for long options are mandatory for short options too.", &opts).as_slice());
        println!("");
        println!("With no FILE, or when FILE is -, read standard input.");
        return 0;
    }

    if matches.opt_present("version") {
        println!("sort 1.0.0");
        return 0;
    }

    let numeric = matches.opt_present("numeric-sort");
    let reverse = matches.opt_present("reverse");

    let mut files = matches.free;
    if files.is_empty() {
        /* if no file, default to stdin */
        files.push("-".to_string());
    }

    exec(files, numeric, reverse);

    0
}

fn exec(files: Vec<String>, numeric: bool, reverse: bool) {
    for path in files.iter() {
        let (reader, _) = match open(path.as_slice()) {
            Some(x) => x,
            None => continue,
        };

        let mut buf_reader = BufferedReader::new(reader);
        let mut lines = Vec::new();

        for line in buf_reader.lines() {
            match line {
                Ok(n) => {
                    lines.push(n);
                },
                _ => break
            }
        }

        if numeric {
            lines.sort_by(frac_compare);
        } else {
            lines.sort();
        }

        let iter = lines.iter();
        if reverse {
            print_sorted(iter.rev());
        } else {
            print_sorted(iter)
        };
    }
}

fn skip_zeros(mut char_a: char, char_iter: &mut Chars, ret: Ordering) -> Ordering {
    char_a = match char_iter.next() { None => 0 as char, Some(t) => t };
    while char_a == '0' {
        char_a = match char_iter.next() { None => return Ordering::Equal, Some(t) => t };
    }
    if char_a.is_digit(10) { ret } else { Ordering::Equal }
}

/// Compares two decimal fractions as strings (n < 1)
/// This requires the strings to start with a decimal, otherwise it's treated as 0
fn frac_compare(a: &String, b: &String) -> Ordering {
    let a_chars = &mut a.as_slice().chars();
    let b_chars = &mut b.as_slice().chars();

    let mut char_a = match a_chars.next() { None => 0 as char, Some(t) => t };
    let mut char_b = match b_chars.next() { None => 0 as char, Some(t) => t };

    if char_a == DECIMAL_PT && char_b == DECIMAL_PT {
        while char_a == char_b {
            char_a = match a_chars.next() { None => 0 as char, Some(t) => t };
            char_b = match b_chars.next() { None => 0 as char, Some(t) => t };
            // hit the end at the same time, they are equal
            if !char_a.is_digit(10) {
                return Ordering::Equal;
            }
        }
        if char_a.is_digit(10) && char_b.is_digit(10) {
            (char_a as isize).cmp(&(char_b as isize))
        } else if char_a.is_digit(10) {
            skip_zeros(char_a, a_chars, Ordering::Greater)
        } else if char_b.is_digit(10) {
            skip_zeros(char_b, b_chars, Ordering::Less)
        } else { Ordering::Equal }
    } else if char_a == DECIMAL_PT {
        skip_zeros(char_a, a_chars, Ordering::Greater)
    } else if char_b == DECIMAL_PT {
        skip_zeros(char_b, b_chars, Ordering::Less)
    } else { Ordering::Equal }
}

#[inline(always)]
fn print_sorted<S, T: Iterator<Item=S>>(mut iter: T) where S: std::fmt::Display {
    for line in iter {
        print!("{}", line);
    }
}

// from cat.rs
fn open<'a>(path: &str) -> Option<(Box<Reader + 'a>, bool)> {
    if path == "-" {
        let stdin = stdin_raw();
        let interactive = stdin.isatty();
        return Some((Box::new(stdin) as Box<Reader>, interactive));
    }

    match File::open(&std::path::Path::new(path)) {
        Ok(f) => Some((Box::new(f) as Box<Reader>, false)),
        Err(e) => {
            show_error!("sort: {0}: {1}", path, e.to_string());
            None
        },
    }
}

<|endoftext|>


<commit_before>// xfail-test
// error-pattern:unresolved import: m::f
use x = m::f;

mod m {
    #[legacy_exports];
}

fn main() {
}
<commit_msg>Update error message and un-xfail test<commit_after>use x = m::f; //~ ERROR failed to resolve import

mod m {
    #[legacy_exports];
}

fn main() {
}
<|endoftext|>


<commit_before><commit_msg>year年あけましておめでとうございます<commit_after><|endoftext|>


<commit_before><commit_msg>Check whether glslangValidator is available on the path and provide a suitable message if not<commit_after><|endoftext|>


<commit_before><commit_msg>struct rect<commit_after><|endoftext|>


<commit_before>// Copyright 2012 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 cast;
use iterator::Iterator;
use libc;
use ops::Drop;
use option::{Option, Some, None};
use ptr::RawPtr;
use ptr;
use str::StrSlice;
use vec::ImmutableVector;

/**
 * The representation of a C String.
 *
 * This structure wraps a `*libc::c_char`, and will automatically free the
 * memory it is pointing to when it goes out of scope.
 */
pub struct CString {
    priv buf: *libc::c_char,
}

impl<'self> CString {
    /**
     * Create a C String from a str.
     */
    pub fn from_str(s: &str) -> CString {
        s.to_c_str()
    }

    /**
     * Take the wrapped `*libc::c_char` from the `CString` wrapper.
     *
     * # Failure
     *
     * If the wrapper is empty.
     */
    pub unsafe fn take(&mut self) -> *libc::c_char {
        if self.buf.is_null() {
            fail!("CString has no wrapped `*libc::c_char`");
        }
        let buf = self.buf;
        self.buf = ptr::null();
        buf
    }

    /**
     * Puts a `*libc::c_char` into the `CString` wrapper.
     *
     * # Failure
     *
     * If the `*libc::c_char` is null.
     * If the wrapper is not empty.
     */
    pub fn put_back(&mut self, buf: *libc::c_char) {
        if buf.is_null() {
            fail!("attempt to put a null pointer into a CString");
        }
        if self.buf.is_not_null() {
            fail!("CString already wraps a `*libc::c_char`");
        }
        self.buf = buf;
    }

    /**
     * Calls a closure with a reference to the underlying `*libc::c_char`.
     */
    pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
        if self.buf.is_null() {
            fail!("CString already wraps a `*libc::c_char`");
        }
        f(self.buf)
    }

    /**
     * Calls a closure with a mutable reference to the underlying `*libc::c_char`.
     */
    pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T {
        if self.buf.is_not_null() {
            fail!("CString already wraps a `*libc::c_char`");
        }
        f(unsafe { cast::transmute(self.buf) })
    }

    /**
     * Returns true if the CString does not wrap a `*libc::c_char`.
     */
    pub fn is_empty(&self) -> bool {
        self.buf.is_null()
    }

    /**
     * Returns true if the CString wraps a `*libc::c_char`.
     */
    pub fn is_not_empty(&self) -> bool {
        self.buf.is_not_null()
    }

    /**
     * Converts the CString into a `&[u8]` without copying.
     */
    pub fn as_bytes(&self) -> &'self [u8] {
        unsafe {
            let len = libc::strlen(self.buf) as uint;
            cast::transmute((self.buf, len + 1))
        }
    }

    /**
     * Return a CString iterator.
     */
    fn iter(&self) -> CStringIterator<'self> {
        CStringIterator {
            ptr: self.buf,
            lifetime: unsafe { cast::transmute(self.buf) },
        }
    }
}

impl Drop for CString {
    fn drop(&self) {
        if self.buf.is_not_null() {
            unsafe {
                libc::free(self.buf as *libc::c_void)
            };
        }
    }
}

/**
 * A generic trait for converting a value to a CString.
 */
pub trait ToCStr {
    /**
     * Create a C String.
     */
    fn to_c_str(&self) -> CString;
}

impl<'self> ToCStr for &'self str {
    /**
     * Create a C String from a `&str`.
     */
    fn to_c_str(&self) -> CString {
        self.as_bytes().to_c_str()
    }
}

impl<'self> ToCStr for &'self [u8] {
    /**
     * Create a C String from a `&[u8]`.
     */
    fn to_c_str(&self) -> CString {
        do self.as_imm_buf |self_buf, self_len| {
            unsafe {
                let buf = libc::malloc(self_len as u64 + 1) as *mut u8;
                if buf.is_null() {
                    fail!("failed to allocate memory!");
                }

                ptr::copy_memory(buf, self_buf, self_len);
                *ptr::mut_offset(buf, self_len as int) = 0;
                CString { buf: buf as *libc::c_char }
            }
        }
    }
}

/**
 * External iterator for a CString's bytes.
 *
 * Use with the `std::iterator` module.
 */
pub struct CStringIterator<'self> {
    priv ptr: *libc::c_char,
    priv lifetime: &'self libc::c_char, // FIXME: #5922
}

impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
    /**
     * Advance the iterator.
     */
    fn next(&mut self) -> Option<libc::c_char> {
        if self.ptr.is_null() {
            None
        } else {
            let ch = unsafe { *self.ptr };
            self.ptr = ptr::offset(self.ptr, 1);
            Some(ch)
        }
    }
}

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

    #[test]
    fn test_to_c_str() {
        do "".to_c_str().with_ref |buf| {
            unsafe {
                assert_eq!(*ptr::offset(buf, 0), 0);
            }
        }

        do "hello".to_c_str().with_ref |buf| {
            unsafe {
                assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 5), 0);
            }
        }
    }

    #[test]
    fn test_take() {
        let mut c_str = "hello".to_c_str();
        unsafe { libc::free(c_str.take() as *libc::c_void) }
        assert!(c_str.is_empty());
    }

    #[test]
    fn test_take_and_put_back() {
        let mut c_str = "hello".to_c_str();
        assert!(c_str.is_not_empty());

        let buf = unsafe { c_str.take() };

        assert!(c_str.is_empty());

        c_str.put_back(buf);

        assert!(c_str.is_not_empty());
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_take_empty_fail() {
        let mut c_str = "hello".to_c_str();
        unsafe {
            libc::free(c_str.take() as *libc::c_void);
            c_str.take();
        }
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_put_back_null_fail() {
        let mut c_str = "hello".to_c_str();
        c_str.put_back(ptr::null());
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_put_back_full_fail() {
        let mut c_str = "hello".to_c_str();
        c_str.put_back(0xdeadbeef as *libc::c_char);
    }

    fn test_with() {
        let c_str = "hello".to_c_str();
        let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
        assert!(c_str.is_not_empty());
        assert_eq!(len, 5);
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_with_empty_fail() {
        let mut c_str = "hello".to_c_str();
        unsafe { libc::free(c_str.take() as *libc::c_void) }
        c_str.with_ref(|_| ());
    }
}
<commit_msg>std: Update the c_str docs, and support CString not owning the pointer<commit_after>// Copyright 2012 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 cast;
use iterator::Iterator;
use libc;
use ops::Drop;
use option::{Option, Some, None};
use ptr::RawPtr;
use ptr;
use str::StrSlice;
use vec::ImmutableVector;

/// The representation of a C String.
///
/// This structure wraps a `*libc::c_char`, and will automatically free the
/// memory it is pointing to when it goes out of scope.
pub struct CString {
    priv buf: *libc::c_char,
    priv owns_buffer_: bool,
}

impl<'self> CString {
    /// Create a C String from a pointer.
    pub fn new(buf: *libc::c_char, owns_buffer: bool) -> CString {
        CString { buf: buf, owns_buffer_: owns_buffer }
    }

    /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
    pub unsafe fn unwrap(self) -> *libc::c_char {
        let mut c_str = self;
        c_str.owns_buffer_ = false;
        c_str.buf
    }

    /// Calls a closure with a reference to the underlying `*libc::c_char`.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
        if self.buf.is_null() { fail!("CString is null!"); }
        f(self.buf)
    }

    /// Calls a closure with a mutable reference to the underlying `*libc::c_char`.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T {
        if self.buf.is_null() { fail!("CString is null!"); }
        f(unsafe { cast::transmute(self.buf) })
    }

    /// Returns true if the CString is a null.
    pub fn is_null(&self) -> bool {
        self.buf.is_null()
    }

    /// Returns true if the CString is not null.
    pub fn is_not_null(&self) -> bool {
        self.buf.is_not_null()
    }

    /// Returns whether or not the `CString` owns the buffer.
    pub fn owns_buffer(&self) -> bool {
        self.owns_buffer_
    }

    /// Converts the CString into a `&[u8]` without copying.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn as_bytes(&self) -> &'self [u8] {
        if self.buf.is_null() { fail!("CString is null!"); }
        unsafe {
            let len = libc::strlen(self.buf) as uint;
            cast::transmute((self.buf, len + 1))
        }
    }

    /// Return a CString iterator.
    fn iter(&self) -> CStringIterator<'self> {
        CStringIterator {
            ptr: self.buf,
            lifetime: unsafe { cast::transmute(self.buf) },
        }
    }
}

impl Drop for CString {
    fn drop(&self) {
        if self.owns_buffer_ && self.buf.is_not_null() {
            unsafe {
                libc::free(self.buf as *libc::c_void)
            }
        }
    }
}

/// A generic trait for converting a value to a CString.
pub trait ToCStr {
    /// Create a C String.
    fn to_c_str(&self) -> CString;
}

impl<'self> ToCStr for &'self str {
    #[inline]
    fn to_c_str(&self) -> CString {
        self.as_bytes().to_c_str()
    }
}

impl<'self> ToCStr for &'self [u8] {
    fn to_c_str(&self) -> CString {
        do self.as_imm_buf |self_buf, self_len| {
            unsafe {
                let buf = libc::malloc(self_len as u64 + 1) as *mut u8;
                if buf.is_null() {
                    fail!("failed to allocate memory!");
                }

                ptr::copy_memory(buf, self_buf, self_len);
                *ptr::mut_offset(buf, self_len as int) = 0;

                CString::new(buf as *libc::c_char, true)
            }
        }
    }
}

/// External iterator for a CString's bytes.
///
/// Use with the `std::iterator` module.
pub struct CStringIterator<'self> {
    priv ptr: *libc::c_char,
    priv lifetime: &'self libc::c_char, // FIXME: #5922
}

impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
    fn next(&mut self) -> Option<libc::c_char> {
        if self.ptr.is_null() {
            None
        } else {
            let ch = unsafe { *self.ptr };
            self.ptr = ptr::offset(self.ptr, 1);
            Some(ch)
        }
    }
}

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

    #[test]
    fn test_to_c_str() {
        do "".to_c_str().with_ref |buf| {
            unsafe {
                assert_eq!(*ptr::offset(buf, 0), 0);
            }
        }

        do "hello".to_c_str().with_ref |buf| {
            unsafe {
                assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 5), 0);
            }
        }
    }

    #[test]
    fn test_is_null() {
        let c_str = CString::new(ptr::null(), false);
        assert!(c_str.is_null());
        assert!(!c_str.is_not_null());
    }

    #[test]
    fn test_unwrap() {
        let c_str = "hello".to_c_str();
        unsafe { libc::free(c_str.unwrap() as *libc::c_void) }
    }

    #[test]
    fn test_with_ref() {
        let c_str = "hello".to_c_str();
        let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
        assert!(!c_str.is_null());
        assert!(c_str.is_not_null());
        assert_eq!(len, 5);
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_with_ref_empty_fail() {
        let c_str = CString::new(ptr::null(), false);
        c_str.with_ref(|_| ());
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove use of deprecated language construct.<commit_after><|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::io::{stdout, Write};

use super::peg::Job;
use super::input_editor::readln;

pub struct Variables {
    variables: BTreeMap<String, String>,
}

impl Variables {
    pub fn new() -> Variables {
        Variables { variables: BTreeMap::new() }
    }

    pub fn read(&mut self, args: &[String]) {
        let mut out = stdout();
        for i in 1..args.len() {
            if let Some(arg_original) = args.get(i) {
                let arg = arg_original.trim();
                print!("{}=", arg);
                if let Err(message) = out.flush() {
                    println!("{}: Failed to flush stdout", message);
                }
                if let Some(value_original) = readln() {
                    let value = value_original.trim();
                    self.set_var(arg, value);
                }
            }
        }
    }

    pub fn let_(&mut self, args: &[String]) {
        match (args.get(1), args.get(2)) {
            (Some(key), Some(value)) => {
                self.variables.insert(key.clone(), value.clone());
            },
            (Some(key), None) => {
                self.variables.remove(key);
            },
            _ => {
                for (key, value) in self.variables.iter() {
                    println!("{}={}", key, value);
                }
            }
        }
    }

    pub fn set_var(&mut self, name: &str, value: &str) {
        if !name.is_empty() {
            if value.is_empty() {
                self.variables.remove(&name.to_string());
            } else {
                self.variables.insert(name.to_string(), value.to_string());
            }
        }
    }

    pub fn expand_variables(&self, jobs: &mut [Job]) {
        for mut job in &mut jobs[..] {
            job.command = self.expand_string(&job.command).to_string();
            job.args = job.args
                          .iter()
                          .map(|original: &String| self.expand_string(&original).to_string())
                          .collect();
        }
    }

    #[inline]
    fn expand_string<'a>(&'a self, original: &'a str) -> &'a str {
        if original.starts_with("$") {
            if let Some(value) = self.variables.get(&original[1..]) {
                &value
            } else {
                ""
            }
        } else {
            original
        }
    }
}
<commit_msg>Fix style<commit_after>use std::collections::BTreeMap;
use std::io::{stdout, Write};

use super::peg::Job;
use super::input_editor::readln;

pub struct Variables {
    variables: BTreeMap<String, String>,
}

impl Variables {
    pub fn new() -> Variables {
        Variables { variables: BTreeMap::new() }
    }

    pub fn read(&mut self, args: &[String]) {
        let mut out = stdout();
        for i in 1..args.len() {
            if let Some(arg_original) = args.get(i) {
                let arg = arg_original.trim();
                print!("{}=", arg);
                if let Err(message) = out.flush() {
                    println!("{}: Failed to flush stdout", message);
                }
                if let Some(value_original) = readln() {
                    let value = value_original.trim();
                    self.set_var(arg, value);
                }
            }
        }
    }

    pub fn let_(&mut self, args: &[String]) {
        match (args.get(1), args.get(2)) {
            (Some(key), Some(value)) => {
                self.variables.insert(key.clone(), value.clone());
            }
            (Some(key), None) => {
                self.variables.remove(key);
            }
            _ => {
                for (key, value) in self.variables.iter() {
                    println!("{}={}", key, value);
                }
            }
        }
    }

    pub fn set_var(&mut self, name: &str, value: &str) {
        if !name.is_empty() {
            if value.is_empty() {
                self.variables.remove(&name.to_string());
            } else {
                self.variables.insert(name.to_string(), value.to_string());
            }
        }
    }

    pub fn expand_variables(&self, jobs: &mut [Job]) {
        for mut job in &mut jobs[..] {
            job.command = self.expand_string(&job.command).to_string();
            job.args = job.args
                          .iter()
                          .map(|original: &String| self.expand_string(&original).to_string())
                          .collect();
        }
    }

    #[inline]
    fn expand_string<'a>(&'a self, original: &'a str) -> &'a str {
        if original.starts_with("$") {
            if let Some(value) = self.variables.get(&original[1..]) {
                &value
            } else {
                ""
            }
        } else {
            original
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate version;

extern crate libimagbookmark;
extern crate libimagentrylink;
extern crate libimagentrytag;
extern crate libimagrt;
extern crate libimagerror;
extern crate libimagutil;

use libimagentrytag::ui::{get_add_tags, get_remove_tags};
use libimagentrylink::internal::Link;
use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagbookmark::collection::BookmarkCollection;
use libimagbookmark::link::Link as BookmarkLink;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-bookmark",
                                    &version!()[..],
                                    "Bookmark collection tool",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            debug!("Call {}", name);
            match name {
                "add"        => add(&rt),
                "collection" => collection(&rt),
                "list"       => list(&rt),
                "remove"     => remove(&rt),
                _            => {
                    debug!("Unknown command"); // More error handling
                },
            }
        });
}

fn add(rt: &Runtime) {
    let scmd = rt.cli().subcommand_matches("add").unwrap();
    let coll = scmd.value_of("collection").unwrap(); // enforced by clap

    BookmarkCollection::get(rt.store(), coll)
        .map(|mut collection| {
            for url in scmd.values_of("urls").unwrap() { // enforced by clap
                collection.add_link(BookmarkLink::from(url)).map_err(|e| trace_error(&e));
            }
        });
    info!("Ready");
}

fn collection(rt: &Runtime) {
    unimplemented!()
}

fn list(rt: &Runtime) {
    unimplemented!()
}

fn remove(rt: &Runtime) {
    let scmd = rt.cli().subcommand_matches("remove").unwrap();
    let coll = scmd.value_of("collection").unwrap(); // enforced by clap

    BookmarkCollection::get(rt.store(), coll)
        .map(|mut collection| {
            for url in scmd.values_of("urls").unwrap() { // enforced by clap
                collection.remove_link(BookmarkLink::from(url)).map_err(|e| trace_error(&e));
            }
        });
    info!("Ready");
}

<commit_msg>Impl collection()<commit_after>extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate version;

extern crate libimagbookmark;
extern crate libimagentrylink;
extern crate libimagentrytag;
extern crate libimagrt;
extern crate libimagerror;
extern crate libimagutil;

use std::process::exit;

use libimagentrytag::ui::{get_add_tags, get_remove_tags};
use libimagentrylink::internal::Link;
use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagbookmark::collection::BookmarkCollection;
use libimagbookmark::link::Link as BookmarkLink;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;

fn main() {
    let rt = generate_runtime_setup("imag-bookmark",
                                    &version!()[..],
                                    "Bookmark collection tool",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            debug!("Call {}", name);
            match name {
                "add"        => add(&rt),
                "collection" => collection(&rt),
                "list"       => list(&rt),
                "remove"     => remove(&rt),
                _            => {
                    debug!("Unknown command"); // More error handling
                },
            }
        });
}

fn add(rt: &Runtime) {
    let scmd = rt.cli().subcommand_matches("add").unwrap();
    let coll = scmd.value_of("collection").unwrap(); // enforced by clap

    BookmarkCollection::get(rt.store(), coll)
        .map(|mut collection| {
            for url in scmd.values_of("urls").unwrap() { // enforced by clap
                collection.add_link(BookmarkLink::from(url)).map_err(|e| trace_error(&e));
            }
        });
    info!("Ready");
}

fn collection(rt: &Runtime) {
    let scmd = rt.cli().subcommand_matches("collection").unwrap();

    if scmd.is_present("add") { // adding a new collection
        let name = scmd.value_of("add").unwrap();
        if let Ok(_) = BookmarkCollection::new(rt.store(), name) {
            info!("Created: {}", name);
        } else {
            warn!("Creating collection {} failed", name);
            exit(1);
        }
    }

    if scmd.is_present("remove") { // remove a collection
        let name = scmd.value_of("remove").unwrap();
        if let Ok(_) = BookmarkCollection::delete(rt.store(), name) {
            info!("Deleted: {}", name);
        } else {
            warn!("Deleting collection {} failed", name);
            exit(1);
        }
    }
}

fn list(rt: &Runtime) {
    unimplemented!()
}

fn remove(rt: &Runtime) {
    let scmd = rt.cli().subcommand_matches("remove").unwrap();
    let coll = scmd.value_of("collection").unwrap(); // enforced by clap

    BookmarkCollection::get(rt.store(), coll)
        .map(|mut collection| {
            for url in scmd.values_of("urls").unwrap() { // enforced by clap
                collection.remove_link(BookmarkLink::from(url)).map_err(|e| trace_error(&e));
            }
        });
    info!("Ready");
}

<|endoftext|>


<commit_before><commit_msg>unit-like structures added<commit_after><|endoftext|>


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

use collections::string::{String, ToString};
use collections::vec::Vec;
use collections::vec_deque::VecDeque;

use core::ops::DerefMut;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use core::usize;

use common::elf::Elf;
use common::event::Event;
use common::get_slice::GetSlice;
use common::memory;

use scheduler::context::{context_switch, Context, ContextMemory};

use schemes::{Result, KScheme, Resource, ResourceSeek, Url};

use sync::Intex;

use syscall::SysError;
use syscall::handle::*;

pub enum Msg {
    Start,
    Stop,
    Open(*const u8, usize),
    Close(usize),
    Dup(usize),
    Path(usize, *mut u8, usize),
    Read(usize, *mut u8, usize),
    Write(usize, *const u8, usize),
    Seek(usize, isize, isize),
    Sync(usize),
    Truncate(usize, usize),
    Event(*const Event),
}

pub struct Response {
    msg: Msg,
    result: AtomicUsize,
    ready: AtomicBool,
}

impl Response {
    pub fn new(msg: Msg) -> Box<Response> {
        box Response {
            msg: msg,
            result: AtomicUsize::new(0),
            ready: AtomicBool::new(false),
        }
    }

    pub fn set(&mut self, result: usize) {
        self.result.store(result, Ordering::SeqCst);
        self.ready.store(true, Ordering::SeqCst);
    }

    pub fn get(&self) -> usize {
        while !self.ready.load(Ordering::SeqCst) {
            unsafe { context_switch(false) };
        }

        return self.result.load(Ordering::SeqCst);
    }
}

impl Drop for Response {
    fn drop(&mut self) {
        while !self.ready.load(Ordering::SeqCst) {
            unsafe { context_switch(false) };
        }
    }
}

/// A scheme resource
pub struct SchemeResource {
    /// Pointer to parent
    pub parent: *mut SchemeItem,
    /// File handle
    pub handle: usize,
}

impl SchemeResource {
    pub fn send(&self, msg: Msg) -> Result<usize> {
        unsafe { (*self.parent).send(msg) }
    }
}

impl Resource for SchemeResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        match self.send(Msg::Dup(self.handle)) {
            Ok(fd) => Ok(box SchemeResource {
                parent: self.parent,
                handle: fd,
            }),
            Err(err) => Err(err)
        }
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        let mut buf: [u8; 4096] = [0; 4096];
        match self.send(Msg::Path(self.handle, buf.as_mut_ptr(), buf.len())) {
            Ok(result) => Url::from_string(unsafe {
                String::from_utf8_unchecked(Vec::from(buf.get_slice(None, Some(result))))
            }),
            Err(err) => Url::new()
        }
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let mut ptr = buf.as_mut_ptr();

        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(translated) = unsafe { current.translate(ptr as usize) } {
                ptr = translated as *mut u8;
            }
        }

        self.send(Msg::Read(self.handle, ptr, buf.len()))
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let mut ptr = buf.as_ptr();

        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(translated) = unsafe { current.translate(ptr as usize) } {
                ptr = translated as *const u8;
            }
        }

        self.send(Msg::Write(self.handle, ptr, buf.len()))
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        let offset;
        let whence;
        match pos {
            ResourceSeek::Start(off) => {
                whence = 0;
                offset = off as isize;
            }
            ResourceSeek::Current(off) => {
                whence = 1;
                offset = off;
            }
            ResourceSeek::End(off) => {
                whence = 2;
                offset = off;
            }
        }

        self.send(Msg::Seek(self.handle, offset, whence))
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        match self.send(Msg::Sync(self.handle)) {
            Ok(_) => Ok(()),
            Err(err) => Err(err)
        }
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        match self.send(Msg::Truncate(self.handle, len)) {
            Ok(_) => Ok(()),
            Err(err) => Err(err)
        }
    }
}

impl Drop for SchemeResource {
    fn drop(&mut self) {
        self.send(Msg::Close(self.handle));
    }
}

/// A scheme item
pub struct SchemeItem {
    /// The URL
    url: Url,
    /// The scheme
    scheme: String,
    /// The binary for the scheme
    binary: Url,
    /// Messages to be responded to
    responses: Intex<VecDeque<*mut Response>>,
    /// The handle
    handle: usize,
    _start: usize,
    _stop: usize,
    _open: usize,
    _dup: usize,
    _fpath: usize,
    _read: usize,
    _write: usize,
    _lseek: usize,
    _fsync: usize,
    _ftruncate: usize,
    _close: usize,
    _event: usize,
}

impl SchemeItem {
    /// Load scheme item from URL
    pub fn from_url(url: &Url) -> Box<SchemeItem> {
        let mut scheme_item = box SchemeItem {
            url: url.clone(),
            scheme: String::new(),
            binary: Url::from_string(url.to_string() + "main.bin"),
            responses: Intex::new(VecDeque::new()),
            handle: 0,
            _start: 0,
            _stop: 0,
            _open: 0,
            _dup: 0,
            _fpath: 0,
            _read: 0,
            _write: 0,
            _lseek: 0,
            _fsync: 0,
            _ftruncate: 0,
            _close: 0,
            _event: 0,
        };

        for part in url.reference().rsplit('/') {
            if !part.is_empty() {
                scheme_item.scheme = part.to_string();
                break;
            }
        }

        let mut memory = Vec::new();
        if let Ok(mut resource) = scheme_item.binary.open() {
            let mut vec: Vec<u8> = Vec::new();
            resource.read_to_end(&mut vec);

            unsafe {
                let executable = Elf::from_data(vec.as_ptr() as usize);

                scheme_item._start = executable.symbol("_start");
                scheme_item._stop = executable.symbol("_stop");
                scheme_item._open = executable.symbol("_open");
                scheme_item._dup = executable.symbol("_dup");
                scheme_item._fpath = executable.symbol("_fpath");
                scheme_item._read = executable.symbol("_read");
                scheme_item._write = executable.symbol("_write");
                scheme_item._lseek = executable.symbol("_lseek");
                scheme_item._fsync = executable.symbol("_fsync");
                scheme_item._ftruncate = executable.symbol("_ftruncate");
                scheme_item._close = executable.symbol("_close");
                scheme_item._event = executable.symbol("_event");

                for segment in executable.load_segment().iter() {
                    let virtual_address = segment.vaddr as usize;
                    let virtual_size = segment.mem_len as usize;
                    let physical_address = memory::alloc(virtual_size);

                    if physical_address > 0 {
                        // Copy progbits
                        ::memcpy(physical_address as *mut u8,
                                 (executable.data + segment.off as usize) as *const u8,
                                 segment.file_len as usize);
                        // Zero bss
                        ::memset((physical_address + segment.file_len as usize) as *mut u8,
                                 0,
                                 segment.mem_len as usize - segment.file_len as usize);

                        memory.push(ContextMemory {
                            physical_address: physical_address,
                            virtual_address: virtual_address,
                            virtual_size: virtual_size,
                            writeable: segment.flags & 2 == 2,
                        });
                    }
                }
            }
        }

        let wd = url.to_string();
        let scheme_item_ptr: *mut SchemeItem = scheme_item.deref_mut();
        Context::spawn(scheme_item.binary.to_string(),
                       box move || {
                           unsafe {
                               {
                                   let wd_c = wd + "\0";
                                   do_sys_chdir(wd_c.as_ptr());

                                   let stdio_c = "debug:\0";
                                   do_sys_open(stdio_c.as_ptr(), 0);
                                   do_sys_open(stdio_c.as_ptr(), 0);
                                   do_sys_open(stdio_c.as_ptr(), 0);

                                   let mut contexts = ::env().contexts.lock();
                                   if let Some(mut current) = contexts.current_mut() {
                                       current.unmap();
                                       (*current.memory.get()) = memory;
                                       current.map();
                                   }
                               }

                               (*scheme_item_ptr).run();
                           }
                       });

        scheme_item.handle = match scheme_item.send(Msg::Start) {
            Ok(handle) => handle,
            Err(_) => 0
        };

        scheme_item
    }
}

impl KScheme for SchemeItem {
    fn scheme(&self) -> &str {
        return &self.scheme;
    }

    // TODO: Hack for orbital
    fn event(&mut self, event: &Event) {
        self.send(Msg::Event(event));
    }

    fn open(&mut self, url: &Url, flags: usize) -> Result<Box<Resource>> {
        let c_str = url.to_string() + "\0";
        match self.send(Msg::Open(c_str.as_ptr(), flags)) {
            Ok(fd) => Ok(box SchemeResource {
                parent: self,
                handle: fd,
            }),
            Err(err) => Err(err)
        }
    }
}

impl Drop for SchemeItem {
    fn drop(&mut self) {
        self.send(Msg::Stop);
    }
}

impl SchemeItem {
    pub fn send(&mut self, msg: Msg) -> Result<usize> {
        let mut response = Response::new(msg);

        self.responses.lock().push_back(response.deref_mut());

        SysError::demux(response.get())
    }

    // TODO: More advanced check
    pub fn valid(&self, call: usize) -> bool {
        call > 0
    }

    pub unsafe fn run(&mut self) {
        let mut running = true;
        while running {
            let response_option = self.responses.lock().pop_front();

            if let Some(response_ptr) = response_option {
                let ret = match (*response_ptr).msg {
                    Msg::Start => if self.valid(self._start) {
                        let fn_ptr: *const usize = &self._start;
                        (*(fn_ptr as *const extern "C" fn() -> usize))()
                    } else {
                        0
                    },
                    Msg::Stop => if self.valid(self._stop) {
                        running = false;
                        let fn_ptr: *const usize = &self._stop;
                        (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle)
                    } else {
                        usize::MAX
                    },
                    Msg::Open(path, flags) => if self.valid(self._open) {
                        let fn_ptr: *const usize = &self._open;
                        (*(fn_ptr as *const extern "C" fn(usize, *const u8, usize) -> usize))(self.handle, path, flags)
                    } else {
                        usize::MAX
                    },
                    Msg::Event(event_ptr) => if self.valid(self._event) {
                        let fn_ptr: *const usize = &self._event;
                        (*(fn_ptr as *const extern "C" fn(usize, usize) -> usize))(self.handle, event_ptr as usize)
                    } else {
                        usize::MAX
                    },
                    Msg::Dup(fd) => if self.valid(self._dup) {
                        let fn_ptr: *const usize = &self._dup;
                        (*(fn_ptr as *const extern "C" fn(usize) -> usize))(fd)
                    } else {
                        usize::MAX
                    },
                    Msg::Path(fd, ptr, len) => if self.valid(self._fpath) {
                        let fn_ptr: *const usize = &self._fpath;
                        (*(fn_ptr as *const extern "C" fn(usize, *mut u8, usize) -> usize))(fd,
                                                                                ptr,
                                                                                len)
                    } else {
                        usize::MAX
                    },
                    Msg::Read(fd, ptr, len) => if self.valid(self._read) {
                        let fn_ptr: *const usize = &self._read;
                        (*(fn_ptr as *const extern "C" fn(usize, *mut u8, usize) -> usize))(fd,
                                                                                ptr,
                                                                                len)
                    } else {
                        usize::MAX
                    },
                    Msg::Write(fd, ptr, len) =>
                        if self.valid(self._write) {
                            let fn_ptr: *const usize = &self._write;
                            (*(fn_ptr as *const extern "C" fn(usize, *const u8, usize) -> usize))(fd, ptr, len)
                        } else {
                            usize::MAX
                        },
                    Msg::Seek(fd, offset, whence) =>
                        if self.valid(self._lseek) {
                            let fn_ptr: *const usize = &self._lseek;
                            (*(fn_ptr as *const extern "C" fn(usize, isize, isize) -> usize))(fd, offset, whence)
                        } else {
                            usize::MAX
                        },
                    Msg::Sync(fd) => if self.valid(self._fsync) {
                        let fn_ptr: *const usize = &self._fsync;
                        (*(fn_ptr as *const extern "C" fn(usize) -> usize))(fd)
                    } else {
                        usize::MAX
                    },
                    Msg::Truncate(fd, len) => if self.valid(self._ftruncate) {
                        let fn_ptr: *const usize = &self._ftruncate;
                        (*(fn_ptr as *const extern "C" fn(usize, usize) -> usize))(fd, len)
                    } else {
                        usize::MAX
                    },
                    Msg::Close(fd) => if self.valid(self._close) {
                        let fn_ptr: *const usize = &self._close;
                        (*(fn_ptr as *const extern "C" fn(usize) -> usize))(fd)
                    } else {
                        usize::MAX
                    },
                };

                (*response_ptr).set(ret);
            } else {
                context_switch(false);
            }
        }
    }
}
<commit_msg>Modify scheme loader as well<commit_after>use alloc::boxed::Box;

use collections::string::{String, ToString};
use collections::vec::Vec;
use collections::vec_deque::VecDeque;

use core::ops::DerefMut;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use core::usize;

use common::elf::Elf;
use common::event::Event;
use common::get_slice::GetSlice;
use common::memory;

use scheduler::context::{context_switch, Context, ContextMemory};

use schemes::{Result, KScheme, Resource, ResourceSeek, Url};

use sync::Intex;

use syscall::SysError;
use syscall::handle::*;

pub enum Msg {
    Start,
    Stop,
    Open(*const u8, usize),
    Close(usize),
    Dup(usize),
    Path(usize, *mut u8, usize),
    Read(usize, *mut u8, usize),
    Write(usize, *const u8, usize),
    Seek(usize, isize, isize),
    Sync(usize),
    Truncate(usize, usize),
    Event(*const Event),
}

pub struct Response {
    msg: Msg,
    result: AtomicUsize,
    ready: AtomicBool,
}

impl Response {
    pub fn new(msg: Msg) -> Box<Response> {
        box Response {
            msg: msg,
            result: AtomicUsize::new(0),
            ready: AtomicBool::new(false),
        }
    }

    pub fn set(&mut self, result: usize) {
        self.result.store(result, Ordering::SeqCst);
        self.ready.store(true, Ordering::SeqCst);
    }

    pub fn get(&self) -> usize {
        while !self.ready.load(Ordering::SeqCst) {
            unsafe { context_switch(false) };
        }

        return self.result.load(Ordering::SeqCst);
    }
}

impl Drop for Response {
    fn drop(&mut self) {
        while !self.ready.load(Ordering::SeqCst) {
            unsafe { context_switch(false) };
        }
    }
}

/// A scheme resource
pub struct SchemeResource {
    /// Pointer to parent
    pub parent: *mut SchemeItem,
    /// File handle
    pub handle: usize,
}

impl SchemeResource {
    pub fn send(&self, msg: Msg) -> Result<usize> {
        unsafe { (*self.parent).send(msg) }
    }
}

impl Resource for SchemeResource {
    /// Duplicate the resource
    fn dup(&self) -> Result<Box<Resource>> {
        match self.send(Msg::Dup(self.handle)) {
            Ok(fd) => Ok(box SchemeResource {
                parent: self.parent,
                handle: fd,
            }),
            Err(err) => Err(err)
        }
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        let mut buf: [u8; 4096] = [0; 4096];
        match self.send(Msg::Path(self.handle, buf.as_mut_ptr(), buf.len())) {
            Ok(result) => Url::from_string(unsafe {
                String::from_utf8_unchecked(Vec::from(buf.get_slice(None, Some(result))))
            }),
            Err(err) => Url::new()
        }
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        let mut ptr = buf.as_mut_ptr();

        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(translated) = unsafe { current.translate(ptr as usize) } {
                ptr = translated as *mut u8;
            }
        }

        self.send(Msg::Read(self.handle, ptr, buf.len()))
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let mut ptr = buf.as_ptr();

        let contexts = ::env().contexts.lock();
        if let Some(current) = contexts.current() {
            if let Some(translated) = unsafe { current.translate(ptr as usize) } {
                ptr = translated as *const u8;
            }
        }

        self.send(Msg::Write(self.handle, ptr, buf.len()))
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Result<usize> {
        let offset;
        let whence;
        match pos {
            ResourceSeek::Start(off) => {
                whence = 0;
                offset = off as isize;
            }
            ResourceSeek::Current(off) => {
                whence = 1;
                offset = off;
            }
            ResourceSeek::End(off) => {
                whence = 2;
                offset = off;
            }
        }

        self.send(Msg::Seek(self.handle, offset, whence))
    }

    /// Sync the resource
    fn sync(&mut self) -> Result<()> {
        match self.send(Msg::Sync(self.handle)) {
            Ok(_) => Ok(()),
            Err(err) => Err(err)
        }
    }

    fn truncate(&mut self, len: usize) -> Result<()> {
        match self.send(Msg::Truncate(self.handle, len)) {
            Ok(_) => Ok(()),
            Err(err) => Err(err)
        }
    }
}

impl Drop for SchemeResource {
    fn drop(&mut self) {
        self.send(Msg::Close(self.handle));
    }
}

/// A scheme item
pub struct SchemeItem {
    /// The URL
    url: Url,
    /// The scheme
    scheme: String,
    /// The binary for the scheme
    binary: Url,
    /// Messages to be responded to
    responses: Intex<VecDeque<*mut Response>>,
    /// The handle
    handle: usize,
    _start: usize,
    _stop: usize,
    _open: usize,
    _dup: usize,
    _fpath: usize,
    _read: usize,
    _write: usize,
    _lseek: usize,
    _fsync: usize,
    _ftruncate: usize,
    _close: usize,
    _event: usize,
}

impl SchemeItem {
    /// Load scheme item from URL
    pub fn from_url(url: &Url) -> Box<SchemeItem> {
        let mut scheme_item = box SchemeItem {
            url: url.clone(),
            scheme: String::new(),
            binary: Url::from_string(url.to_string() + "main.bin"),
            responses: Intex::new(VecDeque::new()),
            handle: 0,
            _start: 0,
            _stop: 0,
            _open: 0,
            _dup: 0,
            _fpath: 0,
            _read: 0,
            _write: 0,
            _lseek: 0,
            _fsync: 0,
            _ftruncate: 0,
            _close: 0,
            _event: 0,
        };

        for part in url.reference().rsplit('/') {
            if !part.is_empty() {
                scheme_item.scheme = part.to_string();
                break;
            }
        }

        let mut memory = Vec::new();
        if let Ok(mut resource) = scheme_item.binary.open() {
            let mut vec: Vec<u8> = Vec::new();
            resource.read_to_end(&mut vec);

            unsafe {
                let executable = Elf::from_data(vec.as_ptr() as usize);

                scheme_item._start = executable.symbol("_start");
                scheme_item._stop = executable.symbol("_stop");
                scheme_item._open = executable.symbol("_open");
                scheme_item._dup = executable.symbol("_dup");
                scheme_item._fpath = executable.symbol("_fpath");
                scheme_item._read = executable.symbol("_read");
                scheme_item._write = executable.symbol("_write");
                scheme_item._lseek = executable.symbol("_lseek");
                scheme_item._fsync = executable.symbol("_fsync");
                scheme_item._ftruncate = executable.symbol("_ftruncate");
                scheme_item._close = executable.symbol("_close");
                scheme_item._event = executable.symbol("_event");

                for segment in executable.load_segment().iter() {
                    let virtual_address = segment.vaddr as usize;
                    let virtual_size = segment.mem_len as usize;

                    //TODO: Warning: Investigate this hack!
                    let hack = virtual_address % 4096;

                    let physical_address = memory::alloc(virtual_size + hack);

                    if physical_address > 0 {
                        debugln!("VADDR: {:X} OFF: {:X} FLG: {:X} HACK: {:X}", segment.vaddr, segment.off, segment.flags, hack);

                        // Copy progbits
                        ::memcpy((physical_address + hack) as *mut u8,
                                 (executable.data + segment.off as usize) as *const u8,
                                 segment.file_len as usize);
                        // Zero bss
                        if segment.mem_len > segment.file_len {
                            debugln!("BSS: {:X} {}", segment.vaddr + segment.file_len, segment.mem_len - segment.file_len);
                            ::memset((physical_address + hack + segment.file_len as usize) as *mut u8,
                                    0,
                                    segment.mem_len as usize - segment.file_len as usize);
                        }

                        memory.push(ContextMemory {
                            physical_address: physical_address,
                            virtual_address: virtual_address - hack,
                            virtual_size: virtual_size + hack,
                            writeable: segment.flags & 2 == 2
                        });
                    }
                }
            }
        }

        let wd = url.to_string();
        let scheme_item_ptr: *mut SchemeItem = scheme_item.deref_mut();
        Context::spawn(scheme_item.binary.to_string(),
                       box move || {
                           unsafe {
                               {
                                   let wd_c = wd + "\0";
                                   do_sys_chdir(wd_c.as_ptr());

                                   let stdio_c = "debug:\0";
                                   do_sys_open(stdio_c.as_ptr(), 0);
                                   do_sys_open(stdio_c.as_ptr(), 0);
                                   do_sys_open(stdio_c.as_ptr(), 0);

                                   let mut contexts = ::env().contexts.lock();
                                   if let Some(mut current) = contexts.current_mut() {
                                       current.unmap();
                                       (*current.memory.get()) = memory;
                                       current.map();
                                   }
                               }

                               (*scheme_item_ptr).run();
                           }
                       });

        scheme_item.handle = match scheme_item.send(Msg::Start) {
            Ok(handle) => handle,
            Err(_) => 0
        };

        scheme_item
    }
}

impl KScheme for SchemeItem {
    fn scheme(&self) -> &str {
        return &self.scheme;
    }

    // TODO: Hack for orbital
    fn event(&mut self, event: &Event) {
        self.send(Msg::Event(event));
    }

    fn open(&mut self, url: &Url, flags: usize) -> Result<Box<Resource>> {
        let c_str = url.to_string() + "\0";
        match self.send(Msg::Open(c_str.as_ptr(), flags)) {
            Ok(fd) => Ok(box SchemeResource {
                parent: self,
                handle: fd,
            }),
            Err(err) => Err(err)
        }
    }
}

impl Drop for SchemeItem {
    fn drop(&mut self) {
        self.send(Msg::Stop);
    }
}

impl SchemeItem {
    pub fn send(&mut self, msg: Msg) -> Result<usize> {
        let mut response = Response::new(msg);

        self.responses.lock().push_back(response.deref_mut());

        SysError::demux(response.get())
    }

    // TODO: More advanced check
    pub fn valid(&self, call: usize) -> bool {
        call > 0
    }

    pub unsafe fn run(&mut self) {
        let mut running = true;
        while running {
            let response_option = self.responses.lock().pop_front();

            if let Some(response_ptr) = response_option {
                let ret = match (*response_ptr).msg {
                    Msg::Start => if self.valid(self._start) {
                        let fn_ptr: *const usize = &self._start;
                        (*(fn_ptr as *const extern "C" fn() -> usize))()
                    } else {
                        0
                    },
                    Msg::Stop => if self.valid(self._stop) {
                        running = false;
                        let fn_ptr: *const usize = &self._stop;
                        (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle)
                    } else {
                        usize::MAX
                    },
                    Msg::Open(path, flags) => if self.valid(self._open) {
                        let fn_ptr: *const usize = &self._open;
                        (*(fn_ptr as *const extern "C" fn(usize, *const u8, usize) -> usize))(self.handle, path, flags)
                    } else {
                        usize::MAX
                    },
                    Msg::Event(event_ptr) => if self.valid(self._event) {
                        let fn_ptr: *const usize = &self._event;
                        (*(fn_ptr as *const extern "C" fn(usize, usize) -> usize))(self.handle, event_ptr as usize)
                    } else {
                        usize::MAX
                    },
                    Msg::Dup(fd) => if self.valid(self._dup) {
                        let fn_ptr: *const usize = &self._dup;
                        (*(fn_ptr as *const extern "C" fn(usize) -> usize))(fd)
                    } else {
                        usize::MAX
                    },
                    Msg::Path(fd, ptr, len) => if self.valid(self._fpath) {
                        let fn_ptr: *const usize = &self._fpath;
                        (*(fn_ptr as *const extern "C" fn(usize, *mut u8, usize) -> usize))(fd,
                                                                                ptr,
                                                                                len)
                    } else {
                        usize::MAX
                    },
                    Msg::Read(fd, ptr, len) => if self.valid(self._read) {
                        let fn_ptr: *const usize = &self._read;
                        (*(fn_ptr as *const extern "C" fn(usize, *mut u8, usize) -> usize))(fd,
                                                                                ptr,
                                                                                len)
                    } else {
                        usize::MAX
                    },
                    Msg::Write(fd, ptr, len) =>
                        if self.valid(self._write) {
                            let fn_ptr: *const usize = &self._write;
                            (*(fn_ptr as *const extern "C" fn(usize, *const u8, usize) -> usize))(fd, ptr, len)
                        } else {
                            usize::MAX
                        },
                    Msg::Seek(fd, offset, whence) =>
                        if self.valid(self._lseek) {
                            let fn_ptr: *const usize = &self._lseek;
                            (*(fn_ptr as *const extern "C" fn(usize, isize, isize) -> usize))(fd, offset, whence)
                        } else {
                            usize::MAX
                        },
                    Msg::Sync(fd) => if self.valid(self._fsync) {
                        let fn_ptr: *const usize = &self._fsync;
                        (*(fn_ptr as *const extern "C" fn(usize) -> usize))(fd)
                    } else {
                        usize::MAX
                    },
                    Msg::Truncate(fd, len) => if self.valid(self._ftruncate) {
                        let fn_ptr: *const usize = &self._ftruncate;
                        (*(fn_ptr as *const extern "C" fn(usize, usize) -> usize))(fd, len)
                    } else {
                        usize::MAX
                    },
                    Msg::Close(fd) => if self.valid(self._close) {
                        let fn_ptr: *const usize = &self._close;
                        (*(fn_ptr as *const extern "C" fn(usize) -> usize))(fd)
                    } else {
                        usize::MAX
                    },
                };

                (*response_ptr).set(ret);
            } else {
                context_switch(false);
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>mkdir init<commit_after>#[crate_id(name="mkdir", vers="1.0.0", author="Nicholas Juszczak")];

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

extern mod extra;

use std::os;
use std::io::stderr;
use extra::getopts::groups;
use std::io::fs::mkdir;
use std::path;

static VERSION: &'static str = "1.0.0";

fn print_help(opts: &[groups::OptGroup]) {
    println!("mkdir v{} - make a new directory with the given path", VERSION);
    println("");
    println("Usage:");
    print(groups::usage("Create the given DIRECTORY(ies)" +
                        " if they do not exist", opts));
}

fn main() {
    let args: ~[~str] = os::args();
    let program: ~str = args[0].clone();

    let opts: ~[groups::OptGroup] = ~[
        //groups::optflag("m", "mode", "set file mode"),
        groups::optflag("p", "parents", "make parent directories as needed"),
        groups::optflag("v", "verbose",
                        "print a message for each printed directory"),
        groups::optflag("", "help", "display this help"),
        groups::optflag("", "version", "display this version")
    ];

    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                     "Invalid options\n{}", f.to_err_msg());
            os::set_exit_status(1);
            return;
        }
    };

    if matches.opt_present("help") {
        print_help(opts);
        return;
    }
    if matches.opt_present("version") {
        println("mkdir v" + VERSION);
        return;
    }

    let parents: bool = matches.opt_present("parents");
    mkdir(parents);
}

fn mkdir(mk_parents: bool) {

}

<|endoftext|>


<commit_before><commit_msg>Add missing file<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

pub mod timeout {
    use ffi;

    pub fn add<T>(interval: u32, func: fn(&T) -> i32, data: &T) -> u32 {
        let tmp = data as *const T;
        let tmp_f = func as ffi::gpointer;

        unsafe { ffi::g_timeout_add(interval, tmp_f, tmp as ffi::gpointer) }
    }

    pub fn add_seconds<T>(interval: u32, func: fn(&T) -> i32, data: &T) -> u32 {
        let tmp = data as *const T;
        let tmp_f = func as ffi::gpointer;

        unsafe { ffi::g_timeout_add_seconds(interval, tmp_f, tmp as ffi::gpointer) }
    }
}<|endoftext|>


<commit_before><commit_msg>Add Vec<Box<T>> test<commit_after>extern crate ralloc;

#[test]
fn test() {
    let mut vec = Vec::new();

    for i in 0..0xFFFF {
        vec.push(Box::new(i));
    }

    assert_eq!(*vec[0xDEAD], 0xDEAD);
    assert_eq!(*vec[0xBEAF], 0xBEAF);
    assert_eq!(*vec[0xABCD], 0xABCD);
    assert_eq!(*vec[0xFFAB], 0xFFAB);
    assert_eq!(*vec[0xAAAA], 0xAAAA);

    for i in 0xFFFF..0 {
        assert_eq!(*vec.pop().unwrap(), i);
    }

    for i in 0..0xFFFF {
        *vec[i] = 0;
        assert_eq!(*vec[i], 0);
    }
}
<|endoftext|>


<commit_before><commit_msg>Generate random secret number<commit_after><|endoftext|>


<commit_before><commit_msg>add basic test for rustdoc intra links<commit_after>// Copyright 2017 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.

// @has intra_links/index.html
// @has - '//a/@href' '../intra_links/struct.ThisType.html'
// @has - '//a/@href' '../intra_links/enum.ThisEnum.html'
// @has - '//a/@href' '../intra_links/trait.ThisTrait.html'
// @has - '//a/@href' '../intra_links/type.ThisAlias.html'
// @has - '//a/@href' '../intra_links/union.ThisUnion.html'
// @has - '//a/@href' '../intra_links/fn.this_function.html'
// @has - '//a/@href' '../intra_links/constant.THIS_CONST.html'
// @has - '//a/@href' '../intra_links/static.THIS_STATIC.html'
//! In this crate we would like to link to:
//!
//! * [`ThisType`](struct ::ThisType)
//! * [`ThisEnum`](enum ::ThisEnum)
//! * [`ThisTrait`](trait ::ThisTrait)
//! * [`ThisAlias`](type ::ThisAlias)
//! * [`ThisUnion`](union ::ThisUnion)
//! * [`this_function`](::this_function())
//! * [`THIS_CONST`](const ::THIS_CONST)
//! * [`THIS_STATIC`](static ::THIS_STATIC)

pub struct ThisType;
pub enum ThisEnum { ThisVariant, }
pub trait ThisTrait {}
pub type ThisAlias = Result<(), ()>;
pub union ThisUnion { this_field: usize, }

pub fn this_function() {}
pub const THIS_CONST: usize = 5usize;
pub static THIS_STATIC: usize = 5usize;
<|endoftext|>


<commit_before>// Determines the ways in which a generic function body depends
// on its type parameters. Used to aggressively reuse compiled
// function bodies for different types.

// This unfortunately depends on quite a bit of knowledge about the
// details of the language semantics, and is likely to accidentally go
// out of sync when something is changed. It could be made more
// powerful by distinguishing between functions that only need to know
// the size and alignment of a type, and those that also use its
// drop/take glue. But this would increase the fragility of the code
// to a ridiculous level, and probably not catch all that many extra
// opportunities for reuse.

// (An other approach to doing what this code does is to instrument
// the translation code to set flags whenever it does something like
// alloca a type or get a tydesc. This would not duplicate quite as
// much information, but have the disadvantage of being very
// invasive.)

import std::map::hashmap;
import std::list;
import driver::session::session;
import metadata::csearch;
import syntax::ast::*, syntax::ast_util, syntax::visit;
import common::*;

// FIXME distinguish between size/alignment and take/drop dependencies
type type_uses = uint; // Bitmask
const use_repr: uint = 1u; // Dependency on size/alignment and take/drop glue
const use_tydesc: uint = 2u; // Takes the tydesc, or compares

type ctx = {ccx: @crate_ctxt,
            uses: [mut type_uses]};

fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
    -> [type_uses] {
    alt ccx.type_use_cache.find(fn_id) {
      some(uses) { ret uses; }
      none {}
    }
    let fn_id_loc = if fn_id.crate == local_crate { fn_id }
                    else { base::maybe_instantiate_inline(ccx, fn_id) };
    // Conservatively assume full use for recursive loops
    ccx.type_use_cache.insert(fn_id, vec::from_elem(n_tps, 3u));

    let cx = {ccx: ccx, uses: vec::to_mut(vec::from_elem(n_tps, 0u))};
    alt ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).struct {
      ty::ty_fn({inputs, _}) {
        for vec::each(inputs) {|arg|
            if arg.mode == expl(by_val) { type_needs(cx, use_repr, arg.ty); }
        }
      }
      _ {}
    }

    if fn_id_loc.crate != local_crate {
        let uses = vec::from_mut(cx.uses);
        ccx.type_use_cache.insert(fn_id, uses);
        ret uses;
    }
    let map_node = alt ccx.tcx.items.find(fn_id_loc.node) {
        some(x) { x }
        none    { ccx.sess.bug(#fmt("type_uses_for: unbound item ID %?",
                                    fn_id_loc)); }
    };
    alt check map_node {
      ast_map::node_item(@{node: item_fn(_, _, body), _}, _) |
      ast_map::node_item(@{node: item_res(_, _, body, _, _), _}, _) |
      ast_map::node_method(@{body, _}, _, _) {
        handle_body(cx, body);
      }
      ast_map::node_ctor(_, _, ast_map::res_ctor(_, _, _), _) |
      ast_map::node_variant(_, _, _) {
        uint::range(0u, n_tps) {|n| cx.uses[n] |= use_repr;}
      }
      ast_map::node_native_item(i@@{node: native_item_fn(_, _), _}, abi, _) {
        if abi == native_abi_rust_intrinsic {
            let flags = alt check i.ident {
              "size_of" | "align_of" | "init" |
              "reinterpret_cast" { use_repr }
              "get_tydesc" | "needs_drop" { use_tydesc }
              "forget" | "addr_of" { 0u }
            };
            uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;}
        }
      }
      ast_map::node_ctor(_, _, ast_map::class_ctor(ctor, _), _){
        handle_body(cx, ctor.node.body);
      }
    }
    let uses = vec::from_mut(cx.uses);
    ccx.type_use_cache.insert(fn_id, uses);
    uses
}

fn type_needs(cx: ctx, use: uint, ty: ty::t) {
    let mut done = true;
    // Optimization -- don't descend type if all params already have this use
    for vec::each(cx.uses) {|u| if u & use != use { done = false } }
    if !done { type_needs_inner(cx, use, ty, list::nil); }
}

fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
                    enums_seen: list::list<def_id>) {
    ty::maybe_walk_ty(ty) {|ty|
        if ty::type_has_params(ty) {
            alt ty::get(ty).struct {
              ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) |
              ty::ty_box(_) | ty::ty_iface(_, _) { false }
              ty::ty_enum(did, tps) {
                if option::is_none(list::find(enums_seen, {|id| id == did})) {
                    let seen = list::cons(did, @enums_seen);
                    for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v|
                        for vec::each(v.args) {|aty|
                            let t = ty::substitute_type_params(cx.ccx.tcx,
                                                               tps, aty);
                            type_needs_inner(cx, use, t, seen);
                        }
                    }
                }
                false
              }
              ty::ty_param(n, _) {
                cx.uses[n] |= use;
                false
              }
              _ { true }
            }
        } else { false }
    }
}

fn node_type_needs(cx: ctx, use: uint, id: node_id) {
    type_needs(cx, use, ty::node_id_to_type(cx.ccx.tcx, id));
}

fn mark_for_expr(cx: ctx, e: @expr) {
    alt e.node {
      expr_vstore(_, _) |
      expr_vec(_, _) |
      expr_rec(_, _) | expr_tup(_) |
      expr_unary(box(_), _) | expr_unary(uniq(_), _) |
      expr_cast(_, _) | expr_binary(add, _, _) |
      expr_copy(_) | expr_move(_, _) {
        node_type_needs(cx, use_repr, e.id);
      }
      expr_binary(op, lhs, _) {
        alt op {
          eq | lt | le | ne | ge | gt {
            node_type_needs(cx, use_tydesc, lhs.id)
          }
          _ {}
        }
      }
      expr_path(_) {
        option::iter(cx.ccx.tcx.node_type_substs.find(e.id)) {|ts|
            let id = ast_util::def_id_of_def(cx.ccx.tcx.def_map.get(e.id));
            vec::iter2(type_uses_for(cx.ccx, id, ts.len()), ts) {|uses, subst|
                type_needs(cx, uses, subst)
            }
        }
      }
      expr_fn(_, _, _, _) | expr_fn_block(_, _) {
        alt ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) {
          proto_bare | proto_any | proto_uniq {}
          proto_box | proto_block {
            for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) {|fv|
                let node_id = ast_util::def_id_of_def(fv.def).node;
                node_type_needs(cx, use_repr, node_id);
            }
          }
        }
      }
      expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) |
      expr_ret(some(val)) | expr_be(val) {
        node_type_needs(cx, use_repr, val.id);
      }
      expr_index(base, _) | expr_field(base, _, _) {
        // FIXME could be more careful and not count fields
        // after the chosen field
        let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
        type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
      }
      expr_log(_, _, val) {
        node_type_needs(cx, use_tydesc, val.id);
      }
      expr_new(_, _, v) {
        node_type_needs(cx, use_repr, v.id);
      }
      expr_call(f, _, _) {
        vec::iter(ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, f.id))) {|a|
            alt a.mode {
              expl(by_move) | expl(by_copy) | expl(by_val) {
                type_needs(cx, use_repr, a.ty);
              }
              _ {}
            }
        }
      }
      expr_do_while(_, _) | expr_alt(_, _, _) |
      expr_block(_) | expr_if(_, _, _) | expr_while(_, _) |
      expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
      expr_lit(_) | expr_assert(_) | expr_check(_, _) |
      expr_if_check(_, _, _) | expr_mac(_) | expr_addr_of(_, _) |
      expr_ret(_) | expr_loop(_) | expr_bind(_, _) | expr_loop_body(_) {}
    }
}

fn handle_body(cx: ctx, body: blk) {
    let v = visit::mk_vt(@{
        visit_expr: {|e, cx, v|
            visit::visit_expr(e, cx, v);
            mark_for_expr(cx, e);
        },
        visit_local: {|l, cx, v|
            visit::visit_local(l, cx, v);
            node_type_needs(cx, use_repr, l.node.id);
        },
        visit_pat: {|p, cx, v|
            visit::visit_pat(p, cx, v);
            node_type_needs(cx, use_repr, p.id);
        },
        visit_block: {|b, cx, v|
            visit::visit_block(b, cx, v);
            option::iter(b.node.expr) {|e|
                node_type_needs(cx, use_repr, e.id);
            }
        },
        visit_item: {|_i, _cx, _v|}
        with *visit::default_visitor()
    });
    v.visit_block(body, cx, v);
}
<commit_msg>Fix oversight in type_use.rs<commit_after>// Determines the ways in which a generic function body depends
// on its type parameters. Used to aggressively reuse compiled
// function bodies for different types.

// This unfortunately depends on quite a bit of knowledge about the
// details of the language semantics, and is likely to accidentally go
// out of sync when something is changed. It could be made more
// powerful by distinguishing between functions that only need to know
// the size and alignment of a type, and those that also use its
// drop/take glue. But this would increase the fragility of the code
// to a ridiculous level, and probably not catch all that many extra
// opportunities for reuse.

// (An other approach to doing what this code does is to instrument
// the translation code to set flags whenever it does something like
// alloca a type or get a tydesc. This would not duplicate quite as
// much information, but have the disadvantage of being very
// invasive.)

import std::map::hashmap;
import std::list;
import driver::session::session;
import metadata::csearch;
import syntax::ast::*, syntax::ast_util, syntax::visit;
import common::*;

// FIXME distinguish between size/alignment and take/drop dependencies
type type_uses = uint; // Bitmask
const use_repr: uint = 1u; // Dependency on size/alignment and take/drop glue
const use_tydesc: uint = 2u; // Takes the tydesc, or compares

type ctx = {ccx: @crate_ctxt,
            uses: [mut type_uses]};

fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
    -> [type_uses] {
    alt ccx.type_use_cache.find(fn_id) {
      some(uses) { ret uses; }
      none {}
    }
    let fn_id_loc = if fn_id.crate == local_crate { fn_id }
                    else { base::maybe_instantiate_inline(ccx, fn_id) };
    // Conservatively assume full use for recursive loops
    ccx.type_use_cache.insert(fn_id, vec::from_elem(n_tps, 3u));

    let cx = {ccx: ccx, uses: vec::to_mut(vec::from_elem(n_tps, 0u))};
    alt ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).struct {
      ty::ty_fn({inputs, _}) {
        for vec::each(inputs) {|arg|
            if arg.mode == expl(by_val) { type_needs(cx, use_repr, arg.ty); }
        }
      }
      _ {}
    }

    if fn_id_loc.crate != local_crate {
        let uses = vec::from_mut(cx.uses);
        ccx.type_use_cache.insert(fn_id, uses);
        ret uses;
    }
    let map_node = alt ccx.tcx.items.find(fn_id_loc.node) {
        some(x) { x }
        none    { ccx.sess.bug(#fmt("type_uses_for: unbound item ID %?",
                                    fn_id_loc)); }
    };
    alt check map_node {
      ast_map::node_item(@{node: item_fn(_, _, body), _}, _) |
      ast_map::node_item(@{node: item_res(_, _, body, _, _), _}, _) |
      ast_map::node_method(@{body, _}, _, _) {
        handle_body(cx, body);
      }
      ast_map::node_ctor(_, _, ast_map::res_ctor(_, _, _), _) |
      ast_map::node_variant(_, _, _) {
        uint::range(0u, n_tps) {|n| cx.uses[n] |= use_repr;}
      }
      ast_map::node_native_item(i@@{node: native_item_fn(_, _), _}, abi, _) {
        if abi == native_abi_rust_intrinsic {
            let flags = alt check i.ident {
              "size_of" | "align_of" | "init" |
              "reinterpret_cast" { use_repr }
              "get_tydesc" | "needs_drop" { use_tydesc }
              "forget" | "addr_of" { 0u }
            };
            uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;}
        }
      }
      ast_map::node_ctor(_, _, ast_map::class_ctor(ctor, _), _){
        handle_body(cx, ctor.node.body);
      }
    }
    let uses = vec::from_mut(cx.uses);
    ccx.type_use_cache.insert(fn_id, uses);
    uses
}

fn type_needs(cx: ctx, use: uint, ty: ty::t) {
    let mut done = true;
    // Optimization -- don't descend type if all params already have this use
    for vec::each(cx.uses) {|u| if u & use != use { done = false } }
    if !done { type_needs_inner(cx, use, ty, list::nil); }
}

fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
                    enums_seen: list::list<def_id>) {
    ty::maybe_walk_ty(ty) {|ty|
        if ty::type_has_params(ty) {
            alt ty::get(ty).struct {
              ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) |
              ty::ty_box(_) | ty::ty_iface(_, _) { false }
              ty::ty_enum(did, tps) {
                if option::is_none(list::find(enums_seen, {|id| id == did})) {
                    let seen = list::cons(did, @enums_seen);
                    for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v|
                        for vec::each(v.args) {|aty|
                            let t = ty::substitute_type_params(cx.ccx.tcx,
                                                               tps, aty);
                            type_needs_inner(cx, use, t, seen);
                        }
                    }
                }
                false
              }
              ty::ty_param(n, _) {
                cx.uses[n] |= use;
                false
              }
              _ { true }
            }
        } else { false }
    }
}

fn node_type_needs(cx: ctx, use: uint, id: node_id) {
    type_needs(cx, use, ty::node_id_to_type(cx.ccx.tcx, id));
}

fn mark_for_expr(cx: ctx, e: @expr) {
    alt e.node {
      expr_vstore(_, _) |
      expr_vec(_, _) |
      expr_rec(_, _) | expr_tup(_) |
      expr_unary(box(_), _) | expr_unary(uniq(_), _) |
      expr_cast(_, _) | expr_binary(add, _, _) |
      expr_copy(_) | expr_move(_, _) {
        node_type_needs(cx, use_repr, e.id);
      }
      expr_binary(op, lhs, _) {
        alt op {
          eq | lt | le | ne | ge | gt {
            node_type_needs(cx, use_tydesc, lhs.id)
          }
          _ {}
        }
      }
      expr_path(_) {
        option::iter(cx.ccx.tcx.node_type_substs.find(e.id)) {|ts|
            let id = ast_util::def_id_of_def(cx.ccx.tcx.def_map.get(e.id));
            vec::iter2(type_uses_for(cx.ccx, id, ts.len()), ts) {|uses, subst|
                type_needs(cx, uses, subst)
            }
        }
      }
      expr_fn(_, _, _, _) | expr_fn_block(_, _) {
        alt ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) {
          proto_bare | proto_any | proto_uniq {}
          proto_box | proto_block {
            for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) {|fv|
                let node_id = ast_util::def_id_of_def(fv.def).node;
                node_type_needs(cx, use_repr, node_id);
            }
          }
        }
      }
      expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) |
      expr_ret(some(val)) | expr_be(val) {
        node_type_needs(cx, use_repr, val.id);
      }
      expr_index(base, _) | expr_field(base, _, _) {
        // FIXME could be more careful and not count fields
        // after the chosen field
        let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
        type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));

        option::iter(cx.ccx.maps.method_map.find(e.id)) {|mth|
            alt mth {
              typeck::method_static(did) {
                option::iter(cx.ccx.tcx.node_type_substs.find(e.id)) {|ts|
                    vec::iter2(type_uses_for(cx.ccx, did, ts.len()), ts)
                        {|uses, subst| type_needs(cx, uses, subst)}
                }
              }
              typeck::method_param(_, _, param, _) {
                cx.uses[param] |= use_tydesc;
              }
              typeck::method_iface(_, _) {}
            }
        }
      }
      expr_log(_, _, val) {
        node_type_needs(cx, use_tydesc, val.id);
      }
      expr_new(_, _, v) {
        node_type_needs(cx, use_repr, v.id);
      }
      expr_call(f, _, _) {
        vec::iter(ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, f.id))) {|a|
            alt a.mode {
              expl(by_move) | expl(by_copy) | expl(by_val) {
                type_needs(cx, use_repr, a.ty);
              }
              _ {}
            }
        }
      }
      expr_do_while(_, _) | expr_alt(_, _, _) |
      expr_block(_) | expr_if(_, _, _) | expr_while(_, _) |
      expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
      expr_lit(_) | expr_assert(_) | expr_check(_, _) |
      expr_if_check(_, _, _) | expr_mac(_) | expr_addr_of(_, _) |
      expr_ret(_) | expr_loop(_) | expr_bind(_, _) | expr_loop_body(_) {}
    }
}

fn handle_body(cx: ctx, body: blk) {
    let v = visit::mk_vt(@{
        visit_expr: {|e, cx, v|
            visit::visit_expr(e, cx, v);
            mark_for_expr(cx, e);
        },
        visit_local: {|l, cx, v|
            visit::visit_local(l, cx, v);
            node_type_needs(cx, use_repr, l.node.id);
        },
        visit_pat: {|p, cx, v|
            visit::visit_pat(p, cx, v);
            node_type_needs(cx, use_repr, p.id);
        },
        visit_block: {|b, cx, v|
            visit::visit_block(b, cx, v);
            option::iter(b.node.expr) {|e|
                node_type_needs(cx, use_repr, e.id);
            }
        },
        visit_item: {|_i, _cx, _v|}
        with *visit::default_visitor()
    });
    v.visit_block(body, cx, v);
}
<|endoftext|>


<commit_before><commit_msg>continued demacrofication<commit_after><|endoftext|>