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

use core::{cmp, mem, ptr};
use core::sync::atomic::{AtomicBool, Ordering};

use drivers::disk::*;
use drivers::pio::*;
use drivers::pciconfig::PCIConfig;

use common::debug;
use common::queue::Queue;
use common::memory::{self, Memory};
use common::resource::{NoneResource, Resource, ResourceSeek, ResourceType, URL, VecResource};
use common::string::{String, ToString};
use common::vec::Vec;

use programs::session::SessionItem;

use syscall::call::sys_yield;

/// The header of the fs
#[repr(packed)]
pub struct Header {
    pub signature: [u8; 8],
    pub version: u32,
    pub name: [u8; 244],
    pub extents: [Extent; 16],
}

/// Data for a node
#[repr(packed)]
pub struct NodeData {
    pub name: [u8; 256],
    pub extents: [Extent; 16],
}

/// A file node
pub struct Node {
    pub address: u64,
    pub name: String,
    pub extents: [Extent; 16],
}

impl Node {
    /// Create a new file node from an address and some data
    pub fn new(address: u64, data: &NodeData) -> Self {
        let mut utf8: Vec<u8> = Vec::new();
        for i in 0..data.name.len() {
            let c = data.name[i];
            if c == 0 {
                break;
            } else {
                utf8.push(c);
            }
        }

        Node {
            address: address,
            name: String::from_utf8(&utf8),
            extents: data.extents,
        }
    }
}

impl Clone for Node {
    fn clone(&self) -> Self {
        Node {
            address: self.address,
            name: self.name.clone(),
            extents: self.extents,
        }
    }
}

/// A file system
pub struct FileSystem {
    pub disk: Disk,
    pub header: Header,
    pub nodes: Vec<Node>,
}

impl FileSystem {
    /// Create a file system from a disk
    pub fn from_disk(mut disk: Disk) -> Option<Self> {
        unsafe {
            if disk.identify() {
                debug::d(" Disk Found");

                let header_ptr = Memory::<Header>::new(1).unwrap();
                disk.read(1, 1, header_ptr.address());
                let header = header_ptr.read(0);
                drop(header_ptr);

                if header.signature[0] == 'R' as u8 && header.signature[1] == 'E' as u8 &&
                   header.signature[2] == 'D' as u8 &&
                   header.signature[3] == 'O' as u8 &&
                   header.signature[4] == 'X' as u8 &&
                   header.signature[5] == 'F' as u8 &&
                   header.signature[6] == 'S' as u8 &&
                   header.signature[7] == '\0' as u8 &&
                   header.version == 0xFFFFFFFF {

                    debug::d(" Redox Filesystem\n");

                    let mut nodes = Vec::new();
                    for extent in &header.extents {
                        if extent.block > 0 && extent.length > 0 {
                            if let Some(mut data) = Memory::<NodeData>::new(extent.length as usize /
                                                           mem::size_of::<NodeData>()) {
                                let sectors = (extent.length as usize + 511) / 512;
                                let mut sector: usize = 0;
                                while sectors - sector >= 65536 {
                                    let request = Request {
                                        extent: Extent {
                                            block: extent.block + sector as u64,
                                            length: 65536 * 512,
                                        },
                                        mem: data.address() + sector * 512,
                                        read: true,
                                        complete: Arc::new(AtomicBool::new(false)),
                                    };

                                    unsafe {
                                        disk.read(extent.block + sector as u64,
                                                  0,
                                                  data.address() + sector * 512);
                                    }

                                        /*
                                        disk.request(request.clone());

                                        while request.complete.load(Ordering::SeqCst) == false {
                                            disk.on_poll();
                                        }
                                        */

                                    sector += 65535;
                                }
                                if sector < sectors {
                                    let request = Request {
                                        extent: Extent {
                                            block: extent.block + sector as u64,
                                            length: (sectors - sector) as u64 * 512,
                                        },
                                        mem: data.address() + sector * 512,
                                        read: true,
                                        complete: Arc::new(AtomicBool::new(false)),
                                    };

                                    unsafe {
                                        disk.read(extent.block + sector as u64,
                                                  (sectors - sector) as u16,
                                                  data.address() + sector * 512);
                                    }
                                        /*
                                        disk.request(request.clone());

                                        while request.complete.load(Ordering::SeqCst) == false {
                                            disk.on_poll();
                                        }
                                        */
                                }

                                for i in 0..extent.length as usize / mem::size_of::<NodeData>() {
                                    nodes.push(Node::new(extent.block + i as u64, &data[i]));
                                }
                            }
                        }
                    }

                    return Some(FileSystem {
                        disk: disk,
                        header: header,
                        nodes: nodes,
                    });
                } else {
                    debug::d(" Unknown Filesystem\n");
                }
            } else {
                debug::d(" Disk Not Found\n");
            }
        }

        Option::None
    }

    /// Get node with a given filename
    pub fn node(&self, filename: &String) -> Option<Node> {
        for node in self.nodes.iter() {
            if node.name == *filename {
                return Option::Some(node.clone());
            }
        }

        Option::None
    }

    /// List nodes in a given directory
    pub fn list(&self, directory: &String) -> Vec<String> {
        let mut ret = Vec::<String>::new();

        for node in self.nodes.iter() {
            if node.name.starts_with(directory.clone()) {
                ret.push(node.name.substr(directory.len(), node.name.len() - directory.len()));
            }
        }

        ret
    }
}

/// A file resource
pub struct FileResource {
    pub scheme: *mut FileScheme,
    pub node: Node,
    pub vec: Vec<u8>,
    pub seek: usize,
    pub dirty: bool,
}

impl Resource for FileResource {
    fn url(&self) -> URL {
        URL::from_string(&("file:///".to_string() + &self.node.name))
    }

    fn stat(&self) -> ResourceType {
        ResourceType::File
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            match self.vec.get(self.seek) {
                Option::Some(b) => buf[i] = *b,
                Option::None => (),
            }
            self.seek += 1;
            i += 1;
        }
        Option::Some(i)
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            self.vec.set(self.seek, buf[i]);
            self.seek += 1;
            i += 1;
        }
        while i < buf.len() {
            self.vec.push(buf[i]);
            self.seek += 1;
            i += 1;
        }
        if i > 0 {
            self.dirty = true;
        }
        Option::Some(i)
    }

    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        match pos {
            ResourceSeek::Start(offset) => self.seek = offset,
            ResourceSeek::Current(offset) =>
                self.seek = cmp::max(0, self.seek as isize + offset) as usize,
            ResourceSeek::End(offset) =>
                self.seek = cmp::max(0, self.vec.len() as isize + offset) as usize,
        }
        while self.vec.len() < self.seek {
            self.vec.push(0);
        }
        Option::Some(self.seek)
    }

    // TODO: Rename to sync
    // TODO: Check to make sure proper amount of bytes written. See Disk::write
    // TODO: Allow reallocation
    fn sync(&mut self) -> bool {
        if self.dirty {
            let block_size: usize = 512;

            let mut node_dirty = false;
            let mut pos: isize = 0;
            let mut remaining = self.vec.len() as isize;
            for ref mut extent in &mut self.node.extents {
                //Make sure it is a valid extent
                if extent.block > 0 && extent.length > 0 {
                    let current_sectors = (extent.length as usize + block_size - 1) / block_size;
                    let max_size = current_sectors * 512;

                    let size = cmp::min(remaining as usize, max_size);
                    let sectors = (size + block_size - 1) / block_size;

                    if size as u64 != extent.length {
                        extent.length = size as u64;
                        node_dirty = true;
                    }

                    unsafe {
                        let data = self.vec.as_ptr().offset(pos) as usize;
                        //TODO: Make sure data is copied safely into an zeroed area of the right size!

                        let sectors = (extent.length as usize + 511) / 512;
                        let mut sector: usize = 0;
                        while sectors - sector >= 65536 {
                            let request = Request {
                                extent: Extent {
                                    block: extent.block + sector as u64,
                                    length: 65536 * 512,
                                },
                                mem: data + sector * 512,
                                read: false,
                                complete: Arc::new(AtomicBool::new(false)),
                            };

                            (*self.scheme).fs.disk.request(request.clone());

                            while request.complete.load(Ordering::SeqCst) == false {
                                sys_yield();
                            }

                            sector += 65535;
                        }
                        if sector < sectors {
                            let request = Request {
                                extent: Extent {
                                    block: extent.block + sector as u64,
                                    length: (sectors - sector) as u64 * 512,
                                },
                                mem: data + sector * 512,
                                read: false,
                                complete: Arc::new(AtomicBool::new(false)),
                            };

                            (*self.scheme).fs.disk.request(request.clone());

                            while request.complete.load(Ordering::SeqCst) == false {
                                sys_yield();
                            }
                        }
                    }

                    pos += size as isize;
                    remaining -= size as isize;
                }
            }

            if node_dirty {
                debug::d("Node dirty, should rewrite\n");
            }

            self.dirty = false;

            if remaining > 0 {
                debug::d("Need to reallocate file, extra: ");
                debug::ds(remaining);
                debug::dl();
                return false;
            }
        }
        true
    }
}

