<commit_before>/// # Module variables

use self::LpExpression::*;
use std::convert::Into;
use std::rc::Rc;
use variables::Constraint::*;

pub trait BoundableLp : PartialEq + Clone {
    fn lower_bound(&self, lw: f32) -> Self;
    fn upper_bound(&self, up: f32) -> Self;
}

#[derive(Debug, Clone, PartialEq)]
pub struct LpBinary {
    pub name: String
}
impl LpBinary {
    pub fn new(name: &str) -> LpBinary {
        LpBinary { name: name.to_string() }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct LpInteger {
    pub name: String,
    pub lower_bound: Option<f32>,
    pub upper_bound: Option<f32>,
}
impl LpInteger {
    pub fn new(name: &str) -> LpInteger {
        LpInteger { name: name.to_string(), lower_bound: None, upper_bound: None }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct LpContinuous {
    pub name: String,
    pub lower_bound: Option<f32>,
    pub upper_bound: Option<f32>,
}
impl LpContinuous {
    pub fn new(name: &str) -> LpContinuous {
        LpContinuous { name: name.to_string(), lower_bound: None, upper_bound: None }
    }
}

macro_rules! implement_boundable {
    ($lp_type: ident) => {
        impl BoundableLp for $lp_type {
            fn lower_bound(&self, lw: f32) -> $lp_type {
                $lp_type {
                    name: self.name.clone(),
                    lower_bound: Some(lw),
                    upper_bound: self.upper_bound
                }
            }
            fn upper_bound(&self, up: f32) -> $lp_type {
                $lp_type {
                    name: self.name.clone(),
                    lower_bound: self.lower_bound,
                    upper_bound: Some(up)
                }
            }
        }
    }
}
implement_boundable!(LpInteger);
implement_boundable!(LpContinuous);

/// ADT for Linear Programming Expression
#[derive(Debug, Clone, PartialEq)]
pub enum LpExpression {
    ConsInt(LpInteger),
    ConsBin(LpBinary),
    ConsCont(LpContinuous),
    MulExpr(Rc<LpExpression>, Rc<LpExpression>),
    AddExpr(Rc<LpExpression>, Rc<LpExpression>),
    SubExpr(Rc<LpExpression>, Rc<LpExpression>),
    LitVal(f32),
    EmptyExpr
}

impl LpExpression {
    pub fn dfs_remove_constant(&self) -> LpExpression {
        match self {
            &MulExpr(ref rc_e1, ref rc_e2) => {
                let ref e1 = **rc_e1;
                let ref e2 = **rc_e2;
                if let &LitVal(..) = e1 {
                    if let &LitVal(..) = e2 {
                        EmptyExpr
                    }else{
                        MulExpr(rc_e1.clone(), Rc::new(e2.dfs_remove_constant()))
                    }
                }else{
                    MulExpr(Rc::new(e1.dfs_remove_constant()), Rc::new(e2.dfs_remove_constant()))
                }
            },
            &AddExpr(ref rc_e1, ref rc_e2) => {
                let ref e1 = **rc_e1;
                let ref e2 = **rc_e2;
                if let &LitVal(..) = e1 {
                    if let &LitVal(..) = e2 {
                        EmptyExpr
                    }else {
                        e2.dfs_remove_constant()
                    }
                }else{
                    if let &LitVal(..) = e2 {
                        e1.dfs_remove_constant()
                    }else {
                        AddExpr(Rc::new(e1.dfs_remove_constant()), Rc::new(e2.dfs_remove_constant()))
                    }
                }
            },
            &SubExpr(ref rc_e1, ref rc_e2) => {
                let ref e1 = **rc_e1;
                let ref e2 = **rc_e2;
                if let &LitVal(..) = e1 {
                    if let &LitVal(..) = e2 {
                        EmptyExpr
                    }else {
                        e2.dfs_remove_constant()
                    }
                }else{
                    if let &LitVal(..) = e2 {
                        e1.dfs_remove_constant()
                    }else {
                        SubExpr(Rc::new(e1.dfs_remove_constant()), Rc::new(e2.dfs_remove_constant()))
                    }
                }
            },
            _ => self.clone()
        }
    }
    /// Fix the numeric operand in a multiplication in an expression
    /// c * 4 must be considered as 4 c in a linear formulation lp file
    pub fn normalize(&self) -> LpExpression {
        if let &MulExpr(ref rc_e1, ref rc_e2) = self {
            let ref e1 = **rc_e1;
            let ref e2 = **rc_e2;
            if let &LitVal(..) = e1 {
                println!("{:?}", e1);
                return self.clone();
            }else{
                if let &LitVal(..) = e2 {
                    return MulExpr(rc_e2.clone(), rc_e1.clone());
                }else {
                    return MulExpr(rc_e1.clone(), rc_e2.clone());
                }
            }
        }
        self.clone()
    }
}

impl ToString for LpExpression {
    fn to_string(&self) -> String {

        fn dfs(expr: &LpExpression, acc: &String) -> String {
            match expr {
                &MulExpr(ref e1, ref e2) => {
                    e1.to_string() + " " + &e2.to_string()
                },
                &AddExpr(ref e1, ref e2) => {
                    e1.to_string() + " + " + &e2.to_string()
                },
                &SubExpr(ref e1, ref e2) => {
                    e1.to_string() + " - " + &e2.to_string()
                },
                &ConsBin(LpBinary {name: ref n, .. }) => {
                    acc.clone() + n
                },
                &ConsInt(LpInteger {name: ref n, .. }) => {
                    acc.clone() + n
                },
                &ConsCont(LpContinuous {name: ref n, .. }) => {
                    acc.clone() + n
                },
                &LitVal(n) => {
                    acc.clone() + &n.to_string()
                },
                _ => acc.clone()
            }
        }

        dfs(self, &String::new())
    }
}

#[derive(Debug, Clone)]
pub enum Constraint {
    /* Not supported by solver format files (lp file or mps file) !
    Greater,
    Less,
    */
    GreaterOrEqual,
    LessOrEqual,
    Equal
}

#[derive(Debug, Clone)]
pub struct LpConstraint(pub LpExpression, pub Constraint, pub LpExpression);

impl LpConstraint {
    pub fn generalize(&self) -> LpConstraint {
        // TODO: Optimize tailrec
        fn dfs_constant(expr: &LpExpression, acc: f32) -> f32 {
            match expr {
                &MulExpr(ref rc_e1, ref rc_e2) => {
                    let ref e1 = **rc_e1;
                    let ref e2 = **rc_e2;
                    if let &LitVal(ref x) = e1 {
                        if let &LitVal(ref y) = e2 {
                            acc+x*y
                        }else{
                            dfs_constant(e2, acc)
                        }
                    }else{
                        if let &LitVal(ref y) = e2 {
                            dfs_constant(e1, acc+y)
                        }else {
                            dfs_constant(e2, acc) + dfs_constant(e1, 0.0)
                        }
                    }
                },
                &AddExpr(ref rc_e1, ref rc_e2) => {
                    let ref e1 = **rc_e1;
                    let ref e2 = **rc_e2;
                    if let &LitVal(ref x) = e1 {
                        if let &LitVal(ref y) = e2 {
                            acc+x+y
                        }else {
                            dfs_constant(e2, acc+x)
                        }
                    }else{
                        if let &LitVal(ref y) = e2 {
                            dfs_constant(e1, acc+y)
                        }else {
                            dfs_constant(e2, acc) + dfs_constant(e1, 0.0)
                        }
                    }
                },
                &SubExpr(ref rc_e1, ref rc_e2) => {
                    let ref e1 = **rc_e1;
                    let ref e2 = **rc_e2;
                    if let &LitVal(ref x) = e1 {
                        if let &LitVal(ref y) = e2 {
                            acc+x-y
                        }else {
                            dfs_constant(e2, acc+x)
                        }
                    }else{
                        if let &LitVal(ref y) = e2 {
                            dfs_constant(e1, acc-y)
                        }else {
                            dfs_constant(e1, acc) - dfs_constant(e2, 0.0)
                        }
                    }
                },
                _ => acc
            }
        }

        let &LpConstraint(ref lhs, ref op, ref rhs) = self;
        if let &LitVal(0.0) = rhs {
            self.clone()
        }else{
            let ref lhs_expr = lhs - rhs;
            let constant = dfs_constant(lhs_expr, 0.0);
            let lhs_expr = lhs_expr.dfs_remove_constant();
            LpConstraint(lhs_expr, op.clone(), LitVal(-constant))
        }
    }
}

impl ToString for LpConstraint {
    fn to_string(&self) -> String {
        let mut res = String::new();
        res.push_str(&self.0.to_string());
        match self.1 {
            GreaterOrEqual => res.push_str(" >= "),
            LessOrEqual => res.push_str(" <= "),
            Equal => res.push_str(" = "),
        }
        res.push_str(&self.2.to_string());
        res
    }
}

/// make a complete expression or a constraint with a vector of expressions
///
/// # Examples
///
/// ```
/// use lp_modeler::problem::{LpObjective, LpProblem};
/// use lp_modeler::operations::LpOperations;
/// use lp_modeler::variables::{LpBinary, lp_sum};
///
/// let mut problem = LpProblem::new("My Problem", LpObjective::Maximize);
/// let ref a = LpBinary::new("a");
/// let ref b = LpBinary::new("b");
/// let ref c = LpBinary::new("c");
///
/// let ref v = vec!(a, b, c);
/// problem += lp_sum(v).equal(10.0);
/// ```
///
pub fn lp_sum<T>(expr: &Vec<T>) -> LpExpression where T : Into<LpExpression> + Clone {

    let mut expr = expr.clone();
    if let Some(e1) = expr.pop() {
        if let Some(e2) = expr.pop() {
            expr.push(e2);
            AddExpr(Rc::new(e1.into()), Rc::new(lp_sum(&expr)))
        } else {
            e1.into()
        }
    }else{
        EmptyExpr
    }
}

<commit_msg>Patch for signs in an expression<commit_after>/// # Module variables

use self::LpExpression::*;
use std::convert::Into;
use std::rc::Rc;
use variables::Constraint::*;

pub trait BoundableLp : PartialEq + Clone {
    fn lower_bound(&self, lw: f32) -> Self;
    fn upper_bound(&self, up: f32) -> Self;
}

#[derive(Debug, Clone, PartialEq)]
pub struct LpBinary {
    pub name: String
}
impl LpBinary {
    pub fn new(name: &str) -> LpBinary {
        LpBinary { name: name.to_string() }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct LpInteger {
    pub name: String,
    pub lower_bound: Option<f32>,
    pub upper_bound: Option<f32>,
}
impl LpInteger {
    pub fn new(name: &str) -> LpInteger {
        LpInteger { name: name.to_string(), lower_bound: None, upper_bound: None }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct LpContinuous {
    pub name: String,
    pub lower_bound: Option<f32>,
    pub upper_bound: Option<f32>,
}
impl LpContinuous {
    pub fn new(name: &str) -> LpContinuous {
        LpContinuous { name: name.to_string(), lower_bound: None, upper_bound: None }
    }
}

macro_rules! implement_boundable {
    ($lp_type: ident) => {
        impl BoundableLp for $lp_type {
            fn lower_bound(&self, lw: f32) -> $lp_type {
                $lp_type {
                    name: self.name.clone(),
                    lower_bound: Some(lw),
                    upper_bound: self.upper_bound
                }
            }
            fn upper_bound(&self, up: f32) -> $lp_type {
                $lp_type {
                    name: self.name.clone(),
                    lower_bound: self.lower_bound,
                    upper_bound: Some(up)
                }
            }
        }
    }
}
implement_boundable!(LpInteger);
implement_boundable!(LpContinuous);

/// ADT for Linear Programming Expression
#[derive(Debug, Clone, PartialEq)]
pub enum LpExpression {
    ConsInt(LpInteger),
    ConsBin(LpBinary),
    ConsCont(LpContinuous),
    MulExpr(Rc<LpExpression>, Rc<LpExpression>),
    AddExpr(Rc<LpExpression>, Rc<LpExpression>),
    SubExpr(Rc<LpExpression>, Rc<LpExpression>),
    LitVal(f32),
    EmptyExpr
}

impl LpExpression {
    pub fn dfs_remove_constant(&self) -> LpExpression {
        match self {
            &MulExpr(ref rc_e1, ref rc_e2) => {
                let ref e1 = **rc_e1;
                let ref e2 = **rc_e2;
                if let &LitVal(..) = e1 {
                    if let &LitVal(..) = e2 {
                        EmptyExpr
                    }else{
                        MulExpr(rc_e1.clone(), Rc::new(e2.dfs_remove_constant()))
                    }
                }else{
                    MulExpr(Rc::new(e1.dfs_remove_constant()), Rc::new(e2.dfs_remove_constant()))
                }
            },
            &AddExpr(ref rc_e1, ref rc_e2) => {
                let ref e1 = **rc_e1;
                let ref e2 = **rc_e2;
                if let &LitVal(..) = e1 {
                    if let &LitVal(..) = e2 {
                        EmptyExpr
                    }else {
                        e2.dfs_remove_constant()
                    }
                }else{
                    if let &LitVal(..) = e2 {
                        e1.dfs_remove_constant()
                    }else {
                        AddExpr(Rc::new(e1.dfs_remove_constant()), Rc::new(e2.dfs_remove_constant()))
                    }
                }
            },
            &SubExpr(ref rc_e1, ref rc_e2) => {
                let ref e1 = **rc_e1;
                let ref e2 = **rc_e2;
                if let &LitVal(..) = e1 {
                    if let &LitVal(..) = e2 {
                        EmptyExpr
                    }else {
                        e2.dfs_remove_constant()
                    }
                }else{
                    if let &LitVal(..) = e2 {
                        e1.dfs_remove_constant()
                    }else {
                        SubExpr(Rc::new(e1.dfs_remove_constant()), Rc::new(e2.dfs_remove_constant()))
                    }
                }
            },
            _ => self.clone()
        }
    }
    /// Fix the numeric operand in a multiplication in an expression
    /// c * 4 must be considered as 4 c in a linear formulation lp file
    pub fn normalize(&self) -> LpExpression {
        if let &MulExpr(ref rc_e1, ref rc_e2) = self {
            let ref e1 = **rc_e1;
            let ref e2 = **rc_e2;
            if let &LitVal(..) = e1 {
                println!("{:?}", e1);
                return self.clone();
            }else{
                if let &LitVal(..) = e2 {
                    return MulExpr(rc_e2.clone(), rc_e1.clone());
                }else {
                    return MulExpr(rc_e1.clone(), rc_e2.clone());
                }
            }
        }
        self.clone()
    }
}

impl ToString for LpExpression {
    fn to_string(&self) -> String {

        fn dfs(expr: &LpExpression, acc: &String) -> String {
            match expr {
                &MulExpr(ref e1, ref e2) => {
                    match **e1 {
                        LitVal(v) if v == 1.0 => e2.to_string(),
                        LitVal(v) if v == -1.0 => "-".to_string() + &e2.to_string(),
                        _ => e1.to_string() + " " + &e2.to_string()
                    }
                },
                &AddExpr(ref e1, ref e2) => {
                    e1.to_string() + " + " + &e2.to_string()
                },
                &SubExpr(ref e1, ref e2) => {
                    e1.to_string() + " - " + &e2.to_string()
                },
                &ConsBin(LpBinary {name: ref n, .. }) => {
                    acc.clone() + n
                },
                &ConsInt(LpInteger {name: ref n, .. }) => {
                    acc.clone() + n
                },
                &ConsCont(LpContinuous {name: ref n, .. }) => {
                    acc.clone() + n
                },
                &LitVal(n) => {
                    acc.clone() + &n.to_string()
                },
                _ => acc.clone()
            }
        }

        fn formalize_signs(s: String) -> String {
            let mut s = s.clone();
            let mut t = "".to_string();
            while s != t {
                t = s.clone();
                s = s.replace("+ +", "+ ");
                s = s.replace("- +", "- ");
                s = s.replace("+ -", "- ");
                s = s.replace("- -", "+ ");
                s = s.replace("  ", " ");
            }
            s
        }
        formalize_signs(dfs(self, &String::new()))
    }
}

#[derive(Debug, Clone)]
pub enum Constraint {
    /* Not supported by solver format files (lp file or mps file) !
    Greater,
    Less,
    */
    GreaterOrEqual,
    LessOrEqual,
    Equal
}

#[derive(Debug, Clone)]
pub struct LpConstraint(pub LpExpression, pub Constraint, pub LpExpression);

impl LpConstraint {
    pub fn generalize(&self) -> LpConstraint {
        // TODO: Optimize tailrec
        fn dfs_constant(expr: &LpExpression, acc: f32) -> f32 {
            match expr {
                &MulExpr(ref rc_e1, ref rc_e2) => {
                    let ref e1 = **rc_e1;
                    let ref e2 = **rc_e2;
                    if let &LitVal(ref x) = e1 {
                        if let &LitVal(ref y) = e2 {
                            acc+x*y
                        }else{
                            dfs_constant(e2, acc)
                        }
                    }else{
                        if let &LitVal(ref y) = e2 {
                            dfs_constant(e1, acc+y)
                        }else {
                            dfs_constant(e2, acc) + dfs_constant(e1, 0.0)
                        }
                    }
                },
                &AddExpr(ref rc_e1, ref rc_e2) => {
                    let ref e1 = **rc_e1;
                    let ref e2 = **rc_e2;
                    if let &LitVal(ref x) = e1 {
                        if let &LitVal(ref y) = e2 {
                            acc+x+y
                        }else {
                            dfs_constant(e2, acc+x)
                        }
                    }else{
                        if let &LitVal(ref y) = e2 {
                            dfs_constant(e1, acc+y)
                        }else {
                            dfs_constant(e2, acc) + dfs_constant(e1, 0.0)
                        }
                    }
                },
                &SubExpr(ref rc_e1, ref rc_e2) => {
                    let ref e1 = **rc_e1;
                    let ref e2 = **rc_e2;
                    if let &LitVal(ref x) = e1 {
                        if let &LitVal(ref y) = e2 {
                            acc+x-y
                        }else {
                            dfs_constant(e2, acc+x)
                        }
                    }else{
                        if let &LitVal(ref y) = e2 {
                            dfs_constant(e1, acc-y)
                        }else {
                            dfs_constant(e1, acc) - dfs_constant(e2, 0.0)
                        }
                    }
                },
                _ => acc
            }
        }

        let &LpConstraint(ref lhs, ref op, ref rhs) = self;
        if let &LitVal(0.0) = rhs {
            self.clone()
        }else{
            let ref lhs_expr = lhs - rhs;
            let constant = dfs_constant(lhs_expr, 0.0);
            let lhs_expr = lhs_expr.dfs_remove_constant();
            LpConstraint(lhs_expr, op.clone(), LitVal(-constant))
        }
    }
}

impl ToString for LpConstraint {
    fn to_string(&self) -> String {
        let mut res = String::new();
        res.push_str(&self.0.to_string());
        match self.1 {
            GreaterOrEqual => res.push_str(" >= "),
            LessOrEqual => res.push_str(" <= "),
            Equal => res.push_str(" = "),
        }
        res.push_str(&self.2.to_string());
        res
    }
}

/// make a complete expression or a constraint with a vector of expressions
///
/// # Examples
///
/// ```
/// use lp_modeler::problem::{LpObjective, LpProblem};
/// use lp_modeler::operations::LpOperations;
/// use lp_modeler::variables::{LpBinary, lp_sum};
///
/// let mut problem = LpProblem::new("My Problem", LpObjective::Maximize);
/// let ref a = LpBinary::new("a");
/// let ref b = LpBinary::new("b");
/// let ref c = LpBinary::new("c");
///
/// let ref v = vec!(a, b, c);
/// problem += lp_sum(v).equal(10.0);
/// ```
///
pub fn lp_sum<T>(expr: &Vec<T>) -> LpExpression where T : Into<LpExpression> + Clone {

    let mut expr = expr.clone();
    if let Some(e1) = expr.pop() {
        if let Some(e2) = expr.pop() {
            expr.push(e2);
            AddExpr(Rc::new(e1.into()), Rc::new(lp_sum(&expr)))
        } else {
            e1.into()
        }
    }else{
        EmptyExpr
    }
}

<|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.

// compile-flags: --cfg fooA --cfg fooB

// fooA AND !bar
#[cfg(fooA, not(bar))]
fn foo1() -> int { 1 }

// !fooA AND !bar
#[cfg(not(fooA, bar))]
fn foo2() -> int { 2 }

// fooC OR (fooB AND !bar)
#[cfg(fooC)]
#[cfg(fooB, not(bar))]
fn foo2() -> int { 3 }

fn main() {
    fail_unless!(1 == foo1());
    fail_unless!(3 == foo2());
}
<commit_msg>Mark cfg test xfail-fast since check-fast doesn't understand compile-flags.<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.

// xfail-fast
// compile-flags: --cfg fooA --cfg fooB

// fooA AND !bar
#[cfg(fooA, not(bar))]
fn foo1() -> int { 1 }

// !fooA AND !bar
#[cfg(not(fooA, bar))]
fn foo2() -> int { 2 }

// fooC OR (fooB AND !bar)
#[cfg(fooC)]
#[cfg(fooB, not(bar))]
fn foo2() -> int { 3 }

fn main() {
    fail_unless!(1 == foo1());
    fail_unless!(3 == foo2());
}
<|endoftext|>


<commit_before>#[crate_type = "rlib"];
#[crate_id="github.com/xsleonard/sdl2_image-rs#sdl2_image:0.1"];
#[desc = "SDL2_image bindings and wrappers"];
#[comment = "SDL2_image bindings and wrappers"];
#[license = "MIT"];

extern mod sdl2;

use std::libc::{c_int, c_char};
use std::ptr;
use std::cast;
use std::io;
use sdl2::surface::Surface;
use sdl2::render::Texture;
use sdl2::render::Renderer;
use sdl2::get_error;

// Setup linking for all targets.
#[cfg(target_os="macos")]
mod mac {
    #[cfg(mac_framework)]
    #[link(kind="framework", name="SDL2_image")]
    extern {}

    #[cfg(not(mac_framework))]
    #[link(name="SDL2_image")]
    extern {}
}

#[cfg(target_os="win32")]
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
mod others {
    #[link(name="SDL2_image")]
    extern {}
}

mod ffi;

#[deriving(Clone, Eq, IterBytes, ToStr)]
pub enum InitFlag {
    InitJpg = ffi::IMG_INIT_JPG as int,
    InitPng = ffi::IMG_INIT_PNG as int,
    InitTif = ffi::IMG_INIT_TIF as int,
    InitWebp = ffi::IMG_INIT_WEBP as int,
}

#[deriving(Eq, Clone)]
pub struct ImageVersion {
    major: int,
    minor: int,
    patch: int,
}

impl ToStr for ImageVersion {
    fn to_str(&self) -> ~str {
        format!("{}.{}.{}", self.major, self.minor, self.patch)
    }
}

impl ImageVersion {
    fn from_sdl_version(sv: *ffi::SDL_version) -> ImageVersion {
        unsafe {
            let v = *sv;
            ImageVersion{ major: v.major, minor: v.minor, patch: v.patch }
        }
    }
}

pub trait ImageLoader {
    // Self is only returned here to type hint to the compiler.
    // The syntax for type hinting in this case is not yet defined.
    // The intended return value is Result<~Surface, ~str>.
    fn from_file(filename: &str) -> Result<~Self, ~str>;
    fn from_xpm_array(xpm: **i8) -> Result<~Self, ~str>;
}

pub trait ImageSaver {
    fn save(&self, filename: &str) -> Result<(), ~str>;
}

impl ImageLoader for Surface {
    fn from_file(filename: &str) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::IMG_Load(filename.to_c_str().unwrap());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    fn from_xpm_array(xpm: **i8) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::IMG_ReadXPMFromArray(xpm as **c_char);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }
}

impl ImageSaver for Surface {
    fn save(&self, filename: &str) -> Result<(), ~str> {
        unsafe {
            let status = ffi::IMG_SavePNG(self.raw,
                                          filename.to_c_str().unwrap());
            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }
}

pub trait TextureLoader {
    fn load_texture_from_file(&self, filename: &str) -> Result<~Texture, ~str>;
}

impl TextureLoader for Renderer {
    fn load_texture_from_file(&self,
                              filename: &str) -> Result<~Texture, ~str> {
        unsafe {
            let raw = ffi::IMG_LoadTexture(self.raw,
                                           filename.to_c_str().unwrap());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Texture{ raw: raw, owned: true })
            }
        }
    }
}

pub fn init(flags: &[InitFlag]) -> ~[InitFlag] {
    //! Initializes SDL2_image with InitFlags and returns which
    //! InitFlags were actually used.
    let mut used = ~[];
    unsafe {
        let used_flags = ffi::IMG_Init(
            flags.iter().fold(0, |flags, &flag| {
                flags | flag as ffi::IMG_InitFlags
            })
        );
        for flag in flags.iter() {
            if used_flags & *flag as c_int != 0 {
                used.push(*flag)
            }
        }
    }
    used
}

pub fn quit() {
    //! Teardown the SDL2_Image subsystem
    unsafe { ffi::IMG_Quit(); }
}

pub fn get_linked_version() -> ImageVersion {
    //! Returns the version of the dynamically linked SDL_image library
    unsafe {
        ImageVersion::from_sdl_version(ffi::IMG_Linked_Version())
    }
}

// TODO -- this should be in rust-sdl2
// Most of the sdl2_image API relies on SDL_RWops.

// #[deriving(Eq)]
// pub struct RWops {
//     raw: *SDL_RWops;
//     owned: bool;
// }

// impl Drop for RWops {
//     fn drop(&mut self) {
//         if self.owned {
//             unsafe {
//                 // TODO -- close() returns a c_int error status.
//                 // How do we deal with errors in the destructor?
//                 // Probably either kill the task, or don't implement this
//                 // as a destructor
//                 self.raw.close()
//             }
//         }
//     }
// }
<commit_msg>rename traits & methods<commit_after>#[crate_type = "rlib"];
#[crate_id="github.com/xsleonard/sdl2_image-rs#sdl2_image:0.1"];
#[desc = "SDL2_image bindings and wrappers"];
#[comment = "SDL2_image bindings and wrappers"];
#[license = "MIT"];

extern mod sdl2;

use std::libc::{c_int, c_char};
use std::ptr;
use std::cast;
use std::io;
use sdl2::surface::Surface;
use sdl2::render::Texture;
use sdl2::render::Renderer;
use sdl2::get_error;

// Setup linking for all targets.
#[cfg(target_os="macos")]
mod mac {
    #[cfg(mac_framework)]
    #[link(kind="framework", name="SDL2_image")]
    extern {}

    #[cfg(not(mac_framework))]
    #[link(name="SDL2_image")]
    extern {}
}

#[cfg(target_os="win32")]
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
mod others {
    #[link(name="SDL2_image")]
    extern {}
}

mod ffi;

#[deriving(Clone, Eq, IterBytes, ToStr)]
pub enum InitFlag {
    InitJpg = ffi::IMG_INIT_JPG as int,
    InitPng = ffi::IMG_INIT_PNG as int,
    InitTif = ffi::IMG_INIT_TIF as int,
    InitWebp = ffi::IMG_INIT_WEBP as int,
}

#[deriving(Eq, Clone)]
pub struct SDLImageVersion {
    major: int,
    minor: int,
    patch: int,
}

impl ToStr for SDLImageVersion {
    fn to_str(&self) -> ~str {
        format!("{}.{}.{}", self.major, self.minor, self.patch)
    }
}

impl SDLImageVersion {
    fn from_sdl_version(sv: *ffi::SDL_version) -> SDLImageVersion {
        unsafe {
            let v = *sv;
            SDLImageVersion{ major: v.major, minor: v.minor, patch: v.patch }
        }
    }
}

pub trait LoadSurface {
    // Self is only returned here to type hint to the compiler.
    // The syntax for type hinting in this case is not yet defined.
    // The intended return value is Result<~Surface, ~str>.
    fn from_file(filename: &str) -> Result<~Self, ~str>;
    fn from_xpm_array(xpm: **i8) -> Result<~Self, ~str>;
}

pub trait SaveImage {
    fn save(&self, filename: &str) -> Result<(), ~str>;
}

impl LoadSurface for Surface {
    fn from_file(filename: &str) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::IMG_Load(filename.to_c_str().unwrap());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }

    fn from_xpm_array(xpm: **i8) -> Result<~Surface, ~str> {
        unsafe {
            let raw = ffi::IMG_ReadXPMFromArray(xpm as **c_char);
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Surface { raw: raw, owned: true })
            }
        }
    }
}

impl SaveImage for Surface {
    fn save(&self, filename: &str) -> Result<(), ~str> {
        unsafe {
            let status = ffi::IMG_SavePNG(self.raw,
                                          filename.to_c_str().unwrap());
            if status != 0 {
                Err(get_error())
            } else {
                Ok(())
            }
        }
    }
}

pub trait LoadTexture {
    fn load_texture(&self, filename: &str) -> Result<~Texture, ~str>;
}

impl LoadTexture for Renderer {
    fn load_texture(&self, filename: &str) -> Result<~Texture, ~str> {
        unsafe {
            let raw = ffi::IMG_LoadTexture(self.raw,
                                           filename.to_c_str().unwrap());
            if raw == ptr::null() {
                Err(get_error())
            } else {
                Ok(~Texture{ raw: raw, owned: true })
            }
        }
    }
}

pub fn init(flags: &[InitFlag]) -> ~[InitFlag] {
    //! Initializes SDL2_image with InitFlags and returns which
    //! InitFlags were actually used.
    let mut used = ~[];
    unsafe {
        let used_flags = ffi::IMG_Init(
            flags.iter().fold(0, |flags, &flag| {
                flags | flag as ffi::IMG_InitFlags
            })
        );
        for flag in flags.iter() {
            if used_flags & *flag as c_int != 0 {
                used.push(*flag)
            }
        }
    }
    used
}

pub fn quit() {
    //! Teardown the SDL2_Image subsystem
    unsafe { ffi::IMG_Quit(); }
}

pub fn get_linked_version() -> SDLImageVersion {
    //! Returns the version of the dynamically linked SDL_image library
    unsafe {
        SDLImageVersion::from_sdl_version(ffi::IMG_Linked_Version())
    }
}

// TODO -- this should be in rust-sdl2
// Most of the sdl2_image API relies on SDL_RWops.

// #[deriving(Eq)]
// pub struct RWops {
//     raw: *SDL_RWops;
//     owned: bool;
// }

// impl Drop for RWops {
//     fn drop(&mut self) {
//         if self.owned {
//             unsafe {
//                 // TODO -- close() returns a c_int error status.
//                 // How do we deal with errors in the destructor?
//                 // Probably either kill the task, or don't implement this
//                 // as a destructor
//                 self.raw.close()
//             }
//         }
//     }
// }
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::ops::Deref;
use std::path::PathBuf;
use std::collections::{HashSet, HashMap};
use cargo::core::Workspace;
use cargo::sources::PathSource;
use syntex_syntax::attr;
use syntex_syntax::visit::{self, Visitor, FnKind};
use syntex_syntax::codemap::{CodeMap, Span, FilePathMapping};
use syntex_syntax::ast::{NodeId, Mac, Attribute, Mod, StructField, Block, Item, ItemKind, FnDecl};
use syntex_syntax::parse::{self, ParseSess};
use syntex_syntax::errors::Handler;
use syntex_syntax::errors::emitter::ColorConfig;
use config::Config;

/// Represents the results of analysis of a single file. Does not store the file
/// in question as this is expected to be maintained by the user.
struct LineAnalysis {
    /// This represents lines that should be ignored in coverage
    /// but may be identifed as coverable in the DWARF tables
    pub ignore: HashSet<usize>,
    /// This represents lines that should be included in coverage
    /// But may be ignored.
    pub cover: HashSet<usize>,
}

impl LineAnalysis {
    fn new() -> LineAnalysis {
        LineAnalysis {
            ignore: HashSet::new(),
            cover: HashSet::new()
        }
    }
}

struct IgnoredLines<'a> {
    lines: Vec<(PathBuf, usize)>,
    coverable: Vec<(PathBuf, usize)>,
    covered: &'a HashSet<PathBuf>,
    codemap: &'a CodeMap,
    config: &'a Config,
}

/// Returns a list of files and line numbers to ignore (not indexes!)
pub fn get_lines_to_ignore(project: &Workspace, config: &Config) -> Vec<(PathBuf, usize)> {
    let mut result: Vec<(PathBuf, usize)> = Vec::new();
    let pkg = project.current().unwrap();
    let mut src = PathSource::new(pkg.root(), pkg.package_id().source_id(), project.config());
    if let Ok(package) = src.root_package() {

        let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
        let handler = Handler::with_tty_emitter(ColorConfig::Auto, false, false, Some(codemap.clone()));
        let parse_session = ParseSess::with_span_handler(handler, codemap.clone());

        let mut done_files: HashSet<PathBuf> = HashSet::new();
        for target in package.targets() {
            let file = target.src_path();
            if !(config.ignore_tests && file.starts_with(project.root().join("tests"))) {
                let mut parser = parse::new_parser_from_file(&parse_session, file);
                parser.cfg_mods = false;
                if let Ok(krate) = parser.parse_crate_mod() {

                    let mut lines = {
                        let mut visitor = IgnoredLines::from_session(&parse_session, &done_files, config);
                        visitor.visit_mod(&krate.module, krate.span, &krate.attrs, NodeId::new(0));
                        visitor.lines
                    };

                    for l in &lines {
                        done_files.insert(l.0.clone());
                    }
                    result.append(&mut lines);
                }
            }
        }
    }
    result
}

fn add_lines(codemap: &CodeMap, lines: &mut Vec<(PathBuf, usize)>, s: Span) {
    if let Ok(ls) = codemap.span_to_lines(s) {
        for line in &ls.lines {
            let pb = PathBuf::from(codemap.span_to_filename(s) as String);
            // Line number is index+1
            lines.push((pb, line.line_index + 1));
        }
    }
}

impl<'a> IgnoredLines<'a> {
    /// Construct a new ignored lines object for the given project
    fn from_session(session: &'a ParseSess,
                    covered: &'a HashSet<PathBuf>,
                    config: &'a Config) -> IgnoredLines<'a> {
        IgnoredLines {
            lines: vec![],
            coverable: vec![],
            covered: covered,
            codemap: session.codemap(),
            config: config,
        }
    }

    /// Add lines to the line ignore list
    fn ignore_lines(&mut self, span: Span) {
        add_lines(self.codemap, &mut self.lines, span);
    }

    fn cover_lines(&mut self, span: Span) {
        add_lines(self.codemap, &mut self.coverable, span);
    }

    /// Looks for #[cfg(test)] attribute.
    fn contains_cfg_test(&mut self, attrs: &[Attribute]) -> bool {
        attrs.iter()
             .filter(|x| x.path == "cfg")
             .filter_map(|x| x.meta_item_list())
             .flat_map(|x| x)
             .any(|x| {
                 if let Some(w) = x.word() {
                    w.name().as_str() == "test"
                 } else {
                     false
                 }
             })
    }

    /// This function finds ignorable lines within actual coverable code.
    /// As opposed to other functions which find isolated lines that aren't
    /// executed or lines filtered by the user. These lines are things like
    /// close braces that are within coverable code but not coverable.
    fn find_ignorable_lines(&mut self, span: Span) {
        if let Ok(l) = self.codemap.span_to_lines(span) {
            for line in &l.lines {
                let pb = PathBuf::from(self.codemap.span_to_filename(span) as String);
                if let Some(s) = l.file.get_line(line.line_index) {
                    // Is this one of those pointless {, } or }; only lines?
                    if !s.chars().any(|x| !"{}[];\t ,".contains(x)) {
                        self.lines.push((pb, line.line_index + 1));
                    }
                }
            }
        }
    }
}

impl<'v, 'a> Visitor<'v> for IgnoredLines<'a> {

    fn visit_item(&mut self, i: &'v Item) {
        match i.node {
            ItemKind::ExternCrate(..) => self.ignore_lines(i.span),
            ItemKind::Fn(_, _, _, _, _, ref block) => {
                if attr::contains_name(&i.attrs, "test") && self.config.ignore_tests {
                    self.ignore_lines(i.span);
                    self.ignore_lines(block.deref().span);
                }
            },
            _ => {},
        }
        visit::walk_item(self, i);
    }

    fn visit_mod(&mut self, m: &'v Mod, s: Span, _attrs: &[Attribute], _n: NodeId) {
        // If mod is cfg(test) and --ignore-tests ignore contents!
        if let Ok(fl) = self.codemap.span_to_lines(s) {
            if self.config.ignore_tests && self.contains_cfg_test(_attrs) {
                self.ignore_lines(s);
                if fl.lines.len() == 1 {
                    // Ignore the file
                    self.ignore_lines(m.inner);
                }
            }
            else {
                if fl.lines.len() == 1 {
                    // mod imports show up as coverable. Ignore
                    self.ignore_lines(s);
                }
                let mod_path = PathBuf::from(self.codemap.span_to_filename(m.inner));
                if !self.covered.contains(&mod_path) {
                    visit::walk_mod(self, m);
                }
            }
        }
    }

    fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, s: Span, _: NodeId) {
        match fk {
            FnKind::ItemFn(_, g, _,_,_,_,_) => {
                if !g.ty_params.is_empty() {
                    self.cover_lines(s);
                }
            },
            FnKind::Method(_, sig, _, _) => {
                if !sig.generics.ty_params.is_empty() {
                    self.cover_lines(s);
                }
            },
            _ => {},
        }
        visit::walk_fn(self, fk, fd, s);
    }

    fn visit_mac(&mut self, mac: &Mac) {
        // Use this to ignore unreachable lines
        let mac_text = &format!("{}", mac.node.path)[..];
        // TODO unimplemented should have extra logic to exclude the
        // function from coverage
        match mac_text {
            "unimplemented" => self.ignore_lines(mac.span),
            "unreachable" => self.ignore_lines(mac.span),
            _ => {},
        }
        visit::walk_mac(self, mac);
    }

    /// Ignores attributes which may get identified as coverable lines.
    fn visit_attribute(&mut self, attr: &Attribute) {
        if attr.check_name("derive") {
            self.ignore_lines(attr.span);
        }
    }

    /// Struct fields are mistakenly identified as instructions and uncoverable.
    fn visit_struct_field(&mut self, s: &'v StructField) {
        self.ignore_lines(s.span);
        visit::walk_struct_field(self, s);
    }

    fn visit_block(&mut self, b: &'v Block) {
        self.find_ignorable_lines(b.span);
        visit::walk_block(self, b);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use syntex_syntax::parse::filemap_to_parser;
    use syntex_syntax::parse::parser::Parser;

    struct TestContext {
        conf: Config,
        codemap: Rc<CodeMap>,
        parse_session: ParseSess
    }

    impl TestContext {
        fn generate_parser(&self, filename: &str, src_string: &str) -> Parser {
            let filemap = self.codemap.new_filemap(filename.to_string(),
                                                   src_string.to_string());
            filemap_to_parser(&self.parse_session, filemap)
        }
    }

    impl Default for TestContext {
        fn default() -> TestContext {
            let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
            let handler = Handler::with_tty_emitter(ColorConfig::Auto, false, false, Some(codemap.clone()));
            let parse_session = ParseSess::with_span_handler(handler, codemap.clone());
            TestContext {
                conf: Config::default(),
                codemap: codemap,
                parse_session: parse_session
            }
        }
    }

    fn parse_crate(ctx: &TestContext, parser: &mut Parser) -> Vec<usize>  {
        let krate = parser.parse_crate_mod();
        assert!(krate.is_ok());
        let krate = krate.unwrap();
        let unused: HashSet<PathBuf> = HashSet::new();
        let mut visitor = IgnoredLines::from_session(&ctx.parse_session, &unused, &ctx.conf);
        visitor.visit_mod(&krate.module, krate.span, &krate.attrs, NodeId::new(0));
        visitor.lines.iter().map(|x| x.1).collect::<Vec<_>>()
    }

    #[test]
    fn filter_struct_members() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("struct_test.rs", "#[derive(Debug)]\npub struct Struct {\npub i: i32,\nj:String,\n}");
        let lines = parse_crate(&ctx, &mut parser);

        assert_eq!(lines.len(), 3);
        assert!(lines.contains(&1));
        assert!(lines.contains(&3));
        assert!(lines.contains(&4));
    }

    #[test]
    fn filter_mods() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("test.rs", "mod foo {\nfn double(x:i32)->i32 {\n x*2\n}\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&3));

        let mut parser = ctx.generate_parser("test.rs", "mod foo{}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&1));
    }

    #[test]
    fn filter_macros() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("test.rs", "\n\nfn unused() {\nunimplemented!();\n}");

        let lines = parse_crate(&ctx, &mut parser);
        // Braces should be ignored so number could be higher
        assert!(lines.len() >= 1);
        assert!(lines.contains(&4));

        let mut parser = ctx.generate_parser("test.rs", "fn unused() {\nunreachable!();\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.len() >= 1);
        assert!(lines.contains(&2));

        let mut parser = ctx.generate_parser("test.rs", "fn unused() {\nprintln!(\"text\");\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&2));
    }

    #[test]
    fn filter_tests() {
        let ctx = TestContext::default();
        let src_string = "#[cfg(test)]\nmod tests {\n fn boo(){\nassert!(true);\n}\n}";
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&4));

        let mut ctx = TestContext::default();
        ctx.conf.ignore_tests = true;
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&4));

        let ctx = TestContext::default();
        let src_string = "#[test]\nfn mytest() { \n assert!(true);\n}";
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&2));
        assert!(!lines.contains(&3));

        let mut ctx = TestContext::default();
        ctx.conf.ignore_tests = true;
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&2));
        assert!(lines.contains(&3));

    }
}
<commit_msg>Rename IgnoredLines to CoverageVisitor<commit_after>use std::rc::Rc;
use std::ops::Deref;
use std::path::PathBuf;
use std::collections::{HashSet, HashMap};
use cargo::core::Workspace;
use cargo::sources::PathSource;
use syntex_syntax::attr;
use syntex_syntax::visit::{self, Visitor, FnKind};
use syntex_syntax::codemap::{CodeMap, Span, FilePathMapping};
use syntex_syntax::ast::{NodeId, Mac, Attribute, Mod, StructField, Block, Item, ItemKind, FnDecl};
use syntex_syntax::parse::{self, ParseSess};
use syntex_syntax::errors::Handler;
use syntex_syntax::errors::emitter::ColorConfig;
use config::Config;

