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

//! Finds crate binaries and loads their metadata

use core::prelude::*;

use lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
use metadata::decoder;
use metadata::encoder;
use metadata::filesearch::FileSearch;
use metadata::filesearch;
use syntax::codemap::span;
use syntax::diagnostic::span_handler;
use syntax::parse::token;
use syntax::parse::token::ident_interner;
use syntax::print::pprust;
use syntax::{ast, attr};

use core::cast;
use core::io;
use core::option;
use core::os::consts::{macos, freebsd, linux, android, win32};
use core::ptr;
use core::str;
use core::uint;
use core::vec;
use extra::flate;

pub enum os {
    os_macos,
    os_win32,
    os_linux,
    os_android,
    os_freebsd
}

pub struct Context {
    diag: @span_handler,
    filesearch: @FileSearch,
    span: span,
    ident: ast::ident,
    metas: ~[@ast::meta_item],
    hash: @str,
    os: os,
    is_static: bool,
    intr: @ident_interner
}

pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) {
    match find_library_crate(cx) {
      Some(ref t) => return (/*bad*/copy *t),
      None => {
        cx.diag.span_fatal(
            cx.span, fmt!("can't find crate for `%s`",
                          token::ident_to_str(&cx.ident)));
      }
    }
}

fn find_library_crate(cx: &Context) -> Option<(~str, @~[u8])> {
    attr::require_unique_names(cx.diag, cx.metas);
    find_library_crate_aux(cx, libname(cx), cx.filesearch)
}

fn libname(cx: &Context) -> (~str, ~str) {
    if cx.is_static { return (~"lib", ~".rlib"); }
    let (dll_prefix, dll_suffix) = match cx.os {
        os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
        os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
        os_linux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
        os_android => (android::DLL_PREFIX, android::DLL_SUFFIX),
        os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
    };

    (str::to_owned(dll_prefix), str::to_owned(dll_suffix))
}

fn find_library_crate_aux(
    cx: &Context,
    (prefix, suffix): (~str, ~str),
    filesearch: @filesearch::FileSearch
) -> Option<(~str, @~[u8])> {
    let crate_name = crate_name_from_metas(cx.metas);
    let prefix = prefix + crate_name + "-";

    let mut matches = ~[];
    filesearch::search(filesearch, |path| -> Option<()> {
        debug!("inspecting file %s", path.to_str());
        match path.filename() {
            Some(ref f) if f.starts_with(prefix) && f.ends_with(suffix) => {
                debug!("%s is a candidate", path.to_str());
                match get_metadata_section(cx.os, path) {
                    Some(cvec) =>
                        if !crate_matches(cvec, cx.metas, cx.hash) {
                            debug!("skipping %s, metadata doesn't match",
                                   path.to_str());
                            None
                        } else {
                            debug!("found %s with matching metadata", path.to_str());
                            matches.push((path.to_str(), cvec));
                            None
                        },
                    _ => {
                        debug!("could not load metadata for %s", path.to_str());
                        None
                    }
                }
            }
            _ => {
                debug!("skipping %s, doesn't look like %s*%s", path.to_str(),
                       prefix, suffix);
                None
            }
        }});

    match matches.len() {
        0 => None,
        1 => Some(matches[0]),
        _ => {
            cx.diag.span_err(
                    cx.span, fmt!("multiple matching crates for `%s`", crate_name));
                cx.diag.handler().note("candidates:");
                for matches.each |&(ident, data)| {
                    cx.diag.handler().note(fmt!("path: %s", ident));
                    let attrs = decoder::get_crate_attributes(data);
                    note_linkage_attrs(cx.intr, cx.diag, attrs);
                }
                cx.diag.handler().abort_if_errors();
                None
            }
        }
}

pub fn crate_name_from_metas(metas: &[@ast::meta_item]) -> @str {
    for metas.each |m| {
        match m.node {
            ast::meta_name_value(s, ref l) if s == @"name" =>
                match l.node {
                    ast::lit_str(s) => return s,
                    _ => ()
                },
            _ => ()
        }
    }
    fail!("expected to find the crate name")
}

pub fn note_linkage_attrs(intr: @ident_interner,
                          diag: @span_handler,
                          attrs: ~[ast::attribute]) {
    let r = attr::find_linkage_metas(attrs);
    for r.iter().advance |mi| {
        diag.handler().note(fmt!("meta: %s", pprust::meta_item_to_str(*mi,intr)));
    }
}

fn crate_matches(crate_data: @~[u8],
                 metas: &[@ast::meta_item],
                 hash: @str) -> bool {
    let attrs = decoder::get_crate_attributes(crate_data);
    let linkage_metas = attr::find_linkage_metas(attrs);
    if !hash.is_empty() {
        let chash = decoder::get_crate_hash(crate_data);
        if chash != hash { return false; }
    }
    metadata_matches(linkage_metas, metas)
}

pub fn metadata_matches(extern_metas: &[@ast::meta_item],
                        local_metas: &[@ast::meta_item]) -> bool {

    debug!("matching %u metadata requirements against %u items",
           local_metas.len(), extern_metas.len());

    for local_metas.iter().advance |needed| {
        if !attr::contains(extern_metas, *needed) {
            return false;
        }
    }
    return true;
}

fn get_metadata_section(os: os,
                        filename: &Path) -> Option<@~[u8]> {
    unsafe {
        let mb = str::as_c_str(filename.to_str(), |buf| {
            llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
        });
        if mb as int == 0 { return option::None::<@~[u8]>; }
        let of = match mk_object_file(mb) {
            option::Some(of) => of,
            _ => return option::None::<@~[u8]>
        };
        let si = mk_section_iter(of.llof);
        while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
            let name_buf = llvm::LLVMGetSectionName(si.llsi);
            let name = str::raw::from_c_str(name_buf);
            debug!("get_metadata_section: name %s", name);
            if name == read_meta_section_name(os) {
                let cbuf = llvm::LLVMGetSectionContents(si.llsi);
                let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
                let mut found = None;
                let cvbuf: *u8 = cast::transmute(cbuf);
                let vlen = encoder::metadata_encoding_version.len();
                debug!("checking %u bytes of metadata-version stamp",
                       vlen);
                let minsz = uint::min(vlen, csz);
                let mut version_ok = false;
                do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| {
                    version_ok = (buf0 ==
                                  encoder::metadata_encoding_version);
                }
                if !version_ok { return None; }

                let cvbuf1 = ptr::offset(cvbuf, vlen);
                debug!("inflating %u bytes of compressed metadata",
                       csz - vlen);
                do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| {
                    let inflated = flate::inflate_bytes(bytes);
                    found = Some(@(inflated));
                }
                if found != None {
                    return found;
                }
            }
            llvm::LLVMMoveToNextSection(si.llsi);
        }
        return option::None::<@~[u8]>;
    }
}

pub fn meta_section_name(os: os) -> ~str {
    match os {
      os_macos => ~"__DATA,__note.rustc",
      os_win32 => ~".note.rustc",
      os_linux => ~".note.rustc",
      os_android => ~".note.rustc",
      os_freebsd => ~".note.rustc"
    }
}

pub fn read_meta_section_name(os: os) -> ~str {
    match os {
      os_macos => ~"__note.rustc",
      os_win32 => ~".note.rustc",
      os_linux => ~".note.rustc",
      os_android => ~".note.rustc",
      os_freebsd => ~".note.rustc"
    }
}

// A diagnostic function for dumping crate metadata to an output stream
pub fn list_file_metadata(intr: @ident_interner,
                          os: os,
                          path: &Path,
                          out: @io::Writer) {
    match get_metadata_section(os, path) {
      option::Some(bytes) => decoder::list_crate_metadata(intr, bytes, out),
      option::None => {
        out.write_str(fmt!("could not find metadata in %s.\n", path.to_str()))
      }
    }
}
<commit_msg>Fix old .each usage<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.

//! Finds crate binaries and loads their metadata

use core::prelude::*;

use lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
use metadata::decoder;
use metadata::encoder;
use metadata::filesearch::FileSearch;
use metadata::filesearch;
use syntax::codemap::span;
use syntax::diagnostic::span_handler;
use syntax::parse::token;
use syntax::parse::token::ident_interner;
use syntax::print::pprust;
use syntax::{ast, attr};

use core::cast;
use core::io;
use core::option;
use core::os::consts::{macos, freebsd, linux, android, win32};
use core::ptr;
use core::str;
use core::uint;
use core::vec;
use extra::flate;

pub enum os {
    os_macos,
    os_win32,
    os_linux,
    os_android,
    os_freebsd
}

pub struct Context {
    diag: @span_handler,
    filesearch: @FileSearch,
    span: span,
    ident: ast::ident,
    metas: ~[@ast::meta_item],
    hash: @str,
    os: os,
    is_static: bool,
    intr: @ident_interner
}

pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) {
    match find_library_crate(cx) {
      Some(ref t) => return (/*bad*/copy *t),
      None => {
        cx.diag.span_fatal(
            cx.span, fmt!("can't find crate for `%s`",
                          token::ident_to_str(&cx.ident)));
      }
    }
}

fn find_library_crate(cx: &Context) -> Option<(~str, @~[u8])> {
    attr::require_unique_names(cx.diag, cx.metas);
    find_library_crate_aux(cx, libname(cx), cx.filesearch)
}

fn libname(cx: &Context) -> (~str, ~str) {
    if cx.is_static { return (~"lib", ~".rlib"); }
    let (dll_prefix, dll_suffix) = match cx.os {
        os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
        os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
        os_linux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
        os_android => (android::DLL_PREFIX, android::DLL_SUFFIX),
        os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
    };

    (str::to_owned(dll_prefix), str::to_owned(dll_suffix))
}

