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

#![allow(dead_code)]

use core::prelude::*;

use cmp;
use ffi::CString;
use io;
use libc::consts::os::posix01::PTHREAD_STACK_MIN;
use libc;
use mem;
use ptr;
use sys::os;
use thunk::Thunk;
use time::Duration;

use sys_common::stack::RED_ZONE;
use sys_common::thread::*;

pub type rust_thread = libc::pthread_t;

#[cfg(all(not(target_os = "linux"),
          not(target_os = "macos"),
          not(target_os = "bitrig"),
          not(target_os = "openbsd")))]
pub mod guard {
    pub unsafe fn current() -> usize { 0 }
    pub unsafe fn main() -> usize { 0 }
    pub unsafe fn init() {}
}

#[cfg(any(target_os = "linux",
          target_os = "macos",
          target_os = "bitrig",
          target_os = "openbsd"))]
#[allow(unused_imports)]
pub mod guard {
    use libc::{self, pthread_t};
    use libc::funcs::posix88::mman::mmap;
    use libc::consts::os::posix88::{PROT_NONE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED,
                                    MAP_FIXED};
    use mem;
    use ptr;
    use super::{pthread_self, pthread_attr_destroy};
    use sys::os;

    // These are initialized in init() and only read from after
    static mut GUARD_PAGE: usize = 0;

    #[cfg(any(target_os = "macos",
              target_os = "bitrig",
              target_os = "openbsd"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        current() as *mut libc::c_void
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
        let mut stackaddr = ptr::null_mut();
        let mut stacksize = 0;
        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);
        stackaddr
    }

    pub unsafe fn init() {
        let psize = os::page_size();
        let mut stackaddr = get_stack_start();

        // Ensure stackaddr is page aligned! A parent process might
        // have reset RLIMIT_STACK to be non-page aligned. The
        // pthread_attr_getstack() reports the usable stack area
        // stackaddr < stackaddr + stacksize, so if stackaddr is not
        // page-aligned, calculate the fix such that stackaddr <
        // new_page_aligned_stackaddr < stackaddr + stacksize
        let remainder = (stackaddr as usize) % psize;
        if remainder != 0 {
            stackaddr = ((stackaddr as usize) + psize - remainder)
                as *mut libc::c_void;
        }

        // Rellocate the last page of the stack.
        // This ensures SIGBUS will be raised on
        // stack overflow.
        let result = mmap(stackaddr,
                          psize as libc::size_t,
                          PROT_NONE,
                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                          -1,
                          0);

        if result != stackaddr || result == MAP_FAILED {
            panic!("failed to allocate a guard page");
        }

        let offset = if cfg!(target_os = "linux") {2} else {1};

        GUARD_PAGE = stackaddr as usize + offset * psize;
    }

    pub unsafe fn main() -> usize {
        GUARD_PAGE
    }

    #[cfg(target_os = "macos")]
    pub unsafe fn current() -> usize {
        extern {
            fn pthread_get_stackaddr_np(thread: pthread_t) -> *mut libc::c_void;
            fn pthread_get_stacksize_np(thread: pthread_t) -> libc::size_t;
        }
        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
         pthread_get_stacksize_np(pthread_self())) as usize
    }

    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
    pub unsafe fn current() -> usize {
        #[repr(C)]
        struct stack_t {
            ss_sp: *mut libc::c_void,
            ss_size: libc::size_t,
            ss_flags: libc::c_int,
        }
        extern {
            fn pthread_main_np() -> libc::c_uint;
            fn pthread_stackseg_np(thread: pthread_t,
                                   sinfo: *mut stack_t) -> libc::c_uint;
        }

        let mut current_stack: stack_t = mem::zeroed();
        assert_eq!(pthread_stackseg_np(pthread_self(), &mut current_stack), 0);

        let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
        if pthread_main_np() == 1 {
            // main thread
            current_stack.ss_sp as usize - current_stack.ss_size as usize + extra
        } else {
            // new thread
            current_stack.ss_sp as usize - current_stack.ss_size as usize
        }
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub unsafe fn current() -> usize {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
        let mut guardsize = 0;
        assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0);
        if guardsize == 0 {
            panic!("there is no guard page");
        }
        let mut stackaddr = ptr::null_mut();
        let mut size = 0;
        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);

        stackaddr as usize + guardsize as usize
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    extern {
        fn pthread_getattr_np(native: libc::pthread_t,
                              attr: *mut libc::pthread_attr_t) -> libc::c_int;
        fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t,
                                     guardsize: *mut libc::size_t) -> libc::c_int;
        fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
                                 stackaddr: *mut *mut libc::c_void,
                                 stacksize: *mut libc::size_t) -> libc::c_int;
    }
}

pub unsafe fn create(stack: usize, p: Thunk) -> io::Result<rust_thread> {
    let p = box p;
    let mut native: libc::pthread_t = mem::zeroed();
    let mut attr: libc::pthread_attr_t = mem::zeroed();
    assert_eq!(pthread_attr_init(&mut attr), 0);

    // Reserve room for the red zone, the runtime's stack of last resort.
    let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as usize);
    match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
        0 => {}
        n => {
            assert_eq!(n, libc::EINVAL);
            // EINVAL means |stack_size| is either too small or not a
            // multiple of the system page size.  Because it's definitely
            // >= PTHREAD_STACK_MIN, it must be an alignment issue.
            // Round up to the nearest page and try again.
            let page_size = os::page_size();
            let stack_size = (stack_size + page_size - 1) &
                             (-(page_size as isize - 1) as usize - 1);
            assert_eq!(pthread_attr_setstacksize(&mut attr,
                                                 stack_size as libc::size_t), 0);
        }
    };

    let ret = pthread_create(&mut native, &attr, thread_start,
                             &*p as *const _ as *mut _);
    assert_eq!(pthread_attr_destroy(&mut attr), 0);

    return if ret != 0 {
        Err(io::Error::from_os_error(ret))
    } else {
        mem::forget(p); // ownership passed to pthread_create
        Ok(native)
    };

    #[no_stack_check]
    extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
        start_thread(main);
        0 as *mut _
    }
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub unsafe fn set_name(name: &str) {
    // pthread_setname_np() since glibc 2.12
    // availability autodetected via weak linkage
    type F = unsafe extern fn(libc::pthread_t, *const libc::c_char)
                              -> libc::c_int;
    extern {
        #[linkage = "extern_weak"]
        static pthread_setname_np: *const ();
    }
    if !pthread_setname_np.is_null() {
        let cname = CString::new(name).unwrap();
        mem::transmute::<*const (), F>(pthread_setname_np)(pthread_self(),
                                                           cname.as_ptr());
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "openbsd"))]
pub unsafe fn set_name(name: &str) {
    extern {
        fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
    }
    let cname = CString::new(name).unwrap();
    pthread_set_name_np(pthread_self(), cname.as_ptr());
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) {
    extern {
        fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
    }
    let cname = CString::new(name).unwrap();
    pthread_setname_np(cname.as_ptr());
}

pub unsafe fn join(native: rust_thread) {
    assert_eq!(pthread_join(native, ptr::null_mut()), 0);
}

pub unsafe fn detach(native: rust_thread) {
    assert_eq!(pthread_detach(native), 0);
}

pub unsafe fn yield_now() {
    assert_eq!(sched_yield(), 0);
}

pub fn sleep(dur: Duration) {
    unsafe {
        if dur < Duration::zero() {
            return yield_now()
        }
        let seconds = dur.num_seconds();
        let ns = dur - Duration::seconds(seconds);
        let mut ts = libc::timespec {
            tv_sec: seconds as libc::time_t,
            tv_nsec: ns.num_nanoseconds().unwrap() as libc::c_long,
        };
        // If we're awoken with a signal then the return value will be -1 and
        // nanosleep will fill in `ts` with the remaining time.
        while dosleep(&mut ts) == -1 {
            assert_eq!(os::errno(), libc::EINTR);
        }
    }

    #[cfg(target_os = "linux")]
    unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int {
        extern {
            fn clock_nanosleep(clock_id: libc::c_int, flags: libc::c_int,
                               request: *const libc::timespec,
                               remain: *mut libc::timespec) -> libc::c_int;
        }
        clock_nanosleep(libc::CLOCK_MONOTONIC, 0, ts, ts)
    }
    #[cfg(not(target_os = "linux"))]
    unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int {
        libc::nanosleep(ts, ts)
    }
}

// glibc >= 2.15 has a __pthread_get_minstack() function that returns
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
// storage.  We need that information to avoid blowing up when a small stack
// is created in an application with big thread-local storage requirements.
// See #6233 for rationale and details.
//
// Link weakly to the symbol for compatibility with older versions of glibc.
// Assumes that we've been dynamically linked to libpthread but that is
// currently always the case.  Note that you need to check that the symbol
// is non-null before calling it!
#[cfg(target_os = "linux")]
fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
    type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
    extern {
        #[linkage = "extern_weak"]
        static __pthread_get_minstack: *const ();
    }
    if __pthread_get_minstack.is_null() {
        PTHREAD_STACK_MIN
    } else {
        unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) }
    }
}

// __pthread_get_minstack() is marked as weak but extern_weak linkage is
// not supported on OS X, hence this kludge...
#[cfg(not(target_os = "linux"))]
fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
    PTHREAD_STACK_MIN
}