/// Represents the results of analysis of a single file. Does not store the file
/// in question as this is expected to be maintained by the user.
struct LineAnalysis {
    /// This represents lines that should be ignored in coverage
    /// but may be identifed as coverable in the DWARF tables
    pub ignore: HashSet<usize>,
    /// This represents lines that should be included in coverage
    /// But may be ignored.
    pub cover: HashSet<usize>,
}

impl LineAnalysis {
    fn new() -> LineAnalysis {
        LineAnalysis {
            ignore: HashSet::new(),
            cover: HashSet::new()
        }
    }
}

struct CoverageVisitor<'a> {
    lines: Vec<(PathBuf, usize)>,
    coverable: Vec<(PathBuf, usize)>,
    covered: &'a HashSet<PathBuf>,
    codemap: &'a CodeMap,
    config: &'a Config,
}

/// Returns a list of files and line numbers to ignore (not indexes!)
pub fn get_lines_to_ignore(project: &Workspace, config: &Config) -> Vec<(PathBuf, usize)> {
    let mut result: Vec<(PathBuf, usize)> = Vec::new();
    let pkg = project.current().unwrap();
    let mut src = PathSource::new(pkg.root(), pkg.package_id().source_id(), project.config());
    if let Ok(package) = src.root_package() {

        let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
        let handler = Handler::with_tty_emitter(ColorConfig::Auto, false, false, Some(codemap.clone()));
        let parse_session = ParseSess::with_span_handler(handler, codemap.clone());

        let mut done_files: HashSet<PathBuf> = HashSet::new();
        for target in package.targets() {
            let file = target.src_path();
            if !(config.ignore_tests && file.starts_with(project.root().join("tests"))) {
                let mut parser = parse::new_parser_from_file(&parse_session, file);
                parser.cfg_mods = false;
                if let Ok(krate) = parser.parse_crate_mod() {

                    let mut lines = {
                        let mut visitor = CoverageVisitor::from_session(&parse_session, &done_files, config);
                        visitor.visit_mod(&krate.module, krate.span, &krate.attrs, NodeId::new(0));
                        visitor.lines
                    };

                    for l in &lines {
                        done_files.insert(l.0.clone());
                    }
                    result.append(&mut lines);
                }
            }
        }
    }
    result
}