fn find_library_crate_aux(
    cx: &Context,
    (prefix, suffix): (~str, ~str),
    filesearch: @filesearch::FileSearch
) -> Option<(~str, @~[u8])> {
    let crate_name = crate_name_from_metas(cx.metas);
    let prefix = prefix + crate_name + "-";

    let mut matches = ~[];
    filesearch::search(filesearch, |path| -> Option<()> {
        debug!("inspecting file %s", path.to_str());
        match path.filename() {
            Some(ref f) if f.starts_with(prefix) && f.ends_with(suffix) => {
                debug!("%s is a candidate", path.to_str());
                match get_metadata_section(cx.os, path) {
                    Some(cvec) =>
                        if !crate_matches(cvec, cx.metas, cx.hash) {
                            debug!("skipping %s, metadata doesn't match",
                                   path.to_str());
                            None
                        } else {
                            debug!("found %s with matching metadata", path.to_str());
                            matches.push((path.to_str(), cvec));
                            None
                        },
                    _ => {
                        debug!("could not load metadata for %s", path.to_str());
                        None
                    }
                }
            }
            _ => {
                debug!("skipping %s, doesn't look like %s*%s", path.to_str(),
                       prefix, suffix);
                None
            }
        }});

    match matches.len() {
        0 => None,
        1 => Some(matches[0]),
        _ => {
            cx.diag.span_err(
                    cx.span, fmt!("multiple matching crates for `%s`", crate_name));
                cx.diag.handler().note("candidates:");
                for matches.iter().advance |&(ident, data)| {
                    cx.diag.handler().note(fmt!("path: %s", ident));
                    let attrs = decoder::get_crate_attributes(data);
                    note_linkage_attrs(cx.intr, cx.diag, attrs);
                }
                cx.diag.handler().abort_if_errors();
                None
            }
        }
}

pub fn crate_name_from_metas(metas: &[@ast::meta_item]) -> @str {
    for metas.iter().advance |m| {
        match m.node {
            ast::meta_name_value(s, ref l) if s == @"name" =>
                match l.node {
                    ast::lit_str(s) => return s,
                    _ => ()
                },
            _ => ()
        }
    }
    fail!("expected to find the crate name")
}

pub fn note_linkage_attrs(intr: @ident_interner,
                          diag: @span_handler,
                          attrs: ~[ast::attribute]) {
    let r = attr::find_linkage_metas(attrs);
    for r.iter().advance |mi| {
        diag.handler().note(fmt!("meta: %s", pprust::meta_item_to_str(*mi,intr)));
    }
}

fn crate_matches(crate_data: @~[u8],
                 metas: &[@ast::meta_item],
                 hash: @str) -> bool {
    let attrs = decoder::get_crate_attributes(crate_data);
    let linkage_metas = attr::find_linkage_metas(attrs);
    if !hash.is_empty() {
        let chash = decoder::get_crate_hash(crate_data);
        if chash != hash { return false; }
    }
    metadata_matches(linkage_metas, metas)
}

pub fn metadata_matches(extern_metas: &[@ast::meta_item],
                        local_metas: &[@ast::meta_item]) -> bool {

    debug!("matching %u metadata requirements against %u items",
           local_metas.len(), extern_metas.len());

    for local_metas.iter().advance |needed| {
        if !attr::contains(extern_metas, *needed) {
            return false;
        }
    }
    return true;
}

fn get_metadata_section(os: os,
                        filename: &Path) -> Option<@~[u8]> {
    unsafe {
        let mb = str::as_c_str(filename.to_str(), |buf| {
            llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
        });
        if mb as int == 0 { return option::None::<@~[u8]>; }
        let of = match mk_object_file(mb) {
            option::Some(of) => of,
            _ => return option::None::<@~[u8]>
        };
        let si = mk_section_iter(of.llof);
        while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
            let name_buf = llvm::LLVMGetSectionName(si.llsi);
            let name = str::raw::from_c_str(name_buf);
            debug!("get_metadata_section: name %s", name);
            if name == read_meta_section_name(os) {
                let cbuf = llvm::LLVMGetSectionContents(si.llsi);
                let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
                let mut found = None;
                let cvbuf: *u8 = cast::transmute(cbuf);
                let vlen = encoder::metadata_encoding_version.len();
                debug!("checking %u bytes of metadata-version stamp",
                       vlen);
                let minsz = uint::min(vlen, csz);
                let mut version_ok = false;
                do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| {
                    version_ok = (buf0 ==
                                  encoder::metadata_encoding_version);
                }
                if !version_ok { return None; }

                let cvbuf1 = ptr::offset(cvbuf, vlen);
                debug!("inflating %u bytes of compressed metadata",
                       csz - vlen);
                do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| {
                    let inflated = flate::inflate_bytes(bytes);
                    found = Some(@(inflated));
                }
                if found != None {
                    return found;
                }
            }
            llvm::LLVMMoveToNextSection(si.llsi);
        }
        return option::None::<@~[u8]>;
    }
}

pub fn meta_section_name(os: os) -> ~str {
    match os {
      os_macos => ~"__DATA,__note.rustc",
      os_win32 => ~".note.rustc",
      os_linux => ~".note.rustc",
      os_android => ~".note.rustc",
      os_freebsd => ~".note.rustc"
    }
}

pub fn read_meta_section_name(os: os) -> ~str {
    match os {
      os_macos => ~"__note.rustc",
      os_win32 => ~".note.rustc",
      os_linux => ~".note.rustc",
      os_android => ~".note.rustc",
      os_freebsd => ~".note.rustc"
    }
}