extern {
    fn pthread_self() -> libc::pthread_t;
    fn pthread_create(native: *mut libc::pthread_t,
                      attr: *const libc::pthread_attr_t,
                      f: extern fn(*mut libc::c_void) -> *mut libc::c_void,
                      value: *mut libc::c_void) -> libc::c_int;
    fn pthread_join(native: libc::pthread_t,
                    value: *mut *mut libc::c_void) -> libc::c_int;
    fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
                                 stack_size: libc::size_t) -> libc::c_int;
    fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                   state: libc::c_int) -> libc::c_int;
    fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
    fn sched_yield() -> libc::c_int;
}
<commit_msg>rollup merge of #23631: andersk/minstack-dlsym<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]

use core::prelude::*;

use cmp;
use dynamic_lib::DynamicLibrary;
use ffi::CString;
use io;
use libc::consts::os::posix01::PTHREAD_STACK_MIN;
use libc;
use mem;
use ptr;
use sync::{Once, ONCE_INIT};
use sys::os;
use thunk::Thunk;
use time::Duration;

use sys_common::stack::RED_ZONE;
use sys_common::thread::*;

pub type rust_thread = libc::pthread_t;

#[cfg(all(not(target_os = "linux"),
          not(target_os = "macos"),
          not(target_os = "bitrig"),
          not(target_os = "openbsd")))]
pub mod guard {
    pub unsafe fn current() -> usize { 0 }
    pub unsafe fn main() -> usize { 0 }
    pub unsafe fn init() {}
}

#[cfg(any(target_os = "linux",
          target_os = "macos",
          target_os = "bitrig",
          target_os = "openbsd"))]
#[allow(unused_imports)]
pub mod guard {
    use libc::{self, pthread_t};
    use libc::funcs::posix88::mman::mmap;
    use libc::consts::os::posix88::{PROT_NONE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED,
                                    MAP_FIXED};
    use mem;
    use ptr;
    use super::{pthread_self, pthread_attr_destroy};
    use sys::os;

    // These are initialized in init() and only read from after
    static mut GUARD_PAGE: usize = 0;

    #[cfg(any(target_os = "macos",
              target_os = "bitrig",
              target_os = "openbsd"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        current() as *mut libc::c_void
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
        let mut stackaddr = ptr::null_mut();
        let mut stacksize = 0;
        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);
        stackaddr
    }

    pub unsafe fn init() {
        let psize = os::page_size();
        let mut stackaddr = get_stack_start();

        // Ensure stackaddr is page aligned! A parent process might
        // have reset RLIMIT_STACK to be non-page aligned. The
        // pthread_attr_getstack() reports the usable stack area
        // stackaddr < stackaddr + stacksize, so if stackaddr is not
        // page-aligned, calculate the fix such that stackaddr <
        // new_page_aligned_stackaddr < stackaddr + stacksize
        let remainder = (stackaddr as usize) % psize;
        if remainder != 0 {
            stackaddr = ((stackaddr as usize) + psize - remainder)
                as *mut libc::c_void;
        }

        // Rellocate the last page of the stack.
        // This ensures SIGBUS will be raised on
        // stack overflow.
        let result = mmap(stackaddr,
                          psize as libc::size_t,
                          PROT_NONE,
                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                          -1,
                          0);

        if result != stackaddr || result == MAP_FAILED {
            panic!("failed to allocate a guard page");
        }

        let offset = if cfg!(target_os = "linux") {2} else {1};

        GUARD_PAGE = stackaddr as usize + offset * psize;
    }

    pub unsafe fn main() -> usize {
        GUARD_PAGE
    }

    #[cfg(target_os = "macos")]
    pub unsafe fn current() -> usize {
        extern {
            fn pthread_get_stackaddr_np(thread: pthread_t) -> *mut libc::c_void;
            fn pthread_get_stacksize_np(thread: pthread_t) -> libc::size_t;
        }
        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
         pthread_get_stacksize_np(pthread_self())) as usize
    }

    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
    pub unsafe fn current() -> usize {
        #[repr(C)]
        struct stack_t {
            ss_sp: *mut libc::c_void,
            ss_size: libc::size_t,
            ss_flags: libc::c_int,
        }
        extern {
            fn pthread_main_np() -> libc::c_uint;
            fn pthread_stackseg_np(thread: pthread_t,
                                   sinfo: *mut stack_t) -> libc::c_uint;
        }

        let mut current_stack: stack_t = mem::zeroed();
        assert_eq!(pthread_stackseg_np(pthread_self(), &mut current_stack), 0);

        let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
        if pthread_main_np() == 1 {
            // main thread
            current_stack.ss_sp as usize - current_stack.ss_size as usize + extra
        } else {
            // new thread
            current_stack.ss_sp as usize - current_stack.ss_size as usize
        }
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub unsafe fn current() -> usize {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        assert_eq!(pthread_getattr_np(pthread_self(), &mut attr), 0);
        let mut guardsize = 0;
        assert_eq!(pthread_attr_getguardsize(&attr, &mut guardsize), 0);
        if guardsize == 0 {
            panic!("there is no guard page");
        }
        let mut stackaddr = ptr::null_mut();
        let mut size = 0;
        assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
        assert_eq!(pthread_attr_destroy(&mut attr), 0);

        stackaddr as usize + guardsize as usize
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    extern {
        fn pthread_getattr_np(native: libc::pthread_t,
                              attr: *mut libc::pthread_attr_t) -> libc::c_int;
        fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t,
                                     guardsize: *mut libc::size_t) -> libc::c_int;
        fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
                                 stackaddr: *mut *mut libc::c_void,
                                 stacksize: *mut libc::size_t) -> libc::c_int;
    }
}

pub unsafe fn create(stack: usize, p: Thunk) -> io::Result<rust_thread> {
    let p = box p;
    let mut native: libc::pthread_t = mem::zeroed();
    let mut attr: libc::pthread_attr_t = mem::zeroed();
    assert_eq!(pthread_attr_init(&mut attr), 0);

    // Reserve room for the red zone, the runtime's stack of last resort.
    let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as usize);
    match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
        0 => {}
        n => {
            assert_eq!(n, libc::EINVAL);
            // EINVAL means |stack_size| is either too small or not a
            // multiple of the system page size.  Because it's definitely
            // >= PTHREAD_STACK_MIN, it must be an alignment issue.
            // Round up to the nearest page and try again.
            let page_size = os::page_size();
            let stack_size = (stack_size + page_size - 1) &
                             (-(page_size as isize - 1) as usize - 1);
            assert_eq!(pthread_attr_setstacksize(&mut attr,
                                                 stack_size as libc::size_t), 0);
        }
    };

    let ret = pthread_create(&mut native, &attr, thread_start,
                             &*p as *const _ as *mut _);
    assert_eq!(pthread_attr_destroy(&mut attr), 0);

    return if ret != 0 {
        Err(io::Error::from_os_error(ret))
    } else {
        mem::forget(p); // ownership passed to pthread_create
        Ok(native)
    };

    #[no_stack_check]
    extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
        start_thread(main);
        0 as *mut _
    }
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub unsafe fn set_name(name: &str) {
    // pthread_setname_np() since glibc 2.12
    // availability autodetected via weak linkage
    type F = unsafe extern fn(libc::pthread_t, *const libc::c_char)
                              -> libc::c_int;
    extern {
        #[linkage = "extern_weak"]
        static pthread_setname_np: *const ();
    }
    if !pthread_setname_np.is_null() {
        let cname = CString::new(name).unwrap();
        mem::transmute::<*const (), F>(pthread_setname_np)(pthread_self(),
                                                           cname.as_ptr());
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "openbsd"))]
pub unsafe fn set_name(name: &str) {
    extern {
        fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
    }
    let cname = CString::new(name).unwrap();
    pthread_set_name_np(pthread_self(), cname.as_ptr());
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) {
    extern {
        fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
    }
    let cname = CString::new(name).unwrap();
    pthread_setname_np(cname.as_ptr());
}

pub unsafe fn join(native: rust_thread) {
    assert_eq!(pthread_join(native, ptr::null_mut()), 0);
}

pub unsafe fn detach(native: rust_thread) {
    assert_eq!(pthread_detach(native), 0);
}

pub unsafe fn yield_now() {
    assert_eq!(sched_yield(), 0);
}

pub fn sleep(dur: Duration) {
    unsafe {
        if dur < Duration::zero() {
            return yield_now()
        }
        let seconds = dur.num_seconds();
        let ns = dur - Duration::seconds(seconds);
        let mut ts = libc::timespec {
            tv_sec: seconds as libc::time_t,
            tv_nsec: ns.num_nanoseconds().unwrap() as libc::c_long,
        };
        // If we're awoken with a signal then the return value will be -1 and
        // nanosleep will fill in `ts` with the remaining time.
        while dosleep(&mut ts) == -1 {
            assert_eq!(os::errno(), libc::EINTR);
        }
    }

    #[cfg(target_os = "linux")]
    unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int {
        extern {
            fn clock_nanosleep(clock_id: libc::c_int, flags: libc::c_int,
                               request: *const libc::timespec,
                               remain: *mut libc::timespec) -> libc::c_int;
        }
        clock_nanosleep(libc::CLOCK_MONOTONIC, 0, ts, ts)
    }
    #[cfg(not(target_os = "linux"))]
    unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int {
        libc::nanosleep(ts, ts)
    }
}