fn add_lines(codemap: &CodeMap, lines: &mut Vec<(PathBuf, usize)>, s: Span) {
    if let Ok(ls) = codemap.span_to_lines(s) {
        for line in &ls.lines {
            let pb = PathBuf::from(codemap.span_to_filename(s) as String);
            // Line number is index+1
            lines.push((pb, line.line_index + 1));
        }
    }
}

impl<'a> CoverageVisitor<'a> {
    /// Construct a new ignored lines object for the given project
    fn from_session(session: &'a ParseSess,
                    covered: &'a HashSet<PathBuf>,
                    config: &'a Config) -> CoverageVisitor<'a> {
        CoverageVisitor {
            lines: vec![],
            coverable: vec![],
            covered: covered,
            codemap: session.codemap(),
            config: config,
        }
    }

    /// Add lines to the line ignore list
    fn ignore_lines(&mut self, span: Span) {
        add_lines(self.codemap, &mut self.lines, span);
    }

    fn cover_lines(&mut self, span: Span) {
        add_lines(self.codemap, &mut self.coverable, span);
    }

    /// Looks for #[cfg(test)] attribute.
    fn contains_cfg_test(&mut self, attrs: &[Attribute]) -> bool {
        attrs.iter()
             .filter(|x| x.path == "cfg")
             .filter_map(|x| x.meta_item_list())
             .flat_map(|x| x)
             .any(|x| {
                 if let Some(w) = x.word() {
                    w.name().as_str() == "test"
                 } else {
                     false
                 }
             })
    }

    /// This function finds ignorable lines within actual coverable code.
    /// As opposed to other functions which find isolated lines that aren't
    /// executed or lines filtered by the user. These lines are things like
    /// close braces that are within coverable code but not coverable.
    fn find_ignorable_lines(&mut self, span: Span) {
        if let Ok(l) = self.codemap.span_to_lines(span) {
            for line in &l.lines {
                let pb = PathBuf::from(self.codemap.span_to_filename(span) as String);
                if let Some(s) = l.file.get_line(line.line_index) {
                    // Is this one of those pointless {, } or }; only lines?
                    if !s.chars().any(|x| !"{}[];\t ,".contains(x)) {
                        self.lines.push((pb, line.line_index + 1));
                    }
                }
            }
        }
    }
}

impl<'v, 'a> Visitor<'v> for CoverageVisitor<'a> {