// A diagnostic function for dumping crate metadata to an output stream
pub fn list_file_metadata(intr: @ident_interner,
                          os: os,
                          path: &Path,
                          out: @io::Writer) {
    match get_metadata_section(os, path) {
      option::Some(bytes) => decoder::list_crate_metadata(intr, bytes, out),
      option::None => {
        out.write_str(fmt!("could not find metadata in %s.\n", path.to_str()))
      }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 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(non_camel_case_types)]

use core::prelude::*;
use libc;
use local::Local;
use task::Task;

pub unsafe fn init() {
    imp::init();
}

pub unsafe fn cleanup() {
    imp::cleanup();
}

pub struct Handler {
    _data: *mut libc::c_void
}

impl Handler {
    pub unsafe fn new() -> Handler {
        imp::make_handler()
    }
}

impl Drop for Handler {
    fn drop(&mut self) {
        unsafe {
            imp::drop_handler(self);
        }
    }
}

pub unsafe fn report() {
    // See the message below for why this is not emitted to the
    // ^ Where did the message below go?
    // task's logger. This has the additional conundrum of the
    // logger may not be initialized just yet, meaning that an FFI
    // call would happen to initialized it (calling out to libuv),
    // and the FFI call needs 2MB of stack when we just ran out.

    let task: Option<*mut Task> = Local::try_unsafe_borrow();

    let name = task.and_then(|task| {
        (*task).name.as_ref().map(|n| n.as_slice())
    });

    rterrln!("\ntask '{}' has overflowed its stack", name.unwrap_or("<unknown>"));
}

// get_task_info is called from an exception / signal handler.
// It returns the guard page of the current task or 0 if that
// guard page doesn't exist. None is returned if there's currently
// no local task.
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
unsafe fn get_task_guard_page() -> Option<uint> {
    let task: Option<*mut Task> = Local::try_unsafe_borrow();
    task.map(|task| (&*task).stack_guard().unwrap_or(0))
}

#[cfg(windows)]
#[allow(non_snake_case)]
mod imp {
    use core::ptr;
    use core::mem;
    use libc;
    use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
    use stack;
    use super::{Handler, get_task_guard_page, report};

    // This is initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;

    #[no_stack_check]
    extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG {
        unsafe {
            let rec = &(*(*ExceptionInfo).ExceptionRecord);
            let code = rec.ExceptionCode;

            if code != EXCEPTION_STACK_OVERFLOW {
                return EXCEPTION_CONTINUE_SEARCH;
            }

            // We're calling into functions with stack checks,
            // however stack checks by limit should be disabled on Windows
            stack::record_sp_limit(0);

            if get_task_guard_page().is_some() {
               report();
            }

            EXCEPTION_CONTINUE_SEARCH
        }
    }

    pub unsafe fn init() {
        let mut info = mem::zeroed();
        libc::GetSystemInfo(&mut info);
        PAGE_SIZE = info.dwPageSize as uint;

        if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() {
            panic!("failed to install exception handler");
        }

        mem::forget(make_handler());
    }

    pub unsafe fn cleanup() {
    }

    pub unsafe fn make_handler() -> Handler {
        if SetThreadStackGuarantee(&mut 0x5000) == 0 {
            panic!("failed to reserve stack space for exception handling");
        }

        super::Handler { _data: 0i as *mut libc::c_void }
    }

    pub unsafe fn drop_handler(_handler: &mut Handler) {
    }

    pub struct EXCEPTION_RECORD {
        pub ExceptionCode: DWORD,
        pub ExceptionFlags: DWORD,
        pub ExceptionRecord: *mut EXCEPTION_RECORD,
        pub ExceptionAddress: LPVOID,
        pub NumberParameters: DWORD,
        pub ExceptionInformation: [LPVOID, ..EXCEPTION_MAXIMUM_PARAMETERS]
    }

    pub struct EXCEPTION_POINTERS {
        pub ExceptionRecord: *mut EXCEPTION_RECORD,
        pub ContextRecord: LPVOID
    }

    pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
            fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;

    pub type ULONG = libc::c_ulong;

    const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
    const EXCEPTION_MAXIMUM_PARAMETERS: uint = 15;
    const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;

    extern "system" {
        fn AddVectoredExceptionHandler(FirstHandler: ULONG,
                                       VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
                                      -> LPVOID;
        fn SetThreadStackGuarantee(StackSizeInBytes: *mut ULONG) -> BOOL;
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
mod imp {
    use core::prelude::*;
    use stack;

    use super::{Handler, get_task_guard_page, report};
    use core::mem;
    use core::ptr;
    use core::intrinsics;
    use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
                       SA_SIGINFO, SA_ONSTACK, sigaltstack,
                       SIGSTKSZ};
    use libc;
    use libc::funcs::posix88::mman::{mmap, munmap};
    use libc::consts::os::posix88::{SIGSEGV,
                                    PROT_READ,
                                    PROT_WRITE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED};

    // This is initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;

    #[no_stack_check]
    unsafe extern fn signal_handler(signum: libc::c_int,
                                     info: *mut siginfo,
                                     _data: *mut libc::c_void) {

        // We can not return from a SIGSEGV or SIGBUS signal.
        // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html

        unsafe fn term(signum: libc::c_int) -> ! {
            use core::mem::transmute;

            signal(signum, transmute(SIG_DFL));
            raise(signum);
            intrinsics::abort();
        }

        // We're calling into functions with stack checks
        stack::record_sp_limit(0);

        match get_task_guard_page() {
            Some(guard) => {
                let addr = (*info).si_addr as uint;

                if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
                    term(signum);
                }

                report();

                intrinsics::abort()
            }
            None => term(signum)
        }
    }

    static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;

    pub unsafe fn init() {
        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
        if psize == -1 {
            panic!("failed to get page size");
        }

        PAGE_SIZE = psize as uint;

        let mut action: sigaction = mem::zeroed();
        action.sa_flags = SA_SIGINFO | SA_ONSTACK;
        action.sa_sigaction = signal_handler as sighandler_t;
        sigaction(SIGSEGV, &action, ptr::null_mut());
        sigaction(SIGBUS, &action, ptr::null_mut());

        let handler = make_handler();
        MAIN_ALTSTACK = handler._data;
        mem::forget(handler);
    }

    pub unsafe fn cleanup() {
        Handler { _data: MAIN_ALTSTACK };
    }

    pub unsafe fn make_handler() -> Handler {
        let alt_stack = mmap(ptr::null_mut(),
                             signal::SIGSTKSZ,
                             PROT_READ | PROT_WRITE,
                             MAP_PRIVATE | MAP_ANON,
                             -1,
                             0);
        if alt_stack == MAP_FAILED {
            panic!("failed to allocate an alternative stack");
        }

        let mut stack: sigaltstack = mem::zeroed();

        stack.ss_sp = alt_stack;
        stack.ss_flags = 0;
        stack.ss_size = SIGSTKSZ;

        sigaltstack(&stack, ptr::null_mut());

        Handler { _data: alt_stack }
    }

    pub unsafe fn drop_handler(handler: &mut Handler) {
        munmap(handler._data, SIGSTKSZ);
    }

    type sighandler_t = *mut libc::c_void;

    #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
              all(target_os = "linux", target_arch = "x86_64"),
              all(target_os = "linux", target_arch = "arm"), // may not match
              all(target_os = "linux", target_arch = "mips"), // may not match
              target_os = "android"))] // may not match
    mod signal {
        use libc;
        use super::sighandler_t;

        pub static SA_ONSTACK: libc::c_int = 0x08000000;
        pub static SA_SIGINFO: libc::c_int = 0x00000004;
        pub static SIGBUS: libc::c_int = 7;

        pub static SIGSTKSZ: libc::size_t = 8192;

        pub static SIG_DFL: sighandler_t = 0i as sighandler_t;

        // This definition is not as accurate as it could be, {si_addr} is
        // actually a giant union. Currently we're only interested in that field,
        // however.
        #[repr(C)]
        pub struct siginfo {
            si_signo: libc::c_int,
            si_errno: libc::c_int,
            si_code: libc::c_int,
            pub si_addr: *mut libc::c_void
        }

        #[repr(C)]
        pub struct sigaction {
            pub sa_sigaction: sighandler_t,
            pub sa_mask: sigset_t,
            pub sa_flags: libc::c_int,
            sa_restorer: *mut libc::c_void,
        }

        #[cfg(target_word_size = "32")]
        #[repr(C)]
        pub struct sigset_t {
            __val: [libc::c_ulong, ..32],
        }
        #[cfg(target_word_size = "64")]
        #[repr(C)]
        pub struct sigset_t {
            __val: [libc::c_ulong, ..16],
        }

        #[repr(C)]
        pub struct sigaltstack {
            pub ss_sp: *mut libc::c_void,
            pub ss_flags: libc::c_int,
            pub ss_size: libc::size_t
        }

    }

    #[cfg(target_os = "macos")]
    mod signal {
        use libc;
        use super::sighandler_t;

        pub const SA_ONSTACK: libc::c_int = 0x0001;
        pub const SA_SIGINFO: libc::c_int = 0x0040;
        pub const SIGBUS: libc::c_int = 10;

        pub const SIGSTKSZ: libc::size_t = 131072;

        pub const SIG_DFL: sighandler_t = 0i as sighandler_t;

        pub type sigset_t = u32;

        // This structure has more fields, but we're not all that interested in
        // them.
        #[repr(C)]
        pub struct siginfo {
            pub si_signo: libc::c_int,
            pub si_errno: libc::c_int,
            pub si_code: libc::c_int,
            pub pid: libc::pid_t,
            pub uid: libc::uid_t,
            pub status: libc::c_int,
            pub si_addr: *mut libc::c_void
        }

        #[repr(C)]
        pub struct sigaltstack {
            pub ss_sp: *mut libc::c_void,
            pub ss_size: libc::size_t,
            pub ss_flags: libc::c_int
        }

        #[repr(C)]
        pub struct sigaction {
            pub sa_sigaction: sighandler_t,
            pub sa_mask: sigset_t,
            pub sa_flags: libc::c_int,
        }
    }

    extern {
        pub fn signal(signum: libc::c_int, handler: sighandler_t) -> sighandler_t;
        pub fn raise(signum: libc::c_int) -> libc::c_int;

        pub fn sigaction(signum: libc::c_int,
                         act: *const sigaction,
                         oldact: *mut sigaction) -> libc::c_int;

        pub fn sigaltstack(ss: *const sigaltstack,
                           oss: *mut sigaltstack) -> libc::c_int;
    }
}

#[cfg(not(any(target_os = "linux",
              target_os = "macos",
              windows)))]
mod imp {
    use libc;

    pub unsafe fn init() {
    }

    pub unsafe fn cleanup() {
    }

    pub unsafe fn make_handler() -> super::Handler {
        super::Handler { _data: 0i as *mut libc::c_void }
    }

    pub unsafe fn drop_handler(_handler: &mut super::Handler) {
    }
}
<commit_msg>librustrt: stack_overflow support mipsel linux<commit_after>// Copyright 2014 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(non_camel_case_types)]

use core::prelude::*;
use libc;
use local::Local;
use task::Task;

pub unsafe fn init() {
    imp::init();
}

pub unsafe fn cleanup() {
    imp::cleanup();
}

pub struct Handler {
    _data: *mut libc::c_void
}

impl Handler {
    pub unsafe fn new() -> Handler {
        imp::make_handler()
    }
}

impl Drop for Handler {
    fn drop(&mut self) {
        unsafe {
            imp::drop_handler(self);
        }
    }
}

pub unsafe fn report() {
    // See the message below for why this is not emitted to the
    // ^ Where did the message below go?
    // task's logger. This has the additional conundrum of the
    // logger may not be initialized just yet, meaning that an FFI
    // call would happen to initialized it (calling out to libuv),
    // and the FFI call needs 2MB of stack when we just ran out.

    let task: Option<*mut Task> = Local::try_unsafe_borrow();

    let name = task.and_then(|task| {
        (*task).name.as_ref().map(|n| n.as_slice())
    });

    rterrln!("\ntask '{}' has overflowed its stack", name.unwrap_or("<unknown>"));
}

// get_task_info is called from an exception / signal handler.
// It returns the guard page of the current task or 0 if that
// guard page doesn't exist. None is returned if there's currently
// no local task.
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
unsafe fn get_task_guard_page() -> Option<uint> {
    let task: Option<*mut Task> = Local::try_unsafe_borrow();
    task.map(|task| (&*task).stack_guard().unwrap_or(0))
}

#[cfg(windows)]
#[allow(non_snake_case)]
mod imp {
    use core::ptr;
    use core::mem;
    use libc;
    use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
    use stack;
    use super::{Handler, get_task_guard_page, report};

    // This is initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;

    #[no_stack_check]
    extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG {
        unsafe {
            let rec = &(*(*ExceptionInfo).ExceptionRecord);
            let code = rec.ExceptionCode;

            if code != EXCEPTION_STACK_OVERFLOW {
                return EXCEPTION_CONTINUE_SEARCH;
            }

            // We're calling into functions with stack checks,
            // however stack checks by limit should be disabled on Windows
            stack::record_sp_limit(0);

            if get_task_guard_page().is_some() {
               report();
            }

            EXCEPTION_CONTINUE_SEARCH
        }
    }

    pub unsafe fn init() {
        let mut info = mem::zeroed();
        libc::GetSystemInfo(&mut info);
        PAGE_SIZE = info.dwPageSize as uint;

        if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() {
            panic!("failed to install exception handler");
        }

        mem::forget(make_handler());
    }

    pub unsafe fn cleanup() {
    }

    pub unsafe fn make_handler() -> Handler {
        if SetThreadStackGuarantee(&mut 0x5000) == 0 {
            panic!("failed to reserve stack space for exception handling");
        }

        super::Handler { _data: 0i as *mut libc::c_void }
    }

    pub unsafe fn drop_handler(_handler: &mut Handler) {
    }

    pub struct EXCEPTION_RECORD {
        pub ExceptionCode: DWORD,
        pub ExceptionFlags: DWORD,
        pub ExceptionRecord: *mut EXCEPTION_RECORD,
        pub ExceptionAddress: LPVOID,
        pub NumberParameters: DWORD,
        pub ExceptionInformation: [LPVOID, ..EXCEPTION_MAXIMUM_PARAMETERS]
    }

    pub struct EXCEPTION_POINTERS {
        pub ExceptionRecord: *mut EXCEPTION_RECORD,
        pub ContextRecord: LPVOID
    }

    pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
            fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;

    pub type ULONG = libc::c_ulong;

    const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
    const EXCEPTION_MAXIMUM_PARAMETERS: uint = 15;
    const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;