// glibc >= 2.15 has a __pthread_get_minstack() function that returns
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
// storage.  We need that information to avoid blowing up when a small stack
// is created in an application with big thread-local storage requirements.
// See #6233 for rationale and details.
//
// Use dlsym to get the symbol value at runtime, both for
// compatibility with older versions of glibc, and to avoid creating
// dependencies on GLIBC_PRIVATE symbols.  Assumes that we've been
// dynamically linked to libpthread but that is currently always the
// case.  We previously used weak linkage (under the same assumption),
// but that caused Debian to detect an unnecessarily strict versioned
// dependency on libc6 (#23628).
#[cfg(target_os = "linux")]
fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
    type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
    static INIT: Once = ONCE_INIT;
    static mut __pthread_get_minstack: Option<F> = None;

    INIT.call_once(|| {
        let lib = DynamicLibrary::open(None).unwrap();
        unsafe {
            if let Ok(f) = lib.symbol("__pthread_get_minstack") {
                __pthread_get_minstack = Some(mem::transmute::<*const (), F>(f));
            }
        }
    });

    match unsafe { __pthread_get_minstack } {
        None => PTHREAD_STACK_MIN,
        Some(f) => unsafe { f(attr) },
    }
}

// No point in looking up __pthread_get_minstack() on non-glibc
// platforms.
#[cfg(not(target_os = "linux"))]
fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
    PTHREAD_STACK_MIN
}

extern {
    fn pthread_self() -> libc::pthread_t;
    fn pthread_create(native: *mut libc::pthread_t,
                      attr: *const libc::pthread_attr_t,
                      f: extern fn(*mut libc::c_void) -> *mut libc::c_void,
                      value: *mut libc::c_void) -> libc::c_int;
    fn pthread_join(native: libc::pthread_t,
                    value: *mut *mut libc::c_void) -> libc::c_int;
    fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
                                 stack_size: libc::size_t) -> libc::c_int;
    fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                   state: libc::c_int) -> libc::c_int;
    fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
    fn sched_yield() -> libc::c_int;
}
<|endoftext|>


<commit_before><commit_msg>[add] rock paper scissors game<commit_after>#![allow(dead_code)]
pub mod pseudo;

use std::time::SystemTime;
use std::cmp::Ordering;
use std::str::FromStr;
use pseudo::Rng;
use std::io;

#[derive(Debug, Eq, Copy, Clone)]
enum Figure {
    Rock,
    Paper,
    Scissors
}

impl Ord for Figure {
    fn cmp(&self, other: &Figure) -> Ordering {
        use Figure::*;
        match (self, other) {
            (&Rock, &Rock) => Ordering::Equal,
            (&Rock, &Paper) => Ordering::Less,
            (&Rock, &Scissors) => Ordering::Greater,
            (&Paper, &Rock) => Ordering::Greater,
            (&Paper, &Paper) => Ordering::Equal,
            (&Paper, &Scissors) => Ordering::Less,
            (&Scissors, &Rock) => Ordering::Less,
            (&Scissors, &Paper) => Ordering::Greater,
            (&Scissors, &Scissors) => Ordering::Equal
        }
    }
}

impl PartialEq for Figure {
    fn eq(&self, other: &Figure) -> bool {
        self.cmp(other) == Ordering::Equal
    }
}

impl PartialOrd for Figure {
    fn partial_cmp(&self, other: &Figure) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl FromStr for Figure {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        use Figure::*;
        match s.trim() {
            "r" | "rock" => Ok(Rock),
            "p" | "paper" => Ok(Paper),
            "s" | "scissors" => Ok(Scissors),
            _ => Err(())
        }
    }
}

impl Figure {
    fn select(n: u8) -> Figure {
        match n {
            0 => Figure::Rock,
            1 => Figure::Paper,
            2 => Figure::Scissors,
            _ => panic!("unknown figure index")
        }
    }
}

fn main() {
    let time = SystemTime::now().elapsed().unwrap();
    let mut rng = Rng::new(time.subsec_nanos());
    let mut buffer = String::new();
    loop {
        let computer_figure = Figure::select((rng.rand() % 3) as u8);
        println!("[?] Rock, paper or scissors ?");
        io::stdin().read_line(&mut buffer)
                   .unwrap();
        let user_figure = Figure::from_str(&buffer.to_lowercase()).unwrap();
        let result = if computer_figure > user_figure {
            "computer wins!"
        } else if computer_figure == user_figure {
            "draw"
        } else {
            "user wins!"
        };
        println!(">>> {:?} vs {:?}: {}", computer_figure, user_figure, result);
        buffer.clear();
        println!("[?] Again (y|yes|n|no)?");
        io::stdin().read_line(&mut buffer)
                   .unwrap();
        match buffer.to_lowercase().trim() {
            "n" | "no" => break,
            _ => {}
        };
        buffer.clear();
    }
}
<|endoftext|>


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

trait Foo {
  fn answer(self);
}

struct NoData<T>;
//~^ ERROR: parameter `T` is never used

impl<T> Foo for T where NoData<T>: Foo {
//~^ ERROR: overflow evaluating the requirement
  fn answer(self) {
    let val: NoData<T> = NoData;
  }
}

fn main() {}
<|endoftext|>


<commit_before><commit_msg>Add test (fixes #27340)<commit_after>// Copyright 2016 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.

struct Foo;
#[derive(Copy, Clone)]
//~^ ERROR the trait `Copy` may not be implemented for this type; field `0` does not implement
struct Bar(Foo);

fn main() {}
<|endoftext|>


<commit_before><commit_msg>Adds Rust Problem 26<commit_after>/// Problem 26
/// A unit fraction contains 1 in the numerator. The decimal representation of
/// the unit fractions with denominators 2 to 10 are given:
///
/// 		1/2	= 	0.5
/// 		1/3	= 	0.(3)
/// 		1/4	= 	0.25
/// 		1/5	= 	0.2
/// 		1/6	= 	0.1(6)
/// 		1/7	= 	0.(142857)
/// 		1/8	= 	0.125
/// 		1/9	= 	0.(1)
/// 		1/10	= 	0.1
/// Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can
/// be seen that 1/7 has a 6-digit recurring cycle.
///
/// Find the value of d < 1000 for which 1/d contains the longest recurring
/// cycle in its decimal fraction part.
fn main() {
	let mut longest = 1;
	for d in 2u16..1000u16 {
		let mut top: u16 = 10;
		let mut cycle: Vec<u16> = Vec::new();
		let bot: u16 = d;
		// let mut div = 0;
		let mut rem = 1;
		while rem > 0 {
			// div = top/bot;
			rem = top%bot;
			match cycle.iter().position(|&x| x == top) {
				Some(_) => break,
				None => cycle.push(top)
			};
			top = rem*10;
		}
		if cycle.len() > longest {
			longest = cycle.len();
			println!("1/{} cycle length = {}", d, cycle.len());
		}
	}
	println!("Answer: {}", longest);
}
<|endoftext|>


<commit_before><commit_msg>Derive deserialize for key::verification::start::raw::StartEventContent<commit_after><|endoftext|>


<commit_before><commit_msg>Add struct representing virtual machine<commit_after>type Cell = u8;

pub struct VM {
    cells: [Cell; 30_000],
    data_pointer: usize,
}
<|endoftext|>


<commit_before><commit_msg>RANDOM!<commit_after><|endoftext|>


<commit_before><commit_msg>Remove Store::walk()<commit_after><|endoftext|>


<commit_before><commit_msg>libimagutil: Move from error-chain to failure<commit_after><|endoftext|>


<commit_before>#[allow(dead_code)]
pub struct ImmutableFieldsWithReferences<'a> {
    // Read PrivateFields and ImmutableFields first.
    c: String,

    // Now we have a reference to a String that was allocated somewhere else.
    // We need a lifetime to indicate that e must live for at least as long
    // as the struct.
    e: &'a String
}

impl<'a> ImmutableFieldsWithReferences<'a> {
    pub fn new(s: &'a String) -> ImmutableFieldsWithReferences<'a> {
        ImmutableFieldsWithReferences {
            c: "an owned string".to_owned(),
            e: s
        }
    }

    /* ====================== BEST PRACTICE BELOW ====================== */
    pub fn get_c(&self) -> &String {
        // This is typically what we want, similar to returning a string in C#.
        // The caller can get a reference to c with 'let x = i.get_c()' but
        // 'let mut x = i.get_c()' will generate a compilation error:
        // "cannot borrow immutable borrowed content *x as mutable".
        &self.c
    }

    pub fn get_c_mutable(&mut self) -> &mut String {
        // This function allows callers to mutate c.
        // Note that self is now a mutable reference.

        // There is no real equivalent in C#, where strings are immutable. However,
        // it is similar to having a 'public string Foo { get; set; }' property.
        &mut self.c
    }

    pub fn get_e(&self) -> &String {
        // This is in some respects the same as get_c(). The return type of the function
        // is an immutable borrow, so the caller will not be able to change it.
        // They will get the same compilation error.

        // The main difference is that in the body of this function we can just
        // use 'self.e' instead of needing to borrow it.

        // This function can be called multiple times without moving e out of
        // the struct.
        self.e
    }
}
<commit_msg>Add TODO about structs with mutable reference fields.<commit_after>#[allow(dead_code)]
pub struct ImmutableFieldsWithReferences<'a> {
    // Read PrivateFields and ImmutableFields first.
    c: String,