    fn visit_item(&mut self, i: &'v Item) {
        match i.node {
            ItemKind::ExternCrate(..) => self.ignore_lines(i.span),
            ItemKind::Fn(_, _, _, _, _, ref block) => {
                if attr::contains_name(&i.attrs, "test") && self.config.ignore_tests {
                    self.ignore_lines(i.span);
                    self.ignore_lines(block.deref().span);
                }
            },
            _ => {},
        }
        visit::walk_item(self, i);
    }

    fn visit_mod(&mut self, m: &'v Mod, s: Span, _attrs: &[Attribute], _n: NodeId) {
        // If mod is cfg(test) and --ignore-tests ignore contents!
        if let Ok(fl) = self.codemap.span_to_lines(s) {
            if self.config.ignore_tests && self.contains_cfg_test(_attrs) {
                self.ignore_lines(s);
                if fl.lines.len() == 1 {
                    // Ignore the file
                    self.ignore_lines(m.inner);
                }
            }
            else {
                if fl.lines.len() == 1 {
                    // mod imports show up as coverable. Ignore
                    self.ignore_lines(s);
                }
                let mod_path = PathBuf::from(self.codemap.span_to_filename(m.inner));
                if !self.covered.contains(&mod_path) {
                    visit::walk_mod(self, m);
                }
            }
        }
    }

    fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, s: Span, _: NodeId) {
        match fk {
            FnKind::ItemFn(_, g, _,_,_,_,_) => {
                if !g.ty_params.is_empty() {
                    self.cover_lines(s);
                }
            },
            FnKind::Method(_, sig, _, _) => {
                if !sig.generics.ty_params.is_empty() {
                    self.cover_lines(s);
                }
            },
            _ => {},
        }
        visit::walk_fn(self, fk, fd, s);
    }

    fn visit_mac(&mut self, mac: &Mac) {
        // Use this to ignore unreachable lines
        let mac_text = &format!("{}", mac.node.path)[..];
        // TODO unimplemented should have extra logic to exclude the
        // function from coverage
        match mac_text {
            "unimplemented" => self.ignore_lines(mac.span),
            "unreachable" => self.ignore_lines(mac.span),
            _ => {},
        }
        visit::walk_mac(self, mac);
    }

    /// Ignores attributes which may get identified as coverable lines.
    fn visit_attribute(&mut self, attr: &Attribute) {
        if attr.check_name("derive") {
            self.ignore_lines(attr.span);
        }
    }

    /// Struct fields are mistakenly identified as instructions and uncoverable.
    fn visit_struct_field(&mut self, s: &'v StructField) {
        self.ignore_lines(s.span);
        visit::walk_struct_field(self, s);
    }

    fn visit_block(&mut self, b: &'v Block) {
        self.find_ignorable_lines(b.span);
        visit::walk_block(self, b);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use syntex_syntax::parse::filemap_to_parser;
    use syntex_syntax::parse::parser::Parser;

    struct TestContext {
        conf: Config,
        codemap: Rc<CodeMap>,
        parse_session: ParseSess
    }

    impl TestContext {
        fn generate_parser(&self, filename: &str, src_string: &str) -> Parser {
            let filemap = self.codemap.new_filemap(filename.to_string(),
                                                   src_string.to_string());
            filemap_to_parser(&self.parse_session, filemap)
        }
    }

    impl Default for TestContext {
        fn default() -> TestContext {
            let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
            let handler = Handler::with_tty_emitter(ColorConfig::Auto, false, false, Some(codemap.clone()));
            let parse_session = ParseSess::with_span_handler(handler, codemap.clone());
            TestContext {
                conf: Config::default(),
                codemap: codemap,
                parse_session: parse_session
            }
        }
    }

    fn parse_crate(ctx: &TestContext, parser: &mut Parser) -> Vec<usize>  {
        let krate = parser.parse_crate_mod();
        assert!(krate.is_ok());
        let krate = krate.unwrap();
        let unused: HashSet<PathBuf> = HashSet::new();
        let mut visitor = CoverageVisitor::from_session(&ctx.parse_session, &unused, &ctx.conf);
        visitor.visit_mod(&krate.module, krate.span, &krate.attrs, NodeId::new(0));
        visitor.lines.iter().map(|x| x.1).collect::<Vec<_>>()
    }

    #[test]
    fn filter_struct_members() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("struct_test.rs", "#[derive(Debug)]\npub struct Struct {\npub i: i32,\nj:String,\n}");
        let lines = parse_crate(&ctx, &mut parser);

        assert_eq!(lines.len(), 3);
        assert!(lines.contains(&1));
        assert!(lines.contains(&3));
        assert!(lines.contains(&4));
    }

    #[test]
    fn filter_mods() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("test.rs", "mod foo {\nfn double(x:i32)->i32 {\n x*2\n}\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&3));

        let mut parser = ctx.generate_parser("test.rs", "mod foo{}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&1));
    }

    #[test]
    fn filter_macros() {
        let ctx = TestContext::default();
        let mut parser = ctx.generate_parser("test.rs", "\n\nfn unused() {\nunimplemented!();\n}");

        let lines = parse_crate(&ctx, &mut parser);
        // Braces should be ignored so number could be higher
        assert!(lines.len() >= 1);
        assert!(lines.contains(&4));

        let mut parser = ctx.generate_parser("test.rs", "fn unused() {\nunreachable!();\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.len() >= 1);
        assert!(lines.contains(&2));

        let mut parser = ctx.generate_parser("test.rs", "fn unused() {\nprintln!(\"text\");\n}");
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&2));
    }

    #[test]
    fn filter_tests() {
        let ctx = TestContext::default();
        let src_string = "#[cfg(test)]\nmod tests {\n fn boo(){\nassert!(true);\n}\n}";
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&4));

        let mut ctx = TestContext::default();
        ctx.conf.ignore_tests = true;
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&4));

        let ctx = TestContext::default();
        let src_string = "#[test]\nfn mytest() { \n assert!(true);\n}";
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(!lines.contains(&2));
        assert!(!lines.contains(&3));

        let mut ctx = TestContext::default();
        ctx.conf.ignore_tests = true;
        let mut parser = ctx.generate_parser("test.rs", src_string);
        let lines = parse_crate(&ctx, &mut parser);
        assert!(lines.contains(&2));
        assert!(lines.contains(&3));

    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use light_arena::Allocator;

use bsdf::{BxDF, Fresnel, LambertianReflection, MicrofacetReflection, SpecularReflection,
           SpecularTransmission, TrowbridgeReitzDistribution, BSDF};
use interaction::SurfaceInteraction;
use material::{Material, TransportMode};
use paramset::TextureParams;
use spectrum::Spectrum;
use texture::Texture;

type TextureSpectrum = Texture<Spectrum> + Send + Sync;
type TextureFloat = Texture<f32> + Send + Sync;

#[derive(Debug)]
pub struct UberMaterial {
    kd: Arc<TextureSpectrum>,
    ks: Arc<TextureSpectrum>,
    kr: Arc<TextureSpectrum>,
    kt: Arc<TextureSpectrum>,
    opacity: Arc<TextureSpectrum>,
    roughness: Arc<TextureFloat>,
    roughnessu: Option<Arc<TextureFloat>>,
    roughnessv: Option<Arc<TextureFloat>>,
    eta: Arc<TextureFloat>,
    bumpmap: Option<Arc<TextureFloat>>,
    remap_roughness: bool,
}

impl UberMaterial {
    pub fn create(mp: &mut TextureParams) -> Arc<Material + Send + Sync> {
        let kd = mp.get_spectrum_texture("Kd", &Spectrum::from(0.25));
        let ks = mp.get_spectrum_texture("Kd", &Spectrum::from(0.25));
        let kr = mp.get_spectrum_texture("Kd", &Spectrum::from(0.0));
        let kt = mp.get_spectrum_texture("Kd", &Spectrum::from(0.0));
        let roughness = mp.get_float_texture("roughness", 0.1);
        let uroughness = mp.get_float_texture_or_none("uroughness");
        let vroughness = mp.get_float_texture_or_none("vroughness");
        let eta = mp.get_float_texture_or_none("eta")
            .unwrap_or_else(|| mp.get_float_texture("index", 1.5));
        let opacity = mp.get_spectrum_texture("opacity", &Spectrum::from(1.0));
        let bumpmap = mp.get_float_texture_or_none("bumpmap");
        let remap_roughness = mp.find_bool("remaproughness", true);

        Arc::new(UberMaterial {
                     kd,
                     ks,
                     kr,
                     kt,
                     opacity,
                     roughness,
                     roughnessu: uroughness,
                     roughnessv: vroughness,
                     eta,
                     bumpmap,
                     remap_roughness,
                 })
    }
}