    extern "system" {
        fn AddVectoredExceptionHandler(FirstHandler: ULONG,
                                       VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
                                      -> LPVOID;
        fn SetThreadStackGuarantee(StackSizeInBytes: *mut ULONG) -> BOOL;
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
mod imp {
    use core::prelude::*;
    use stack;

    use super::{Handler, get_task_guard_page, report};
    use core::mem;
    use core::ptr;
    use core::intrinsics;
    use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
                       SA_SIGINFO, SA_ONSTACK, sigaltstack,
                       SIGSTKSZ};
    use libc;
    use libc::funcs::posix88::mman::{mmap, munmap};
    use libc::consts::os::posix88::{SIGSEGV,
                                    PROT_READ,
                                    PROT_WRITE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED};

    // This is initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;

    #[no_stack_check]
    unsafe extern fn signal_handler(signum: libc::c_int,
                                     info: *mut siginfo,
                                     _data: *mut libc::c_void) {

        // We can not return from a SIGSEGV or SIGBUS signal.
        // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html

        unsafe fn term(signum: libc::c_int) -> ! {
            use core::mem::transmute;

            signal(signum, transmute(SIG_DFL));
            raise(signum);
            intrinsics::abort();
        }

        // We're calling into functions with stack checks
        stack::record_sp_limit(0);

        match get_task_guard_page() {
            Some(guard) => {
                let addr = (*info).si_addr as uint;

                if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
                    term(signum);
                }

                report();

                intrinsics::abort()
            }
            None => term(signum)
        }
    }

    static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;

    pub unsafe fn init() {
        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
        if psize == -1 {
            panic!("failed to get page size");
        }

        PAGE_SIZE = psize as uint;

        let mut action: sigaction = mem::zeroed();
        action.sa_flags = SA_SIGINFO | SA_ONSTACK;
        action.sa_sigaction = signal_handler as sighandler_t;
        sigaction(SIGSEGV, &action, ptr::null_mut());
        sigaction(SIGBUS, &action, ptr::null_mut());

        let handler = make_handler();
        MAIN_ALTSTACK = handler._data;
        mem::forget(handler);
    }

    pub unsafe fn cleanup() {
        Handler { _data: MAIN_ALTSTACK };
    }

    pub unsafe fn make_handler() -> Handler {
        let alt_stack = mmap(ptr::null_mut(),
                             signal::SIGSTKSZ,
                             PROT_READ | PROT_WRITE,
                             MAP_PRIVATE | MAP_ANON,
                             -1,
                             0);
        if alt_stack == MAP_FAILED {
            panic!("failed to allocate an alternative stack");
        }

        let mut stack: sigaltstack = mem::zeroed();

        stack.ss_sp = alt_stack;
        stack.ss_flags = 0;
        stack.ss_size = SIGSTKSZ;

        sigaltstack(&stack, ptr::null_mut());

        Handler { _data: alt_stack }
    }

    pub unsafe fn drop_handler(handler: &mut Handler) {
        munmap(handler._data, SIGSTKSZ);
    }

    type sighandler_t = *mut libc::c_void;

    #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
              all(target_os = "linux", target_arch = "x86_64"),
              all(target_os = "linux", target_arch = "arm"), // may not match
              all(target_os = "linux", target_arch = "mips"), // may not match
              all(target_os = "linux", target_arch = "mipsel"), // may not match
              target_os = "android"))] // may not match
    mod signal {
        use libc;
        use super::sighandler_t;

        pub static SA_ONSTACK: libc::c_int = 0x08000000;
        pub static SA_SIGINFO: libc::c_int = 0x00000004;
        pub static SIGBUS: libc::c_int = 7;

        pub static SIGSTKSZ: libc::size_t = 8192;

        pub static SIG_DFL: sighandler_t = 0i as sighandler_t;

        // This definition is not as accurate as it could be, {si_addr} is
        // actually a giant union. Currently we're only interested in that field,
        // however.
        #[repr(C)]
        pub struct siginfo {
            si_signo: libc::c_int,
            si_errno: libc::c_int,
            si_code: libc::c_int,
            pub si_addr: *mut libc::c_void
        }

        #[repr(C)]
        pub struct sigaction {
            pub sa_sigaction: sighandler_t,
            pub sa_mask: sigset_t,
            pub sa_flags: libc::c_int,
            sa_restorer: *mut libc::c_void,
        }

        #[cfg(target_word_size = "32")]
        #[repr(C)]
        pub struct sigset_t {
            __val: [libc::c_ulong, ..32],
        }
        #[cfg(target_word_size = "64")]
        #[repr(C)]
        pub struct sigset_t {
            __val: [libc::c_ulong, ..16],
        }

        #[repr(C)]
        pub struct sigaltstack {
            pub ss_sp: *mut libc::c_void,
            pub ss_flags: libc::c_int,
            pub ss_size: libc::size_t
        }

    }

    #[cfg(target_os = "macos")]
    mod signal {
        use libc;
        use super::sighandler_t;

        pub const SA_ONSTACK: libc::c_int = 0x0001;
        pub const SA_SIGINFO: libc::c_int = 0x0040;
        pub const SIGBUS: libc::c_int = 10;

        pub const SIGSTKSZ: libc::size_t = 131072;

        pub const SIG_DFL: sighandler_t = 0i as sighandler_t;

        pub type sigset_t = u32;

        // This structure has more fields, but we're not all that interested in
        // them.
        #[repr(C)]
        pub struct siginfo {
            pub si_signo: libc::c_int,
            pub si_errno: libc::c_int,
            pub si_code: libc::c_int,
            pub pid: libc::pid_t,
            pub uid: libc::uid_t,
            pub status: libc::c_int,
            pub si_addr: *mut libc::c_void
        }

        #[repr(C)]
        pub struct sigaltstack {
            pub ss_sp: *mut libc::c_void,
            pub ss_size: libc::size_t,
            pub ss_flags: libc::c_int
        }

        #[repr(C)]
        pub struct sigaction {
            pub sa_sigaction: sighandler_t,
            pub sa_mask: sigset_t,
            pub sa_flags: libc::c_int,
        }
    }

    extern {
        pub fn signal(signum: libc::c_int, handler: sighandler_t) -> sighandler_t;
        pub fn raise(signum: libc::c_int) -> libc::c_int;

        pub fn sigaction(signum: libc::c_int,
                         act: *const sigaction,
                         oldact: *mut sigaction) -> libc::c_int;

        pub fn sigaltstack(ss: *const sigaltstack,
                           oss: *mut sigaltstack) -> libc::c_int;
    }
}

#[cfg(not(any(target_os = "linux",
              target_os = "macos",
              windows)))]
mod imp {
    use libc;

    pub unsafe fn init() {
    }

    pub unsafe fn cleanup() {
    }

    pub unsafe fn make_handler() -> super::Handler {
        super::Handler { _data: 0i as *mut libc::c_void }
    }

    pub unsafe fn drop_handler(_handler: &mut super::Handler) {
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 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.

//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of
//! these syntaxes is tested by compile-test/obsolete-syntax.rs.
//!
//! Obsolete syntax that becomes too hard to parse can be removed.

use ast::{Expr, ExprTup};
use codemap::Span;
use parse::parser;
use parse::token;
use ptr::P;

/// The specific types of unsupported syntax
#[derive(Copy, PartialEq, Eq, Hash)]
pub enum ObsoleteSyntax {
    Sized,
    ForSized,
    ProcType,
    ProcExpr,
    ClosureType,
    ClosureKind,
}

pub trait ParserObsoleteMethods {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax);
    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr>;
    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str);
    fn is_obsolete_ident(&mut self, ident: &str) -> bool;
    fn eat_obsolete_ident(&mut self, ident: &str) -> bool;
}

impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
        let (kind_str, desc) = match kind {
            ObsoleteSyntax::ForSized => (
                "for Sized?",
                "no longer required. Traits (and their `Self` type) do not have the `Sized` bound \
                 by default",
            ),
            ObsoleteSyntax::ProcType => (
                "the `proc` type",
                "use unboxed closures instead",
            ),
            ObsoleteSyntax::ProcExpr => (
                "`proc` expression",
                "use a `move ||` expression instead",
            ),
            ObsoleteSyntax::ClosureType => (
                "`|usize| -> bool` closure type syntax",
                "use unboxed closures instead, no type annotation needed"
            ),
            ObsoleteSyntax::ClosureKind => (
                "`:`, `&mut:`, or `&:` syntax",
                "rely on inference instead"
            ),
            ObsoleteSyntax::Sized => (
                "`Sized? T` syntax for removing the `Sized` bound",
                "write `T: ?Sized` instead"
            ),
        };

        self.report(sp, kind, kind_str, desc);
    }

    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr> {
        self.obsolete(sp, kind);
        self.mk_expr(sp.lo, sp.hi, ExprTup(vec![]))
    }

    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str) {
        self.span_err(sp,
                      &format!("obsolete syntax: {}", kind_str)[]);

        if !self.obsolete_set.contains(&kind) {
            self.sess
                .span_diagnostic
                .handler()
                .note(&format!("{}", desc)[]);
            self.obsolete_set.insert(kind);
        }
    }

    fn is_obsolete_ident(&mut self, ident: &str) -> bool {
        match self.token {
            token::Ident(sid, _) => {
                token::get_ident(sid) == ident
            }
            _ => false
        }
    }

    fn eat_obsolete_ident(&mut self, ident: &str) -> bool {
        if self.is_obsolete_ident(ident) {
            self.bump();
            true
        } else {
            false
        }
    }
}
<commit_msg>Remove word syntax from obsolete syntax messages<commit_after>// Copyright 2012-2014 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.

//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of
//! these syntaxes is tested by compile-test/obsolete-syntax.rs.
//!
//! Obsolete syntax that becomes too hard to parse can be removed.

use ast::{Expr, ExprTup};
use codemap::Span;
use parse::parser;
use parse::token;
use ptr::P;

/// The specific types of unsupported syntax
#[derive(Copy, PartialEq, Eq, Hash)]
pub enum ObsoleteSyntax {
    Sized,
    ForSized,
    ProcType,
    ProcExpr,
    ClosureType,
    ClosureKind,
}