impl Drop for FileResource {
    fn drop(&mut self) {
        self.sync();
    }
}

/// A file scheme (pci + fs)
pub struct FileScheme {
    pci: PCIConfig,
    fs: FileSystem,
}

impl FileScheme {
    ///TODO Allow busmaster for secondary
    /// Create a new file scheme from a PCI configuration
    pub fn new(mut pci: PCIConfig) -> Option<Box<Self>> {
        unsafe { pci.flag(4, 4, true) }; // Bus mastering

        let base = unsafe { pci.read(0x20) } as u16 & 0xFFF0;

        debug::d("IDE on ");
        debug::dh(base as usize);
        debug::dl();

        debug::d("Primary Master:");
        if let Some(fs) = FileSystem::from_disk(Disk::primary_master(base)) {
            return Some(box FileScheme {
                pci: pci,
                fs: fs,
            });
        }

        debug::d("Primary Slave:");
        if let Some(fs) = FileSystem::from_disk(Disk::primary_slave(base)) {
            return Some(box FileScheme {
                pci: pci,
                fs: fs,
            });
        }

        debug::d("Secondary Master:");
        if let Some(fs) = FileSystem::from_disk(Disk::secondary_master(base)) {
            return Some(box FileScheme {
                pci: pci,
                fs: fs,
            });
        }

        debug::d("Secondary Slave:");
        if let Some(fs) = FileSystem::from_disk(Disk::secondary_slave(base)) {
            return Some(box FileScheme {
                pci: pci,
                fs: fs,
            });
        }

        None
    }
}

impl SessionItem for FileScheme {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.fs.disk.irq {
            self.on_poll();
        }
    }

    fn on_poll(&mut self) {
        unsafe {
            self.fs.disk.on_poll();
        }
    }

    fn scheme(&self) -> String {
        return "file".to_string();
    }

    fn open(&mut self, url: &URL) -> Box<Resource> {
        let path = url.path();
        if path.len() == 0 || path.ends_with("/".to_string()) {
            let mut list = String::new();
            let mut dirs: Vec<String> = Vec::new();

            for file in self.fs.list(&path).iter() {
                let line;
                match file.find("/".to_string()) {
                    Option::Some(index) => {
                        let dirname = file.substr(0, index + 1);
                        let mut found = false;
                        for dir in dirs.iter() {
                            if dirname == *dir {
                                found = true;
                                break;
                            }
                        }
                        if found {
                            line = String::new();
                        } else {
                            line = dirname.clone();
                            dirs.push(dirname);
                        }
                    }
                    Option::None => line = file.clone(),
                }
                if line.len() > 0 {
                    if list.len() > 0 {
                        list = list + '\n' + line;
                    } else {
                        list = line;
                    }
                }
            }

            return box VecResource::new(url.clone(), ResourceType::Dir, list.to_utf8());
        } else {
            match self.fs.node(&path) {
                Option::Some(node) => {
                    let mut vec: Vec<u8> = Vec::new();
                    //TODO: Handle more extents
                    for extent in &node.extents {
                        if extent.block > 0 && extent.length > 0 {
                            if let Some(mut data) = Memory::<u8>::new(extent.length as usize) {
                                let sectors = (extent.length as usize + 511) / 512;
                                let mut sector: usize = 0;
                                while sectors - sector >= 65536 {
                                    let request = Request {
                                        extent: Extent {
                                            block: extent.block + sector as u64,
                                            length: 65536 * 512,
                                        },
                                        mem: unsafe { data.address() } + sector * 512,
                                        read: true,
                                        complete: Arc::new(AtomicBool::new(false)),
                                    };

                                    unsafe {
                                        self.fs.disk.request(request.clone());
                                    }

                                    while request.complete.load(Ordering::SeqCst) == false {
                                        sys_yield();
                                    }

                                    sector += 65535;
                                }
                                if sector < sectors {
                                    let request = Request {
                                        extent: Extent {
                                            block: extent.block + sector as u64,
                                            length: (sectors - sector) as u64 * 512,
                                        },
                                        mem: unsafe { data.address() } + sector * 512,
                                        read: true,
                                        complete: Arc::new(AtomicBool::new(false)),
                                    };

                                    unsafe {
                                        self.fs.disk.request(request.clone());
                                    }

                                    while request.complete.load(Ordering::SeqCst) == false {
                                        sys_yield();
                                    }
                                }

                                vec.push_all(&Vec {
                                    data: unsafe { data.into_raw() },
                                    length: extent.length as usize,
                                });
                            }
                        }
                    }

                    return box FileResource {
                        scheme: self,
                        node: node,
                        vec: vec,
                        seek: 0,
                        dirty: false,
                    };
                }
                Option::None => {
                    return box NoneResource;
                }
            }
        }
    }
}
<commit_msg>Remove unnessesary unsafe blocks<commit_after>use alloc::arc::Arc;
use alloc::boxed::Box;

use core::{cmp, mem, ptr};
use core::sync::atomic::{AtomicBool, Ordering};

use drivers::disk::*;
use drivers::pio::*;
use drivers::pciconfig::PCIConfig;

use common::debug;
use common::queue::Queue;
use common::memory::{self, Memory};
use common::resource::{NoneResource, Resource, ResourceSeek, ResourceType, URL, VecResource};
use common::string::{String, ToString};
use common::vec::Vec;

use programs::session::SessionItem;

use syscall::call::sys_yield;

/// The header of the fs
#[repr(packed)]
pub struct Header {
    pub signature: [u8; 8],
    pub version: u32,
    pub name: [u8; 244],
    pub extents: [Extent; 16],
}

/// Data for a node
#[repr(packed)]
pub struct NodeData {
    pub name: [u8; 256],
    pub extents: [Extent; 16],
}

/// A file node
pub struct Node {
    pub address: u64,
    pub name: String,
    pub extents: [Extent; 16],
}

impl Node {
    /// Create a new file node from an address and some data
    pub fn new(address: u64, data: &NodeData) -> Self {
        let mut utf8: Vec<u8> = Vec::new();
        for i in 0..data.name.len() {
            let c = data.name[i];
            if c == 0 {
                break;
            } else {
                utf8.push(c);
            }
        }

        Node {
            address: address,
            name: String::from_utf8(&utf8),
            extents: data.extents,
        }
    }
}

impl Clone for Node {
    fn clone(&self) -> Self {
        Node {
            address: self.address,
            name: self.name.clone(),
            extents: self.extents,
        }
    }
}

/// A file system
pub struct FileSystem {
    pub disk: Disk,
    pub header: Header,
    pub nodes: Vec<Node>,
}