impl Material for UberMaterial {
    fn compute_scattering_functions<'a, 'b>(&self,
                                            si: &mut SurfaceInteraction<'a, 'b>,
                                            mode: TransportMode,
                                            _allow_multiple_lobes: bool,
                                            arena: &'b Allocator) {
        let mut bxdfs = arena.alloc_slice::<&BxDF>(8);
        let mut i = 0;

        if let Some(ref bump_map) = self.bumpmap {
            super::bump(bump_map, si);
        }

        let e = self.eta.evaluate(si);
        let op = self.opacity.evaluate(si).clamp();
        let t = (Spectrum::white() - op).clamp();

        let mut eta = e;
        if !t.is_black() {
            eta = 1.0;
            bxdfs[i] = arena <- SpecularTransmission::new(t, 1.0, 1.0, mode);
            i += 1;
        }

        let kd = op * self.kd.evaluate(si).clamp();
        if !kd.is_black() {
            bxdfs[i] = arena <- LambertianReflection::new(kd);
            i += 1;
        }

        let ks = op * self.ks.evaluate(si).clamp();
        if !ks.is_black() {
            let fresnel = arena <- Fresnel::dielectric(1.0, e);
            let mut roughu = self.roughnessu
                .as_ref()
                .unwrap_or(&self.roughness)
                .evaluate(si);
            let mut roughv = self.roughnessv
                .as_ref()
                .unwrap_or(&self.roughness)
                .evaluate(si);
            if self.remap_roughness {
                roughu = TrowbridgeReitzDistribution::roughness_to_alpha(roughu);
                roughv = TrowbridgeReitzDistribution::roughness_to_alpha(roughv);
            }
            let distrib = arena <- TrowbridgeReitzDistribution::new(roughu, roughv);
            bxdfs[i] = arena <- MicrofacetReflection::new(ks, distrib, fresnel);
            i += 1;
        }

        let kr = op * self.kr.evaluate(si).clamp();
        if !kr.is_black() {
            let fresnel = arena <- Fresnel::dielectric(1.0, e);
            bxdfs[i] = arena <-SpecularReflection::new(kr, fresnel);
            i += 1;
        }

        let kt = op * self.kt.evaluate(si).clamp();
        if !kt.is_black() {
            bxdfs[i] = arena <- SpecularTransmission::new(kt, 1.0, e, mode);
            i += 1;
        }

        unsafe {
            let ptr = bxdfs.as_mut_ptr();
            bxdfs = ::std::slice::from_raw_parts_mut(ptr, i);
        }

        let bsdf: BSDF<'b> = BSDF::new(si, eta, bxdfs);
        si.bsdf = Some(Arc::new(bsdf));
    }
}
<commit_msg>Fix loading of Uber params<commit_after>use std::sync::Arc;

use light_arena::Allocator;

use bsdf::{BxDF, Fresnel, LambertianReflection, MicrofacetReflection, SpecularReflection,
           SpecularTransmission, TrowbridgeReitzDistribution, BSDF};
use interaction::SurfaceInteraction;
use material::{Material, TransportMode};
use paramset::TextureParams;
use spectrum::Spectrum;
use texture::Texture;

type TextureSpectrum = Texture<Spectrum> + Send + Sync;
type TextureFloat = Texture<f32> + Send + Sync;

#[derive(Debug)]
pub struct UberMaterial {
    kd: Arc<TextureSpectrum>,
    ks: Arc<TextureSpectrum>,
    kr: Arc<TextureSpectrum>,
    kt: Arc<TextureSpectrum>,
    opacity: Arc<TextureSpectrum>,
    roughness: Arc<TextureFloat>,
    roughnessu: Option<Arc<TextureFloat>>,
    roughnessv: Option<Arc<TextureFloat>>,
    eta: Arc<TextureFloat>,
    bumpmap: Option<Arc<TextureFloat>>,
    remap_roughness: bool,
}

impl UberMaterial {
    pub fn create(mp: &mut TextureParams) -> Arc<Material + Send + Sync> {
        let kd = mp.get_spectrum_texture("Kd", &Spectrum::from(0.25));
        let ks = mp.get_spectrum_texture("Ks", &Spectrum::from(0.25));
        let kr = mp.get_spectrum_texture("Kr", &Spectrum::from(0.0));
        let kt = mp.get_spectrum_texture("Kt", &Spectrum::from(0.0));
        let roughness = mp.get_float_texture("roughness", 0.1);
        let uroughness = mp.get_float_texture_or_none("uroughness");
        let vroughness = mp.get_float_texture_or_none("vroughness");
        let eta = mp.get_float_texture_or_none("eta")
            .unwrap_or_else(|| mp.get_float_texture("index", 1.5));
        let opacity = mp.get_spectrum_texture("opacity", &Spectrum::from(1.0));
        let bumpmap = mp.get_float_texture_or_none("bumpmap");
        let remap_roughness = mp.find_bool("remaproughness", true);

        Arc::new(UberMaterial {
                     kd,
                     ks,
                     kr,
                     kt,
                     opacity,
                     roughness,
                     roughnessu: uroughness,
                     roughnessv: vroughness,
                     eta,
                     bumpmap,
                     remap_roughness,
                 })
    }
}

impl Material for UberMaterial {
    fn compute_scattering_functions<'a, 'b>(&self,
                                            si: &mut SurfaceInteraction<'a, 'b>,
                                            mode: TransportMode,
                                            _allow_multiple_lobes: bool,
                                            arena: &'b Allocator) {
        let mut bxdfs = arena.alloc_slice::<&BxDF>(8);
        let mut i = 0;

        if let Some(ref bump_map) = self.bumpmap {
            super::bump(bump_map, si);
        }

        let e = self.eta.evaluate(si);
        let op = self.opacity.evaluate(si).clamp();
        let t = (Spectrum::white() - op).clamp();

        let mut eta = e;
        if !t.is_black() {
            eta = 1.0;
            bxdfs[i] = arena <- SpecularTransmission::new(t, 1.0, 1.0, mode);
            i += 1;
        }

        let kd = op * self.kd.evaluate(si).clamp();
        if !kd.is_black() {
            bxdfs[i] = arena <- LambertianReflection::new(kd);
            i += 1;
        }

        let ks = op * self.ks.evaluate(si).clamp();
        if !ks.is_black() {
            let fresnel = arena <- Fresnel::dielectric(1.0, e);
            let mut roughu = self.roughnessu
                .as_ref()
                .unwrap_or(&self.roughness)
                .evaluate(si);
            let mut roughv = self.roughnessv
                .as_ref()
                .unwrap_or(&self.roughness)
                .evaluate(si);
            if self.remap_roughness {
                roughu = TrowbridgeReitzDistribution::roughness_to_alpha(roughu);
                roughv = TrowbridgeReitzDistribution::roughness_to_alpha(roughv);
            }
            let distrib = arena <- TrowbridgeReitzDistribution::new(roughu, roughv);
            bxdfs[i] = arena <- MicrofacetReflection::new(ks, distrib, fresnel);
            i += 1;
        }

        let kr = op * self.kr.evaluate(si).clamp();
        if !kr.is_black() {
            let fresnel = arena <- Fresnel::dielectric(1.0, e);
            bxdfs[i] = arena <-SpecularReflection::new(kr, fresnel);
            i += 1;
        }

        let kt = op * self.kt.evaluate(si).clamp();
        if !kt.is_black() {
            bxdfs[i] = arena <- SpecularTransmission::new(kt, 1.0, e, mode);
            i += 1;
        }

        unsafe {
            let ptr = bxdfs.as_mut_ptr();
            bxdfs = ::std::slice::from_raw_parts_mut(ptr, i);
        }

        let bsdf: BSDF<'b> = BSDF::new(si, eta, bxdfs);
        si.bsdf = Some(Arc::new(bsdf));
    }
}
<|endoftext|>


<commit_before>
import str::sbuf;
import vec::vbuf;

// FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
// by https://github.com/graydon/rust/issues#issue/268
native "cdecl" mod libc = "" {
    fn open(sbuf s, int flags, uint mode) -> int;
    fn read(int fd, vbuf buf, uint count) -> int;
    fn write(int fd, vbuf buf, uint count) -> int;
    fn close(int fd) -> int;
    type FILE;
    fn fopen(sbuf path, sbuf mode) -> FILE;
    fn fdopen(int fd, sbuf mode) -> FILE;
    fn fclose(FILE f);
    fn fgetc(FILE f) -> int;
    fn ungetc(int c, FILE f);
    fn feof(FILE f) -> int;
    fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
    fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
    fn fseek(FILE f, int offset, int whence) -> int;
    fn ftell(FILE f) -> int;
    type dir;
    fn opendir(sbuf d) -> dir;
    fn closedir(dir d) -> int;
    type dirent;
    fn readdir(dir d) -> dirent;
    fn getenv(sbuf n) -> sbuf;
    fn setenv(sbuf n, sbuf v, int overwrite) -> int;
    fn unsetenv(sbuf n) -> int;
    fn pipe(*mutable int buf) -> int;
    fn waitpid(int pid, &mutable int status, int options) -> int;
}

native "cdecl" mod libc_ivec = "" {
    fn read(int fd, *u8 buf, uint count) -> int;
    fn write(int fd, *u8 buf, uint count) -> int;
    fn fread(*u8 buf, uint size, uint n, libc::FILE f) -> uint;
    fn fwrite(*u8 buf, uint size, uint n, libc::FILE f) -> uint;
}

mod libc_constants {
    fn O_RDONLY() -> int { ret 0; }
    fn O_WRONLY() -> int { ret 1; }
    fn O_RDWR() -> int { ret 2; }
    fn O_APPEND() -> int { ret 1024; }
    fn O_CREAT() -> int { ret 64; }
    fn O_EXCL() -> int { ret 128; }
    fn O_TRUNC() -> int { ret 512; }
    fn O_TEXT() -> int {
        ret 0; // nonexistent in linux libc

    }
    fn O_BINARY() -> int {
        ret 0; // nonexistent in linux libc

    }
    fn S_IRUSR() -> uint { ret 256u; }
    fn S_IWUSR() -> uint { ret 128u; }
}

fn exec_suffix() -> str { ret ""; }

fn target_os() -> str { ret "linux"; }

fn dylib_filename(str base) -> str { ret "lib" + base + ".so"; }

fn pipe() -> tup(int, int) {
    auto fds = tup(mutable 0, 0);
    assert (os::libc::pipe(ptr::addr_of(fds._0)) == 0);
    ret tup(fds._0, fds._1);
}

fn fd_FILE(int fd) -> libc::FILE { ret libc::fdopen(fd, str::buf("r")); }

fn waitpid(int pid) -> int {
    auto status = 0;
    assert (os::libc::waitpid(pid, status, 0) != -1);
    ret status.(0);
}

native "rust" mod rustrt {
    fn rust_getcwd() -> str;
}

fn getcwd() -> str { ret rustrt::rust_getcwd(); }

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>stdlib: Fix vector index in linux_os::waitpid. Put out burning tinderbox.<commit_after>
import str::sbuf;
import vec::vbuf;

// FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
// by https://github.com/graydon/rust/issues#issue/268
native "cdecl" mod libc = "" {
    fn open(sbuf s, int flags, uint mode) -> int;
    fn read(int fd, vbuf buf, uint count) -> int;
    fn write(int fd, vbuf buf, uint count) -> int;
    fn close(int fd) -> int;
    type FILE;
    fn fopen(sbuf path, sbuf mode) -> FILE;
    fn fdopen(int fd, sbuf mode) -> FILE;
    fn fclose(FILE f);
    fn fgetc(FILE f) -> int;
    fn ungetc(int c, FILE f);
    fn feof(FILE f) -> int;
    fn fread(vbuf buf, uint size, uint n, FILE f) -> uint;
    fn fwrite(vbuf buf, uint size, uint n, FILE f) -> uint;
    fn fseek(FILE f, int offset, int whence) -> int;
    fn ftell(FILE f) -> int;
    type dir;
    fn opendir(sbuf d) -> dir;
    fn closedir(dir d) -> int;
    type dirent;
    fn readdir(dir d) -> dirent;
    fn getenv(sbuf n) -> sbuf;
    fn setenv(sbuf n, sbuf v, int overwrite) -> int;
    fn unsetenv(sbuf n) -> int;
    fn pipe(*mutable int buf) -> int;
    fn waitpid(int pid, &mutable int status, int options) -> int;
}

native "cdecl" mod libc_ivec = "" {
    fn read(int fd, *u8 buf, uint count) -> int;
    fn write(int fd, *u8 buf, uint count) -> int;
    fn fread(*u8 buf, uint size, uint n, libc::FILE f) -> uint;
    fn fwrite(*u8 buf, uint size, uint n, libc::FILE f) -> uint;
}

mod libc_constants {
    fn O_RDONLY() -> int { ret 0; }
    fn O_WRONLY() -> int { ret 1; }
    fn O_RDWR() -> int { ret 2; }
    fn O_APPEND() -> int { ret 1024; }
    fn O_CREAT() -> int { ret 64; }
    fn O_EXCL() -> int { ret 128; }
    fn O_TRUNC() -> int { ret 512; }
    fn O_TEXT() -> int {
        ret 0; // nonexistent in linux libc

    }
    fn O_BINARY() -> int {
        ret 0; // nonexistent in linux libc

    }
    fn S_IRUSR() -> uint { ret 256u; }
    fn S_IWUSR() -> uint { ret 128u; }
}

fn exec_suffix() -> str { ret ""; }

fn target_os() -> str { ret "linux"; }

fn dylib_filename(str base) -> str { ret "lib" + base + ".so"; }

fn pipe() -> tup(int, int) {
    auto fds = tup(mutable 0, 0);
    assert (os::libc::pipe(ptr::addr_of(fds._0)) == 0);
    ret tup(fds._0, fds._1);
}

fn fd_FILE(int fd) -> libc::FILE { ret libc::fdopen(fd, str::buf("r")); }

fn waitpid(int pid) -> int {
    auto status = 0;
    assert (os::libc::waitpid(pid, status, 0) != -1);
    ret status;
}

native "rust" mod rustrt {
    fn rust_getcwd() -> str;
}

fn getcwd() -> str { ret rustrt::rust_getcwd(); }

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


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

//! The "main crate" of the Rust compiler. This crate contains common
//! type definitions that are used by the other crates in the rustc
//! "family". Some prominent examples (note that each of these modules
//! has their own README with further details).
//!
//! - **HIR.** The "high-level (H) intermediate representation (IR)" is
//!   defined in the `hir` module.
//! - **MIR.** The "mid-level (M) intermediate representation (IR)" is
//!   defined in the `mir` module. This module contains only the
//!   *definition* of the MIR; the passes that transform and operate
//!   on MIR are found in `librustc_mir` crate.
//! - **Types.** The internal representation of types used in rustc is
//!   defined in the `ty` module. This includes the **type context**
//!   (or `tcx`), which is the central context during most of
//!   compilation, containing the interners and other things.
//! - **Traits.** Trait resolution is implemented in the `traits` module.
//! - **Type inference.** The type inference code can be found in the `infer` module;
//!   this code handles low-level equality and subtyping operations. The
//!   type check pass in the compiler is found in the `librustc_typeck` crate.
//!
//! For more information about how rustc works, see the [rustc guide].
//!
//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#![feature(from_ref)]
#![feature(fs_read_write)]
#![feature(iterator_find_map)]
#![cfg_attr(windows, feature(libc))]
#![feature(macro_vis_matcher)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![feature(extern_types)]
#![feature(non_exhaustive)]
#![feature(proc_macro_internals)]
#![feature(quote)]
#![feature(optin_builtin_traits)]
#![feature(refcell_replace_swap)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(slice_sort_by_cached_key)]
#![feature(specialization)]
#![feature(unboxed_closures)]
#![feature(trace_macros)]
#![feature(trusted_len)]
#![feature(vec_remove_item)]
#![feature(catch_expr)]
#![feature(step_trait)]
#![feature(integer_atomics)]
#![feature(test)]
#![feature(in_band_lifetimes)]
#![feature(macro_at_most_once_rep)]
#![feature(inclusive_range_methods)]
#![feature(crate_in_paths)]

#![recursion_limit="512"]

extern crate arena;
#[macro_use] extern crate bitflags;
extern crate core;
extern crate fmt_macros;
extern crate getopts;
extern crate graphviz;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate scoped_tls;
#[cfg(windows)]
extern crate libc;
extern crate polonius_engine;
extern crate rustc_target;
#[macro_use] extern crate rustc_data_structures;
extern crate serialize;
extern crate parking_lot;
extern crate rustc_errors as errors;
extern crate rustc_rayon as rayon;
extern crate rustc_rayon_core as rayon_core;
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
extern crate syntax_pos;
extern crate jobserver;
extern crate proc_macro;
extern crate chalk_engine;

extern crate serialize as rustc_serialize; // used by deriving

extern crate rustc_apfloat;
extern crate byteorder;
extern crate backtrace;

// Note that librustc doesn't actually depend on these crates, see the note in
// `Cargo.toml` for this crate about why these are here.
#[allow(unused_extern_crates)]
extern crate flate2;
#[allow(unused_extern_crates)]
extern crate test;

#[macro_use]
mod macros;

// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;

pub mod cfg;
pub mod dep_graph;
pub mod hir;
pub mod ich;
pub mod infer;
pub mod lint;

pub mod middle {
    pub mod allocator;
    pub mod borrowck;
    pub mod expr_use_visitor;
    pub mod cstore;
    pub mod dataflow;
    pub mod dead;
    pub mod dependency_format;
    pub mod entry;
    pub mod exported_symbols;
    pub mod free_region;
    pub mod intrinsicck;
    pub mod lang_items;
    pub mod liveness;
    pub mod mem_categorization;
    pub mod privacy;
    pub mod reachable;
    pub mod region;
    pub mod recursion_limit;
    pub mod resolve_lifetime;
    pub mod stability;
    pub mod weak_lang_items;
}

pub mod mir;
pub mod session;
pub mod traits;
pub mod ty;

pub mod util {
    pub mod captures;
    pub mod common;
    pub mod ppaux;
    pub mod nodemap;
    pub mod fs;
    pub mod time_graph;
    pub mod profiling;
}

// A private module so that macro-expanded idents like
// `::rustc::lint::Lint` will also work in `rustc` itself.
//
// `libstd` uses the same trick.
#[doc(hidden)]
mod rustc {
    pub use lint;
}

// FIXME(#27438): right now the unit tests of librustc don't refer to any actual
//                functions generated in librustc_data_structures (all
//                references are through generic functions), but statics are
//                referenced from time to time. Due to this bug we won't
//                actually correctly link in the statics unless we also
//                reference a function, so be sure to reference a dummy
//                function.
#[test]
fn noop() {
    rustc_data_structures::__noop_fix_for_27438();
}

// Build the diagnostics array at the end so that the metadata includes error use sites.
__build_diagnostic_array! { librustc, DIAGNOSTICS }
<commit_msg>Fix the stage1 build<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The "main crate" of the Rust compiler. This crate contains common
//! type definitions that are used by the other crates in the rustc
//! "family". Some prominent examples (note that each of these modules
//! has their own README with further details).
//!
//! - **HIR.** The "high-level (H) intermediate representation (IR)" is
//!   defined in the `hir` module.
//! - **MIR.** The "mid-level (M) intermediate representation (IR)" is
//!   defined in the `mir` module. This module contains only the
//!   *definition* of the MIR; the passes that transform and operate
//!   on MIR are found in `librustc_mir` crate.
//! - **Types.** The internal representation of types used in rustc is
//!   defined in the `ty` module. This includes the **type context**
//!   (or `tcx`), which is the central context during most of
//!   compilation, containing the interners and other things.
//! - **Traits.** Trait resolution is implemented in the `traits` module.
//! - **Type inference.** The type inference code can be found in the `infer` module;
//!   this code handles low-level equality and subtyping operations. The
//!   type check pass in the compiler is found in the `librustc_typeck` crate.
//!
//! For more information about how rustc works, see the [rustc guide].
//!
//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#![feature(from_ref)]
#![feature(fs_read_write)]
#![feature(iterator_find_map)]
#![cfg_attr(windows, feature(libc))]
#![feature(macro_vis_matcher)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![feature(extern_types)]
#![feature(non_exhaustive)]
#![feature(proc_macro_internals)]
#![feature(quote)]
#![feature(optin_builtin_traits)]
#![feature(refcell_replace_swap)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(slice_sort_by_cached_key)]
#![feature(specialization)]
#![feature(unboxed_closures)]
#![feature(trace_macros)]
#![feature(trusted_len)]
#![feature(vec_remove_item)]
#![feature(catch_expr)]
#![feature(step_trait)]
#![feature(integer_atomics)]
#![feature(test)]
#![cfg_attr(not(stage0), feature(impl_header_lifetime_elision))]
#![feature(in_band_lifetimes)]
#![feature(macro_at_most_once_rep)]
#![feature(inclusive_range_methods)]
#![feature(crate_in_paths)]

#![recursion_limit="512"]

extern crate arena;
#[macro_use] extern crate bitflags;
extern crate core;
extern crate fmt_macros;
extern crate getopts;
extern crate graphviz;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate scoped_tls;
#[cfg(windows)]
extern crate libc;
extern crate polonius_engine;
extern crate rustc_target;
#[macro_use] extern crate rustc_data_structures;
extern crate serialize;
extern crate parking_lot;
extern crate rustc_errors as errors;
extern crate rustc_rayon as rayon;
extern crate rustc_rayon_core as rayon_core;
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
extern crate syntax_pos;
extern crate jobserver;
extern crate proc_macro;
extern crate chalk_engine;

extern crate serialize as rustc_serialize; // used by deriving

extern crate rustc_apfloat;
extern crate byteorder;
extern crate backtrace;

// Note that librustc doesn't actually depend on these crates, see the note in
// `Cargo.toml` for this crate about why these are here.
#[allow(unused_extern_crates)]
extern crate flate2;
#[allow(unused_extern_crates)]
extern crate test;

#[macro_use]
mod macros;

// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;

pub mod cfg;
pub mod dep_graph;
pub mod hir;
pub mod ich;
pub mod infer;
pub mod lint;

pub mod middle {
    pub mod allocator;
    pub mod borrowck;
    pub mod expr_use_visitor;
    pub mod cstore;
    pub mod dataflow;
    pub mod dead;
    pub mod dependency_format;
    pub mod entry;
    pub mod exported_symbols;
    pub mod free_region;
    pub mod intrinsicck;
    pub mod lang_items;
    pub mod liveness;
    pub mod mem_categorization;
    pub mod privacy;
    pub mod reachable;
    pub mod region;
    pub mod recursion_limit;
    pub mod resolve_lifetime;
    pub mod stability;
    pub mod weak_lang_items;
}