    // Now we have a reference to a String that was allocated somewhere else.
    // We need a lifetime to indicate that e must live for at least as long
    // as the struct.
    e: &'a String
}

impl<'a> ImmutableFieldsWithReferences<'a> {
    pub fn new(s: &'a String) -> ImmutableFieldsWithReferences<'a> {
        ImmutableFieldsWithReferences {
            c: "an owned string".to_owned(),
            e: s
        }
    }

    /* ====================== BEST PRACTICE BELOW ====================== */
    pub fn get_c(&self) -> &String {
        // This is typically what we want, similar to returning a string in C#.
        // The caller can get a reference to c with 'let x = i.get_c()' but
        // 'let mut x = i.get_c()' will generate a compilation error:
        // "cannot borrow immutable borrowed content *x as mutable".
        &self.c
    }

    pub fn get_c_mutable(&mut self) -> &mut String {
        // This function allows callers to mutate c.
        // Note that self is now a mutable reference.

        // There is no real equivalent in C#, where strings are immutable. However,
        // it is similar to having a 'public string Foo { get; set; }' property.
        &mut self.c
    }

    pub fn get_e(&self) -> &String {
        // This is in some respects the same as get_c(). The return type of the function
        // is an immutable borrow, so the caller will not be able to change it.
        // They will get the same compilation error.

        // The main difference is that in the body of this function we can just
        // use 'self.e' instead of needing to borrow it.

        // This function can be called multiple times without moving e out of
        // the struct.
        self.e
    }
}

// TODO: We can have a mutable reference in a struct.
struct PointRef<'a> {
    x: &'a mut i32,
    y: &'a mut i32,
}<|endoftext|>


<commit_before><commit_msg>Basic ELF loading into vspace.<commit_after><|endoftext|>


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

use std::path::Path;
use std::process::Command;
use std::fs;

use build_helper::output;
use cmake;

use build::Build;
use build::util::{exe, staticlib};

pub fn llvm(build: &Build, target: &str) {
    // If we're using a custom LLVM bail out here, but we can only use a
    // custom LLVM for the build triple.
    if let Some(config) = build.config.target_config.get(target) {
        if let Some(ref s) = config.llvm_config {
            return check_llvm_version(build, s);
        }
    }

    // If the cleaning trigger is newer than our built artifacts (or if the
    // artifacts are missing) then we keep going, otherwise we bail out.
    let dst = build.llvm_out(target);
    let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
    let llvm_config = dst.join("bin").join(exe("llvm-config", target));
    build.clear_if_dirty(&dst, &stamp);
    if fs::metadata(llvm_config).is_ok() {
        return
    }

    let _ = fs::remove_dir_all(&dst.join("build"));
    t!(fs::create_dir_all(&dst.join("build")));
    let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};

    // http://llvm.org/docs/CMake.html
    let mut cfg = cmake::Config::new(build.src.join("src/llvm"));
    cfg.target(target)
       .host(&build.config.build)
       .out_dir(&dst)
       .profile(if build.config.llvm_optimize {"Release"} else {"Debug"})
       .define("LLVM_ENABLE_ASSERTIONS", assertions)
       .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC")
       .define("LLVM_INCLUDE_EXAMPLES", "OFF")
       .define("LLVM_INCLUDE_TESTS", "OFF")
       .define("LLVM_INCLUDE_DOCS", "OFF")
       .define("LLVM_ENABLE_ZLIB", "OFF")
       .define("WITH_POLLY", "OFF")
       .define("LLVM_ENABLE_TERMINFO", "OFF")
       .define("LLVM_ENABLE_LIBEDIT", "OFF")
       .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string());

    if target.starts_with("i686") {
        cfg.define("LLVM_BUILD_32_BITS", "ON");
    }

    // http://llvm.org/docs/HowToCrossCompileLLVM.html
    if target != build.config.build {
        // FIXME: if the llvm root for the build triple is overridden then we
        //        should use llvm-tblgen from there, also should verify that it
        //        actually exists most of the time in normal installs of LLVM.
        let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen");
        cfg.define("CMAKE_CROSSCOMPILING", "True")
           .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
           .define("LLVM_TABLEGEN", &host)
           .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
    }

    // MSVC handles compiler business itself
    if !target.contains("msvc") {
        if build.config.ccache {
           cfg.define("CMAKE_C_COMPILER", "ccache")
              .define("CMAKE_C_COMPILER_ARG1", build.cc(target))
              .define("CMAKE_CXX_COMPILER", "ccache")
              .define("CMAKE_CXX_COMPILER_ARG1", build.cxx(target));
        } else {
           cfg.define("CMAKE_C_COMPILER", build.cc(target))
              .define("CMAKE_CXX_COMPILER", build.cxx(target));
        }
        cfg.build_arg("-j").build_arg(build.jobs().to_string());
    }

    // FIXME: we don't actually need to build all LLVM tools and all LLVM
    //        libraries here, e.g. we just want a few components and a few
    //        tools. Figure out how to filter them down and only build the right
    //        tools and libs on all platforms.
    cfg.build();
}

fn check_llvm_version(build: &Build, llvm_config: &Path) {
    if !build.config.llvm_version_check {
        return
    }

    let mut cmd = Command::new(llvm_config);
    let version = output(cmd.arg("--version"));
    if version.starts_with("3.5") || version.starts_with("3.6") ||
       version.starts_with("3.7") {
        return
    }
    panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
}

pub fn compiler_rt(build: &Build, target: &str) {
    let dst = build.compiler_rt_out(target);
    let arch = target.split('-').next().unwrap();
    let mode = if build.config.rust_optimize {"Release"} else {"Debug"};
    let (dir, build_target, libname) = if target.contains("linux") ||
                                          target.contains("freebsd") ||
                                          target.contains("netbsd") {
        let os = if target.contains("android") {"-android"} else {""};
        let arch = if arch.starts_with("arm") && target.contains("eabihf") {
            "armhf"
        } else {
            arch
        };
        let target = format!("clang_rt.builtins-{}{}", arch, os);
        ("linux".to_string(), target.clone(), target)
    } else if target.contains("darwin") {
        let target = format!("clang_rt.builtins_{}_osx", arch);
        ("builtins".to_string(), target.clone(), target)
    } else if target.contains("windows-gnu") {
        let target = format!("clang_rt.builtins-{}", arch);
        ("windows".to_string(), target.clone(), target)
    } else if target.contains("windows-msvc") {
        (format!("windows/{}", mode),
         "lib/builtins/builtins".to_string(),
         format!("clang_rt.builtins-{}", arch.replace("i686", "i386")))
    } else {
        panic!("can't get os from target: {}", target)
    };
    let output = dst.join("build/lib").join(dir)
                    .join(staticlib(&libname, target));
    build.compiler_rt_built.borrow_mut().insert(target.to_string(),
                                                output.clone());
    if fs::metadata(&output).is_ok() {
        return
    }
    let _ = fs::remove_dir_all(&dst);
    t!(fs::create_dir_all(&dst));
    let build_llvm_config = build.llvm_out(&build.config.build)
                                 .join("bin")
                                 .join(exe("llvm-config", &build.config.build));
    let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt"));
    cfg.target(target)
       .host(&build.config.build)
       .out_dir(&dst)
       .profile(mode)
       .define("LLVM_CONFIG_PATH", build_llvm_config)
       .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target)
       .define("COMPILER_RT_BUILD_SANITIZERS", "OFF")
       .define("COMPILER_RT_BUILD_EMUTLS", "OFF")
       // inform about c/c++ compilers, the c++ compiler isn't actually used but
       // it's needed to get the initial configure to work on all platforms.
       .define("CMAKE_C_COMPILER", build.cc(target))
       .define("CMAKE_CXX_COMPILER", build.cc(target))
       .build_target(&build_target);
    cfg.build();
}
<commit_msg>Auto merge of #32361 - japaric:no-llvm-assertions-on-arm, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::path::Path;
use std::process::Command;
use std::fs;

use build_helper::output;
use cmake;

use build::Build;
use build::util::{exe, staticlib};