impl FileSystem {
    /// Create a file system from a disk
    pub fn from_disk(mut disk: Disk) -> Option<Self> {
        unsafe {
            if disk.identify() {
                debug::d(" Disk Found");

                let header_ptr = Memory::<Header>::new(1).unwrap();
                disk.read(1, 1, header_ptr.address());
                let header = header_ptr.read(0);
                drop(header_ptr);

                if header.signature[0] == 'R' as u8 && header.signature[1] == 'E' as u8 &&
                   header.signature[2] == 'D' as u8 &&
                   header.signature[3] == 'O' as u8 &&
                   header.signature[4] == 'X' as u8 &&
                   header.signature[5] == 'F' as u8 &&
                   header.signature[6] == 'S' as u8 &&
                   header.signature[7] == '\0' as u8 &&
                   header.version == 0xFFFFFFFF {

                    debug::d(" Redox Filesystem\n");

                    let mut nodes = Vec::new();
                    for extent in &header.extents {
                        if extent.block > 0 && extent.length > 0 {
                            if let Some(mut data) = Memory::<NodeData>::new(extent.length as usize /
                                                           mem::size_of::<NodeData>()) {
                                let sectors = (extent.length as usize + 511) / 512;
                                let mut sector: usize = 0;
                                while sectors - sector >= 65536 {
                                    let request = Request {
                                        extent: Extent {
                                            block: extent.block + sector as u64,
                                            length: 65536 * 512,
                                        },
                                        mem: data.address() + sector * 512,
                                        read: true,
                                        complete: Arc::new(AtomicBool::new(false)),
                                    };

                                    disk.read(extent.block + sector as u64,
                                              0,
                                              data.address() + sector * 512);

                                        /*
                                        disk.request(request.clone());

                                        while request.complete.load(Ordering::SeqCst) == false {
                                            disk.on_poll();
                                        }
                                        */

                                    sector += 65535;
                                }
                                if sector < sectors {
                                    let request = Request {
                                        extent: Extent {
                                            block: extent.block + sector as u64,
                                            length: (sectors - sector) as u64 * 512,
                                        },
                                        mem: data.address() + sector * 512,
                                        read: true,
                                        complete: Arc::new(AtomicBool::new(false)),
                                    };

                                    unsafe {
                                        disk.read(extent.block + sector as u64,
                                                  (sectors - sector) as u16,
                                                  data.address() + sector * 512);
                                    }
                                        /*
                                        disk.request(request.clone());

                                        while request.complete.load(Ordering::SeqCst) == false {
                                            disk.on_poll();
                                        }
                                        */
                                }

                                for i in 0..extent.length as usize / mem::size_of::<NodeData>() {
                                    nodes.push(Node::new(extent.block + i as u64, &data[i]));
                                }
                            }
                        }
                    }

                    return Some(FileSystem {
                        disk: disk,
                        header: header,
                        nodes: nodes,
                    });
                } else {
                    debug::d(" Unknown Filesystem\n");
                }
            } else {
                debug::d(" Disk Not Found\n");
            }
        }

        Option::None
    }

    /// Get node with a given filename
    pub fn node(&self, filename: &String) -> Option<Node> {
        for node in self.nodes.iter() {
            if node.name == *filename {
                return Option::Some(node.clone());
            }
        }

        Option::None
    }

    /// List nodes in a given directory
    pub fn list(&self, directory: &String) -> Vec<String> {
        let mut ret = Vec::<String>::new();

        for node in self.nodes.iter() {
            if node.name.starts_with(directory.clone()) {
                ret.push(node.name.substr(directory.len(), node.name.len() - directory.len()));
            }
        }

        ret
    }
}

/// A file resource
pub struct FileResource {
    pub scheme: *mut FileScheme,
    pub node: Node,
    pub vec: Vec<u8>,
    pub seek: usize,
    pub dirty: bool,
}

impl Resource for FileResource {
    fn url(&self) -> URL {
        URL::from_string(&("file:///".to_string() + &self.node.name))
    }

    fn stat(&self) -> ResourceType {
        ResourceType::File
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            match self.vec.get(self.seek) {
                Option::Some(b) => buf[i] = *b,
                Option::None => (),
            }
            self.seek += 1;
            i += 1;
        }
        Option::Some(i)
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            self.vec.set(self.seek, buf[i]);
            self.seek += 1;
            i += 1;
        }
        while i < buf.len() {
            self.vec.push(buf[i]);
            self.seek += 1;
            i += 1;
        }
        if i > 0 {
            self.dirty = true;
        }
        Option::Some(i)
    }

    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        match pos {
            ResourceSeek::Start(offset) => self.seek = offset,
            ResourceSeek::Current(offset) =>
                self.seek = cmp::max(0, self.seek as isize + offset) as usize,
            ResourceSeek::End(offset) =>
                self.seek = cmp::max(0, self.vec.len() as isize + offset) as usize,
        }
        while self.vec.len() < self.seek {
            self.vec.push(0);
        }
        Option::Some(self.seek)
    }

    // TODO: Rename to sync
    // TODO: Check to make sure proper amount of bytes written. See Disk::write
    // TODO: Allow reallocation
    fn sync(&mut self) -> bool {
        if self.dirty {
            let block_size: usize = 512;

            let mut node_dirty = false;
            let mut pos: isize = 0;
            let mut remaining = self.vec.len() as isize;
            for ref mut extent in &mut self.node.extents {
                //Make sure it is a valid extent
                if extent.block > 0 && extent.length > 0 {
                    let current_sectors = (extent.length as usize + block_size - 1) / block_size;
                    let max_size = current_sectors * 512;

                    let size = cmp::min(remaining as usize, max_size);
                    let sectors = (size + block_size - 1) / block_size;

                    if size as u64 != extent.length {
                        extent.length = size as u64;
                        node_dirty = true;
                    }

                    unsafe {
                        let data = self.vec.as_ptr().offset(pos) as usize;
                        //TODO: Make sure data is copied safely into an zeroed area of the right size!

                        let sectors = (extent.length as usize + 511) / 512;
                        let mut sector: usize = 0;
                        while sectors - sector >= 65536 {
                            let request = Request {
                                extent: Extent {
                                    block: extent.block + sector as u64,
                                    length: 65536 * 512,
                                },
                                mem: data + sector * 512,
                                read: false,
                                complete: Arc::new(AtomicBool::new(false)),
                            };

                            (*self.scheme).fs.disk.request(request.clone());

                            while request.complete.load(Ordering::SeqCst) == false {
                                sys_yield();
                            }

                            sector += 65535;
                        }
                        if sector < sectors {
                            let request = Request {
                                extent: Extent {
                                    block: extent.block + sector as u64,
                                    length: (sectors - sector) as u64 * 512,
                                },
                                mem: data + sector * 512,
                                read: false,
                                complete: Arc::new(AtomicBool::new(false)),
                            };

                            (*self.scheme).fs.disk.request(request.clone());

                            while request.complete.load(Ordering::SeqCst) == false {
                                sys_yield();
                            }
                        }
                    }

                    pos += size as isize;
                    remaining -= size as isize;
                }
            }

            if node_dirty {
                debug::d("Node dirty, should rewrite\n");
            }

            self.dirty = false;

            if remaining > 0 {
                debug::d("Need to reallocate file, extra: ");
                debug::ds(remaining);
                debug::dl();
                return false;
            }
        }
        true
    }
}

impl Drop for FileResource {
    fn drop(&mut self) {
        self.sync();
    }
}

/// A file scheme (pci + fs)
pub struct FileScheme {
    pci: PCIConfig,
    fs: FileSystem,
}

impl FileScheme {
    ///TODO Allow busmaster for secondary
    /// Create a new file scheme from a PCI configuration
    pub fn new(mut pci: PCIConfig) -> Option<Box<Self>> {
        unsafe { pci.flag(4, 4, true) }; // Bus mastering

        let base = unsafe { pci.read(0x20) } as u16 & 0xFFF0;

        debug::d("IDE on ");
        debug::dh(base as usize);
        debug::dl();

        debug::d("Primary Master:");
        if let Some(fs) = FileSystem::from_disk(Disk::primary_master(base)) {
            return Some(box FileScheme {
                pci: pci,
                fs: fs,
            });
        }

        debug::d("Primary Slave:");
        if let Some(fs) = FileSystem::from_disk(Disk::primary_slave(base)) {
            return Some(box FileScheme {
                pci: pci,
                fs: fs,
            });
        }

        debug::d("Secondary Master:");
        if let Some(fs) = FileSystem::from_disk(Disk::secondary_master(base)) {
            return Some(box FileScheme {
                pci: pci,
                fs: fs,
            });
        }

        debug::d("Secondary Slave:");
        if let Some(fs) = FileSystem::from_disk(Disk::secondary_slave(base)) {
            return Some(box FileScheme {
                pci: pci,
                fs: fs,
            });
        }

        None
    }
}

impl SessionItem for FileScheme {
    fn on_irq(&mut self, irq: u8) {
        if irq == self.fs.disk.irq {
            self.on_poll();
        }
    }

    fn on_poll(&mut self) {
        unsafe {
            self.fs.disk.on_poll();
        }
    }

    fn scheme(&self) -> String {
        return "file".to_string();
    }