pub mod mir;
pub mod session;
pub mod traits;
pub mod ty;

pub mod util {
    pub mod captures;
    pub mod common;
    pub mod ppaux;
    pub mod nodemap;
    pub mod fs;
    pub mod time_graph;
    pub mod profiling;
}

// A private module so that macro-expanded idents like
// `::rustc::lint::Lint` will also work in `rustc` itself.
//
// `libstd` uses the same trick.
#[doc(hidden)]
mod rustc {
    pub use lint;
}

// FIXME(#27438): right now the unit tests of librustc don't refer to any actual
//                functions generated in librustc_data_structures (all
//                references are through generic functions), but statics are
//                referenced from time to time. Due to this bug we won't
//                actually correctly link in the statics unless we also
//                reference a function, so be sure to reference a dummy
//                function.
#[test]
fn noop() {
    rustc_data_structures::__noop_fix_for_27438();
}

// Build the diagnostics array at the end so that the metadata includes error use sites.
__build_diagnostic_array! { librustc, DIAGNOSTICS }
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Small system utility modules for usage by other modules.

extern crate data_model;
extern crate libc;
extern crate syscall_defines;

#[macro_use]
pub mod handle_eintr;
#[macro_use]
pub mod ioctl;
#[macro_use]
pub mod syslog;
mod mmap;
mod shm;
mod eventfd;
mod errno;
mod guest_address;
mod guest_memory;
mod poll;
mod struct_util;
mod tempdir;
mod terminal;
mod signal;
mod fork;
mod signalfd;
mod sock_ctrl_msg;
mod passwd;

pub use mmap::*;
pub use shm::*;
pub use eventfd::*;
pub use errno::{Error, Result};
use errno::errno_result;
pub use guest_address::*;
pub use guest_memory::*;
pub use poll::*;
pub use struct_util::*;
pub use tempdir::*;
pub use terminal::*;
pub use signal::*;
pub use fork::*;
pub use signalfd::*;
pub use ioctl::*;
pub use sock_ctrl_msg::*;
pub use passwd::*;

pub use mmap::Error as MmapError;
pub use guest_memory::Error as GuestMemoryError;
pub use signalfd::Error as SignalFdError;

use std::ptr;

use libc::{kill, syscall, waitpid, c_long, pid_t, uid_t, gid_t, SIGKILL, WNOHANG};

use syscall_defines::linux::LinuxSyscall::SYS_getpid;

/// This bypasses `libc`'s caching `getpid(2)` wrapper which can be invalid if a raw clone was used
/// elsewhere.
#[inline(always)]
pub fn getpid() -> pid_t {
    // Safe because this syscall can never fail and we give it a valid syscall number.
    unsafe { syscall(SYS_getpid as c_long) as pid_t }
}

/// Safe wrapper for `geteuid(2)`.
#[inline(always)]
pub fn geteuid() -> uid_t {
    // trivially safe
    unsafe { libc::geteuid() }
}

/// Safe wrapper for `getegid(2)`.
#[inline(always)]
pub fn getegid() -> gid_t {
    // trivially safe
    unsafe { libc::getegid() }
}

/// Reaps a child process that has terminated.
///
/// Returns `Ok(pid)` where `pid` is the process that was reaped or `Ok(0)` if none of the children
/// have terminated. An `Error` is with `errno == ECHILD` if there are no children left to reap.
///
/// # Examples
///
/// Reaps all child processes until there are no terminated children to reap.
///
/// ```
/// # extern crate libc;
/// # extern crate sys_util;
/// fn reap_children() {
///     loop {
///         match sys_util::reap_child() {
///             Ok(0) => println!("no children ready to reap"),
///             Ok(pid) => {
///                 println!("reaped {}", pid);
///                 continue
///             },
///             Err(e) if e.errno() == libc::ECHILD => println!("no children left"),
///             Err(e) => println!("error reaping children: {:?}", e),
///         }
///         break
///     }
/// }
/// ```
pub fn reap_child() -> Result<pid_t> {
    // Safe because we pass in no memory, prevent blocking with WNOHANG, and check for error.
    let ret = unsafe { waitpid(-1, ptr::null_mut(), WNOHANG) };
    if ret == -1 {
        errno_result()
    } else {
        Ok(ret)
    }
}

/// Kill all processes in the current process group.
///
/// On success, this kills all processes in the current process group, including the current
/// process, meaning this will not return. This is equivalent to a call to `kill(0, SIGKILL)`.
pub fn kill_process_group() -> Result<()> {
    let ret = unsafe { kill(0, SIGKILL) };
    if ret == -1 {
        errno_result()
    } else {
        // Kill succeeded, so this process never reaches here.
        unreachable!();
    }
}
<commit_msg>sys_util: add chown wrapper<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Small system utility modules for usage by other modules.

extern crate data_model;
extern crate libc;
extern crate syscall_defines;

#[macro_use]
pub mod handle_eintr;
#[macro_use]
pub mod ioctl;
#[macro_use]
pub mod syslog;
mod mmap;
mod shm;
mod eventfd;
mod errno;
mod guest_address;
mod guest_memory;
mod poll;
mod struct_util;
mod tempdir;
mod terminal;
mod signal;
mod fork;
mod signalfd;
mod sock_ctrl_msg;
mod passwd;

pub use mmap::*;
pub use shm::*;
pub use eventfd::*;
pub use errno::{Error, Result};
use errno::errno_result;
pub use guest_address::*;
pub use guest_memory::*;
pub use poll::*;
pub use struct_util::*;
pub use tempdir::*;
pub use terminal::*;
pub use signal::*;
pub use fork::*;
pub use signalfd::*;
pub use ioctl::*;
pub use sock_ctrl_msg::*;
pub use passwd::*;

pub use mmap::Error as MmapError;
pub use guest_memory::Error as GuestMemoryError;
pub use signalfd::Error as SignalFdError;

use std::ffi::CStr;
use std::ptr;

use libc::{kill, syscall, waitpid, c_long, pid_t, uid_t, gid_t, SIGKILL, WNOHANG};

use syscall_defines::linux::LinuxSyscall::SYS_getpid;

/// This bypasses `libc`'s caching `getpid(2)` wrapper which can be invalid if a raw clone was used
/// elsewhere.
#[inline(always)]
pub fn getpid() -> pid_t {
    // Safe because this syscall can never fail and we give it a valid syscall number.
    unsafe { syscall(SYS_getpid as c_long) as pid_t }
}

/// Safe wrapper for `geteuid(2)`.
#[inline(always)]
pub fn geteuid() -> uid_t {
    // trivially safe
    unsafe { libc::geteuid() }
}

/// Safe wrapper for `getegid(2)`.
#[inline(always)]
pub fn getegid() -> gid_t {
    // trivially safe
    unsafe { libc::getegid() }
}

/// Safe wrapper for chown(2).
#[inline(always)]
pub fn chown(path: &CStr, uid: uid_t, gid: gid_t) -> Result<()> {
    // Safe since we pass in a valid string pointer and check the return value.
    let ret = unsafe { libc::chown(path.as_ptr(), uid, gid) };

    if ret < 0 {
        errno_result()
    } else {
        Ok(())
    }
}

/// Reaps a child process that has terminated.
///
/// Returns `Ok(pid)` where `pid` is the process that was reaped or `Ok(0)` if none of the children
/// have terminated. An `Error` is with `errno == ECHILD` if there are no children left to reap.
///
/// # Examples
///
/// Reaps all child processes until there are no terminated children to reap.
///
/// ```
/// # extern crate libc;
/// # extern crate sys_util;
/// fn reap_children() {
///     loop {
///         match sys_util::reap_child() {
///             Ok(0) => println!("no children ready to reap"),
///             Ok(pid) => {
///                 println!("reaped {}", pid);
///                 continue
///             },
///             Err(e) if e.errno() == libc::ECHILD => println!("no children left"),
///             Err(e) => println!("error reaping children: {:?}", e),
///         }
///         break
///     }
/// }
/// ```
pub fn reap_child() -> Result<pid_t> {
    // Safe because we pass in no memory, prevent blocking with WNOHANG, and check for error.
    let ret = unsafe { waitpid(-1, ptr::null_mut(), WNOHANG) };
    if ret == -1 {
        errno_result()
    } else {
        Ok(ret)
    }
}

/// Kill all processes in the current process group.
///
/// On success, this kills all processes in the current process group, including the current
/// process, meaning this will not return. This is equivalent to a call to `kill(0, SIGKILL)`.
pub fn kill_process_group() -> Result<()> {
    let ret = unsafe { kill(0, SIGKILL) };
    if ret == -1 {
        errno_result()
    } else {
        // Kill succeeded, so this process never reaches here.
        unreachable!();
    }
}
<|endoftext|>


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

#[crate_id = "github.com/mozilla-servo/rust-core-foundation#core_foundation:0.1"];

extern crate std;

pub mod array;
pub mod base;
pub mod boolean;
pub mod data;
pub mod dictionary;
pub mod number;
pub mod set;
pub mod string;
pub mod url;

#[cfg(test)]
pub mod test {
    #[test]
    fn test_stuff() {
        use base::TCFType;
        use boolean::CFBoolean;
        use number::number;
        use dictionary::CFDictionary;
        use string::CFString;

        /*let n = CFNumber::new_number(42 as i32);
        io::println(format!("%d", (&n).retain_count() as int));
        (&n).show();*/

        let bar = CFString::from_static_string("Bar");
        let baz = CFString::from_static_string("Baz");
        let boo = CFString::from_static_string("Boo");
        let foo = CFString::from_static_string("Foo");
        let tru = CFBoolean::true_value();
        let n42 = number(42);

        let _d = CFDictionary::from_CFType_pairs([
            (bar.as_CFType(), boo.as_CFType()),
            (baz.as_CFType(), tru.as_CFType()),
            (foo.as_CFType(), n42.as_CFType()),
        ]);
    }
}
<commit_msg>Generate both dylib and rlib for rustup<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[crate_id = "github.com/mozilla-servo/rust-core-foundation#core_foundation:0.1"];
#[crate_type = "lib"];
#[crate_type = "dylib"];
#[crate_type = "rlib"];

extern crate std;

pub mod array;
pub mod base;
pub mod boolean;
pub mod data;
pub mod dictionary;
pub mod number;
pub mod set;
pub mod string;
pub mod url;

#[cfg(test)]
pub mod test {
    #[test]
    fn test_stuff() {
        use base::TCFType;
        use boolean::CFBoolean;
        use number::number;
        use dictionary::CFDictionary;
        use string::CFString;

        /*let n = CFNumber::new_number(42 as i32);
        io::println(format!("%d", (&n).retain_count() as int));
        (&n).show();*/

        let bar = CFString::from_static_string("Bar");
        let baz = CFString::from_static_string("Baz");
        let boo = CFString::from_static_string("Boo");
        let foo = CFString::from_static_string("Foo");
        let tru = CFBoolean::true_value();
        let n42 = number(42);

        let _d = CFDictionary::from_CFType_pairs([
            (bar.as_CFType(), boo.as_CFType()),
            (baz.as_CFType(), tru.as_CFType()),
            (foo.as_CFType(), n42.as_CFType()),
        ]);
    }
}
<|endoftext|>