pub fn llvm(build: &Build, target: &str) {
    // If we're using a custom LLVM bail out here, but we can only use a
    // custom LLVM for the build triple.
    if let Some(config) = build.config.target_config.get(target) {
        if let Some(ref s) = config.llvm_config {
            return check_llvm_version(build, s);
        }
    }

    // If the cleaning trigger is newer than our built artifacts (or if the
    // artifacts are missing) then we keep going, otherwise we bail out.
    let dst = build.llvm_out(target);
    let stamp = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
    let llvm_config = dst.join("bin").join(exe("llvm-config", target));
    build.clear_if_dirty(&dst, &stamp);
    if fs::metadata(llvm_config).is_ok() {
        return
    }

    let _ = fs::remove_dir_all(&dst.join("build"));
    t!(fs::create_dir_all(&dst.join("build")));
    let mut assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};

    // Disable LLVM assertions on ARM compilers until #32360 is fixed
    if target.contains("arm") && target.contains("gnu") {
        assertions = "OFF";
    }

    // http://llvm.org/docs/CMake.html
    let mut cfg = cmake::Config::new(build.src.join("src/llvm"));
    cfg.target(target)
       .host(&build.config.build)
       .out_dir(&dst)
       .profile(if build.config.llvm_optimize {"Release"} else {"Debug"})
       .define("LLVM_ENABLE_ASSERTIONS", assertions)
       .define("LLVM_TARGETS_TO_BUILD", "X86;ARM;AArch64;Mips;PowerPC")
       .define("LLVM_INCLUDE_EXAMPLES", "OFF")
       .define("LLVM_INCLUDE_TESTS", "OFF")
       .define("LLVM_INCLUDE_DOCS", "OFF")
       .define("LLVM_ENABLE_ZLIB", "OFF")
       .define("WITH_POLLY", "OFF")
       .define("LLVM_ENABLE_TERMINFO", "OFF")
       .define("LLVM_ENABLE_LIBEDIT", "OFF")
       .define("LLVM_PARALLEL_COMPILE_JOBS", build.jobs().to_string());

    if target.starts_with("i686") {
        cfg.define("LLVM_BUILD_32_BITS", "ON");
    }

    // http://llvm.org/docs/HowToCrossCompileLLVM.html
    if target != build.config.build {
        // FIXME: if the llvm root for the build triple is overridden then we
        //        should use llvm-tblgen from there, also should verify that it
        //        actually exists most of the time in normal installs of LLVM.
        let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen");
        cfg.define("CMAKE_CROSSCOMPILING", "True")
           .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
           .define("LLVM_TABLEGEN", &host)
           .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
    }

    // MSVC handles compiler business itself
    if !target.contains("msvc") {
        if build.config.ccache {
           cfg.define("CMAKE_C_COMPILER", "ccache")
              .define("CMAKE_C_COMPILER_ARG1", build.cc(target))
              .define("CMAKE_CXX_COMPILER", "ccache")
              .define("CMAKE_CXX_COMPILER_ARG1", build.cxx(target));
        } else {
           cfg.define("CMAKE_C_COMPILER", build.cc(target))
              .define("CMAKE_CXX_COMPILER", build.cxx(target));
        }
        cfg.build_arg("-j").build_arg(build.jobs().to_string());
    }

    // FIXME: we don't actually need to build all LLVM tools and all LLVM
    //        libraries here, e.g. we just want a few components and a few
    //        tools. Figure out how to filter them down and only build the right
    //        tools and libs on all platforms.
    cfg.build();
}

fn check_llvm_version(build: &Build, llvm_config: &Path) {
    if !build.config.llvm_version_check {
        return
    }

    let mut cmd = Command::new(llvm_config);
    let version = output(cmd.arg("--version"));
    if version.starts_with("3.5") || version.starts_with("3.6") ||
       version.starts_with("3.7") {
        return
    }
    panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
}

pub fn compiler_rt(build: &Build, target: &str) {
    let dst = build.compiler_rt_out(target);
    let arch = target.split('-').next().unwrap();
    let mode = if build.config.rust_optimize {"Release"} else {"Debug"};
    let (dir, build_target, libname) = if target.contains("linux") ||
                                          target.contains("freebsd") ||
                                          target.contains("netbsd") {
        let os = if target.contains("android") {"-android"} else {""};
        let arch = if arch.starts_with("arm") && target.contains("eabihf") {
            "armhf"
        } else {
            arch
        };
        let target = format!("clang_rt.builtins-{}{}", arch, os);
        ("linux".to_string(), target.clone(), target)
    } else if target.contains("darwin") {
        let target = format!("clang_rt.builtins_{}_osx", arch);
        ("builtins".to_string(), target.clone(), target)
    } else if target.contains("windows-gnu") {
        let target = format!("clang_rt.builtins-{}", arch);
        ("windows".to_string(), target.clone(), target)
    } else if target.contains("windows-msvc") {
        (format!("windows/{}", mode),
         "lib/builtins/builtins".to_string(),
         format!("clang_rt.builtins-{}", arch.replace("i686", "i386")))
    } else {
        panic!("can't get os from target: {}", target)
    };
    let output = dst.join("build/lib").join(dir)
                    .join(staticlib(&libname, target));
    build.compiler_rt_built.borrow_mut().insert(target.to_string(),
                                                output.clone());
    if fs::metadata(&output).is_ok() {
        return
    }
    let _ = fs::remove_dir_all(&dst);
    t!(fs::create_dir_all(&dst));
    let build_llvm_config = build.llvm_out(&build.config.build)
                                 .join("bin")
                                 .join(exe("llvm-config", &build.config.build));
    let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt"));
    cfg.target(target)
       .host(&build.config.build)
       .out_dir(&dst)
       .profile(mode)
       .define("LLVM_CONFIG_PATH", build_llvm_config)
       .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target)
       .define("COMPILER_RT_BUILD_SANITIZERS", "OFF")
       .define("COMPILER_RT_BUILD_EMUTLS", "OFF")
       // inform about c/c++ compilers, the c++ compiler isn't actually used but
       // it's needed to get the initial configure to work on all platforms.
       .define("CMAKE_C_COMPILER", build.cc(target))
       .define("CMAKE_CXX_COMPILER", build.cc(target))
       .build_target(&build_target);
    cfg.build();
}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #10975 - theCapypara:flock-enosys-android, r=weihanglo<commit_after><|endoftext|>


<commit_before><commit_msg>Renamed method_variant_to_expr to method_to_path.<commit_after><|endoftext|>


<commit_before><commit_msg>fix #18: unicode not displayed correctly.<commit_after><|endoftext|>


<commit_before><commit_msg>chore: catch_unwind<commit_after><|endoftext|>


<commit_before>use ears::{Sound, AudioController};
use std::collections::HashMap;
use find_folder;

pub struct SoundHandler {
    pub map: HashMap<&'static str, Sound>,
}

impl SoundHandler {
    pub fn fill() -> Self {
        let mut map: HashMap<&str, Sound> = HashMap::new();
        for path in SOUNDS {
            // Sprites are located here Create Path
            let sound_path = match find_folder::Search::ParentsThenKids(2, 2)
                .for_folder("Sounds") {
                Ok(res) => res.join(path),
                Err(_) => panic!("Folder not found!"),
            };
            // Create String from path
            let sound_string = match sound_path.to_str() {
                Some(res) => res,
                None => panic!("Sound not found"),
            };

            // Open path an create image
            println!("{}", sound_string);
            let sound = match Sound::new(sound_string) {
                Some(x) => x,
                None => panic!("Can't open {} in {}", path, sound_string),
            };
            map.insert(*path, sound);

        }
        SoundHandler { map: map }
    }
    pub fn play(&mut self, sound: &str) {
        let plays = match self.map.get_mut(sound) {
            Some(res) => res,
            None => {
                panic!("Can't play {}", sound);
            }
        };
        plays.play();

    }
}

const SOUNDS: &'static [&'static str] = &["test.ogg", "Welcome.ogg"];
<commit_msg>Repair<commit_after>use ears::{Sound, AudioController};
use std::collections::HashMap;
use find_folder;

pub struct SoundHandler {
    pub map: HashMap<&'static str, Sound>,
}

impl SoundHandler {
    pub fn fill() -> Self {
        let mut map: HashMap<&str, Sound> = HashMap::new();
        for path in SOUNDS {
            // Sprites are located here Create Path
            let sound_path = match find_folder::Search::ParentsThenKids(2, 2)
                .for_folder("Sounds") {
                Ok(res) => res.join(path),
                Err(_) => panic!("Folder not found!"),
            };
            // Create String from path
            let sound_string = match sound_path.to_str() {
                Some(res) => res,
                None => panic!("Sound not found"),
            };

            // Open path an create image
            println!("{}", sound_string);
            let sound = match Sound::new(sound_string) {
                Some(x) => x,
                None => panic!("Can't open {} in {}", path, sound_string),
            };
            map.insert(*path, sound);

        }
        SoundHandler { map: map }
    }
    pub fn play(&mut self, sound: &str) {
        let plays = match self.map.get_mut(sound) {
            Some(res) => res,
            None => {
                panic!("Can't play {}", sound);
            }
        };
        plays.play();

    }
}

const SOUNDS: &'static [&'static str] = &[
                                            "Chicken.ogg",
                                            "Dagger.ogg",
                                            "Dead.ogg",
                                            "Item.ogg",
                                            "Spear.ogg",
                                            "Sword.ogg",
                                            "test.ogg",
                                            "Welcome.ogg",
                                            ];
<|endoftext|>


<commit_before>extern crate libc;

use libc::{c_int, c_uchar};

#[link(name = "stb_truetype")]
extern { }

pub mod ffi {
    use libc::{c_int, c_uchar, c_float, c_void};
    use std::ptr;

    pub struct FontInfo {
       userdata: *const c_void,

       // pointer to .ttf file
       data: *const c_uchar,

       // offset of start of font
       fontstart: c_int,

       // number of glyphs, needed for range checking
       numGlyphs: c_int,

       // table locations as offset from start of .ttf
       loca: c_int,
       head: c_int,
       glyf: c_int,
       hhea: c_int,
       hmtx: c_int,
       kern: c_int,

       // a cmap mapping for our chosen character encoding
       index_map: c_int,