    fn open(&mut self, url: &URL) -> Box<Resource> {
        let path = url.path();
        if path.len() == 0 || path.ends_with("/".to_string()) {
            let mut list = String::new();
            let mut dirs: Vec<String> = Vec::new();

            for file in self.fs.list(&path).iter() {
                let line;
                match file.find("/".to_string()) {
                    Option::Some(index) => {
                        let dirname = file.substr(0, index + 1);
                        let mut found = false;
                        for dir in dirs.iter() {
                            if dirname == *dir {
                                found = true;
                                break;
                            }
                        }
                        if found {
                            line = String::new();
                        } else {
                            line = dirname.clone();
                            dirs.push(dirname);
                        }
                    }
                    Option::None => line = file.clone(),
                }
                if line.len() > 0 {
                    if list.len() > 0 {
                        list = list + '\n' + line;
                    } else {
                        list = line;
                    }
                }
            }

            return box VecResource::new(url.clone(), ResourceType::Dir, list.to_utf8());
        } else {
            match self.fs.node(&path) {
                Option::Some(node) => {
                    let mut vec: Vec<u8> = Vec::new();
                    //TODO: Handle more extents
                    for extent in &node.extents {
                        if extent.block > 0 && extent.length > 0 {
                            if let Some(mut data) = Memory::<u8>::new(extent.length as usize) {
                                let sectors = (extent.length as usize + 511) / 512;
                                let mut sector: usize = 0;
                                while sectors - sector >= 65536 {
                                    let request = Request {
                                        extent: Extent {
                                            block: extent.block + sector as u64,
                                            length: 65536 * 512,
                                        },
                                        mem: unsafe { data.address() } + sector * 512,
                                        read: true,
                                        complete: Arc::new(AtomicBool::new(false)),
                                    };

                                    self.fs.disk.request(request.clone());

                                    while request.complete.load(Ordering::SeqCst) == false {
                                        sys_yield();
                                    }

                                    sector += 65535;
                                }
                                if sector < sectors {
                                    let request = Request {
                                        extent: Extent {
                                            block: extent.block + sector as u64,
                                            length: (sectors - sector) as u64 * 512,
                                        },
                                        mem: unsafe { data.address() } + sector * 512,
                                        read: true,
                                        complete: Arc::new(AtomicBool::new(false)),
                                    };

                                    self.fs.disk.request(request.clone());

                                    while request.complete.load(Ordering::SeqCst) == false {
                                        sys_yield();
                                    }
                                }

                                vec.push_all(&Vec {
                                    data: unsafe { data.into_raw() },
                                    length: extent.length as usize,
                                });
                            }
                        }
                    }

                    return box FileResource {
                        scheme: self,
                        node: node,
                        vec: vec,
                        seek: 0,
                        dirty: false,
                    };
                }
                Option::None => {
                    return box NoneResource;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add test for issue 2214<commit_after>import libc::{c_double, c_int};

fn lgamma(n: c_double, value: &mut int) -> c_double {
  ret m::lgamma(n, value as &mut c_int);
}

#[link_name = "m"]
#[abi = "cdecl"]
native mod m {
    #[link_name="lgamma_r"] fn lgamma(n: c_double, sign: &mut c_int)
      -> c_double;
}

fn main() {
  let mut y: int = 5;
  let x: &mut int = &mut y;
  assert (lgamma(1.0 as c_double, x) == 42.0 as c_double);
}<|endoftext|>


<commit_before><commit_msg>Rollup merge of #70741 - DutchGhost:test-59023, r=Centril<commit_after>// check-pass

trait A {
    type Foo;
}

impl<T> A for T {
    type Foo = ();
}

fn foo() -> impl std::borrow::Borrow<<u8 as A>::Foo> {
    ()
}

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


<commit_before><commit_msg>smbus: add implementation for two remaining smbus fns<commit_after><|endoftext|>


<commit_before><commit_msg>Tidy up a bit<commit_after><|endoftext|>


<commit_before><commit_msg>Implement Drop for Owned<commit_after><|endoftext|>


<commit_before><commit_msg>Use Eq qualified<commit_after><|endoftext|>


<commit_before>use std::path::PathBuf;
use std::process::Command;
use std::env;
use std::io::stderr;
use std::io::Write;

pub use clap::App;

use clap::{Arg, ArgMatches};
use log;
use log::LogLevelFilter;

use configuration::Configuration;
use error::RuntimeError;
use error::RuntimeErrorKind;
use error::MapErrInto;
use logger::ImagLogger;

use libimagstore::store::Store;

#[derive(Debug)]
pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Option<Configuration>,
    cli_matches: ArgMatches<'a>,
    store: Store,
}

impl<'a> Runtime<'a> {

    /**
     * Gets the CLI spec for the program and retreives the config file path (or uses the default on
     * in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
     * and builds the Runtime object with it.
     *
     * The cli_spec object should be initially build with the ::get_default_cli_builder() function.
     *
     */
    pub fn new(cli_spec: App<'a, 'a>) -> Result<Runtime<'a>, RuntimeError> {
        use std::env;

        use libimagstore::hook::position::HookPosition as HP;
        use libimagstore::hook::Hook;
        use libimagstore::error::StoreErrorKind;
        use libimagstorestdhook::debug::DebugHook;
        use libimagerror::trace::trace_error;
        use libimagerror::trace::trace_error_dbg;
        use libimagerror::into::IntoError;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();

        let is_debugging = matches.is_present("debugging");
        let is_verbose   = matches.is_present("verbosity");
        let colored      = !matches.is_present("no-color-output");

        Runtime::init_logger(is_debugging, is_verbose, colored);

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map_or_else(|| {
                env::var("HOME")
                    .map(PathBuf::from)
                    .map(|mut p| { p.push(".imag"); p})
                    .unwrap_or_else(|_| {
                        panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
                    })
            }, PathBuf::from);
        let storepath = matches.value_of("storepath")
                                .map_or_else(|| {
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                }, PathBuf::from);

        let configpath = matches.value_of("config")
                                .map_or_else(|| rtp.clone(), PathBuf::from);

        let cfg = match Configuration::new(&configpath) {
            Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound {
                return Err(RuntimeErrorKind::Instantiate.into_error_with_cause(Box::new(e)));
            } else {
                warn!("No config file found.");
                warn!("Continuing without configuration file");
                None
            },

            Ok(mut cfg) => {
                if let Err(e) = cfg.override_config(get_override_specs(&matches)) {
                    error!("Could not apply config overrides");
                    trace_error(&e);

                    // TODO: continue question (interactive)
                }

                Some(cfg)
            }
        };

        let store_config = match cfg {
            Some(ref c) => c.store_config().cloned(),
            None        => None,
        };

        if is_debugging {
            write!(stderr(), "Config: {:?}\n", cfg).ok();
            write!(stderr(), "Store-config: {:?}\n", store_config).ok();
        }

        Store::new(storepath, store_config).map(|mut store| {
            // If we are debugging, generate hooks for all positions
            if is_debugging {
                let hooks : Vec<(Box<Hook>, &str, HP)> = vec![
                    (Box::new(DebugHook::new(HP::PreCreate))          , "debug", HP::PreCreate),
                    (Box::new(DebugHook::new(HP::PostCreate))         , "debug", HP::PostCreate),
                    (Box::new(DebugHook::new(HP::PreRetrieve))        , "debug", HP::PreRetrieve),
                    (Box::new(DebugHook::new(HP::PostRetrieve))       , "debug", HP::PostRetrieve),
                    (Box::new(DebugHook::new(HP::PreUpdate))          , "debug", HP::PreUpdate),
                    (Box::new(DebugHook::new(HP::PostUpdate))         , "debug", HP::PostUpdate),
                    (Box::new(DebugHook::new(HP::PreDelete))          , "debug", HP::PreDelete),
                    (Box::new(DebugHook::new(HP::PostDelete))         , "debug", HP::PostDelete),
                ];

                // If hook registration fails, trace the error and warn, but continue.
                for (hook, aspectname, position) in hooks {
                    if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) {
                        if e.err_type() == StoreErrorKind::HookRegisterError {
                            trace_error_dbg(&e);
                            warn!("Registering debug hook with store failed");
                        } else {
                            trace_error(&e);
                        };
                    }
                }
            }

            Runtime {
                cli_matches: matches,
                configuration: cfg,
                rtp: rtp,
                store: store,
            }
        })
        .map_err_into(RuntimeErrorKind::Instantiate)
    }

    /**
     * Get a commandline-interface builder object from `clap`
     *
     * This commandline interface builder object already contains some predefined interface flags:
     *   * -v | --verbose for verbosity
     *   * --debug for debugging
     *   * -c <file> | --config <file> for alternative configuration file
     *   * -r <path> | --rtp <path> for alternative runtimepath
     *   * --store <path> for alternative store path
     * Each has the appropriate help text included.
     *
     * The `appname` shall be "imag-<command>".
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a>
    {
        App::new(appname)
            .version(version)
            .author("Matthias Beyer <mail@beyermatthias.de>")
            .about(about)
            .arg(Arg::with_name(Runtime::arg_verbosity_name())
                .short("v")
                .long("verbose")
                .help("Enables verbosity")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_debugging_name())
                .long("debug")
                .help("Enables debugging output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_no_color_output_name())
                .long("no-color")
                .help("Disable color output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_config_name())
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_config_override_name())
                 .long("override-config")
                 .help("Override a configuration settings. Use 'key=value' pairs, where the key is a path in the TOML configuration. The value must be present in the configuration and be convertible to the type of the configuration setting. If the argument does not contain a '=', it gets ignored. Setting Arrays and Tables is not yet supported.")
                 .required(false)
                 .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_runtimepath_name())
                .long("rtp")
                .help("Alternative runtimepath")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_storepath_name())
                .long("store")
                .help("Alternative storepath. Must be specified as full path, can be outside of the RTP")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_editor_name())
                .long("editor")
                .help("Set editor")
                .required(false)
                .takes_value(true))
    }

    pub fn arg_names() -> Vec<&'static str> {
        vec![
            Runtime::arg_verbosity_name(),
            Runtime::arg_debugging_name(),
            Runtime::arg_no_color_output_name(),
            Runtime::arg_config_name(),
            Runtime::arg_config_override_name(),
            Runtime::arg_runtimepath_name(),
            Runtime::arg_storepath_name(),
            Runtime::arg_editor_name(),
        ]
    }

    pub fn arg_verbosity_name() -> &'static str {
        "verbosity"
    }

    pub fn arg_debugging_name() -> &'static str {
        "debugging"
    }

    pub fn arg_no_color_output_name() -> &'static str {
        "no-color-output"
    }

    pub fn arg_config_name() -> &'static str {
        "config"
    }

    pub fn arg_config_override_name() -> &'static str {
        "config-override"
    }

    pub fn arg_runtimepath_name() -> &'static str {
        "runtimepath"
    }

    pub fn arg_storepath_name() -> &'static str {
        "storepath"
    }

    pub fn arg_editor_name() -> &'static str {
        "editor"
    }

    /**
     * Initialize the internal logger
     */
    fn init_logger(is_debugging: bool, is_verbose: bool, colored: bool) {
        use std::env::var as env_var;
        use env_logger;

        if env_var("IMAG_LOG_ENV").is_ok() {
            env_logger::init().unwrap();
        } else {
            let lvl = if is_debugging {
                LogLevelFilter::Debug
            } else if is_verbose {
                LogLevelFilter::Info
            } else {
                LogLevelFilter::Warn
            };

            log::set_logger(|max_log_lvl| {
                max_log_lvl.set(lvl);
                debug!("Init logger with {}", lvl);
                Box::new(ImagLogger::new(lvl.to_log_level().unwrap()).with_color(colored))
            })
            .map_err(|_| {
                panic!("Could not setup logger");
            })
            .ok();
        }
    }

    /**
     * Get the verbosity flag value
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    /**
     * Get the debugging flag value
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    /**
     * Get the runtimepath
     */
    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    /**
     * Get the commandline interface matches
     */
    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    /**
     * Get the configuration object
     */
    pub fn config(&self) -> Option<&Configuration> {
        self.configuration.as_ref()
    }

    /**
     * Get the store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

    pub fn editor(&self) -> Option<Command> {
        self.cli()
            .value_of("editor")
            .map(String::from)
            .or({
                match self.configuration {
                    Some(ref c) => c.editor().cloned(),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

fn get_override_specs(matches: &ArgMatches) -> Vec<String> {
    matches
        .values_of("config-override")
        .map(|values| {
             values
             .filter(|s| {
                 let b = s.contains("=");
                 if !b { warn!("override '{}' does not contain '=' - will be ignored!", s); }
                 b
             })
             .map(String::from)
             .collect()
        })
        .unwrap_or(vec![])
}

<commit_msg>Add git hooks in the runtime setup code<commit_after>use std::path::PathBuf;
use std::process::Command;
use std::env;
use std::io::stderr;
use std::io::Write;

pub use clap::App;

use clap::{Arg, ArgMatches};
use log;
use log::LogLevelFilter;

use configuration::Configuration;
use error::RuntimeError;
use error::RuntimeErrorKind;
use error::MapErrInto;
use logger::ImagLogger;

use libimagstore::store::Store;

#[derive(Debug)]
pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Option<Configuration>,
    cli_matches: ArgMatches<'a>,
    store: Store,
}

impl<'a> Runtime<'a> {

    /**
     * Gets the CLI spec for the program and retreives the config file path (or uses the default on
     * in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
     * and builds the Runtime object with it.
     *
     * The cli_spec object should be initially build with the ::get_default_cli_builder() function.
     *
     */
    pub fn new(cli_spec: App<'a, 'a>) -> Result<Runtime<'a>, RuntimeError> {
        use std::env;

        use libimagstore::hook::position::HookPosition as HP;
        use libimagstore::hook::Hook;
        use libimagstore::error::StoreErrorKind;
        use libimagstorestdhook::debug::DebugHook;
        use libimagstorestdhook::vcs::git::create::CreateHook as GitCreateHook;
        use libimagstorestdhook::vcs::git::delete::DeleteHook as GitDeleteHook;
        use libimagstorestdhook::vcs::git::retrieve::RetrieveHook as GitRetrieveHook;
        use libimagstorestdhook::vcs::git::update::UpdateHook as GitUpdateHook;
        use libimagerror::trace::trace_error;
        use libimagerror::trace::trace_error_dbg;
        use libimagerror::into::IntoError;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();

        let is_debugging = matches.is_present("debugging");
        let is_verbose   = matches.is_present("verbosity");
        let colored      = !matches.is_present("no-color-output");

        Runtime::init_logger(is_debugging, is_verbose, colored);

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map_or_else(|| {
                env::var("HOME")
                    .map(PathBuf::from)
                    .map(|mut p| { p.push(".imag"); p})
                    .unwrap_or_else(|_| {
                        panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
                    })
            }, PathBuf::from);
        let storepath = matches.value_of("storepath")
                                .map_or_else(|| {
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                }, PathBuf::from);

        let configpath = matches.value_of("config")
                                .map_or_else(|| rtp.clone(), PathBuf::from);

        let cfg = match Configuration::new(&configpath) {
            Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound {
                return Err(RuntimeErrorKind::Instantiate.into_error_with_cause(Box::new(e)));
            } else {
                warn!("No config file found.");
                warn!("Continuing without configuration file");
                None
            },

            Ok(mut cfg) => {
                if let Err(e) = cfg.override_config(get_override_specs(&matches)) {
                    error!("Could not apply config overrides");
                    trace_error(&e);

                    // TODO: continue question (interactive)
                }

                Some(cfg)
            }
        };

        let store_config = match cfg {
            Some(ref c) => c.store_config().cloned(),
            None        => None,
        };

        if is_debugging {
            write!(stderr(), "Config: {:?}\n", cfg).ok();
            write!(stderr(), "Store-config: {:?}\n", store_config).ok();
        }

        Store::new(storepath, store_config).map(|mut store| {
            // If we are debugging, generate hooks for all positions
            if is_debugging {
                let hooks : Vec<(Box<Hook>, &str, HP)> = vec![
                    (Box::new(DebugHook::new(HP::PreCreate))          , "debug", HP::PreCreate),
                    (Box::new(DebugHook::new(HP::PostCreate))         , "debug", HP::PostCreate),
                    (Box::new(DebugHook::new(HP::PreRetrieve))        , "debug", HP::PreRetrieve),
                    (Box::new(DebugHook::new(HP::PostRetrieve))       , "debug", HP::PostRetrieve),
                    (Box::new(DebugHook::new(HP::PreUpdate))          , "debug", HP::PreUpdate),
                    (Box::new(DebugHook::new(HP::PostUpdate))         , "debug", HP::PostUpdate),
                    (Box::new(DebugHook::new(HP::PreDelete))          , "debug", HP::PreDelete),
                    (Box::new(DebugHook::new(HP::PostDelete))         , "debug", HP::PostDelete),

                    (Box::new(GitCreateHook::new(HP::PostCreate))     , "vcs",   HP::PostCreate),
                    (Box::new(GitDeleteHook::new(HP::PreDelete))      , "vcs",   HP::PreDelete),
                    (Box::new(GitRetrieveHook::new(HP::PostRetrieve)) , "vcs",   HP::PostRetrieve),
                    (Box::new(GitUpdateHook::new(HP::PostUpdate))     , "vcs",   HP::PostUpdate),
                ];

                // If hook registration fails, trace the error and warn, but continue.
                for (hook, aspectname, position) in hooks {
                    if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) {
                        if e.err_type() == StoreErrorKind::HookRegisterError {
                            trace_error_dbg(&e);
                            warn!("Registering debug hook with store failed");
                        } else {
                            trace_error(&e);
                        };
                    }
                }
            }

            Runtime {
                cli_matches: matches,
                configuration: cfg,
                rtp: rtp,
                store: store,
            }
        })
        .map_err_into(RuntimeErrorKind::Instantiate)
    }