pub trait ParserObsoleteMethods {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax);
    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr>;
    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str);
    fn is_obsolete_ident(&mut self, ident: &str) -> bool;
    fn eat_obsolete_ident(&mut self, ident: &str) -> bool;
}

impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
        let (kind_str, desc) = match kind {
            ObsoleteSyntax::ForSized => (
                "for Sized?",
                "no longer required. Traits (and their `Self` type) do not have the `Sized` bound \
                 by default",
            ),
            ObsoleteSyntax::ProcType => (
                "the `proc` type",
                "use unboxed closures instead",
            ),
            ObsoleteSyntax::ProcExpr => (
                "`proc` expression",
                "use a `move ||` expression instead",
            ),
            ObsoleteSyntax::ClosureType => (
                "`|usize| -> bool` closure type",
                "use unboxed closures instead, no type annotation needed"
            ),
            ObsoleteSyntax::ClosureKind => (
                "`:`, `&mut:`, or `&:`",
                "rely on inference instead"
            ),
            ObsoleteSyntax::Sized => (
                "`Sized? T` for removing the `Sized` bound",
                "write `T: ?Sized` instead"
            ),
        };

        self.report(sp, kind, kind_str, desc);
    }

    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> P<Expr> {
        self.obsolete(sp, kind);
        self.mk_expr(sp.lo, sp.hi, ExprTup(vec![]))
    }

    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str) {
        self.span_err(sp,
                      &format!("obsolete syntax: {}", kind_str)[]);

        if !self.obsolete_set.contains(&kind) {
            self.sess
                .span_diagnostic
                .handler()
                .note(&format!("{}", desc)[]);
            self.obsolete_set.insert(kind);
        }
    }

    fn is_obsolete_ident(&mut self, ident: &str) -> bool {
        match self.token {
            token::Ident(sid, _) => {
                token::get_ident(sid) == ident
            }
            _ => false
        }
    }

    fn eat_obsolete_ident(&mut self, ident: &str) -> bool {
        if self.is_obsolete_ident(ident) {
            self.bump();
            true
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Formatting<commit_after><|endoftext|>


<commit_before><commit_msg>test for negative offsets<commit_after>// error-pattern: pointer to 1 byte starting at offset -1 is out-of-bounds
fn main() {
    let v = [0i8; 4];
    let x = &v as *const i8;
    let x = unsafe { x.offset(-1) };
    panic!("this should never print: {:?}", x);
}
<|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.

// xfail-test
type IMap<K:Copy,V:Copy> = ~[(K, V)];

trait ImmutableMap<K:Copy,V:Copy>
{
    fn contains_key(key: K) -> bool;
}

impl<K:Copy,V:Copy> IMap<K, V> : ImmutableMap<K, V>
{
    fn contains_key(key: K) -> bool {
        vec::find(self, |e| {e.first() == key}).is_some()
    }
}

pub fn main() {}
<commit_msg>This test case is obsolete for two reasons<commit_after><|endoftext|>


<commit_before><commit_msg>add tk ops file<commit_after>#![allow(unused_variables)]
use tensor::*;

macro_rules! impl_tk_dispatch_self_ref {
    ($key:ident, $var:ident, $action:expr ) => {(
        match * $key {
            TensorKind::FloatTensor(ref $var) => TensorKind::FloatTensor($action) ,
            TensorKind::LongTensor(ref $var) => TensorKind::LongTensor($action) ,
            TensorKind::ByteTensor(ref $var) => TensorKind::ByteTensor($action) ,
        }
    )}
}
macro_rules! impl_tk_dispatch_self_ref_other {
    ($key:ident, $var:ident, $action:expr ) => {(
        match * $key {
            TensorKind::FloatTensor(ref $var) => $action,
            TensorKind::LongTensor(ref $var) => $action,
            TensorKind::ByteTensor(ref $var) => $action,
        }
    )}
}
macro_rules! impl_tk_dispatch_self_ref_other_mut {
    ($key:ident, $var:ident, $action:expr ) => {(
        match * $key {
            TensorKind::FloatTensor(ref mut $var) => $action,
            TensorKind::LongTensor(ref mut $var) => $action,
            TensorKind::ByteTensor(ref mut $var) => $action,
        }
    )}
}
macro_rules! impl_tk_dispatch_self {
    ($key:ident, $var:ident, $action:expr ) => {(
        {
        match * $key {
            TensorKind::FloatTensor(ref mut $var) => {$action;} ,
            TensorKind::LongTensor(ref mut $var) => {$action;} ,
            TensorKind::ByteTensor(ref mut $var) => {$action;} ,
        };
        $key
        }
    )}
}

impl TensorKind {
    pub fn abs<T: NumLimits>(&self) -> Self {
        (self.into(): &Tensor<T>).abs().into()
    }
    pub fn abs_<T: NumLimits>(&mut self) -> &mut Self {
        (self.into(): &mut Tensor<T>).abs_();
        self
    }
    pub fn acos<T: NumLimits>(&self) -> Self {
        (self.into(): &Tensor<T>).acos().into()
    }
    pub fn acos_<T: NumLimits>(&mut self) -> &mut Self {
        (self.into(): &mut Tensor<T>).acos_();
        self
    }
    pub fn add<T: NumLimits>(&self, rhs: T) -> Self {
        (self.into(): &Tensor<T>).add(rhs).into()
    }
    pub fn add_<T: NumLimits>(&mut self, rhs: T) -> &mut Self {
        (self.into(): &mut Tensor<T>).add_(rhs);
        self
    }
    pub fn addt<T: NumLimits>(&self, val: T, rhs: &Self) -> Self {
        (self.into(): &Tensor<T>).addt(val, rhs.into()).into()
    }
    pub fn addt_<T: NumLimits>(&mut self, val: T, rhs: &Self) -> &mut Self {
        (self.into(): &mut Tensor<T>).addt_(val, rhs.into());
        self
    }
    pub fn addbmm<T: NumLimits>(&self, beta: T, alpha: T, tensor1: &Self, tensor2: &Self) -> Self {
        unimplemented!()
    }
    pub fn addbmm_<T: NumLimits>(&mut self,
                                 beta: T,
                                 alpha: T,
                                 tensor1: &Self,
                                 tensor2: &Self)
                                 -> &mut Self {
        unimplemented!()
    }
    pub fn addcdiv<T: NumLimits>(&self, value: T, tensor1: &Self, tensor2: &Self) -> Self {
        unimplemented!()
    }
    pub fn addcdiv_<T: NumLimits>(&mut self,
                                  value: T,
                                  tensor1: &Self,
                                  tensor2: &Self)
                                  -> &mut Self {
        unimplemented!()
    }
    pub fn addcmul<T: NumLimits>(&self, value: T, tensor1: &Self, tensor2: &Self) -> Self {
        unimplemented!()
    }
    pub fn addcmul_<T: NumLimits>(&mut self,
                                  value: T,
                                  tensor1: &Self,
                                  tensor2: &Self)
                                  -> &mut Self {
        unimplemented!()
    }
    pub fn addmm<T: NumLimits>(&self, beta: T, alpha: T, tensor1: &Self, tensor2: &Self) -> Self {
        unimplemented!()
    }
    pub fn addmm_<T: NumLimits>(&mut self,
                                beta: T,
                                alpha: T,
                                tensor1: &Self,
                                tensor2: &Self)
                                -> &mut Self {
        unimplemented!()
    }
    pub fn addmv<T: NumLimits>(&self, beta: T, alpha: T, tensor1: &Self, vec: &Self) -> Self {
        unimplemented!()
    }
    pub fn addmv_<T: NumLimits>(&mut self,
                                beta: T,
                                alpha: T,
                                tensor1: &Self,
                                vec: &Self)
                                -> &mut Self {
        unimplemented!()
    }
    pub fn addr<T: NumLimits>(&self, beta: T, alpha: T, vec1: &Self, vec2: &Self) -> Self {
        unimplemented!()
    }
    pub fn addr_<T: NumLimits>(&mut self,
                               beta: T,
                               alpha: T,
                               vec1: &Self,
                               vec2: &Self)
                               -> &mut Self {
        unimplemented!()
    }
    pub fn asin<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn asin_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn atan<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn atan2<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn atan2_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn baddbmm<T: NumLimits>(&self, beta: T, alpha: T, tensor1: &Self, tensor2: &Self) -> Self {
        unimplemented!()
    }
    pub fn baddbmm_<T: NumLimits>(&mut self,
                                  beta: T,
                                  alpha: T,
                                  tensor1: &Self,
                                  tensor2: &Self)
                                  -> &mut Self {
        unimplemented!()
    }
    pub fn bernoulli<T: NumLimits>(&self, p: T) -> Self {
        unimplemented!()
    }
    pub fn bernoulli_<T: NumLimits>(&mut self, p: T) -> &mut Self {
        unimplemented!()
    }
    pub fn bmm<T: NumLimits>(&self, other: &Self) -> Self {
        unimplemented!()
    }
    pub fn byte(&mut self) -> &mut Self {
        unimplemented!()
    }
    //
    // cauchy_
    //
    pub fn ceil(&self) -> Self {
        impl_tk_dispatch_self_ref!(self, t, t.ceil())

    }
    pub fn ceil_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn char(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn chunk<T: NumLimits>(&self, n_chunks: usize, dim: usize) -> Vec<Self> {
        unimplemented!()
    }
    pub fn clamp<T: NumLimits>(&self, min: T, max: T) -> Self {
        unimplemented!()
    }
    pub fn clamp_<T: NumLimits>(&mut self, min: T, max: T) -> &mut Self {
        unimplemented!()
    }
    pub fn contiguous<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    // perform deep copy
    pub fn copy(&self) -> Self {
        unimplemented!()
    }
    pub fn copy_(&mut self, src: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn copy_async_(&mut self, src: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn cos<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn cos_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn cosh<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn cosh_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn cpu<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn cross<T: NumLimits>(&self, dim: Option<i32>) -> Self {
        unimplemented!()
    }
    pub fn cuda<T: NumLimits>(&self, device: Option<i32>) -> Self {
        unimplemented!()
    }
    pub fn cuda_async<T: NumLimits>(&self, device: Option<i32>) -> Self {
        unimplemented!()
    }
    pub fn diag<T: NumLimits>(&self, diag: u32) -> Self {
        unimplemented!()
    }
    pub fn dim(&self) -> i32 {
        unimplemented!()
    }
    pub fn dist<T: NumLimits>(&self, other: &Self, p: u32) -> f32 {
        unimplemented!()
    }
    pub fn div<T: NumLimits>(&self, value: T) -> Self {
        unimplemented!()
    }
    pub fn div_<T: NumLimits>(&mut self, value: T) -> &mut Self {
        unimplemented!()
    }
    pub fn divt<T: NumLimits>(&self, value: &Self) -> Self {

        unimplemented!()
    }
    pub fn divt_(&mut self, value: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn dot<T: NumLimits>(&self, other: &Self) -> Self {
        unimplemented!()
    }
    pub fn double<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn eig<T: NumLimits>(&self, eigenvectors: bool) -> (Self, Self) {
        unimplemented!()
    }
    pub fn element_size<T: NumLimits>(&self) -> i32 {
        unimplemented!()
    }
    pub fn eq_tensor(&self, other: &Self) -> Tensor<u8> {
        unimplemented!()
    }
    pub fn eq_tensor_<T: NumLimits>(&self, other: &Self) -> Self {
        unimplemented!()
    }
    pub fn exp<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn exp_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn expand<T: NumLimits>(&self, dims: &[u32]) -> Self {
        unimplemented!()
    }
    pub fn expand_as(&self, tensor: &Self) -> Self {
        unimplemented!()
    }
    pub fn fill_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn float(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn floor<T: NumLimits>(&self) -> Self {
        unimplemented!()
    }
    pub fn floor_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn fmod<T: NumLimits>(&self, divisor: T) -> Self {
        unimplemented!()
    }
    pub fn fmod_<T: NumLimits>(&mut self, divisor: T) -> &mut Self {
        unimplemented!()
    }
    pub fn frac(&self) -> Self {
        unimplemented!()
    }
    pub fn frac_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn gather(&self, dim: i32, index: Tensor<i64>) {
        unimplemented!()
    }
    pub fn ge_tensor(&self, other: &Self) -> Tensor<u8> {
        unimplemented!()
    }
    pub fn ge_tensor_(&self, other: &Self) -> Self {
        unimplemented!()
    }
    pub fn gels(&self, other: &Self) -> Self {
        unimplemented!();
    }
    pub fn gt_tensor(&self, other: &Self) -> Tensor<u8> {
        unimplemented!()
    }
    pub fn gt_tensor_(&self, other: &Self) -> Self {
        unimplemented!()
    }
    pub fn half(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn id(&self) -> usize {
        impl_tk_dispatch_self_ref_other!(self, t, t.id())
    }
    pub fn index_masked(&self, m: &Tensor<u8>) -> Self {
        unimplemented!()
    }
    pub fn index_add_(&mut self, dim: i32, index: Tensor<i64>, tensor: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn index_copy_(&mut self, dim: i32, index: Tensor<i64>, tensor: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn index_fill_(&mut self, dim: i32, index: Tensor<i64>, val: f32) -> &mut Self {
        unimplemented!()
    }
    pub fn index_select(&self, dim: i32, index: Tensor<i64>) -> Self {
        unimplemented!()
    }
    pub fn int(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn is_cuda(&self) -> bool {
        unimplemented!()
    }
    pub fn is_pinned(&self) -> bool {
        unimplemented!()
    }
    pub fn is_set_to(&self, tensor: &Self) -> bool {
        unimplemented!()
    }
    pub fn is_signed(&self) -> bool {
        unimplemented!()
    }
    pub fn kthvalue(&self, k: i32, dim: Option<i32>) -> (Self, Tensor<i64>) {
        unimplemented!()
    }
    pub fn le_tensor(&self, other: &Self) -> Tensor<u8> {
        unimplemented!()
    }
    pub fn le_tensor_(&self, other: &Self) -> Self {
        unimplemented!()
    }
    pub fn lerp(&self, start: &Self, end: &Self, weight: f32) -> Self {
        unimplemented!()
    }
    pub fn lerp_(&self, start: &Self, end: &Self, weight: f32) -> Self {
        unimplemented!()
    }
    pub fn log(&self) -> Self {
        unimplemented!()
    }
    pub fn log_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn log1p(&self) -> Self {
        unimplemented!()
    }
    pub fn log1p_(&mut self) -> &mut Self {
        unimplemented!()
    }
    //
    // log_normal(...)
    //
    pub fn long(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn lt_tensor(&self, other: &Self) -> Tensor<u8> {
        unimplemented!()
    }
    pub fn lt_tensor_(&mut self, other: &Self) -> &mut Self {
        unimplemented!()
    }
    //
    // map_
    //
    pub fn masked_copy_(&mut self, mask: Tensor<u8>, source: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn masked_select(&self, mask: Tensor<u8>) -> Self {
        unimplemented!()
    }
    pub fn max<T: NumLimits>(&self) -> T {
        unimplemented!()
    }
    pub fn max_reduce(&self, dim: i32) -> (Self, Tensor<i64>) {
        unimplemented!()
    }
    pub fn mean<T: NumLimits>(&self) -> T {
        unimplemented!()
    }
    pub fn mean_reduce(&self, dim: i32) -> (Self, Tensor<i64>) {
        unimplemented!()
    }
    //
    // median
    //
    pub fn min<T: NumLimits>(&self) -> T {
        unimplemented!()
    }
    pub fn min_reduce(&self, dim: i32) -> (Self, Tensor<i64>) {
        unimplemented!()
    }
    pub fn mm(&self, rhs: &Self) -> Self {
        unimplemented!()
    }
    //
    // mode
    //
    pub fn mul<T: NumLimits>(&self, rhs: T) -> Self {
        unimplemented!()
    }
    pub fn mul_<T: NumLimits>(&mut self, rhs: T) -> &mut Self {
        unimplemented!()
    }
    pub fn mult(&self, rhs: &Self) -> Self {
        unimplemented!()
    }
    pub fn mult_(&mut self, rhs: &Self) -> &mut Self {
        unimplemented!()
    }
    //
    // multinomial
    //
    pub fn mv(&self, vec: &Self) -> Self {
        unimplemented!()
    }
    pub fn narrow(&self, dim: i32, start: i32, length: i32) -> Self {
        unimplemented!()
    }
    pub fn ndimension(&self) -> i32 {
        unimplemented!()
    }
    pub fn ne_tensor(&self, other: &Self) -> Tensor<u8> {
        unimplemented!()
    }
    pub fn ne_tensor_(&mut self, other: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn neg(&self) -> Self {
        unimplemented!()
    }
    pub fn neg_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn nonzero(&self) -> Tensor<i64> {
        unimplemented!()
    }
    pub fn norm(&self, p: i32) -> f32 {
        unimplemented!()
    }
    //
    // normal_
    //
    pub fn numel(&self) -> i32 {
        unimplemented!()
    }
    //
    // numpy() (need native tensor equivalent - rust-ndarray?)
    //
    //
    // orgqr
    //
    // ormqr
    //
    pub fn permute(&self, dims: &[u32]) -> Self {
        unimplemented!()
    }
    pub fn pin_memory(&mut self) -> &mut Self {
        unimplemented!()
    }
    //
    // potrf
    //
    //
    // potri
    //
    //
    // potrs
    //
    pub fn pow(&self) -> Self {
        unimplemented!()
    }
    pub fn pow_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn prod<T: NumLimits>(&self) -> T {
        unimplemented!()
    }
    //
    // pstrf
    //
    //
    // qr
    //
    //
    // random_
    //
    pub fn reciprocal(&self) -> Self {
        unimplemented!()
    }
    pub fn reciprocal_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn remainder<T: NumLimits>(&self, divisor: T) -> Self {
        unimplemented!()
    }
    pub fn remainder_<T: NumLimits>(&mut self, divisor: T) -> &mut Self {
        unimplemented!()
    }
    //
    // renorm
    //
    //
    // renorm_
    //
    pub fn repeat(&self, sizes: &[i32]) -> Self {
        // NB: copies data
        unimplemented!()
    }
    pub fn resize_(&mut self, sizes: &[i32]) -> &mut Self {
        unimplemented!()
    }
    pub fn resize_as_(&mut self, tensor: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn round(&self) -> Self {
        unimplemented!()
    }
    pub fn round_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn rsqrt(&self) -> Self {
        unimplemented!()
    }
    pub fn rsqrt_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn scatter_(&mut self, dim: i32, index: Tensor<i64>, src: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn select(&self, dim: i32, index: i32) -> Self {
        unimplemented!()
    }
    //
    // set_
    //
    //
    // share_memory_
    //
    pub fn short(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn sigmoid(&self) -> Self {
        unimplemented!()
    }
    pub fn sigmoid_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn sign(&self) -> Self {
        unimplemented!()
    }
    pub fn sign_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn sin(&self) -> Self {
        unimplemented!()
    }
    pub fn sin_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn sinh(&self) -> Self {
        unimplemented!()
    }
    pub fn sinh_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn size(&self) -> Vec<usize> {
        impl_tk_dispatch_self_ref_other!(self, t, t.size())
    }
    pub fn sort(&self, dim: Option<i32>, descending: bool) -> (Self, Tensor<i64>) {
        unimplemented!()
    }
    pub fn sqrt(&self) -> Self {
        unimplemented!()
    }
    pub fn sqrt_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn squeeze(&self, dim: Option<i32>) -> Self {
        unimplemented!()
    }
    pub fn squeeze_(&mut self, dim: Option<i32>) -> &mut Self {
        unimplemented!()
    }
    pub fn std<T: NumLimits>(&self) -> T {
        unimplemented!()
    }
    //
    // storage
    //
    //
    // storage_offset
    //
    pub fn stride(&self) -> Vec<i32> {
        unimplemented!()
    }
    pub fn sub(&self, rhs: &Self) -> Self {
        unimplemented!()
    }
    pub fn sub_(&mut self, rhs: &Self) -> &mut Self {
        unimplemented!()
    }
    pub fn sum<T: NumLimits>(&self) -> T {
        unimplemented!()
    }
    pub fn sum_reduce(&self, dim: i32, keepdim: bool) -> Self {
        unimplemented!()
    }
    pub fn svd(&self, some: bool) -> (Self, Self, Self) {
        unimplemented!()
    }
    //
    // symeig
    //
    pub fn t(&self) -> Self {
        unimplemented!()
    }
    pub fn t_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn tan(&self) -> Self {
        unimplemented!()
    }
    pub fn tan_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn tanh(&self) -> Self {
        unimplemented!()
    }
    pub fn tanh_(&mut self) -> &mut Self {
        unimplemented!()
    }
    //
    // tolist
    //
    pub fn topk(k: i32, dim: Option<i32>, largest: bool, sorted: bool) -> (Self, Tensor<i64>) {
        unimplemented!()
    }
    pub fn trace(&self) -> Self {
        unimplemented!()
    }
    pub fn transpose(&self, dim0: i32, dim1: i32) -> Self {
        unimplemented!()
    }
    pub fn transpose_(&self, dim0: i32, dim1: i32) -> Self {
        unimplemented!()
    }
    //
    // tril
    //
    //
    // tril_
    //
    //
    // triu
    //
    //
    // tril_
    //
    //
    // trtrs
    //
    pub fn trunc(&self) -> Self {
        unimplemented!()
    }
    pub fn trunc_(&mut self) -> &mut Self {
        unimplemented!()
    }
    pub fn type_as(&self, tensor: &Self) -> Self {
        unimplemented!()
    }
    pub fn typecast(&self, new_type: TensorType, async: bool) -> Self {
        unimplemented!()
    }
    pub fn unfold(&self, dim: i32, size: i32, step: i32) -> Self {
        unimplemented!()
    }
    pub fn uniform_(&mut self, range: (f64, f64)) -> &mut Self {
        impl_tk_dispatch_self_ref_other_mut!(self, v, {v.uniform_(range);});
        self
    }
    pub fn unsqueeze(&self, dim: i32) -> Self {
        unimplemented!()
    }
    pub fn unsqueeze_(&mut self, dim: i32) -> &mut Self {
        unimplemented!()
    }
    pub fn var<T: NumLimits>(&self) -> T {
        unimplemented!()
    }
    pub fn view<D>(&self, dims: D) -> Self
        where D: AsRef<[isize]>
    {
        impl_tk_dispatch_self_ref!(self, t, (t.view(dims)))
    }
    pub fn view_as(&self, tensor: &Self) -> Self {
        unimplemented!()
    }
    pub fn zero_(&mut self) -> &mut Self {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before><commit_msg>Add a mechanism for secondary command buffers to inherit a framebuffer<commit_after><|endoftext|>


<commit_before><commit_msg>Fix spelling of "corresponding" in 'status' docs.<commit_after><|endoftext|>


<commit_before><commit_msg>tests: adds stub integration tests<commit_after>extern crate mgrs;

#[test]
fn mgrs_to_ll_point() {
    let ll = LatLon::from("33UXP04");
    assert_eq!(ll[0].lat, 16.41450); // May need to change to close to
    assert_eq!(ll[0].lon, 0.000001);
    assert_eq!(ll[1].lat, 48.24949); // May need to change to close to
    assert_eq!(ll[1].lon, 0.000001);

    // it('MGRS reference with highest accuracy correct.', function() {
    // mgrs.forward(point).should.equal("33UXP0500444998");
    // it('MGRS reference with 1-digit accuracy correct.', function() {
    // mgrs.forward(point,1).should.equal(mgrsStr);
}

#[test]
fn mgrs_to_ll_point_near_zone_border() {
  // var mgrsStr = "24XWT783908"; // near UTM zone border, so there are two ways to reference this
  // var point = mgrs.toPoint(mgrsStr);
  // it('Longitude of point from MGRS correct.', function() {
  //   point[0].should.be.closeTo(-32.66433, 0.00001);
  // });
  // it('Latitude of point from MGRS correct.', function() {
  //   point[1].should.be.closeTo(83.62778, 0.00001);
  // });
  // it('MGRS reference with 1-digit accuracy correct.', function() {
  //   mgrs.forward(point,3).should.equal('25XEN041865');
  // });
  // it('MGRS reference with 5-digit accuracy, northing all zeros', function(){
  //   mgrs.forward([0,0],5).should.equal('31NAA6602100000');
  // });
  // it('MGRS reference with 5-digit accuracy, northing one digit', function(){
  //   mgrs.forward([0,0.00001],5).should.equal('31NAA6602100001');
  // });
}
<|endoftext|>


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

//! A stack-allocated vector, allowing storage of N elements on the stack.

use std::marker::Unsize;
use std::iter::Extend;
use std::ptr::{self, drop_in_place, Shared};
use std::ops::{Deref, DerefMut, Range};
use std::hash::{Hash, Hasher};
use std::slice;
use std::fmt;
use std::mem;
use std::collections::range::RangeArgument;

pub unsafe trait Array {
    type Element;
    type PartialStorage: Default + Unsize<[ManuallyDrop<Self::Element>]>;
    const LEN: usize;
}

unsafe impl<T> Array for [T; 1] {
    type Element = T;
    type PartialStorage = [ManuallyDrop<T>; 1];
    const LEN: usize = 1;
}

unsafe impl<T> Array for [T; 8] {
    type Element = T;
    type PartialStorage = [ManuallyDrop<T>; 8];
    const LEN: usize = 8;
}

pub struct ArrayVec {
    count: usize,
    values: A::PartialStorage
}

impl Hash for ArrayVec
    where A: Array,
          A::Element: Hash {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        (&self[..]).hash(state);
    }
}

impl PartialEq for ArrayVec {
    fn eq(&self, other: &Self) -> bool {
        self == other
    }
}

impl Eq for ArrayVec {}

impl Clone for ArrayVec
    where A: Array,
          A::Element: Clone {
    fn clone(&self) -> Self {
        let mut v = ArrayVec::new();
        v.extend(self.iter().cloned());
        v
    }
}

impl ArrayVec {
    pub fn new() -> Self {
        ArrayVec {
            count: 0,
            values: Default::default(),
        }
    }

    pub fn len(&self) -> usize {
        self.count
    }

    pub unsafe fn set_len(&mut self, len: usize) {
        self.count = len;
    }

    /// Panics when the stack vector is full.
    pub fn push(&mut self, el: A::Element) {
        let arr = &mut self.values as &mut [ManuallyDrop<_>];
        arr[self.count] = ManuallyDrop { value: el };
        self.count += 1;
    }

    pub fn pop(&mut self) -> Option {
        if self.count > 0 {
            let arr = &mut self.values as &mut [ManuallyDrop<_>];
            self.count -= 1;
            unsafe {
                let value = ptr::read(&arr[self.count]);
                Some(value.value)
            }
        } else {
            None
        }
    }

    pub fn drain<R>(&mut self, range: R) -> Drain
        where R: RangeArgument<usize>
    {
        // Memory safety
        //
        // When the Drain is first created, it shortens the length of
        // the source vector to make sure no uninitalized or moved-from elements
        // are accessible at all if the Drain's destructor never gets to run.
        //
        // Drain will ptr::read out the values to remove.
        // When finished, remaining tail of the vec is copied back to cover
        // the hole, and the vector length is restored to the new length.
        //
        let len = self.len();
        let start = *range.start().unwrap_or(&0);
        let end = *range.end().unwrap_or(&len);
        assert!(start <= end);
        assert!(end <= len);

        unsafe {
            // set self.vec length's to start, to be safe in case Drain is leaked
            self.set_len(start);
            // Use the borrow in the IterMut to indicate borrowing behavior of the
            // whole Drain iterator (like &mut T).
            let range_slice = {
                let arr = &mut self.values as &mut [ManuallyDrop<_>];
                slice::from_raw_parts_mut(arr.as_mut_ptr().offset(start as isize),
                                          end - start)
            };
            Drain {
                tail_start: end,
                tail_len: len - end,
                iter: range_slice.iter(),
                array_vec: Shared::new(self as *mut _),
            }
        }
    }
}

impl Default for ArrayVec
    where A: Array {
    fn default() -> Self {
        ArrayVec::new()
    }
}

impl fmt::Debug for ArrayVec
    where A: Array,
          A::Element: fmt::Debug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self[..].fmt(f)
    }
}

impl Deref for ArrayVec {
    type Target = [A::Element];
    fn deref(&self) -> &Self::Target {
        unsafe {
            slice::from_raw_parts(&self.values as *const _ as *const A::Element, self.count)
        }
    }
}

impl DerefMut for ArrayVec {
    fn deref_mut(&mut self) -> &mut [A::Element] {
        unsafe {
            slice::from_raw_parts_mut(&mut self.values as *mut _ as *mut A::Element, self.count)
        }
    }
}

impl Drop for ArrayVec {
    fn drop(&mut self) {
        unsafe {
            drop_in_place(&mut self[..])
        }
    }
}

impl Extend for ArrayVec {
    fn extend(&mut self, iter: I) where I: IntoIterator<Item=A::Element> {
        for el in iter {
            self.push(el);
        }
    }
}

pub struct Iter {
    indices: Range<usize>,
    store: A::PartialStorage,
}

impl Drop for Iter {
    fn drop(&mut self) {
        for _ in self {}
    }
}

impl Iterator for Iter {
    type Item = A::Element;

    fn next(&mut self) -> Option {
        let arr = &self.store as &[ManuallyDrop<_>];
        unsafe {
            self.indices.next().map(|i| ptr::read(&arr[i]).value)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.indices.size_hint()
    }
}

pub struct Drain<'a, A: Array>
        where A::Element: 'a
{
    tail_start: usize,
    tail_len: usize,
    iter: slice::Iter<'a, ManuallyDrop>,
    array_vec: Shared<ArrayVec>,
}

impl<'a, A: Array> Iterator for Drain<'a, A> {
    type Item = A::Element;

    #[inline]
    fn next(&mut self) -> Option {
        self.iter.next().map(|elt| unsafe { ptr::read(elt as *const ManuallyDrop<_>).value })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a, A: Array> Drop for Drain<'a, A> {
    fn drop(&mut self) {
        // exhaust self first
        while let Some(_) = self.next() {}

        if self.tail_len > 0 {
            unsafe {
                let source_array_vec = &mut **self.array_vec;
                // memmove back untouched tail, update to new length
                let start = source_array_vec.len();
                let tail = self.tail_start;
                {
                    let mut arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>];
                    let src = arr.as_ptr().offset(tail as isize);
                    let dst = arr.as_mut_ptr().offset(start as isize);
                    ptr::copy(src, dst, self.tail_len);
                };
                source_array_vec.set_len(start + self.tail_len);
            }
        }
    }
}

impl IntoIterator for ArrayVec {
    type Item = A::Element;
    type IntoIter = Iter;
    fn into_iter(self) -> Self::IntoIter {
        let store = unsafe {
            ptr::read(&self.values)
        };
        let indices = 0..self.count;
        mem::forget(self);
        Iter {
            indices: indices,
            store: store,
        }
    }
}

impl<'a, A: Array> IntoIterator for &'a ArrayVec {
    type Item = &'a A::Element;
    type IntoIter = slice::Iter<'a, A::Element>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, A: Array> IntoIterator for &'a mut ArrayVec {
    type Item = &'a mut A::Element;
    type IntoIter = slice::IterMut<'a, A::Element>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

// FIXME: This should use repr(transparent) from rust-lang/rfcs#1758.
#[allow(unions_with_drop_fields)]
pub union ManuallyDrop<T> {
    value: T,
    #[allow(dead_code)]
    empty: (),
}

impl<T> ManuallyDrop<T> {
    fn new() -> ManuallyDrop<T> {
        ManuallyDrop {
            empty: ()
        }
    }
}

impl<T> Default for ManuallyDrop<T> {
    fn default() -> Self {
        ManuallyDrop::new()
    }
}

<commit_msg>update array_vec to use new rangeargument<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.

//! A stack-allocated vector, allowing storage of N elements on the stack.

use std::marker::Unsize;
use std::iter::Extend;
use std::ptr::{self, drop_in_place, Shared};
use std::ops::{Deref, DerefMut, Range};
use std::hash::{Hash, Hasher};
use std::slice;
use std::fmt;
use std::mem;
use std::collections::range::RangeArgument;

pub unsafe trait Array {
    type Element;
    type PartialStorage: Default + Unsize<[ManuallyDrop<Self::Element>]>;
    const LEN: usize;
}

unsafe impl<T> Array for [T; 1] {
    type Element = T;
    type PartialStorage = [ManuallyDrop<T>; 1];
    const LEN: usize = 1;
}

unsafe impl<T> Array for [T; 8] {
    type Element = T;
    type PartialStorage = [ManuallyDrop<T>; 8];
    const LEN: usize = 8;
}

pub struct ArrayVec {
    count: usize,
    values: A::PartialStorage
}

impl Hash for ArrayVec
    where A: Array,
          A::Element: Hash {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        (&self[..]).hash(state);
    }
}

impl PartialEq for ArrayVec {
    fn eq(&self, other: &Self) -> bool {
        self == other
    }
}

impl Eq for ArrayVec {}

impl Clone for ArrayVec
    where A: Array,
          A::Element: Clone {
    fn clone(&self) -> Self {
        let mut v = ArrayVec::new();
        v.extend(self.iter().cloned());
        v
    }
}

impl ArrayVec {
    pub fn new() -> Self {
        ArrayVec {
            count: 0,
            values: Default::default(),
        }
    }

    pub fn len(&self) -> usize {
        self.count
    }

    pub unsafe fn set_len(&mut self, len: usize) {
        self.count = len;
    }

    /// Panics when the stack vector is full.
    pub fn push(&mut self, el: A::Element) {
        let arr = &mut self.values as &mut [ManuallyDrop<_>];
        arr[self.count] = ManuallyDrop { value: el };
        self.count += 1;
    }

    pub fn pop(&mut self) -> Option {
        if self.count > 0 {
            let arr = &mut self.values as &mut [ManuallyDrop<_>];
            self.count -= 1;
            unsafe {
                let value = ptr::read(&arr[self.count]);
                Some(value.value)
            }
        } else {
            None
        }
    }

    pub fn drain<R>(&mut self, range: R) -> Drain
        where R: RangeArgument<usize>
    {
        // Memory safety
        //
        // When the Drain is first created, it shortens the length of
        // the source vector to make sure no uninitalized or moved-from elements
        // are accessible at all if the Drain's destructor never gets to run.
        //
        // Drain will ptr::read out the values to remove.
        // When finished, remaining tail of the vec is copied back to cover
        // the hole, and the vector length is restored to the new length.
        //
        let len = self.len();
        let start = match range.start() {
            Included(&n) => n,
            Excluded(&n) => n + 1,
            Unbounded    => 0,
        };
        let end = match range.end() {
            Included(&n) => n + 1,
            Excluded(&n) => n,
            Unbounded    => len,
        };
        assert!(start <= end);
        assert!(end <= len);

        unsafe {
            // set self.vec length's to start, to be safe in case Drain is leaked
            self.set_len(start);
            // Use the borrow in the IterMut to indicate borrowing behavior of the
            // whole Drain iterator (like &mut T).
            let range_slice = {
                let arr = &mut self.values as &mut [ManuallyDrop<_>];
                slice::from_raw_parts_mut(arr.as_mut_ptr().offset(start as isize),
                                          end - start)
            };
            Drain {
                tail_start: end,
                tail_len: len - end,
                iter: range_slice.iter(),
                array_vec: Shared::new(self as *mut _),
            }
        }
    }
}

impl Default for ArrayVec
    where A: Array {
    fn default() -> Self {
        ArrayVec::new()
    }
}

impl fmt::Debug for ArrayVec
    where A: Array,
          A::Element: fmt::Debug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self[..].fmt(f)
    }
}

impl Deref for ArrayVec {
    type Target = [A::Element];
    fn deref(&self) -> &Self::Target {
        unsafe {
            slice::from_raw_parts(&self.values as *const _ as *const A::Element, self.count)
        }
    }
}

impl DerefMut for ArrayVec {
    fn deref_mut(&mut self) -> &mut [A::Element] {
        unsafe {
            slice::from_raw_parts_mut(&mut self.values as *mut _ as *mut A::Element, self.count)
        }
    }
}

impl Drop for ArrayVec {
    fn drop(&mut self) {
        unsafe {
            drop_in_place(&mut self[..])
        }
    }
}

impl Extend for ArrayVec {
    fn extend(&mut self, iter: I) where I: IntoIterator<Item=A::Element> {
        for el in iter {
            self.push(el);
        }
    }
}

pub struct Iter {
    indices: Range<usize>,
    store: A::PartialStorage,
}

impl Drop for Iter {
    fn drop(&mut self) {
        for _ in self {}
    }
}

impl Iterator for Iter {
    type Item = A::Element;

    fn next(&mut self) -> Option {
        let arr = &self.store as &[ManuallyDrop<_>];
        unsafe {
            self.indices.next().map(|i| ptr::read(&arr[i]).value)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.indices.size_hint()
    }
}

pub struct Drain<'a, A: Array>
        where A::Element: 'a
{
    tail_start: usize,
    tail_len: usize,
    iter: slice::Iter<'a, ManuallyDrop>,
    array_vec: Shared<ArrayVec>,
}

impl<'a, A: Array> Iterator for Drain<'a, A> {
    type Item = A::Element;

    #[inline]
    fn next(&mut self) -> Option {
        self.iter.next().map(|elt| unsafe { ptr::read(elt as *const ManuallyDrop<_>).value })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a, A: Array> Drop for Drain<'a, A> {
    fn drop(&mut self) {
        // exhaust self first
        while let Some(_) = self.next() {}

        if self.tail_len > 0 {
            unsafe {
                let source_array_vec = &mut **self.array_vec;
                // memmove back untouched tail, update to new length
                let start = source_array_vec.len();
                let tail = self.tail_start;
                {
                    let mut arr = &mut source_array_vec.values as &mut [ManuallyDrop<_>];
                    let src = arr.as_ptr().offset(tail as isize);
                    let dst = arr.as_mut_ptr().offset(start as isize);
                    ptr::copy(src, dst, self.tail_len);
                };
                source_array_vec.set_len(start + self.tail_len);
            }
        }
    }
}

impl IntoIterator for ArrayVec {
    type Item = A::Element;
    type IntoIter = Iter;
    fn into_iter(self) -> Self::IntoIter {
        let store = unsafe {
            ptr::read(&self.values)
        };
        let indices = 0..self.count;
        mem::forget(self);
        Iter {
            indices: indices,
            store: store,
        }
    }
}

impl<'a, A: Array> IntoIterator for &'a ArrayVec {
    type Item = &'a A::Element;
    type IntoIter = slice::Iter<'a, A::Element>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, A: Array> IntoIterator for &'a mut ArrayVec {
    type Item = &'a mut A::Element;
    type IntoIter = slice::IterMut<'a, A::Element>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

// FIXME: This should use repr(transparent) from rust-lang/rfcs#1758.
#[allow(unions_with_drop_fields)]
pub union ManuallyDrop<T> {
    value: T,
    #[allow(dead_code)]
    empty: (),
}

impl<T> ManuallyDrop<T> {
    fn new() -> ManuallyDrop<T> {
        ManuallyDrop {
            empty: ()
        }
    }
}

impl<T> Default for ManuallyDrop<T> {
    fn default() -> Self {
        ManuallyDrop::new()
    }
}

<|endoftext|>