       // format needed to map from glyph index to glyph
       indexToLocFormat: c_int,
    }

    impl FontInfo {
        pub fn new() -> FontInfo {
            FontInfo {
                userdata: ptr::null(),
                data: ptr::null(),
                fontstart: 0,
                numGlyphs: 0,
                loca: 0,
                head: 0,
                glyf: 0,
                hhea: 0,
                hmtx: 0,
                kern: 0,
                index_map: 0,
                indexToLocFormat: 0,
            }
        }
    }

    extern {
        pub fn stbtt_GetFontOffsetForIndex(
            data: *const c_uchar,
            index: c_int,
        ) -> c_int;

        pub fn stbtt_InitFont(
            info: *mut FontInfo,
            data2: *const c_uchar,
            fontstart: c_int,
        );

        pub fn stbtt_GetFontVMetrics(
            info: *const FontInfo,
            ascent: *mut c_int,
            descent: *mut c_int,
            lineGap: *mut c_int,
        );

        pub fn stbtt_FindGlyphIndex(
            info: *const FontInfo,
            unicode_codepoint: c_int,
        ) -> c_int;

        pub fn stbtt_GetGlyphHMetrics(
            info: *const FontInfo,
            glyph_index: c_int,
            advanceWidth: *mut c_int,
            eftSideBearing: *mut c_int,
        );

        pub fn stbtt_GetGlyphBitmapBox(
            font: *const FontInfo,
            glyph: c_int,
            scale_x: c_float,
            scale_y: c_float,
            ix0: *mut c_int,
            iy0: *mut c_int,
            ix1: *mut c_int,
            iy1: *mut c_int,
        );

        pub fn stbtt_GetGlyphKernAdvance(
            info: *const FontInfo,
            glyph1: c_int,
            glyph2: c_int,
        );

        pub fn stbtt_MakeGlyphBitmap(
            info: *const FontInfo,
            output: *const c_uchar,
            out_w: c_int,
            out_h: c_int,
            out_stride: c_int,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
        );

        pub fn stbtt_ScaleForPixelHeight(
            info: *const FontInfo,
            height: c_float,
        ) -> c_float;

        pub fn stbtt_GetGlyphBitmap(
            info: *const FontInfo,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
            width: *mut c_int,
            height: *mut c_int,
            xoff: *mut c_int,
            yoff: *mut c_int,
        ) -> *const c_uchar;
    }
}

pub struct Font {
    font_info: ffi::FontInfo,
    data: Vec<c_uchar>,
    height: f32,
    scale: f32,
    ascent: i32,
    descent: i32,
    line_gap: i32,
}

impl Font {
    pub fn new(font_path: &Path, height: f32) -> Font {
        let data = {
            use std::io::{BufferedReader, File};
            if !font_path.exists() {
                fail!("Wrong font path: {}", font_path.display());
            }
            let file = File::open(font_path);
            let mut reader = BufferedReader::new(file);
            reader.read_to_end().unwrap()
        };
        let mut font_info = ffi::FontInfo::new();
        unsafe {
            let font_offset = ffi::stbtt_GetFontOffsetForIndex(data.get(0) as *const u8, 0);
            ffi::stbtt_InitFont(&mut font_info, data.get(0) as *const u8, font_offset);
        }
        let scale = unsafe {
            ffi::stbtt_ScaleForPixelHeight(&font_info, height)
        };
        let mut c_ascent: c_int = 0;
        let mut c_descent: c_int = 0;
        let mut c_line_gap: c_int = 0;
        unsafe {
            ffi::stbtt_GetFontVMetrics(&font_info,
                &mut c_ascent, &mut c_descent, &mut c_line_gap);
        }
        let ascent = (c_ascent as f32 * scale) as i32;
        let descent = (c_descent as f32 * scale) as i32;
        let line_gap = (c_line_gap as f32 * scale) as i32;
        Font {
            font_info: font_info,
            data: data,
            height: height,
            scale: scale,
            ascent: ascent,
            descent: descent,
            line_gap: line_gap,
        }
    }

    pub fn get_glyph(&self, glyph_index: i32) -> (Vec<c_uchar>, i32, i32, i32, i32) {
        use std::vec::raw::from_buf;
        let mut w = 0;
        let mut h = 0;
        let mut xoff = 0;
        let mut yoff = 0;
        let bitmap = unsafe {
            let scale_x = 0.0;
            let scale_y = self.scale;
            let buf = ffi::stbtt_GetGlyphBitmap(
                &self.font_info,
                scale_x,
                scale_y,
                glyph_index as c_int,
                &mut w,
                &mut h,
                &mut xoff,
                &mut yoff,
            );
            from_buf(buf, (w * h) as uint)
        };
        (bitmap, w as i32, h as i32, xoff as i32, yoff as i32)
    }

    pub fn find_glyph_index(&self, c: char) -> i32 {
        unsafe {
            ffi::stbtt_FindGlyphIndex(&self.font_info, c as c_int) as i32
        }
    }