    /**
     * Get a commandline-interface builder object from `clap`
     *
     * This commandline interface builder object already contains some predefined interface flags:
     *   * -v | --verbose for verbosity
     *   * --debug for debugging
     *   * -c <file> | --config <file> for alternative configuration file
     *   * -r <path> | --rtp <path> for alternative runtimepath
     *   * --store <path> for alternative store path
     * Each has the appropriate help text included.
     *
     * The `appname` shall be "imag-<command>".
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a>
    {
        App::new(appname)
            .version(version)
            .author("Matthias Beyer <mail@beyermatthias.de>")
            .about(about)
            .arg(Arg::with_name(Runtime::arg_verbosity_name())
                .short("v")
                .long("verbose")
                .help("Enables verbosity")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_debugging_name())
                .long("debug")
                .help("Enables debugging output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_no_color_output_name())
                .long("no-color")
                .help("Disable color output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_config_name())
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_config_override_name())
                 .long("override-config")
                 .help("Override a configuration settings. Use 'key=value' pairs, where the key is a path in the TOML configuration. The value must be present in the configuration and be convertible to the type of the configuration setting. If the argument does not contain a '=', it gets ignored. Setting Arrays and Tables is not yet supported.")
                 .required(false)
                 .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_runtimepath_name())
                .long("rtp")
                .help("Alternative runtimepath")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_storepath_name())
                .long("store")
                .help("Alternative storepath. Must be specified as full path, can be outside of the RTP")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_editor_name())
                .long("editor")
                .help("Set editor")
                .required(false)
                .takes_value(true))
    }

    pub fn arg_names() -> Vec<&'static str> {
        vec![
            Runtime::arg_verbosity_name(),
            Runtime::arg_debugging_name(),
            Runtime::arg_no_color_output_name(),
            Runtime::arg_config_name(),
            Runtime::arg_config_override_name(),
            Runtime::arg_runtimepath_name(),
            Runtime::arg_storepath_name(),
            Runtime::arg_editor_name(),
        ]
    }

    pub fn arg_verbosity_name() -> &'static str {
        "verbosity"
    }

    pub fn arg_debugging_name() -> &'static str {
        "debugging"
    }

    pub fn arg_no_color_output_name() -> &'static str {
        "no-color-output"
    }

    pub fn arg_config_name() -> &'static str {
        "config"
    }

    pub fn arg_config_override_name() -> &'static str {
        "config-override"
    }

    pub fn arg_runtimepath_name() -> &'static str {
        "runtimepath"
    }

    pub fn arg_storepath_name() -> &'static str {
        "storepath"
    }

    pub fn arg_editor_name() -> &'static str {
        "editor"
    }

    /**
     * Initialize the internal logger
     */
    fn init_logger(is_debugging: bool, is_verbose: bool, colored: bool) {
        use std::env::var as env_var;
        use env_logger;

        if env_var("IMAG_LOG_ENV").is_ok() {
            env_logger::init().unwrap();
        } else {
            let lvl = if is_debugging {
                LogLevelFilter::Debug
            } else if is_verbose {
                LogLevelFilter::Info
            } else {
                LogLevelFilter::Warn
            };

            log::set_logger(|max_log_lvl| {
                max_log_lvl.set(lvl);
                debug!("Init logger with {}", lvl);
                Box::new(ImagLogger::new(lvl.to_log_level().unwrap()).with_color(colored))
            })
            .map_err(|_| {
                panic!("Could not setup logger");
            })
            .ok();
        }
    }

    /**
     * Get the verbosity flag value
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    /**
     * Get the debugging flag value
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    /**
     * Get the runtimepath
     */
    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    /**
     * Get the commandline interface matches
     */
    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    /**
     * Get the configuration object
     */
    pub fn config(&self) -> Option<&Configuration> {
        self.configuration.as_ref()
    }

    /**
     * Get the store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

    pub fn editor(&self) -> Option<Command> {
        self.cli()
            .value_of("editor")
            .map(String::from)
            .or({
                match self.configuration {
                    Some(ref c) => c.editor().cloned(),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

fn get_override_specs(matches: &ArgMatches) -> Vec<String> {
    matches
        .values_of("config-override")
        .map(|values| {
             values
             .filter(|s| {
                 let b = s.contains("=");
                 if !b { warn!("override '{}' does not contain '=' - will be ignored!", s); }
                 b
             })
             .map(String::from)
             .collect()
        })
        .unwrap_or(vec![])
}

<|endoftext|>


<commit_before><commit_msg>Add Store::is_borrowed(StoreId)<commit_after><|endoftext|>


<commit_before><commit_msg>chore: some changes<commit_after><|endoftext|>


<commit_before>import ctypes::*;

#[abi = "cdecl"]
#[link_name = ""]
native mod libc {
    fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
    fn write(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
    fn fread(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
    fn fwrite(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
    #[link_name = "_open"]
    fn open(s: str::sbuf, flags: c_int, mode: unsigned) -> c_int;
    #[link_name = "_close"]
    fn close(fd: fd_t) -> c_int;
    type FILE;
    fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
    fn _fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
    fn fclose(f: FILE);
    fn fflush(f: FILE) -> c_int;
    fn fileno(f: FILE) -> fd_t;
    fn fgetc(f: FILE) -> c_int;
    fn ungetc(c: c_int, f: FILE);
    fn feof(f: FILE) -> c_int;
    fn fseek(f: FILE, offset: long, whence: c_int) -> c_int;
    fn ftell(f: FILE) -> long;
    fn _pipe(fds: *mutable fd_t, size: unsigned, mode: c_int) -> c_int;
}

mod libc_constants {
    const O_RDONLY: c_int    = 0i32;
    const O_WRONLY: c_int    = 1i32;
    const O_RDWR: c_int      = 2i32;
    const O_APPEND: c_int    = 8i32;
    const O_CREAT: c_int     = 256i32;
    const O_EXCL: c_int      = 1024i32;
    const O_TRUNC: c_int     = 512i32;
    const O_TEXT: c_int      = 16384i32;
    const O_BINARY: c_int    = 32768i32;
    const O_NOINHERIT: c_int = 128i32;
    const S_IRUSR: unsigned  = 256u32; // really _S_IREAD  in win32
    const S_IWUSR: unsigned  = 128u32; // really _S_IWRITE in win32
}

type DWORD = u32;
type HMODULE = uint;
type LPTSTR = str::sbuf;
type LPCTSTR = str::sbuf;

#[abi = "stdcall"]
native mod kernel32 {
    type LPSECURITY_ATTRIBUTES;
    fn GetEnvironmentVariableA(n: str::sbuf, v: str::sbuf, nsize: uint) ->
       uint;
    fn SetEnvironmentVariableA(n: str::sbuf, v: str::sbuf) -> int;
    fn GetModuleFileNameA(hModule: HMODULE,
                          lpFilename: LPTSTR,
                          nSize: DWORD) -> DWORD;
    fn CreateDirectoryA(lpPathName: LPCTSTR,
                        lpSecurityAttributes: LPSECURITY_ATTRIBUTES) -> bool;
    fn RemoveDirectoryA(lpPathName: LPCTSTR) -> bool;
    fn SetCurrentDirectoryA(lpPathName: LPCTSTR) -> bool;
}

// FIXME turn into constants
fn exec_suffix() -> str { ret ".exe"; }
fn target_os() -> str { ret "win32"; }

fn dylib_filename(base: str) -> str { ret base + ".dll"; }

fn pipe() -> {in: fd_t, out: fd_t} {
    // Windows pipes work subtly differently than unix pipes, and their
    // inheritance has to be handled in a different way that I don't fully
    // understand. Here we explicitly make the pipe non-inheritable,
    // which means to pass it to a subprocess they need to be duplicated
    // first, as in rust_run_program.
    let fds = {mutable in: 0i32, mutable out: 0i32};
    let res =
        os::libc::_pipe(ptr::mut_addr_of(fds.in), 1024u32,
                        libc_constants::O_BINARY |
                            libc_constants::O_NOINHERIT);
    assert (res == 0i32);
    assert (fds.in != -1i32 && fds.in != 0i32);
    assert (fds.out != -1i32 && fds.in != 0i32);
    ret {in: fds.in, out: fds.out};
}

fn fd_FILE(fd: fd_t) -> libc::FILE {
    ret str::as_buf("r", {|modebuf| libc::_fdopen(fd, modebuf) });
}

fn close(fd: fd_t) -> c_int {
    libc::close(fd)
}

fn fclose(file: libc::FILE) {
    libc::fclose(file)
}

fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
    // FIXME
}

#[abi = "cdecl"]
native mod rustrt {
    fn rust_process_wait(handle: c_int) -> c_int;
    fn rust_getcwd() -> str;
}

fn waitpid(pid: pid_t) -> i32 { ret rustrt::rust_process_wait(pid); }

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

fn get_exe_path() -> option::t<fs::path> {
    // FIXME: This doesn't handle the case where the buffer is too small
    let bufsize = 1023u;
    let path = str::unsafe_from_bytes(vec::init_elt(0u8, bufsize));
    ret str::as_buf(path, { |path_buf|
        if kernel32::GetModuleFileNameA(0u, path_buf,
                                        bufsize as u32) != 0u32 {
            option::some(fs::dirname(path) + fs::path_sep())
        } else {
            option::none
        }
    });
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>stdlib: Add issue number to win32 fsync FIXME<commit_after>import ctypes::*;

#[abi = "cdecl"]
#[link_name = ""]
native mod libc {
    fn read(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
    fn write(fd: fd_t, buf: *u8, count: size_t) -> ssize_t;
    fn fread(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
    fn fwrite(buf: *u8, size: size_t, n: size_t, f: libc::FILE) -> size_t;
    #[link_name = "_open"]
    fn open(s: str::sbuf, flags: c_int, mode: unsigned) -> c_int;
    #[link_name = "_close"]
    fn close(fd: fd_t) -> c_int;
    type FILE;
    fn fopen(path: str::sbuf, mode: str::sbuf) -> FILE;
    fn _fdopen(fd: fd_t, mode: str::sbuf) -> FILE;
    fn fclose(f: FILE);
    fn fflush(f: FILE) -> c_int;
    fn fileno(f: FILE) -> fd_t;
    fn fgetc(f: FILE) -> c_int;
    fn ungetc(c: c_int, f: FILE);
    fn feof(f: FILE) -> c_int;
    fn fseek(f: FILE, offset: long, whence: c_int) -> c_int;
    fn ftell(f: FILE) -> long;
    fn _pipe(fds: *mutable fd_t, size: unsigned, mode: c_int) -> c_int;
}

mod libc_constants {
    const O_RDONLY: c_int    = 0i32;
    const O_WRONLY: c_int    = 1i32;
    const O_RDWR: c_int      = 2i32;
    const O_APPEND: c_int    = 8i32;
    const O_CREAT: c_int     = 256i32;
    const O_EXCL: c_int      = 1024i32;
    const O_TRUNC: c_int     = 512i32;
    const O_TEXT: c_int      = 16384i32;
    const O_BINARY: c_int    = 32768i32;
    const O_NOINHERIT: c_int = 128i32;
    const S_IRUSR: unsigned  = 256u32; // really _S_IREAD  in win32
    const S_IWUSR: unsigned  = 128u32; // really _S_IWRITE in win32
}

type DWORD = u32;
type HMODULE = uint;
type LPTSTR = str::sbuf;
type LPCTSTR = str::sbuf;

#[abi = "stdcall"]
native mod kernel32 {
    type LPSECURITY_ATTRIBUTES;
    fn GetEnvironmentVariableA(n: str::sbuf, v: str::sbuf, nsize: uint) ->
       uint;
    fn SetEnvironmentVariableA(n: str::sbuf, v: str::sbuf) -> int;
    fn GetModuleFileNameA(hModule: HMODULE,
                          lpFilename: LPTSTR,
                          nSize: DWORD) -> DWORD;
    fn CreateDirectoryA(lpPathName: LPCTSTR,
                        lpSecurityAttributes: LPSECURITY_ATTRIBUTES) -> bool;
    fn RemoveDirectoryA(lpPathName: LPCTSTR) -> bool;
    fn SetCurrentDirectoryA(lpPathName: LPCTSTR) -> bool;
}

// FIXME turn into constants
fn exec_suffix() -> str { ret ".exe"; }
fn target_os() -> str { ret "win32"; }

fn dylib_filename(base: str) -> str { ret base + ".dll"; }

fn pipe() -> {in: fd_t, out: fd_t} {
    // Windows pipes work subtly differently than unix pipes, and their
    // inheritance has to be handled in a different way that I don't fully
    // understand. Here we explicitly make the pipe non-inheritable,
    // which means to pass it to a subprocess they need to be duplicated
    // first, as in rust_run_program.
    let fds = {mutable in: 0i32, mutable out: 0i32};
    let res =
        os::libc::_pipe(ptr::mut_addr_of(fds.in), 1024u32,
                        libc_constants::O_BINARY |
                            libc_constants::O_NOINHERIT);
    assert (res == 0i32);
    assert (fds.in != -1i32 && fds.in != 0i32);
    assert (fds.out != -1i32 && fds.in != 0i32);
    ret {in: fds.in, out: fds.out};
}

fn fd_FILE(fd: fd_t) -> libc::FILE {
    ret str::as_buf("r", {|modebuf| libc::_fdopen(fd, modebuf) });
}

fn close(fd: fd_t) -> c_int {
    libc::close(fd)
}

fn fclose(file: libc::FILE) {
    libc::fclose(file)
}

fn fsync_fd(fd: fd_t, level: io::fsync::level) -> c_int {
    // FIXME (1253)
}

#[abi = "cdecl"]
native mod rustrt {
    fn rust_process_wait(handle: c_int) -> c_int;
    fn rust_getcwd() -> str;
}

fn waitpid(pid: pid_t) -> i32 { ret rustrt::rust_process_wait(pid); }

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

fn get_exe_path() -> option::t<fs::path> {
    // FIXME: This doesn't handle the case where the buffer is too small
    let bufsize = 1023u;
    let path = str::unsafe_from_bytes(vec::init_elt(0u8, bufsize));
    ret str::as_buf(path, { |path_buf|
        if kernel32::GetModuleFileNameA(0u, path_buf,
                                        bufsize as u32) != 0u32 {
            option::some(fs::dirname(path) + fs::path_sep())
        } else {
            option::none
        }
    });
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before><commit_msg>Simplify implementation of remove_tag()<commit_after><|endoftext|>


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

/*!
 * Computes moves.
 */

use core::prelude::*;
use mc = middle::mem_categorization;
use middle::borrowck::*;
use middle::borrowck::move_data::*;
use middle::moves;
use middle::ty;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::span;
use util::ppaux::{UserString};

pub fn gather_decl(bccx: @BorrowckCtxt,
                   move_data: &mut MoveData,
                   decl_id: ast::node_id,
                   _decl_span: span,
                   var_id: ast::node_id) {
    let loan_path = @LpVar(var_id);
    move_data.add_move(bccx.tcx, loan_path, decl_id, Declared);
}

pub fn gather_move_from_expr(bccx: @BorrowckCtxt,
                             move_data: &mut MoveData,
                             move_expr: @ast::expr,
                             cmt: mc::cmt) {
    gather_move_from_expr_or_pat(bccx, move_data, move_expr.id,
                                 MoveExpr(move_expr), cmt);
}

pub fn gather_move_from_pat(bccx: @BorrowckCtxt,
                            move_data: &mut MoveData,
                            move_pat: @ast::pat,
                            cmt: mc::cmt) {
    gather_move_from_expr_or_pat(bccx, move_data, move_pat.id,
                                 MovePat(move_pat), cmt);
}

fn gather_move_from_expr_or_pat(bccx: @BorrowckCtxt,
                                move_data: &mut MoveData,
                                move_id: ast::node_id,
                                move_kind: MoveKind,
                                cmt: mc::cmt) {
    if !check_is_legal_to_move_from(bccx, cmt, cmt) {
        return;
    }

    match opt_loan_path(cmt) {
        Some(loan_path) => {
            move_data.add_move(bccx.tcx, loan_path, move_id, move_kind);
        }
        None => {
            // move from rvalue or unsafe pointer, hence ok
        }
    }
}

pub fn gather_captures(bccx: @BorrowckCtxt,
                       move_data: &mut MoveData,
                       closure_expr: @ast::expr) {
    let captured_vars = bccx.capture_map.get(&closure_expr.id);
    for captured_vars.each |captured_var| {
        match captured_var.mode {
            moves::CapMove => {
                let fvar_id = ast_util::def_id_of_def(captured_var.def).node;
                let loan_path = @LpVar(fvar_id);
                move_data.add_move(bccx.tcx, loan_path, closure_expr.id,
                                   Captured(closure_expr));
            }
            moves::CapCopy | moves::CapRef => {}
        }
    }
}

pub fn gather_assignment(bccx: @BorrowckCtxt,
                         move_data: &mut MoveData,
                         assignment_id: ast::node_id,
                         assignment_span: span,
                         assignee_loan_path: @LoanPath,
                         assignee_id: ast::node_id) {
    move_data.add_assignment(bccx.tcx,
                             assignee_loan_path,
                             assignment_id,
                             assignment_span,
                             assignee_id);
}

fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
                               cmt0: mc::cmt,
                               cmt: mc::cmt) -> bool {
    match cmt.cat {
        mc::cat_implicit_self(*) |
        mc::cat_deref(_, _, mc::region_ptr(*)) |
        mc::cat_deref(_, _, mc::gc_ptr(*)) |
        mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
            bccx.span_err(
                cmt0.span,
                fmt!("cannot move out of %s",
                     bccx.cmt_to_str(cmt)));
            false
        }

        // These are separate from the above cases for a better error message.
        mc::cat_stack_upvar(*) |
        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, _ }) => {
            bccx.span_err(
                cmt0.span,
                fmt!("cannot move out of %s \
                      (unless the destination closure type is `once fn')",
                     bccx.cmt_to_str(cmt)));
            false
        }

        // Can move out of captured upvars only if the destination closure
        // type is 'once'. 1-shot stack closures emit the copied_upvar form
        // (see mem_categorization.rs).
        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, _ }) => {
            true
        }

        // It seems strange to allow a move out of a static item,
        // but what happens in practice is that you have a
        // reference to a constant with a type that should be
        // moved, like `None::<~int>`.  The type of this constant
        // is technically `Option<~int>`, which moves, but we know
        // that the content of static items will never actually
        // contain allocated pointers, so we can just memcpy it.
        // Since static items can never have allocated memory,
        // this is ok. For now anyhow.
        mc::cat_static_item => {
            true
        }

        mc::cat_rvalue(*) |
        mc::cat_local(*) |
        mc::cat_arg(*) |
        mc::cat_self(*) => {
            true
        }

        mc::cat_downcast(b) |
        mc::cat_interior(b, _) => {
            match ty::get(b.ty).sty {
                ty::ty_struct(did, _) | ty::ty_enum(did, _) => {
                    if ty::has_dtor(bccx.tcx, did) {
                        bccx.span_err(
                            cmt0.span,
                            fmt!("cannot move out of type `%s`, \
                                  which defines the `Drop` trait",
                                 b.ty.user_string(bccx.tcx)));
                        false
                    } else {
                        check_is_legal_to_move_from(bccx, cmt0, b)
                    }
                }
                _ => {
                    check_is_legal_to_move_from(bccx, cmt0, b)
                }
            }
        }

        mc::cat_deref(b, _, mc::uniq_ptr(*)) |
        mc::cat_discr(b, _) => {
            check_is_legal_to_move_from(bccx, cmt0, b)
        }
    }
}
<commit_msg>Oops, hide 'unless once fn' error message hint behind -Z once-fns too.<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.