    pub fn get_glyph_bitmap_box(&self, glyph_index: i32) -> (i32, i32, i32, i32) {
        let scale_x = 0.0;
        let scale_y = self.scale;
        let mut ix0 = 0;
        let mut iy0 = 0;
        let mut ix1 = 0;
        let mut iy1 = 0;
        unsafe {
            ffi::stbtt_GetGlyphBitmapBox(
                &self.font_info,
                glyph_index as c_int,
                scale_x,
                scale_y,
                &mut ix0,
                &mut iy0,
                &mut ix1,
                &mut iy1,
            );
        }
        (ix0 as i32, iy0 as i32, ix1 as i32, iy1 as i32)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Updated for Rust f8426e2e2 2014-09-16<commit_after>extern crate libc;

use libc::{c_int, c_uchar};
use std::io::fs::PathExtensions;

#[link(name = "stb_truetype")]
extern { }

pub mod ffi {
    use libc::{c_int, c_uchar, c_float, c_void};
    use std::ptr;

    pub struct FontInfo {
       userdata: *const c_void,

       // pointer to .ttf file
       data: *const c_uchar,

       // offset of start of font
       fontstart: c_int,

       // number of glyphs, needed for range checking
       numGlyphs: c_int,

       // table locations as offset from start of .ttf
       loca: c_int,
       head: c_int,
       glyf: c_int,
       hhea: c_int,
       hmtx: c_int,
       kern: c_int,

       // a cmap mapping for our chosen character encoding
       index_map: c_int,

       // format needed to map from glyph index to glyph
       indexToLocFormat: c_int,
    }

    impl FontInfo {
        pub fn new() -> FontInfo {
            FontInfo {
                userdata: ptr::null(),
                data: ptr::null(),
                fontstart: 0,
                numGlyphs: 0,
                loca: 0,
                head: 0,
                glyf: 0,
                hhea: 0,
                hmtx: 0,
                kern: 0,
                index_map: 0,
                indexToLocFormat: 0,
            }
        }
    }

    extern {
        pub fn stbtt_GetFontOffsetForIndex(
            data: *const c_uchar,
            index: c_int,
        ) -> c_int;

        pub fn stbtt_InitFont(
            info: *mut FontInfo,
            data2: *const c_uchar,
            fontstart: c_int,
        );

        pub fn stbtt_GetFontVMetrics(
            info: *const FontInfo,
            ascent: *mut c_int,
            descent: *mut c_int,
            lineGap: *mut c_int,
        );

        pub fn stbtt_FindGlyphIndex(
            info: *const FontInfo,
            unicode_codepoint: c_int,
        ) -> c_int;

        pub fn stbtt_GetGlyphHMetrics(
            info: *const FontInfo,
            glyph_index: c_int,
            advanceWidth: *mut c_int,
            eftSideBearing: *mut c_int,
        );

        pub fn stbtt_GetGlyphBitmapBox(
            font: *const FontInfo,
            glyph: c_int,
            scale_x: c_float,
            scale_y: c_float,
            ix0: *mut c_int,
            iy0: *mut c_int,
            ix1: *mut c_int,
            iy1: *mut c_int,
        );

        pub fn stbtt_GetGlyphKernAdvance(
            info: *const FontInfo,
            glyph1: c_int,
            glyph2: c_int,
        );

        pub fn stbtt_MakeGlyphBitmap(
            info: *const FontInfo,
            output: *const c_uchar,
            out_w: c_int,
            out_h: c_int,
            out_stride: c_int,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
        );

        pub fn stbtt_ScaleForPixelHeight(
            info: *const FontInfo,
            height: c_float,
        ) -> c_float;

        pub fn stbtt_GetGlyphBitmap(
            info: *const FontInfo,
            scale_x: c_float,
            scale_y: c_float,
            glyph: c_int,
            width: *mut c_int,
            height: *mut c_int,
            xoff: *mut c_int,
            yoff: *mut c_int,
        ) -> *const c_uchar;
    }
}

pub struct Font {
    font_info: ffi::FontInfo,
    data: Vec<c_uchar>,
    height: f32,
    scale: f32,
    ascent: i32,
    descent: i32,
    line_gap: i32,
}

impl Font {
    pub fn new(font_path: &Path, height: f32) -> Font {
        let data = {
            use std::io::{BufferedReader, File};
            if !font_path.exists() {
                fail!("Wrong font path: {}", font_path.display());
            }
            let file = File::open(font_path);
            let mut reader = BufferedReader::new(file);
            reader.read_to_end().unwrap()
        };
        let mut font_info = ffi::FontInfo::new();
        unsafe {
            let font_offset = ffi::stbtt_GetFontOffsetForIndex(data.get(0) as *const u8, 0);
            ffi::stbtt_InitFont(&mut font_info, data.get(0) as *const u8, font_offset);
        }
        let scale = unsafe {
            ffi::stbtt_ScaleForPixelHeight(&font_info, height)
        };
        let mut c_ascent: c_int = 0;
        let mut c_descent: c_int = 0;
        let mut c_line_gap: c_int = 0;
        unsafe {
            ffi::stbtt_GetFontVMetrics(&font_info,
                &mut c_ascent, &mut c_descent, &mut c_line_gap);
        }
        let ascent = (c_ascent as f32 * scale) as i32;
        let descent = (c_descent as f32 * scale) as i32;
        let line_gap = (c_line_gap as f32 * scale) as i32;
        Font {
            font_info: font_info,
            data: data,
            height: height,
            scale: scale,
            ascent: ascent,
            descent: descent,
            line_gap: line_gap,
        }
    }

    pub fn get_glyph(&self, glyph_index: i32) -> (Vec<c_uchar>, i32, i32, i32, i32) {
        use std::vec::raw::from_buf;
        let mut w = 0;
        let mut h = 0;
        let mut xoff = 0;
        let mut yoff = 0;
        let bitmap = unsafe {
            let scale_x = 0.0;
            let scale_y = self.scale;
            let buf = ffi::stbtt_GetGlyphBitmap(
                &self.font_info,
                scale_x,
                scale_y,
                glyph_index as c_int,
                &mut w,
                &mut h,
                &mut xoff,
                &mut yoff,
            );
            from_buf(buf, (w * h) as uint)
        };
        (bitmap, w as i32, h as i32, xoff as i32, yoff as i32)
    }

    pub fn find_glyph_index(&self, c: char) -> i32 {
        unsafe {
            ffi::stbtt_FindGlyphIndex(&self.font_info, c as c_int) as i32
        }
    }

    pub fn get_glyph_bitmap_box(&self, glyph_index: i32) -> (i32, i32, i32, i32) {
        let scale_x = 0.0;
        let scale_y = self.scale;
        let mut ix0 = 0;
        let mut iy0 = 0;
        let mut ix1 = 0;
        let mut iy1 = 0;
        unsafe {
            ffi::stbtt_GetGlyphBitmapBox(
                &self.font_info,
                glyph_index as c_int,
                scale_x,
                scale_y,
                &mut ix0,
                &mut iy0,
                &mut ix1,
                &mut iy1,
            );
        }
        (ix0 as i32, iy0 as i32, ix1 as i32, iy1 as i32)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before><commit_msg>Auto merge of #34350 - Stebalien:test-30276, r=eddyb<commit_after>// Copyright 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.

struct Test([i32]);
fn main() {
    let _x: fn(_) -> Test = Test;
}
<|endoftext|>


<commit_before><commit_msg>Add an XFAILed test for treating alts as expressions<commit_after>// xfail-boot
// xfail-stage0
// -*- rust -*-

// Tests for using alt as an expression

fn test() {
  let bool res = alt (true) {
    case (true) {
      true
    }
    case (false) {
      false
    }
  };
  check (res);

  res = alt(false) {
    case (true) {
      false
    }
    case (false) {
      true
    }
  };
  check (res);
}

fn main() {
  test();
}<|endoftext|>


<commit_before><commit_msg>Fix: use mod ui and remove unused imports<commit_after><|endoftext|>


<commit_before><commit_msg>add missing test file<commit_after>#![feature(trace_macros)]
#[macro_use]
extern crate nom;

use nom::{IResult,Needed};

#[allow(dead_code)]
struct Range {
  start: char,
  end:   char
}

pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
  if input.len() > 0 {
    IResult::Done(&input[1..], input[0] as char)
  } else {
    IResult::Incomplete(Needed::Size(1))
  }
}

//trace_macros!(true);

#[allow(dead_code)]
named!(range<&[u8], Range>,
    alt!(
        chain!(
            start: take_char ~
            tag!("-") ~
            end: take_char,
            || {
                Range {
                    start: start,
                    end: end,
                }
            }
        ) |
        map!(
            take_char,
            |c| {
                Range {
                    start: c,
                    end: c,
                }
            }
        )
    )
);

#[allow(dead_code)]
named!(literal<&[u8], Vec<char> >,
    map!(
        many1!(take_char),
        |cs| {
          cs
        }
    )
);

#[test]
fn issue_58() {
  range(&b"abcd"[..]);
  literal(&b"abcd"[..]);
}

//trace_macros!(false);
<|endoftext|>


<commit_before><commit_msg>Add 2015 day 20 solution<commit_after>fn get_present_counts(max: u32, presents: u32, limit: Option<u32>) -> Vec<u32> {
    let len = max / presents;
    let mut houses = Vec::with_capacity(len as usize);

    for _ in 0..len {
        houses.push(0);
    }

    for i in 1..len {
        let mut count = 0;
        let mut j = i;

        while j < len {
            houses[j as usize] += i * presents;

            count += 1;
            j += match limit {
                Some(x) if count >= x => break,
                _ => i
            };
        }
    }

    houses
}

fn main() {
    let input = 34000000;
    let result = get_present_counts(input, 10, None)
        .into_iter()
        .position(|x| x >= input).unwrap();

    println!("Part 1: {}", result);

    let result = get_present_counts(input, 11, Some(50))
        .into_iter()
        .position(|x| x >= input).unwrap();

    println!("Part 2: {}", result);
}
<|endoftext|>


<commit_before><commit_msg>Added Envelope and Point structs for amplitude and frequency interpolation.<commit_after>
/// Point for use in the envelope struct.
#[deriving(Clone, Show)]
pub struct Point {
    /// `time` represents the x domain.
    pub time: f32,
    /// `value` represents the y domain.
    pub value: f32,
    /// `curve` represents the bezier curve depth.
    pub curve: f32
}

impl Point {
    /// Constructor method for Point.
    pub fn new(time: f32, value: f32, curve: f32) -> Point {
        Point { time: time, value: value, curve: curve }
    }
}

/// Envelope struct, primarily used for
/// frequency and amplitude interpolation.
#[deriving(Clone, Show)]
pub struct Envelope {
    /// Envelope represented by a vector
    /// of points (sorted by `time`).
    pub points: Vec<Point>
}

impl Envelope {

    /// Default, empty constructor.
    fn new() -> Envelope {
        Envelope {
            points: vec![]
        }
    }

    /// Add a new point to the Envelope.
    fn add_point(&mut self, point: Point) {
        self.points.push(point);
        self.points.sort_by(|a, b| if a.time < b.time { Less }
                                   else if a.time > b.time { Greater }
                                   else { Equal });
    }

    /// Return `value` for the given `time`.
    fn get_value(&self, time: f32) -> f32 {
        // If there is less than two points interpolation
        // is not meaningful, thus we should just return 0.
        if self.points.len() <= 1 { return 0f32 }
        // Iterate through points.
        for i in range(0, self.points.len()) {
            // Find the start point to interpolate.
            if time >= self.points.get(i).time {
                // Interpolate both points and add the value
                // of the first to find our result.
                return self.interpolate(time,
                                        *self.points.get(i-1),
                                        *self.points.get(i))
                    + self.points.get(i-1).value;
            }
        }
        0f32
    }

    /// Interpolate between points.
    fn interpolate(&self, time: f32, start: Point, end: Point) -> f32 {
        // Find time passed from start of interpolation.
        let time_pos = time - start.time;
        // Find duration of interpolation.
        let duration = end.time - start.time;
        // Set gradient for interpolation.
        let gradient_value = end.value - start.value;
        if gradient_value == 0f32 { return 0f32 }
        let gradient = duration / gradient_value;
        let half_gradient_value = gradient_value * 0.5f32;
        // Consider bezier curve.
        let y2 = half_gradient_value + start.curve * half_gradient_value;
        let perc_time = time_pos / duration;
        // Re-adjust linear trajectory.
        let ya = Envelope::get_bezier_pt(0f32, y2, perc_time);
        let yb = Envelope::get_bezier_pt(y2, gradient_value, perc_time);
        Envelope::get_bezier_pt(ya, yb, perc_time)
    }

    /// Get bezier point for bezier curve.
    fn get_bezier_pt(n1: f32, n2: f32, perc: f32) -> f32 {
        (n2 - n1) * perc + n1
    }

}

<|endoftext|>


<commit_before>use rgtk::*;
use std::fs::PathExt;
use std::num::FromPrimitive;
use std::path::Path;
use std::process::Command;

fn remove_expansions_for_path(state: &mut ::utils::State, path_str: &String) {
    for expansion_str in state.expansions.clone().iter() {
        if !Path::new(expansion_str).exists() ||
            path_str == expansion_str ||
            ::utils::is_parent_path(path_str, expansion_str)
        {
            state.expansions.remove(expansion_str);
        }
    }
}

fn save_project(state: &mut ::utils::State, tree: &mut gtk::TreeView, path_str: &String) {
    state.projects.insert(path_str.clone());
    state.selection = Some(path_str.clone());
    ::utils::write_prefs(state);
    ::ui::update_project_tree(state, tree);
}

pub fn new_project(state: &mut ::utils::State, tree: &mut gtk::TreeView) {
    if let Some(dialog) = gtk::FileChooserDialog::new(
        "New Project",
        None,
        gtk::FileChooserAction::Save
    ) {
        if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
            if let Some(path_str) = dialog.get_filename() {
                let path = Path::new(path_str.as_slice());
                if let Some(name_os_str) = path.file_name() {
                    if let Some(name_str) = name_os_str.to_str() {
                        if let Some(parent_path) = path.parent() {
                            match Command::new("cargo").arg("new").arg(name_str).arg("--bin")
                                .current_dir(parent_path).status()
                            {
                                Ok(_) => save_project(state, tree, &path_str),
                                Err(e) => println!("Error creating {}: {}", name_str, e)
                            }
                        }
                    }
                }
            }
        }
        dialog.destroy();
    }
}

pub fn import_project(state: &mut ::utils::State, tree: &mut gtk::TreeView) {
    if let Some(dialog) = gtk::FileChooserDialog::new(
        "Import",
        None,
        gtk::FileChooserAction::SelectFolder
    ) {
        if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
            if let Some(path_str) = dialog.get_filename() {
                save_project(state, tree, &path_str);
            }
        }
        dialog.destroy();
    }
}

pub fn rename_file(state: &mut ::utils::State, fd: i32) {
    if let Some(_) = ::utils::get_selected_path(state) {
        if let Some(dialog) = gtk::FileChooserDialog::new(
            "Rename",
            None,
            gtk::FileChooserAction::Save
        ) {
            if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
                if let Some(path_str) = dialog.get_filename() {
                    state.selection = Some(path_str.clone());
                    ::utils::write_prefs(&state);
                    ::ffi::send_message(fd, format!("Move {}", path_str).as_slice());
                }
            }
            dialog.destroy();
        }
    }
}