/*!
 * Computes moves.
 */

use core::prelude::*;
use mc = middle::mem_categorization;
use middle::borrowck::*;
use middle::borrowck::move_data::*;
use middle::moves;
use middle::ty;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::span;
use util::ppaux::{UserString};

pub fn gather_decl(bccx: @BorrowckCtxt,
                   move_data: &mut MoveData,
                   decl_id: ast::node_id,
                   _decl_span: span,
                   var_id: ast::node_id) {
    let loan_path = @LpVar(var_id);
    move_data.add_move(bccx.tcx, loan_path, decl_id, Declared);
}

pub fn gather_move_from_expr(bccx: @BorrowckCtxt,
                             move_data: &mut MoveData,
                             move_expr: @ast::expr,
                             cmt: mc::cmt) {
    gather_move_from_expr_or_pat(bccx, move_data, move_expr.id,
                                 MoveExpr(move_expr), cmt);
}

pub fn gather_move_from_pat(bccx: @BorrowckCtxt,
                            move_data: &mut MoveData,
                            move_pat: @ast::pat,
                            cmt: mc::cmt) {
    gather_move_from_expr_or_pat(bccx, move_data, move_pat.id,
                                 MovePat(move_pat), cmt);
}

fn gather_move_from_expr_or_pat(bccx: @BorrowckCtxt,
                                move_data: &mut MoveData,
                                move_id: ast::node_id,
                                move_kind: MoveKind,
                                cmt: mc::cmt) {
    if !check_is_legal_to_move_from(bccx, cmt, cmt) {
        return;
    }

    match opt_loan_path(cmt) {
        Some(loan_path) => {
            move_data.add_move(bccx.tcx, loan_path, move_id, move_kind);
        }
        None => {
            // move from rvalue or unsafe pointer, hence ok
        }
    }
}