pub fn remove_item(state: &mut ::utils::State, tree: &mut gtk::TreeView, fd: i32) {
    if let Some(path_str) = ::utils::get_selected_path(state) {
        if let Some(dialog) = gtk::MessageDialog::new_with_markup(
            Some(state.window.clone()),
            gtk::DialogFlags::Modal,
            gtk::MessageType::Question,
            gtk::ButtonsType::OkCancel,
            if state.projects.contains(&path_str) {
                "Remove this project? It WILL NOT be deleted from the disk."
            } else {
                "Remove this file? It WILL be deleted from the disk."
            }
        ) {
            if let Some(gtk::ResponseType::Ok) = FromPrimitive::from_i32(dialog.run()) {
                if state.projects.contains(&path_str) {
                    state.projects.remove(&path_str);
                    remove_expansions_for_path(state, &path_str);
                    ::utils::write_prefs(state);
                    ::ui::update_project_tree(state, tree);
                } else {
                    ::ffi::send_message(fd, "call delete(expand('%')) | bdelete!".as_slice());
                }
            }
            dialog.destroy();
        }
    }
}

pub fn set_selection(state: &mut ::utils::State, tree: &mut gtk::TreeView, fd: i32) {
    if !state.is_refreshing_tree {
        if let Some(path_str) = ::utils::get_selected_path(state) {
            state.selection = Some(path_str.clone());
            ::utils::write_prefs(state);
            ::ui::update_project_tree(state, tree);
            ::ffi::send_message(fd, format!("e {}", path_str).as_slice());
        }
    }
}

pub fn remove_expansion(state: &mut ::utils::State, iter: &gtk::TreeIter) {
    if let Some(path_str) = state.tree_model.get_value(iter, 1).get_string() {
        remove_expansions_for_path(state, &path_str);
        ::utils::write_prefs(state);
    }
}

pub fn add_expansion(state: &mut ::utils::State, iter: &gtk::TreeIter) {
    if let Some(path_str) = state.tree_model.get_value(iter, 1).get_string() {
        state.expansions.insert(path_str);
        ::utils::write_prefs(state);
    }
}
<commit_msg>Update for latest changes in rgtk<commit_after>use rgtk::*;
use std::fs::PathExt;
use std::num::FromPrimitive;
use std::path::Path;
use std::process::Command;

fn remove_expansions_for_path(state: &mut ::utils::State, path_str: &String) {
    for expansion_str in state.expansions.clone().iter() {
        if !Path::new(expansion_str).exists() ||
            path_str == expansion_str ||
            ::utils::is_parent_path(path_str, expansion_str)
        {
            state.expansions.remove(expansion_str);
        }
    }
}

fn save_project(state: &mut ::utils::State, tree: &mut gtk::TreeView, path_str: &String) {
    state.projects.insert(path_str.clone());
    state.selection = Some(path_str.clone());
    ::utils::write_prefs(state);
    ::ui::update_project_tree(state, tree);
}

pub fn new_project(state: &mut ::utils::State, tree: &mut gtk::TreeView) {
    let dialog = gtk::FileChooserDialog::new(
        "New Project",
        None,
        gtk::FileChooserAction::Save,
        [("Save", gtk::ResponseType::Ok), ("Cancel", gtk::ResponseType::Cancel)]
    );
    if let Some(gtk::ResponseType::Ok) = FromPrimitive::from_i32(dialog.run()) {
        if let Some(path_str) = dialog.get_filename() {
            let path = Path::new(path_str.as_slice());
            if let Some(name_os_str) = path.file_name() {
                if let Some(name_str) = name_os_str.to_str() {
                    if let Some(parent_path) = path.parent() {
                        match Command::new("cargo").arg("new").arg(name_str).arg("--bin")
                            .current_dir(parent_path).status()
                        {
                            Ok(_) => save_project(state, tree, &path_str),
                            Err(e) => println!("Error creating {}: {}", name_str, e)
                        }
                    }
                }
            }
        }
    }
    dialog.destroy();
}

pub fn import_project(state: &mut ::utils::State, tree: &mut gtk::TreeView) {
    let dialog = gtk::FileChooserDialog::new(
        "Import",
        None,
        gtk::FileChooserAction::SelectFolder,
        [("Open", gtk::ResponseType::Ok), ("Cancel", gtk::ResponseType::Cancel)]
    );
    if let Some(gtk::ResponseType::Ok) = FromPrimitive::from_i32(dialog.run()) {
        if let Some(path_str) = dialog.get_filename() {
            save_project(state, tree, &path_str);
        }
    }
    dialog.destroy();
}

pub fn rename_file(state: &mut ::utils::State, fd: i32) {
    if let Some(_) = ::utils::get_selected_path(state) {
        let dialog = gtk::FileChooserDialog::new(
            "Rename",
            None,
            gtk::FileChooserAction::Save,
            [("Save", gtk::ResponseType::Ok), ("Cancel", gtk::ResponseType::Cancel)]
        );
        if let Some(gtk::ResponseType::Ok) = FromPrimitive::from_i32(dialog.run()) {
            if let Some(path_str) = dialog.get_filename() {
                state.selection = Some(path_str.clone());
                ::utils::write_prefs(&state);
                ::ffi::send_message(fd, format!("Move {}", path_str).as_slice());
            }
        }
        dialog.destroy();
    }
}

pub fn remove_item(state: &mut ::utils::State, tree: &mut gtk::TreeView, fd: i32) {
    if let Some(path_str) = ::utils::get_selected_path(state) {
        if let Some(dialog) = gtk::MessageDialog::new_with_markup(
            Some(state.window.clone()),
            gtk::DialogFlags::Modal,
            gtk::MessageType::Question,
            gtk::ButtonsType::OkCancel,
            if state.projects.contains(&path_str) {
                "Remove this project? It WILL NOT be deleted from the disk."
            } else {
                "Remove this file? It WILL be deleted from the disk."
            }
        ) {
            if let Some(gtk::ResponseType::Ok) = FromPrimitive::from_i32(dialog.run()) {
                if state.projects.contains(&path_str) {
                    state.projects.remove(&path_str);
                    remove_expansions_for_path(state, &path_str);
                    ::utils::write_prefs(state);
                    ::ui::update_project_tree(state, tree);
                } else {
                    ::ffi::send_message(fd, "call delete(expand('%')) | bdelete!".as_slice());
                }
            }
            dialog.destroy();
        }
    }
}

pub fn set_selection(state: &mut ::utils::State, tree: &mut gtk::TreeView, fd: i32) {
    if !state.is_refreshing_tree {
        if let Some(path_str) = ::utils::get_selected_path(state) {
            state.selection = Some(path_str.clone());
            ::utils::write_prefs(state);
            ::ui::update_project_tree(state, tree);
            ::ffi::send_message(fd, format!("e {}", path_str).as_slice());
        }
    }
}

pub fn remove_expansion(state: &mut ::utils::State, iter: &gtk::TreeIter) {
    if let Some(path_str) = state.tree_model.get_value(iter, 1).get_string() {
        remove_expansions_for_path(state, &path_str);
        ::utils::write_prefs(state);
    }
}

pub fn add_expansion(state: &mut ::utils::State, iter: &gtk::TreeIter) {
    if let Some(path_str) = state.tree_model.get_value(iter, 1).get_string() {
        state.expansions.insert(path_str);
        ::utils::write_prefs(state);
    }
}
<|endoftext|>