pub fn gather_captures(bccx: @BorrowckCtxt,
                       move_data: &mut MoveData,
                       closure_expr: @ast::expr) {
    let captured_vars = bccx.capture_map.get(&closure_expr.id);
    for captured_vars.each |captured_var| {
        match captured_var.mode {
            moves::CapMove => {
                let fvar_id = ast_util::def_id_of_def(captured_var.def).node;
                let loan_path = @LpVar(fvar_id);
                move_data.add_move(bccx.tcx, loan_path, closure_expr.id,
                                   Captured(closure_expr));
            }
            moves::CapCopy | moves::CapRef => {}
        }
    }
}

pub fn gather_assignment(bccx: @BorrowckCtxt,
                         move_data: &mut MoveData,
                         assignment_id: ast::node_id,
                         assignment_span: span,
                         assignee_loan_path: @LoanPath,
                         assignee_id: ast::node_id) {
    move_data.add_assignment(bccx.tcx,
                             assignee_loan_path,
                             assignment_id,
                             assignment_span,
                             assignee_id);
}

fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
                               cmt0: mc::cmt,
                               cmt: mc::cmt) -> bool {
    match cmt.cat {
        mc::cat_implicit_self(*) |
        mc::cat_deref(_, _, mc::region_ptr(*)) |
        mc::cat_deref(_, _, mc::gc_ptr(*)) |
        mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
            bccx.span_err(
                cmt0.span,
                fmt!("cannot move out of %s",
                     bccx.cmt_to_str(cmt)));
            false
        }

        // These are separate from the above cases for a better error message.
        mc::cat_stack_upvar(*) |
        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, _ }) => {
            let once_hint = if bccx.tcx.sess.once_fns() {
                " (unless the destination closure type is `once fn')"
            } else {
                ""
            };
            bccx.span_err(
                cmt0.span,
                fmt!("cannot move out of %s%s", bccx.cmt_to_str(cmt), once_hint));
            false
        }

        // Can move out of captured upvars only if the destination closure
        // type is 'once'. 1-shot stack closures emit the copied_upvar form
        // (see mem_categorization.rs).
        mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, _ }) => {
            true
        }

        // It seems strange to allow a move out of a static item,
        // but what happens in practice is that you have a
        // reference to a constant with a type that should be
        // moved, like `None::<~int>`.  The type of this constant
        // is technically `Option<~int>`, which moves, but we know
        // that the content of static items will never actually
        // contain allocated pointers, so we can just memcpy it.
        // Since static items can never have allocated memory,
        // this is ok. For now anyhow.
        mc::cat_static_item => {
            true
        }

        mc::cat_rvalue(*) |
        mc::cat_local(*) |
        mc::cat_arg(*) |
        mc::cat_self(*) => {
            true
        }

        mc::cat_downcast(b) |
        mc::cat_interior(b, _) => {
            match ty::get(b.ty).sty {
                ty::ty_struct(did, _) | ty::ty_enum(did, _) => {
                    if ty::has_dtor(bccx.tcx, did) {
                        bccx.span_err(
                            cmt0.span,
                            fmt!("cannot move out of type `%s`, \
                                  which defines the `Drop` trait",
                                 b.ty.user_string(bccx.tcx)));
                        false
                    } else {
                        check_is_legal_to_move_from(bccx, cmt0, b)
                    }
                }
                _ => {
                    check_is_legal_to_move_from(bccx, cmt0, b)
                }
            }
        }

        mc::cat_deref(b, _, mc::uniq_ptr(*)) |
        mc::cat_discr(b, _) => {
            check_is_legal_to_move_from(bccx, cmt0, b)
        }
    }
}
<|endoftext|>