<commit_before>use super::*;

pub(super) fn mod_contents(p: &mut Parser) {
    attributes::inner_attributes(p);
    while !p.at(EOF) {
        item(p);
    }
}

pub(super) const ITEM_FIRST: TokenSet = token_set![
    EXTERN_KW,
    MOD_KW,
    USE_KW,
    STRUCT_KW,
    FN_KW,
    PUB_KW,
    POUND,
];

fn item(p: &mut Parser) {
    let item = p.start();
    attributes::outer_attributes(p);
    visibility(p);
    let la = p.raw_lookahead(1);
    let item_kind = match p.current() {
        EXTERN_KW if la == CRATE_KW => {
            extern_crate_item(p);
            EXTERN_CRATE_ITEM
        }
        MOD_KW => {
            mod_item(p);
            MOD_ITEM
        }
        USE_KW => {
            use_item(p);
            USE_ITEM
        }
        STRUCT_KW => {
            struct_item(p);
            STRUCT_ITEM
        }
        FN_KW => {
            fn_item(p);
            FN_ITEM
        }
        err_token => {
            item.abandon(p);
            let err = p.start();
            let message = if err_token == SEMI {
                //TODO: if the item is incomplete, this message is misleading
                "expected item, found `;`\n\
                consider removing this semicolon"
            } else {
                "expected item"
            };
            p.error()
                .message(message)
                .emit();
            p.bump();
            err.complete(p, ERROR);
            return;
        }
    };
    item.complete(p, item_kind);
}

fn struct_item(p: &mut Parser) {
    assert!(p.at(STRUCT_KW));
    p.bump();

    if !p.expect(IDENT) {
        return;
    }
    generic_parameters(p);
    match p.current() {
        WHERE_KW => {
            where_clause(p);
            match p.current() {
                SEMI => {
                    p.bump();
                    return;
                }
                L_CURLY => named_fields(p),
                _ => { //TODO: special case `(` error message
                    p.error()
                        .message("expected `;` or `{`")
                        .emit();
                    return;
                }
            }
        }
        SEMI => {
            p.bump();
            return;
        }
        L_CURLY => named_fields(p),
        L_PAREN => {
            pos_fields(p);
            p.expect(SEMI);
        }
        _ => {
            p.error()
                .message("expected `;`, `{`, or `(`")
                .emit();
            return;
        }
    }
}

fn named_fields(p: &mut Parser) {
    p.curly_block(|p| comma_list(p, EOF, |p| {
        named_field(p);
        true
    }));

    fn named_field(p: &mut Parser) {
        let field = p.start();
        visibility(p);
        if p.expect(IDENT) && p.expect(COLON) {
            types::type_ref(p);
        };
        field.complete(p, NAMED_FIELD);
    }
}

fn pos_fields(p: &mut Parser) {
    if !p.expect(L_PAREN) {
        return;
    }
    loop {
        if p.at(R_PAREN) || p.at(EOF) {
            break;
        }

        let pos_field = p.start();
        visibility(p);
        types::type_ref(p);
        pos_field.complete(p, POS_FIELD);

        if !p.at(R_PAREN) {
            p.expect(COMMA);
        }
    }
    p.expect(R_PAREN);
}

fn generic_parameters(_: &mut Parser) {}

fn where_clause(_: &mut Parser) {}

fn extern_crate_item(p: &mut Parser) {
    assert!(p.at(EXTERN_KW));
    p.bump();
    assert!(p.at(CRATE_KW));
    p.bump();

    p.expect(IDENT) && alias(p) && p.expect(SEMI);
}

fn mod_item(p: &mut Parser) {
    assert!(p.at(MOD_KW));
    p.bump();

    if p.expect(IDENT) && !p.eat(SEMI) {
        p.curly_block(mod_contents);
    }
}

pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool {
    kind == STAR || kind == L_CURLY
}

fn use_item(p: &mut Parser) {
    assert!(p.at(USE_KW));
    p.bump();

    use_tree(p);
    p.expect(SEMI);

    fn use_tree(p: &mut Parser) -> bool {
        let la = p.raw_lookahead(1);
        let m = p.start();
        match (p.current(), la) {
            (STAR, _) => {
                p.bump();
            }
            (COLONCOLON, STAR) => {
                p.bump();
                p.bump();
            }
            (L_CURLY, _) | (COLONCOLON, L_CURLY) => {
                if p.at(COLONCOLON) {
                    p.bump();
                }
                p.curly_block(|p| {
                    comma_list(p, EOF, use_tree);
                });
            }
            _ if paths::is_path_start(p) => {
                paths::use_path(p);
                match p.current() {
                    AS_KW => {
                        alias(p);
                    }
                    COLONCOLON => {
                        p.bump();
                        match p.current() {
                            STAR => {
                                p.bump();
                            }
                            L_CURLY => {
                                p.curly_block(|p| {
                                    comma_list(p, EOF, use_tree);
                                });
                            }
                            _ => {
                                // is this unreachable?
                                p.error()
                                    .message("expected `{` or `*`")
                                    .emit();
                            }
                        }
                    }
                    _ => (),
                }
            }
            _ => {
                m.abandon(p);
                return false
            },
        }
        m.complete(p, USE_TREE);
        return true;
    }
}

fn fn_item(p: &mut Parser) {
    assert!(p.at(FN_KW));
    p.bump();

    p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN)
        && p.curly_block(|_| ());
}

<commit_msg>Extract nested trees<commit_after>use super::*;

pub(super) fn mod_contents(p: &mut Parser) {
    attributes::inner_attributes(p);
    while !p.at(EOF) {
        item(p);
    }
}

pub(super) const ITEM_FIRST: TokenSet = token_set![
    EXTERN_KW,
    MOD_KW,
    USE_KW,
    STRUCT_KW,
    FN_KW,
    PUB_KW,
    POUND,
];

fn item(p: &mut Parser) {
    let item = p.start();
    attributes::outer_attributes(p);
    visibility(p);
    let la = p.raw_lookahead(1);
    let item_kind = match p.current() {
        EXTERN_KW if la == CRATE_KW => {
            extern_crate_item(p);
            EXTERN_CRATE_ITEM
        }
        MOD_KW => {
            mod_item(p);
            MOD_ITEM
        }
        USE_KW => {
            use_item(p);
            USE_ITEM
        }
        STRUCT_KW => {
            struct_item(p);
            STRUCT_ITEM
        }
        FN_KW => {
            fn_item(p);
            FN_ITEM
        }
        err_token => {
            item.abandon(p);
            let err = p.start();
            let message = if err_token == SEMI {
                //TODO: if the item is incomplete, this message is misleading
                "expected item, found `;`\n\
                consider removing this semicolon"
            } else {
                "expected item"
            };
            p.error()
                .message(message)
                .emit();
            p.bump();
            err.complete(p, ERROR);
            return;
        }
    };
    item.complete(p, item_kind);
}

fn struct_item(p: &mut Parser) {
    assert!(p.at(STRUCT_KW));
    p.bump();

    if !p.expect(IDENT) {
        return;
    }
    generic_parameters(p);
    match p.current() {
        WHERE_KW => {
            where_clause(p);
            match p.current() {
                SEMI => {
                    p.bump();
                    return;
                }
                L_CURLY => named_fields(p),
                _ => { //TODO: special case `(` error message
                    p.error()
                        .message("expected `;` or `{`")
                        .emit();
                    return;
                }
            }
        }
        SEMI => {
            p.bump();
            return;
        }
        L_CURLY => named_fields(p),
        L_PAREN => {
            pos_fields(p);
            p.expect(SEMI);
        }
        _ => {
            p.error()
                .message("expected `;`, `{`, or `(`")
                .emit();
            return;
        }
    }
}

fn named_fields(p: &mut Parser) {
    p.curly_block(|p| comma_list(p, EOF, |p| {
        named_field(p);
        true
    }));

    fn named_field(p: &mut Parser) {
        let field = p.start();
        visibility(p);
        if p.expect(IDENT) && p.expect(COLON) {
            types::type_ref(p);
        };
        field.complete(p, NAMED_FIELD);
    }
}

fn pos_fields(p: &mut Parser) {
    if !p.expect(L_PAREN) {
        return;
    }
    loop {
        if p.at(R_PAREN) || p.at(EOF) {
            break;
        }

        let pos_field = p.start();
        visibility(p);
        types::type_ref(p);
        pos_field.complete(p, POS_FIELD);

        if !p.at(R_PAREN) {
            p.expect(COMMA);
        }
    }
    p.expect(R_PAREN);
}

fn generic_parameters(_: &mut Parser) {}

fn where_clause(_: &mut Parser) {}

fn extern_crate_item(p: &mut Parser) {
    assert!(p.at(EXTERN_KW));
    p.bump();
    assert!(p.at(CRATE_KW));
    p.bump();

    p.expect(IDENT) && alias(p) && p.expect(SEMI);
}

fn mod_item(p: &mut Parser) {
    assert!(p.at(MOD_KW));
    p.bump();

    if p.expect(IDENT) && !p.eat(SEMI) {
        p.curly_block(mod_contents);
    }
}

pub(super) fn is_use_tree_start(kind: SyntaxKind) -> bool {
    kind == STAR || kind == L_CURLY
}

fn use_item(p: &mut Parser) {
    assert!(p.at(USE_KW));
    p.bump();

    use_tree(p);
    p.expect(SEMI);

    fn use_tree(p: &mut Parser) -> bool {
        let la = p.raw_lookahead(1);
        let m = p.start();
        match (p.current(), la) {
            (STAR, _) => {
                p.bump();
            }
            (COLONCOLON, STAR) => {
                p.bump();
                p.bump();
            }
            (L_CURLY, _) | (COLONCOLON, L_CURLY) => {
                if p.at(COLONCOLON) {
                    p.bump();
                }
                nested_trees(p);
            }
            _ if paths::is_path_start(p) => {
                paths::use_path(p);
                match p.current() {
                    AS_KW => {
                        alias(p);
                    }
                    COLONCOLON => {
                        p.bump();
                        match p.current() {
                            STAR => {
                                p.bump();
                            }
                            L_CURLY => nested_trees(p),
                            _ => {
                                // is this unreachable?
                                p.error()
                                    .message("expected `{` or `*`")
                                    .emit();
                            }
                        }
                    }
                    _ => (),
                }
            }
            _ => {
                m.abandon(p);
                return false
            },
        }
        m.complete(p, USE_TREE);
        return true;
    }

    fn nested_trees(p: &mut Parser) {
        assert!(p.at(L_CURLY));
        p.curly_block(|p| comma_list(p, EOF, use_tree));
    }
}

fn fn_item(p: &mut Parser) {
    assert!(p.at(FN_KW));
    p.bump();

    p.expect(IDENT) && p.expect(L_PAREN) && p.expect(R_PAREN)
        && p.curly_block(|_| ());
}

<|endoftext|>


<commit_before>use std::io::stdio::{stdout, stderr};
use std::io::fs::readlink;

use libc::pid_t;
use libc::consts::os::posix88::{SIGTERM, SIGINT, SIGQUIT};
use collections::treemap::TreeMap;
use argparse::ArgumentParser;

use super::super::env::{Environ, Container};
use super::super::options::env_options;
use super::super::build::{build_container, link_container};
use super::super::config::{Shell, Plain, Supervise};
use super::super::config::{StopOnFailure, WaitAll, Restart};
use super::super::config::Command;
use super::super::commands::shell::exec_shell_command;
use super::super::commands::command::exec_plain_command;
use super::super::monitor::{Monitor, Signal, Exit};

pub fn run_supervise_command(env: &mut Environ, cmdname: &String,
    args: Vec<String>)
    -> Result<int, String>
{
    {
        let mut ap = ArgumentParser::new();
        env_options(env, &mut ap);
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    let command = env.config.commands.find(cmdname).unwrap();
    let mut work_dir = env.work_dir.clone();
    if command.work_dir.is_some() {
        let ncwd = env.project_root.join(
            command.work_dir.as_ref().unwrap().as_slice());
        if !env.project_root.is_ancestor_of(&ncwd) {
            return Err(format!("Command's work-dir must be relative to \
                project root"));
        }
        work_dir = ncwd;
    }
    let (mode, processes) = match command.execute {
        Supervise(ref mode, ref processes) => (mode, processes),
        _ => unreachable!(),
    };
    let mut containers = TreeMap::new();
    for (cmdname, command) in processes.iter() {
        let cname = command.container.as_ref().unwrap();
        let mut container = try!(env.get_container(cname));
        if env.settings.version_check {
            try!(build_container(env, &mut container, false));
            try!(link_container(env, &container));
        } else {
            let lnk = env.local_vagga.join(container.fullname.as_slice());
            container.container_root = match readlink(&lnk) {
                Ok(path) => Some(lnk.dir_path().join(path)),
                Err(e) => return Err(format!("Container {} not found: {}",
                                             container.fullname, e)),
            };
        }
        if command.work_dir.is_some() {
            let ncwd = env.project_root.join(
                command.work_dir.as_ref().unwrap().as_slice());
            if !env.project_root.is_ancestor_of(&ncwd) {
                return Err(format!("The `work-dir` of {} of must be relative \
                    to project root", cmdname));
            }
        }
        containers.insert(cname.clone(), container);
    }

    let mut monitor = Monitor::new();

    let start = |cname: &String, monitor: &mut Monitor| -> bool {
        let command = processes.find(cname).unwrap();
        let fun = match command.execute {
            Shell(_) => exec_shell_command,
            Plain(_) => exec_plain_command,
            Supervise(_, _) => exec_supervise_command,
        };
        let container = containers.find(
            command.container.as_ref().unwrap()).unwrap();

        let cmdworkdir = if command.work_dir.is_some() {
            env.project_root.join(
                command.work_dir.as_ref().unwrap().as_slice())
        } else {
            work_dir.clone()
        };
        match fun(env, &cmdworkdir, command, container) {
            Ok(pid) => {
                info!("Command {} started with pid {}",
                    cname, pid);
                monitor.add(cname.clone(), pid);
                return true;
            }
            Err(e) => {
                error!("Error starting {}: {}", cname, e);
                monitor.send_all(SIGTERM);
                monitor.fail();
                return false;
            }
        }
    };

    for (cname, _) in processes.iter() {
        if !start(cname, &mut monitor) {
            break;
        }
    }

    debug!("Monitoring in {} mode", *mode);
    match *mode {
        StopOnFailure => {
            while monitor.ok() {
                match monitor.next_event() {
                    Exit(cname, pid, status) => {
                        error!("Process {}:{} dead with status {}. Failing.",
                            cname, pid, status);
                        monitor.send_all(SIGTERM);
                        monitor.fail();
                    }
                    Signal(sig)
                    if sig == SIGTERM || sig == SIGINT || sig == SIGQUIT => {
                        debug!("Got {}. Propagating.", sig);
                        monitor.send_all(sig);
                        monitor.fail();
                    }
                    Signal(sig) => {
                        debug!("Got {}. Ignoring.", sig);
                    }
                }
            }
        }
        Restart => {
            while monitor.ok() {
                match monitor.next_event() {
                    Exit(cname, pid, status) => {
                        error!("Process {}:{} dead with status {}",
                            cname, pid, status);
                        start(&cname, &mut monitor);
                    }
                    Signal(sig)
                    if sig == SIGTERM || sig == SIGINT || sig == SIGQUIT => {
                        debug!("Got {}. Propagating.", sig);
                        monitor.send_all(sig);
                        monitor.fail();
                    }
                    Signal(sig) => {
                        debug!("Got {}. Ignoring.", sig);
                    }
                }
            }
        }
        WaitAll => {},
    }

    // Wait all mode always at the end
    debug!("Falled back to WaitAll mode");
    monitor.wait_all();

    return Ok(monitor.get_status());
}

pub fn exec_supervise_command(_env: &Environ, _workdir: &Path,
    _command: &Command, _container: &Container)
    -> Result<pid_t, String> {
    fail!("Nested supervise commands do not work yet");
}
<commit_msg>Implement `--only` and `--exclude` for supervision commands<commit_after>use std::io::stdio::{stdout, stderr};
use std::io::fs::readlink;

use libc::pid_t;
use libc::consts::os::posix88::{SIGTERM, SIGINT, SIGQUIT};
use collections::treemap::TreeMap;
use argparse::{ArgumentParser, List};

use super::super::env::{Environ, Container};
use super::super::options::env_options;
use super::super::build::{build_container, link_container};
use super::super::config::{Shell, Plain, Supervise};
use super::super::config::{StopOnFailure, WaitAll, Restart};
use super::super::config::Command;
use super::super::commands::shell::exec_shell_command;
use super::super::commands::command::exec_plain_command;
use super::super::monitor::{Monitor, Signal, Exit};

pub fn run_supervise_command(env: &mut Environ, cmdname: &String,
    args: Vec<String>)
    -> Result<int, String>
{
    let mut only = Vec::new();
    let mut exclude = Vec::new();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut only)
            .add_option(["--only"], box List::<String>,
                "Run only specified processes process")
            .metavar("PROCESS");
        ap.refer(&mut exclude)
            .add_option(["--exclude"], box List::<String>,
                "Run all processes except specified here")
            .metavar("PROCESS");
        env_options(env, &mut ap);
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => return Ok(122),
        }
    }
    let command = env.config.commands.find(cmdname).unwrap();
    let mut work_dir = env.work_dir.clone();
    if command.work_dir.is_some() {
        let ncwd = env.project_root.join(
            command.work_dir.as_ref().unwrap().as_slice());
        if !env.project_root.is_ancestor_of(&ncwd) {
            return Err(format!("Command's work-dir must be relative to \
                project root"));
        }
        work_dir = ncwd;
    }
    let (mode, processes) = match command.execute {
        Supervise(ref mode, ref processes) => (mode, processes),
        _ => unreachable!(),
    };
    let mut containers = TreeMap::new();
    for (cmdname, command) in processes.iter() {
        let cname = command.container.as_ref().unwrap();
        let mut container = try!(env.get_container(cname));
        if env.settings.version_check {
            try!(build_container(env, &mut container, false));
            try!(link_container(env, &container));
        } else {
            let lnk = env.local_vagga.join(container.fullname.as_slice());
            container.container_root = match readlink(&lnk) {
                Ok(path) => Some(lnk.dir_path().join(path)),
                Err(e) => return Err(format!("Container {} not found: {}",
                                             container.fullname, e)),
            };
        }
        if command.work_dir.is_some() {
            let ncwd = env.project_root.join(
                command.work_dir.as_ref().unwrap().as_slice());
            if !env.project_root.is_ancestor_of(&ncwd) {
                return Err(format!("The `work-dir` of {} of must be relative \
                    to project root", cmdname));
            }
        }
        containers.insert(cname.clone(), container);
    }

    let mut monitor = Monitor::new();

    let start = |cname: &String, monitor: &mut Monitor| -> bool {
        let command = processes.find(cname).unwrap();
        let fun = match command.execute {
            Shell(_) => exec_shell_command,
            Plain(_) => exec_plain_command,
            Supervise(_, _) => exec_supervise_command,
        };
        let container = containers.find(
            command.container.as_ref().unwrap()).unwrap();

        let cmdworkdir = if command.work_dir.is_some() {
            env.project_root.join(
                command.work_dir.as_ref().unwrap().as_slice())
        } else {
            work_dir.clone()
        };
        match fun(env, &cmdworkdir, command, container) {
            Ok(pid) => {
                info!("Command {} started with pid {}",
                    cname, pid);
                monitor.add(cname.clone(), pid);
                return true;
            }
            Err(e) => {
                error!("Error starting {}: {}", cname, e);
                monitor.send_all(SIGTERM);
                monitor.fail();
                return false;
            }
        }
    };

    for (cname, _) in processes.iter() {
        if only.len() > 0 && !only.contains(cname) || exclude.contains(cname) {
            continue;
        }
        if !start(cname, &mut monitor) {
            break;
        }
    }

    debug!("Monitoring in {} mode", *mode);
    match *mode {
        StopOnFailure => {
            while monitor.ok() {
                match monitor.next_event() {
                    Exit(cname, pid, status) => {
                        error!("Process {}:{} dead with status {}. Failing.",
                            cname, pid, status);
                        monitor.send_all(SIGTERM);
                        monitor.fail();
                    }
                    Signal(sig)
                    if sig == SIGTERM || sig == SIGINT || sig == SIGQUIT => {
                        debug!("Got {}. Propagating.", sig);
                        monitor.send_all(sig);
                        monitor.fail();
                    }
                    Signal(sig) => {
                        debug!("Got {}. Ignoring.", sig);
                    }
                }
            }
        }
        Restart => {
            while monitor.ok() {
                match monitor.next_event() {
                    Exit(cname, pid, status) => {
                        error!("Process {}:{} dead with status {}",
                            cname, pid, status);
                        start(&cname, &mut monitor);
                    }
                    Signal(sig)
                    if sig == SIGTERM || sig == SIGINT || sig == SIGQUIT => {
                        debug!("Got {}. Propagating.", sig);
                        monitor.send_all(sig);
                        monitor.fail();
                    }
                    Signal(sig) => {
                        debug!("Got {}. Ignoring.", sig);
                    }
                }
            }
        }
        WaitAll => {},
    }

    // Wait all mode always at the end
    debug!("Falled back to WaitAll mode");
    monitor.wait_all();

    return Ok(monitor.get_status());
}

pub fn exec_supervise_command(_env: &Environ, _workdir: &Path,
    _command: &Command, _container: &Container)
    -> Result<pid_t, String> {
    fail!("Nested supervise commands do not work yet");
}
<|endoftext|>


<commit_before>
use std;
import std::io;
import std::io::{writer_util, reader_util};
import result;

tag state {
    start(bool);
    field(uint, uint);
    escapedfield(uint, uint);
    inquote(uint, uint);
}

type rowreader = {
    delim: char,
    quote: char,
    f : io::reader,
    mutable offset : uint,
    mutable buffers : [@[char]],
    mutable state : state
};

type row = {
    buffers : [@[char]],
    mutable fields : [ field ]
};

enum field {
    bufferfield([@[char]], uint, uint);
    emptyfield();
}

iface rowiter {
    fn readrow() -> result::t<row, str>;
}

iface rowaccess {
    fn len() -> uint;
    fn getchars(uint) -> @[char];
    fn getstr(uint) -> str;
}

fn new_reader(+f: io::reader, +delim: char, +quote: char) -> rowreader {
    let r : rowreader = {
        delim: delim,
        quote: quote,
        f: f,
        mutable offset : 0u,
        mutable buffers : [],
        mutable state : start(false)
    };
    ret r;
}

impl csv of rowiter for rowreader {
    fn readrow() -> result::t<row, str> {
        fn row_from_buf(self: rowreader, &r: row) -> bool {
            fn new_bufferfield(self: rowreader, sb: uint, so: uint, eo: uint) -> field {
                let bufs : [@[char]] = vec::slice(self.buffers, sb, vec::len(self.buffers));
                ret bufferfield(bufs, so, eo);
            }
            let cbuffer = vec::len(self.buffers) - 1u;
            let buf: @[char] = self.buffers[cbuffer];
            while self.offset < vec::len(*buf) {
                let coffset = self.offset;
                let c : char = buf[coffset];
                self.offset += 1u;
                alt self.state {
                    start(after_delim) {
                        //io::println(#fmt("start : after_delim %b", after_delim));
                        if c == self.quote {
                            self.state = escapedfield(cbuffer, coffset);
                        } else if c == '\n' {
                            if after_delim {
                                r.fields += [emptyfield];
                            }
                            ret true;
                        } else if c == self.delim {
                            self.state = start(true);
                            r.fields += [emptyfield];
                        } else {
                            self.state = field(cbuffer, coffset);
                        }
                    }
                    field(b,o) {
                        //io::println(#fmt("field : %u %u", b, o));
                        if c == '\n' {
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                            ret true;
                        } else if c == self.delim {
                            self.state = start(true);
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                        }
                    }
                    escapedfield(b, o) {
                        //io::println(#fmt("escapedfield : %u %u", b, o));
                        if c == self.quote {
                            self.state = inquote(b, o);
                        } else if c == self.delim {
                            self.state = start(true);
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                        }
                    }
                    inquote(b, o) {
                        //io::println(#fmt("inquote : %u %u", b, o));
                        if c == '\n' {
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                            ret true;
                        } else if c == self.quote {
                            // hmm what to do
                            // self.state = escapedfield(x + [self.quote]);
                        } else if c == self.delim {
                            self.state = start(true);
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                        }
                        // swallow odd chars, eg. space between field and "
                    }
                }
            }
            ret false;
        }

        self.state = start(false);
        let do_read = vec::len(self.buffers) == 0u;
        while true {
            if do_read {
                let data: @[char] = @self.f.read_chars(1024u);
                //io::println(#fmt("len %u '%s'", vec::len(*data), str::from_chars(*data)));
                if vec::len(*data) == 0u {
                    ret result::err("EOF");
                }
                self.buffers += [data];
                self.offset = 0u;
            }

            let r: row = { buffers: [], mutable fields: [] };
            if row_from_buf(self, r) {
                ret result::ok(r);
            }
            do_read = true;
        }
        ret result::err("unreachable");
    }
}

fn main(args : [str])
{
    if (vec::len(args) != 2u) {
        ret;
    }
    let f : io::reader = result::get(io::file_reader(args[1]));
    let reader = new_reader(f, ',', '"');
    while true {
        let res = reader.readrow();
        if result::failure(res) {
            break;
        }
        io::println("got a row");
    }
}

<commit_msg>getting closer..<commit_after>
use std;
import std::io;
import std::io::{writer_util, reader_util};
import result;

tag state {
    start(bool);
    field(uint, uint);
    escapedfield(uint, uint);
    inquote(uint, uint);
}

type rowreader = {
    delim: char,
    quote: char,
    f : io::reader,
    mutable offset : uint,
    mutable buffers : [@[char]],
    mutable state : state
};

type row = {
    mutable fields : [ field ]
};

enum field {
    bufferfield([@[char]], uint, uint);
    emptyfield();
}

iface rowiter {
    fn readrow() -> result::t<row, str>;
}

iface rowaccess {
    fn len() -> uint;
    fn getchars(uint) -> [char];
    fn getstr(uint) -> str;
}

fn new_reader(+f: io::reader, +delim: char, +quote: char) -> rowreader {
    let r : rowreader = {
        delim: delim,
        quote: quote,
        f: f,
        mutable offset : 0u,
        mutable buffers : [],
        mutable state : start(false)
    };
    ret r;
}

impl of rowaccess for row {
    fn len() -> uint {
        vec::len(self.fields)
    }
    fn getchars(field: uint) -> [char] {
        alt self.fields[field] {
            emptyfield() { ret []; }
            bufferfield(buffers, so, eo) {
                let r : [char] = [];
                let i = 0u;
                while i < vec::len(buffers) {
                    let from = i == 0u ? so : 0u;
                    let to = (i == vec::len(buffers) - 1u) ? eo : 0u;
                    io::println(#fmt("%u %u %u", i, from, to));
                    r += vec::slice(*buffers[i], from, to);
                    i = i + 1u;
                }
                ret r;
            }
        };
    }
    fn getstr(field: uint) -> str {
        ret str::from_chars(self.getchars(field));
    }
}

impl of rowiter for rowreader {
    fn readrow() -> result::t<row, str> {
        fn row_from_buf(self: rowreader, &r: row) -> bool {
            fn new_bufferfield(self: rowreader, sb: uint, so: uint, eo: uint) -> field {
                let bufs : [@[char]] = vec::slice(self.buffers, sb, vec::len(self.buffers));
                ret bufferfield(bufs, 0u, eo-so);
            }
            let cbuffer = vec::len(self.buffers) - 1u;
            let buf: @[char] = self.buffers[cbuffer];
            while self.offset < vec::len(*buf) {
                let coffset = self.offset;
                let c : char = buf[coffset];
                self.offset += 1u;
                alt self.state {
                    start(after_delim) {
                        //io::println(#fmt("start : after_delim %b", after_delim));
                        if c == self.quote {
                            self.state = escapedfield(cbuffer, coffset);
                        } else if c == '\n' {
                            if after_delim {
                                r.fields += [emptyfield];
                            }
                            ret true;
                        } else if c == self.delim {
                            self.state = start(true);
                            r.fields += [emptyfield];
                        } else {
                            self.state = field(cbuffer, coffset);
                        }
                    }
                    field(b,o) {
                        //io::println(#fmt("field : %u %u", b, o));
                        if c == '\n' {
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                            ret true;
                        } else if c == self.delim {
                            self.state = start(true);
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                        }
                    }
                    escapedfield(b, o) {
                        //io::println(#fmt("escapedfield : %u %u", b, o));
                        if c == self.quote {
                            self.state = inquote(b, o);
                        } else if c == self.delim {
                            self.state = start(true);
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                        }
                    }
                    inquote(b, o) {
                        //io::println(#fmt("inquote : %u %u", b, o));
                        if c == '\n' {
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                            ret true;
                        } else if c == self.quote {
                            // hmm what to do
                            // self.state = escapedfield(x + [self.quote]);
                        } else if c == self.delim {
                            self.state = start(true);
                            r.fields += [new_bufferfield(self, b, o, coffset)];
                        }
                        // swallow odd chars, eg. space between field and "
                    }
                }
            }
            ret false;
        }

        self.state = start(false);
        let do_read = vec::len(self.buffers) == 0u;
        while true {
            if do_read {
                let data: @[char] = @self.f.read_chars(1024u);
                //io::println(#fmt("len %u '%s'", vec::len(*data), str::from_chars(*data)));
                if vec::len(*data) == 0u {
                    ret result::err("EOF");
                }
                self.buffers += [data];
                self.offset = 0u;
            }

            let r: row = { mutable fields: [] };
            if row_from_buf(self, r) {
                ret result::ok(r);
            }
            do_read = true;
        }
        ret result::err("unreachable");
    }
}

fn main(args : [str])
{
    if (vec::len(args) != 2u) {
        ret;
    }
    let f : io::reader = result::get(io::file_reader(args[1]));
    let reader = new_reader(f, ',', '"');
    while true {
        let res = reader.readrow();
        if result::failure(res) {
            break;
        }
        io::println("got a row");
        let row = result::get(res);
        io::println(row.getstr(0u));
    }
}

<|endoftext|>


<commit_before>use std::collections::{BTreeSet, HashMap};
use std::env;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;

use cargo_platform::CfgExpr;
use cargo_util::{paths, ProcessBuilder};

use super::BuildContext;
use crate::core::compiler::{CompileKind, Metadata, Unit};
use crate::core::Package;
use crate::util::{config, CargoResult, Config};

/// Structure with enough information to run `rustdoc --test`.
pub struct Doctest {
    /// What's being doctested
    pub unit: Unit,
    /// Arguments needed to pass to rustdoc to run this test.
    pub args: Vec<OsString>,
    /// Whether or not -Zunstable-options is needed.
    pub unstable_opts: bool,
    /// The -Clinker value to use.
    pub linker: Option<PathBuf>,
    /// The script metadata, if this unit's package has a build script.
    ///
    /// This is used for indexing [`Compilation::extra_env`].
    pub script_meta: Option<Metadata>,

    /// Environment variables to set in the rustdoc process.
    pub env: HashMap<String, OsString>,
}

/// Information about the output of a unit.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub struct UnitOutput {
    /// The unit that generated this output.
    pub unit: Unit,
    /// Path to the unit's primary output (an executable or cdylib).
    pub path: PathBuf,
    /// The script metadata, if this unit's package has a build script.
    ///
    /// This is used for indexing [`Compilation::extra_env`].
    pub script_meta: Option<Metadata>,
}

/// A structure returning the result of a compilation.
pub struct Compilation<'cfg> {
    /// An array of all tests created during this compilation.
    pub tests: Vec<UnitOutput>,

    /// An array of all binaries created.
    pub binaries: Vec<UnitOutput>,

    /// An array of all cdylibs created.
    pub cdylibs: Vec<UnitOutput>,

    /// The crate names of the root units specified on the command-line.
    pub root_crate_names: Vec<String>,

    /// All directories for the output of native build commands.
    ///
    /// This is currently used to drive some entries which are added to the
    /// LD_LIBRARY_PATH as appropriate.
    ///
    /// The order should be deterministic.
    pub native_dirs: BTreeSet<PathBuf>,

    /// Root output directory (for the local package's artifacts)
    pub root_output: HashMap<CompileKind, PathBuf>,

    /// Output directory for rust dependencies.
    /// May be for the host or for a specific target.
    pub deps_output: HashMap<CompileKind, PathBuf>,

    /// The path to the host libdir for the compiler used
    sysroot_host_libdir: PathBuf,

    /// The path to libstd for each target
    sysroot_target_libdir: HashMap<CompileKind, PathBuf>,

    /// Extra environment variables that were passed to compilations and should
    /// be passed to future invocations of programs.
    ///
    /// The key is the build script metadata for uniquely identifying the
    /// `RunCustomBuild` unit that generated these env vars.
    pub extra_env: HashMap<Metadata, Vec<(String, String)>>,

    /// Libraries to test with rustdoc.
    pub to_doc_test: Vec<Doctest>,

    /// The target host triple.
    pub host: String,

    config: &'cfg Config,

    /// Rustc process to be used by default
    rustc_process: ProcessBuilder,
    /// Rustc process to be used for workspace crates instead of rustc_process
    rustc_workspace_wrapper_process: ProcessBuilder,
    /// Optional rustc process to be used for primary crates instead of either rustc_process or
    /// rustc_workspace_wrapper_process
    primary_rustc_process: Option<ProcessBuilder>,

    target_runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,
}

impl<'cfg> Compilation<'cfg> {
    pub fn new<'a>(bcx: &BuildContext<'a, 'cfg>) -> CargoResult<Compilation<'cfg>> {
        let mut rustc = bcx.rustc().process();
        let mut primary_rustc_process = bcx.build_config.primary_unit_rustc.clone();
        let mut rustc_workspace_wrapper_process = bcx.rustc().workspace_process();

        if bcx.config.extra_verbose() {
            rustc.display_env_vars();
            rustc_workspace_wrapper_process.display_env_vars();

            if let Some(rustc) = primary_rustc_process.as_mut() {
                rustc.display_env_vars();
            }
        }

        Ok(Compilation {
            // TODO: deprecated; remove.
            native_dirs: BTreeSet::new(),
            root_output: HashMap::new(),
            deps_output: HashMap::new(),
            sysroot_host_libdir: bcx
                .target_data
                .info(CompileKind::Host)
                .sysroot_host_libdir
                .clone(),
            sysroot_target_libdir: bcx
                .all_kinds
                .iter()
                .map(|&kind| {
                    (
                        kind,
                        bcx.target_data.info(kind).sysroot_target_libdir.clone(),
                    )
                })
                .collect(),
            tests: Vec::new(),
            binaries: Vec::new(),
            cdylibs: Vec::new(),
            root_crate_names: Vec::new(),
            extra_env: HashMap::new(),
            to_doc_test: Vec::new(),
            config: bcx.config,
            host: bcx.host_triple().to_string(),
            rustc_process: rustc,
            rustc_workspace_wrapper_process,
            primary_rustc_process,
            target_runners: bcx
                .build_config
                .requested_kinds
                .iter()
                .chain(Some(&CompileKind::Host))
                .map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
                .collect::<CargoResult<HashMap<_, _>>>()?,
        })
    }

    /// Returns a [`ProcessBuilder`] for running `rustc`.
    ///
    /// `is_primary` is true if this is a "primary package", which means it
    /// was selected by the user on the command-line (such as with a `-p`
    /// flag), see [`crate::core::compiler::Context::primary_packages`].
    ///
    /// `is_workspace` is true if this is a workspace member.
    pub fn rustc_process(
        &self,
        unit: &Unit,
        is_primary: bool,
        is_workspace: bool,
    ) -> CargoResult<ProcessBuilder> {
        let rustc = if is_primary && self.primary_rustc_process.is_some() {
            self.primary_rustc_process.clone().unwrap()
        } else if is_workspace {
            self.rustc_workspace_wrapper_process.clone()
        } else {
            self.rustc_process.clone()
        };

        let cmd = fill_rustc_tool_env(rustc, unit);
        self.fill_env(cmd, &unit.pkg, None, unit.kind, true)
    }

    /// Returns a [`ProcessBuilder`] for running `rustdoc`.
    pub fn rustdoc_process(
        &self,
        unit: &Unit,
        script_meta: Option<Metadata>,
    ) -> CargoResult<ProcessBuilder> {
        let rustdoc = ProcessBuilder::new(&*self.config.rustdoc()?);
        let cmd = fill_rustc_tool_env(rustdoc, unit);
        let mut cmd = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?;
        cmd.retry_with_argfile(true);
        unit.target.edition().cmd_edition_arg(&mut cmd);

        for crate_type in unit.target.rustc_crate_types() {
            cmd.arg("--crate-type").arg(crate_type.as_str());
        }

        Ok(cmd)
    }

    /// Returns a [`ProcessBuilder`] appropriate for running a process for the
    /// host platform.
    ///
    /// This is currently only used for running build scripts. If you use this
    /// for anything else, please be extra careful on how environment
    /// variables are set!
    pub fn host_process<T: AsRef<OsStr>>(
        &self,
        cmd: T,
        pkg: &Package,
    ) -> CargoResult<ProcessBuilder> {
        self.fill_env(
            ProcessBuilder::new(cmd),
            pkg,
            None,
            CompileKind::Host,
            false,
        )
    }

    pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec<String>)> {
        self.target_runners.get(&kind).and_then(|x| x.as_ref())
    }

    /// Returns a [`ProcessBuilder`] appropriate for running a process for the
    /// target platform. This is typically used for `cargo run` and `cargo
    /// test`.
    ///
    /// `script_meta` is the metadata for the `RunCustomBuild` unit that this
    /// unit used for its build script. Use `None` if the package did not have
    /// a build script.
    pub fn target_process<T: AsRef<OsStr>>(
        &self,
        cmd: T,
        kind: CompileKind,
        pkg: &Package,
        script_meta: Option<Metadata>,
    ) -> CargoResult<ProcessBuilder> {
        let builder = if let Some((runner, args)) = self.target_runner(kind) {
            let mut builder = ProcessBuilder::new(runner);
            builder.args(args);
            builder.arg(cmd);
            builder
        } else {
            ProcessBuilder::new(cmd)
        };
        self.fill_env(builder, pkg, script_meta, kind, false)
    }

    /// Prepares a new process with an appropriate environment to run against
    /// the artifacts produced by the build process.
    ///
    /// The package argument is also used to configure environment variables as
    /// well as the working directory of the child process.
    fn fill_env(
        &self,
        mut cmd: ProcessBuilder,
        pkg: &Package,
        script_meta: Option<Metadata>,
        kind: CompileKind,
        is_rustc_tool: bool,
    ) -> CargoResult<ProcessBuilder> {
        let mut search_path = Vec::new();
        if is_rustc_tool {
            search_path.push(self.deps_output[&CompileKind::Host].clone());
            search_path.push(self.sysroot_host_libdir.clone());
        } else {
            search_path.extend(super::filter_dynamic_search_path(
                self.native_dirs.iter(),
                &self.root_output[&kind],
            ));
            search_path.push(self.deps_output[&kind].clone());
            search_path.push(self.root_output[&kind].clone());
            // For build-std, we don't want to accidentally pull in any shared
            // libs from the sysroot that ships with rustc. This may not be
            // required (at least I cannot craft a situation where it
            // matters), but is here to be safe.
            if self.config.cli_unstable().build_std.is_none() {
                search_path.push(self.sysroot_target_libdir[&kind].clone());
            }
        }

        let dylib_path = paths::dylib_path();
        let dylib_path_is_empty = dylib_path.is_empty();
        search_path.extend(dylib_path.into_iter());
        if cfg!(target_os = "macos") && dylib_path_is_empty {
            // These are the defaults when DYLD_FALLBACK_LIBRARY_PATH isn't
            // set or set to an empty string. Since Cargo is explicitly setting
            // the value, make sure the defaults still work.
            if let Some(home) = env::var_os("HOME") {
                search_path.push(PathBuf::from(home).join("lib"));
            }
            search_path.push(PathBuf::from("/usr/local/lib"));
            search_path.push(PathBuf::from("/usr/lib"));
        }
        let search_path = paths::join_paths(&search_path, paths::dylib_path_envvar())?;

        cmd.env(paths::dylib_path_envvar(), &search_path);
        if let Some(meta) = script_meta {
            if let Some(env) = self.extra_env.get(&meta) {
                for (k, v) in env {
                    cmd.env(k, v);
                }
            }
        }

        let metadata = pkg.manifest().metadata();

        let cargo_exe = self.config.cargo_exe()?;
        cmd.env(crate::CARGO_ENV, cargo_exe);

        // When adding new environment variables depending on
        // crate properties which might require rebuild upon change
        // consider adding the corresponding properties to the hash
        // in BuildContext::target_metadata()
        cmd.env("CARGO_MANIFEST_DIR", pkg.root())
            .env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
            .env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
            .env("CARGO_PKG_VERSION_PATCH", &pkg.version().patch.to_string())
            .env("CARGO_PKG_VERSION_PRE", pkg.version().pre.as_str())
            .env("CARGO_PKG_VERSION", &pkg.version().to_string())
            .env("CARGO_PKG_NAME", &*pkg.name())
            .env(
                "CARGO_PKG_DESCRIPTION",
                metadata.description.as_ref().unwrap_or(&String::new()),
            )
            .env(
                "CARGO_PKG_HOMEPAGE",
                metadata.homepage.as_ref().unwrap_or(&String::new()),
            )
            .env(
                "CARGO_PKG_REPOSITORY",
                metadata.repository.as_ref().unwrap_or(&String::new()),
            )
            .env(
                "CARGO_PKG_LICENSE",
                metadata.license.as_ref().unwrap_or(&String::new()),
            )
            .env(
                "CARGO_PKG_LICENSE_FILE",
                metadata.license_file.as_ref().unwrap_or(&String::new()),
            )
            .env("CARGO_PKG_AUTHORS", &pkg.authors().join(":"))
            .env(
                "CARGO_PKG_RUST_VERSION",
                &pkg.rust_version().unwrap_or(&String::new()),
            )
            .cwd(pkg.root());

        // Apply any environment variables from the config
        for (key, value) in self.config.env_config()?.iter() {
            // never override a value that has already been set by cargo
            if cmd.get_envs().contains_key(key) {
                continue;
            }

            if value.is_force() || env::var_os(key).is_none() {
                cmd.env(key, value.resolve(self.config));
            }
        }

        Ok(cmd)
    }
}

/// Prepares a rustc_tool process with additional environment variables
/// that are only relevant in a context that has a unit
fn fill_rustc_tool_env(mut cmd: ProcessBuilder, unit: &Unit) -> ProcessBuilder {
    if unit.target.is_bin() {
        let name = unit
            .target
            .binary_filename()
            .unwrap_or(unit.target.name().to_string());

        cmd.env("CARGO_BIN_NAME", name);
    }
    cmd.env("CARGO_CRATE_NAME", unit.target.crate_name());
    cmd
}

fn target_runner(
    bcx: &BuildContext<'_, '_>,
    kind: CompileKind,
) -> CargoResult<Option<(PathBuf, Vec<String>)>> {
    let target = bcx.target_data.short_name(&kind);

    // try target.{}.runner
    let key = format!("target.{}.runner", target);

    if let Some(v) = bcx.config.get::<Option<config::PathAndArgs>>(&key)? {
        let path = v.path.resolve_program(bcx.config);
        return Ok(Some((path, v.args)));
    }

    // try target.'cfg(...)'.runner
    let target_cfg = bcx.target_data.info(kind).cfg();
    let mut cfgs = bcx
        .config
        .target_cfgs()?
        .iter()
        .filter_map(|(key, cfg)| cfg.runner.as_ref().map(|runner| (key, runner)))
        .filter(|(key, _runner)| CfgExpr::matches_key(key, target_cfg));
    let matching_runner = cfgs.next();
    if let Some((key, runner)) = cfgs.next() {
        anyhow::bail!(
            "several matching instances of `target.'cfg(..)'.runner` in `.cargo/config`\n\
             first match `{}` located in {}\n\
             second match `{}` located in {}",
            matching_runner.unwrap().0,
            matching_runner.unwrap().1.definition,
            key,
            runner.definition
        );
    }
    Ok(matching_runner.map(|(_k, runner)| {
        (
            runner.val.path.clone().resolve_program(bcx.config),
            runner.val.args.clone(),
        )
    }))
}
<commit_msg>Improve error msg for get target runner<commit_after>use std::collections::{BTreeSet, HashMap};
use std::env;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;

use cargo_platform::CfgExpr;
use cargo_util::{paths, ProcessBuilder};

use super::BuildContext;
use crate::core::compiler::{CompileKind, Metadata, Unit};
use crate::core::Package;
use crate::util::{config, CargoResult, Config};

/// Structure with enough information to run `rustdoc --test`.
pub struct Doctest {
    /// What's being doctested
    pub unit: Unit,
    /// Arguments needed to pass to rustdoc to run this test.
    pub args: Vec<OsString>,
    /// Whether or not -Zunstable-options is needed.
    pub unstable_opts: bool,
    /// The -Clinker value to use.
    pub linker: Option<PathBuf>,
    /// The script metadata, if this unit's package has a build script.
    ///
    /// This is used for indexing [`Compilation::extra_env`].
    pub script_meta: Option<Metadata>,

    /// Environment variables to set in the rustdoc process.
    pub env: HashMap<String, OsString>,
}

/// Information about the output of a unit.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub struct UnitOutput {
    /// The unit that generated this output.
    pub unit: Unit,
    /// Path to the unit's primary output (an executable or cdylib).
    pub path: PathBuf,
    /// The script metadata, if this unit's package has a build script.
    ///
    /// This is used for indexing [`Compilation::extra_env`].
    pub script_meta: Option<Metadata>,
}

/// A structure returning the result of a compilation.
pub struct Compilation<'cfg> {
    /// An array of all tests created during this compilation.
    pub tests: Vec<UnitOutput>,

    /// An array of all binaries created.
    pub binaries: Vec<UnitOutput>,

    /// An array of all cdylibs created.
    pub cdylibs: Vec<UnitOutput>,

    /// The crate names of the root units specified on the command-line.
    pub root_crate_names: Vec<String>,

    /// All directories for the output of native build commands.
    ///
    /// This is currently used to drive some entries which are added to the
    /// LD_LIBRARY_PATH as appropriate.
    ///
    /// The order should be deterministic.
    pub native_dirs: BTreeSet<PathBuf>,

    /// Root output directory (for the local package's artifacts)
    pub root_output: HashMap<CompileKind, PathBuf>,

    /// Output directory for rust dependencies.
    /// May be for the host or for a specific target.
    pub deps_output: HashMap<CompileKind, PathBuf>,

    /// The path to the host libdir for the compiler used
    sysroot_host_libdir: PathBuf,

    /// The path to libstd for each target
    sysroot_target_libdir: HashMap<CompileKind, PathBuf>,

    /// Extra environment variables that were passed to compilations and should
    /// be passed to future invocations of programs.
    ///
    /// The key is the build script metadata for uniquely identifying the
    /// `RunCustomBuild` unit that generated these env vars.
    pub extra_env: HashMap<Metadata, Vec<(String, String)>>,

    /// Libraries to test with rustdoc.
    pub to_doc_test: Vec<Doctest>,

    /// The target host triple.
    pub host: String,

    config: &'cfg Config,

    /// Rustc process to be used by default
    rustc_process: ProcessBuilder,
    /// Rustc process to be used for workspace crates instead of rustc_process
    rustc_workspace_wrapper_process: ProcessBuilder,
    /// Optional rustc process to be used for primary crates instead of either rustc_process or
    /// rustc_workspace_wrapper_process
    primary_rustc_process: Option<ProcessBuilder>,

    target_runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,
}

impl<'cfg> Compilation<'cfg> {
    pub fn new<'a>(bcx: &BuildContext<'a, 'cfg>) -> CargoResult<Compilation<'cfg>> {
        let mut rustc = bcx.rustc().process();
        let mut primary_rustc_process = bcx.build_config.primary_unit_rustc.clone();
        let mut rustc_workspace_wrapper_process = bcx.rustc().workspace_process();

        if bcx.config.extra_verbose() {
            rustc.display_env_vars();
            rustc_workspace_wrapper_process.display_env_vars();

            if let Some(rustc) = primary_rustc_process.as_mut() {
                rustc.display_env_vars();
            }
        }

        Ok(Compilation {
            // TODO: deprecated; remove.
            native_dirs: BTreeSet::new(),
            root_output: HashMap::new(),
            deps_output: HashMap::new(),
            sysroot_host_libdir: bcx
                .target_data
                .info(CompileKind::Host)
                .sysroot_host_libdir
                .clone(),
            sysroot_target_libdir: bcx
                .all_kinds
                .iter()
                .map(|&kind| {
                    (
                        kind,
                        bcx.target_data.info(kind).sysroot_target_libdir.clone(),
                    )
                })
                .collect(),
            tests: Vec::new(),
            binaries: Vec::new(),
            cdylibs: Vec::new(),
            root_crate_names: Vec::new(),
            extra_env: HashMap::new(),
            to_doc_test: Vec::new(),
            config: bcx.config,
            host: bcx.host_triple().to_string(),
            rustc_process: rustc,
            rustc_workspace_wrapper_process,
            primary_rustc_process,
            target_runners: bcx
                .build_config
                .requested_kinds
                .iter()
                .chain(Some(&CompileKind::Host))
                .map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
                .collect::<CargoResult<HashMap<_, _>>>()?,
        })
    }

    /// Returns a [`ProcessBuilder`] for running `rustc`.
    ///
    /// `is_primary` is true if this is a "primary package", which means it
    /// was selected by the user on the command-line (such as with a `-p`
    /// flag), see [`crate::core::compiler::Context::primary_packages`].
    ///
    /// `is_workspace` is true if this is a workspace member.
    pub fn rustc_process(
        &self,
        unit: &Unit,
        is_primary: bool,
        is_workspace: bool,
    ) -> CargoResult<ProcessBuilder> {
        let rustc = if is_primary && self.primary_rustc_process.is_some() {
            self.primary_rustc_process.clone().unwrap()
        } else if is_workspace {
            self.rustc_workspace_wrapper_process.clone()
        } else {
            self.rustc_process.clone()
        };

        let cmd = fill_rustc_tool_env(rustc, unit);
        self.fill_env(cmd, &unit.pkg, None, unit.kind, true)
    }

    /// Returns a [`ProcessBuilder`] for running `rustdoc`.
    pub fn rustdoc_process(
        &self,
        unit: &Unit,
        script_meta: Option<Metadata>,
    ) -> CargoResult<ProcessBuilder> {
        let rustdoc = ProcessBuilder::new(&*self.config.rustdoc()?);
        let cmd = fill_rustc_tool_env(rustdoc, unit);
        let mut cmd = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?;
        cmd.retry_with_argfile(true);
        unit.target.edition().cmd_edition_arg(&mut cmd);

        for crate_type in unit.target.rustc_crate_types() {
            cmd.arg("--crate-type").arg(crate_type.as_str());
        }

        Ok(cmd)
    }

    /// Returns a [`ProcessBuilder`] appropriate for running a process for the
    /// host platform.
    ///
    /// This is currently only used for running build scripts. If you use this
    /// for anything else, please be extra careful on how environment
    /// variables are set!
    pub fn host_process<T: AsRef<OsStr>>(
        &self,
        cmd: T,
        pkg: &Package,
    ) -> CargoResult<ProcessBuilder> {
        self.fill_env(
            ProcessBuilder::new(cmd),
            pkg,
            None,
            CompileKind::Host,
            false,
        )
    }

    pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec<String>)> {
        self.target_runners.get(&kind).and_then(|x| x.as_ref())
    }

    /// Returns a [`ProcessBuilder`] appropriate for running a process for the
    /// target platform. This is typically used for `cargo run` and `cargo
    /// test`.
    ///
    /// `script_meta` is the metadata for the `RunCustomBuild` unit that this
    /// unit used for its build script. Use `None` if the package did not have
    /// a build script.
    pub fn target_process<T: AsRef<OsStr>>(
        &self,
        cmd: T,
        kind: CompileKind,
        pkg: &Package,
        script_meta: Option<Metadata>,
    ) -> CargoResult<ProcessBuilder> {
        let builder = if let Some((runner, args)) = self.target_runner(kind) {
            let mut builder = ProcessBuilder::new(runner);
            builder.args(args);
            builder.arg(cmd);
            builder
        } else {
            ProcessBuilder::new(cmd)
        };
        self.fill_env(builder, pkg, script_meta, kind, false)
    }

    /// Prepares a new process with an appropriate environment to run against
    /// the artifacts produced by the build process.
    ///
    /// The package argument is also used to configure environment variables as
    /// well as the working directory of the child process.
    fn fill_env(
        &self,
        mut cmd: ProcessBuilder,
        pkg: &Package,
        script_meta: Option<Metadata>,
        kind: CompileKind,
        is_rustc_tool: bool,
    ) -> CargoResult<ProcessBuilder> {
        let mut search_path = Vec::new();
        if is_rustc_tool {
            search_path.push(self.deps_output[&CompileKind::Host].clone());
            search_path.push(self.sysroot_host_libdir.clone());
        } else {
            search_path.extend(super::filter_dynamic_search_path(
                self.native_dirs.iter(),
                &self.root_output[&kind],
            ));
            search_path.push(self.deps_output[&kind].clone());
            search_path.push(self.root_output[&kind].clone());
            // For build-std, we don't want to accidentally pull in any shared
            // libs from the sysroot that ships with rustc. This may not be
            // required (at least I cannot craft a situation where it
            // matters), but is here to be safe.
            if self.config.cli_unstable().build_std.is_none() {
                search_path.push(self.sysroot_target_libdir[&kind].clone());
            }
        }

        let dylib_path = paths::dylib_path();
        let dylib_path_is_empty = dylib_path.is_empty();
        search_path.extend(dylib_path.into_iter());
        if cfg!(target_os = "macos") && dylib_path_is_empty {
            // These are the defaults when DYLD_FALLBACK_LIBRARY_PATH isn't
            // set or set to an empty string. Since Cargo is explicitly setting
            // the value, make sure the defaults still work.
            if let Some(home) = env::var_os("HOME") {
                search_path.push(PathBuf::from(home).join("lib"));
            }
            search_path.push(PathBuf::from("/usr/local/lib"));
            search_path.push(PathBuf::from("/usr/lib"));
        }
        let search_path = paths::join_paths(&search_path, paths::dylib_path_envvar())?;

        cmd.env(paths::dylib_path_envvar(), &search_path);
        if let Some(meta) = script_meta {
            if let Some(env) = self.extra_env.get(&meta) {
                for (k, v) in env {
                    cmd.env(k, v);
                }
            }
        }

        let metadata = pkg.manifest().metadata();

        let cargo_exe = self.config.cargo_exe()?;
        cmd.env(crate::CARGO_ENV, cargo_exe);

        // When adding new environment variables depending on
        // crate properties which might require rebuild upon change
        // consider adding the corresponding properties to the hash
        // in BuildContext::target_metadata()
        cmd.env("CARGO_MANIFEST_DIR", pkg.root())
            .env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
            .env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
            .env("CARGO_PKG_VERSION_PATCH", &pkg.version().patch.to_string())
            .env("CARGO_PKG_VERSION_PRE", pkg.version().pre.as_str())
            .env("CARGO_PKG_VERSION", &pkg.version().to_string())
            .env("CARGO_PKG_NAME", &*pkg.name())
            .env(
                "CARGO_PKG_DESCRIPTION",
                metadata.description.as_ref().unwrap_or(&String::new()),
            )
            .env(
                "CARGO_PKG_HOMEPAGE",
                metadata.homepage.as_ref().unwrap_or(&String::new()),
            )
            .env(
                "CARGO_PKG_REPOSITORY",
                metadata.repository.as_ref().unwrap_or(&String::new()),
            )
            .env(
                "CARGO_PKG_LICENSE",
                metadata.license.as_ref().unwrap_or(&String::new()),
            )
            .env(
                "CARGO_PKG_LICENSE_FILE",
                metadata.license_file.as_ref().unwrap_or(&String::new()),
            )
            .env("CARGO_PKG_AUTHORS", &pkg.authors().join(":"))
            .env(
                "CARGO_PKG_RUST_VERSION",
                &pkg.rust_version().unwrap_or(&String::new()),
            )
            .cwd(pkg.root());

        // Apply any environment variables from the config
        for (key, value) in self.config.env_config()?.iter() {
            // never override a value that has already been set by cargo
            if cmd.get_envs().contains_key(key) {
                continue;
            }

            if value.is_force() || env::var_os(key).is_none() {
                cmd.env(key, value.resolve(self.config));
            }
        }

        Ok(cmd)
    }
}

/// Prepares a rustc_tool process with additional environment variables
/// that are only relevant in a context that has a unit
fn fill_rustc_tool_env(mut cmd: ProcessBuilder, unit: &Unit) -> ProcessBuilder {
    if unit.target.is_bin() {
        let name = unit
            .target
            .binary_filename()
            .unwrap_or(unit.target.name().to_string());

        cmd.env("CARGO_BIN_NAME", name);
    }
    cmd.env("CARGO_CRATE_NAME", unit.target.crate_name());
    cmd
}

fn target_runner(
    bcx: &BuildContext<'_, '_>,
    kind: CompileKind,
) -> CargoResult<Option<(PathBuf, Vec<String>)>> {
    let target = bcx.target_data.short_name(&kind);

    // try target.{}.runner
    let key = format!("target.{}.runner", target);

    if let Some(v) = bcx.config.get::<Option<config::PathAndArgs>>(&key)? {
        let path = v.path.resolve_program(bcx.config);
        return Ok(Some((path, v.args)));
    }

    // try target.'cfg(...)'.runner
    let target_cfg = bcx.target_data.info(kind).cfg();
    let mut cfgs = bcx
        .config
        .target_cfgs()?
        .iter()
        .filter_map(|(key, cfg)| cfg.runner.as_ref().map(|runner| (key, runner)))
        .filter(|(key, _runner)| CfgExpr::matches_key(key, target_cfg));
    let matching_runner = cfgs.next();
    if let Some((key, runner)) = cfgs.next() {
        anyhow::bail!(
            "several matching instances of `target.'cfg(..)'.runner` in configurations\n\
             first match `{}` located in {}\n\
             second match `{}` located in {}",
            matching_runner.unwrap().0,
            matching_runner.unwrap().1.definition,
            key,
            runner.definition
        );
    }
    Ok(matching_runner.map(|(_k, runner)| {
        (
            runner.val.path.clone().resolve_program(bcx.config),
            runner.val.args.clone(),
        )
    }))
}
<|endoftext|>


<commit_before>// C64 memory map overview: http://www.c64-wiki.com/index.php/Memory_Map
// Details about the PLA: http://www.c64-wiki.de/index.php/PLA_(C64-Chip)
// Even more PLA details: http://skoe.de/docs/c64-dissected/pla/c64_pla_dissected_r1.1_a4ss.pdf

pub struct C64;

impl C64 {
	pub fn new () -> C64 {
		C64
	}

	pub fn run (&mut self) {
		// TODO
	}
}
<commit_msg>Implemented C64Memory<commit_after>use addressable::Addressable;
use ram::Ram;
use rom::Rom;

// C64 memory map overview: http://www.c64-wiki.com/index.php/Memory_Map
// Details about the PLA: http://www.c64-wiki.de/index.php/PLA_(C64-Chip)
// Even more PLA details: http://skoe.de/docs/c64-dissected/pla/c64_pla_dissected_r1.1_a4ss.pdf

// 64K RAM (not every part is always accessible)
// 8K BASIC ROM at $A000
// 4K character ROM at $D000
// 8K kernal ROM at $E000

struct C64Memory {
	ram: Ram<u16>,
	kernal: Rom<u16>,
	basic: Rom<u16>,
	characters: Rom<u16>,
}

impl C64Memory {
	fn new () -> C64Memory {
		C64Memory {
			ram: Ram::new(),
			kernal: Rom::new(&Path("kernal.rom")),
			basic: Rom::new(&Path("basic.rom")),
			characters: Rom::new(&Path("characters.rom")),
		}
	}
}

impl Addressable<u16> for C64Memory {
	fn get (&self, addr: u16) -> u8 {
		match addr {
			// TODO: Switch memory access based on LORAM/HIRAM/CHAREN
			0xa000..0xbfff => self.basic.get(addr - 0xa000),
			0xd000..0xdfff => self.characters.get(addr - 0xd000),
			0xe000..0xffff => self.kernal.get(addr - 0xe000),
			_              => self.ram.get(addr),
		}
	}

	fn set (&mut self, addr: u16, data: u8) {
		self.ram.set(addr, data);
	}
}

pub struct C64;

impl C64 {
	pub fn new () -> C64 {
		C64
	}

	pub fn run (&mut self) {
		// TODO
	}
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate num;

use libc::{c_char, c_double, c_float, c_int};
use num::complex::{Complex32, Complex64};

#[link(name = "arpack")]
extern {

    // single precision symmetric

    fn ssaupd_(ido: *mut c_int,
               bmat: *mut c_char,
               n: *mut c_int,
               which: *mut c_char,
               nev: *mut c_int,
               tol: *mut c_float,
               resid: *mut c_float,
               ncv: *mut c_int,
               v: *mut c_float,
               ldv: *mut c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *mut c_int,
               info: *mut c_int);

    fn sseupd_(rvec: *mut c_int,
               All: *mut c_char,
               select: *mut c_int,
               d: *mut c_float,
               z: *mut c_float,
               ldz: *mut c_int,
               sigma: *mut c_float,
               bmat: *mut c_char,
               n: *mut c_int,
               which: *mut c_char,
               nev: *mut c_int,
               tol: *mut c_float,
               resid: *mut c_float,
               ncv: *mut c_int,
               v: *mut c_float,
               ldv: *mut c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *mut c_int,
               ierr: *mut c_int);

    // double precision symmetric

    fn dsaupd_(ido: *mut c_int,
               bmat: *mut c_char,
               n: *mut c_int,
               which: *mut c_char,
               nev: *mut c_int,
               tol: *mut c_double,
               resid: *mut c_double,
               ncv: *mut c_int,
               v: *mut c_double,
               ldv: *mut c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *mut c_int,
               info: *mut c_int);

    fn dseupd_(rvec: *mut c_int,
               All: *mut c_char,
               select: *mut c_int,
               d: *mut c_double,
               z: *mut c_double,
               ldz: *mut c_int,
               sigma: *mut c_double,
               bmat: *mut c_char,
               n: *mut c_int,
               which: *mut c_char,
               nev: *mut c_int,
               tol: *mut c_double,
               resid: *mut c_double,
               ncv: *mut c_int,
               v: *mut c_double,
               ldv: *mut c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *mut c_int,
               ierr: *mut c_int);

    // single precision non-symmetric

    // fixme: fn snaupd_();
    // fixme: fn sneupd_();

    // double precision non-symmetric

    // fixme: fn dnaupd_();
    // fixme: fn dneupd_();

    // single precision complex

    fn cnaupd_(ido: *mut c_int,
               bmat: *mut c_char,
               n: *mut c_int,
               which: *mut c_char,
               nev: *mut c_int,
               tol: *mut c_float,
               resid: *mut Complex32,
               ncv: *mut c_int,
               v: *mut Complex32,
               ldv: *mut c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex32,
               workl: *mut Complex32,
               lworkl: *mut c_int,
               rwork: *mut c_float,
               info: *mut c_int);

    fn cneupd_(rvec: *mut c_int,
               All: *mut c_char,
               select: *mut c_int,
               d: *mut Complex32,
               v: *mut Complex32,
               ldv: *mut c_int,
               sigma: *mut c_float,
               workev: *mut Complex32,
               bmat: *mut c_char,
               n: *mut c_int,
               which: *mut c_char,
               nev: *mut c_int,
               tol: *mut c_float,
               resid: *mut Complex32,
               ncv: *mut c_int,
               v: *mut Complex32,
               ldv: *mut c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex32,
               workl: *mut Complex32,
               lworkl: *mut c_int,
               rwork: *mut c_float,
               ierr: *mut c_int);

    // double precision complex

    fn znaupd_(ido: *mut c_int,
               bmat: *mut c_char,
               n: *mut c_int,
               which: *mut c_char,
               nev: *mut c_int,
               tol: *mut c_double,
               resid: *mut Complex64,
               ncv: *mut c_int,
               v: *mut Complex64,
               ldv: *mut c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex64,
               workl: *mut Complex64,
               lworkl: *mut c_int,
               rwork: *mut c_double,
               info: *mut c_int);

    fn zneupd_(rvec: *mut c_int,
               All: *mut c_char,
               select: *mut c_int,
               d: *mut Complex64,
               v: *mut Complex64,
               ldv: *mut c_int,
               sigma: *mut c_double,
               workev: *mut Complex64,
               bmat: *mut c_char,
               n: *mut c_int,
               which: *mut c_char,
               nev: *mut c_int,
               tol: *mut c_double,
               resid: *mut Complex64,
               ncv: *mut c_int,
               v: *mut Complex64,
               ldv: *mut c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex64,
               workl: *mut Complex64,
               lworkl: *mut c_int,
               rwork: *mut c_double,
               ierr: *mut c_int);

}
<commit_msg>additional work on mut/const arguments<commit_after>extern crate libc;
extern crate num;

use libc::{c_char, c_double, c_float, c_int};
use num::complex::Complex;

#[link(name = "arpack")]
extern {

    // single precision symmetric

    fn ssaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               info: *mut c_int);

    fn sseupd_(rvec: *const c_int,
               All: *const c_char,
               select: *mut c_int,
               d: *mut c_float,
               z: *mut c_float,
               ldz: *const c_int,
               sigma: *const c_float,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               ierr: *mut c_int);

    // double precision symmetric

    fn dsaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               info: *mut c_int);

    fn dseupd_(rvec: *const c_int,
               All: *const c_char,
               select: *mut c_int,
               d: *mut c_double,
               z: *mut c_double,
               ldz: *const c_int,
               sigma: *const c_double,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               ierr: *mut c_int);

    // single precision non-symmetric

    // fixme: fn snaupd_();
    // fixme: fn sneupd_();

    // double precision non-symmetric

    // fixme: fn dnaupd_();
    // fixme: fn dneupd_();

    // single precision complex

    fn cnaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut Complex<c_float>,
               ncv: *const c_int,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_float>,
               workl: *mut Complex<c_float>,
               lworkl: *const c_int,
               rwork: *mut c_float,
               info: *mut c_int);

    fn cneupd_(rvec: *const c_int,
               All: *const c_char,
               select: *mut c_int,
               d: *mut Complex<c_float>,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               sigma: *const c_float,
               workev: *mut Complex<c_float>,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut Complex<c_float>,
               ncv: *const c_int,
               v: *mut Complex<c_float>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_float>,
               workl: *mut Complex<c_float>,
               lworkl: *const c_int,
               rwork: *mut c_float,
               ierr: *mut c_int);

    // double precision complex

    fn znaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut Complex<c_double>,
               ncv: *const c_int,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_double>,
               workl: *mut Complex<c_double>,
               lworkl: *const c_int,
               rwork: *mut c_double,
               info: *mut c_int);

    fn zneupd_(rvec: *const c_int,
               All: *const c_char,
               select: *mut c_int,
               d: *mut Complex<c_double>,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               sigma: *const c_double,
               workev: *mut Complex<c_double>,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut Complex<c_double>,
               ncv: *const c_int,
               v: *mut Complex<c_double>,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut Complex<c_double>,
               workl: *mut Complex<c_double>,
               lworkl: *const c_int,
               rwork: *mut c_double,
               ierr: *mut c_int);

}
<|endoftext|>


<commit_before>// Copyright 2016, 2017 James Bostock. See the LICENSE file at the
// top-level directory of this distribution.

// An implementation of the rm(1) command in Rust.
// See http://man.cat-v.org/unix-6th/1/rm
use std::env;
use std::fs;
use std::io;
use std::io::Write;

#[macro_use]
mod util;

/// Prompts user for confirmation
fn confirm(msg: &str) -> io::Result<bool> {
    print!("{}: ", msg);
    io::stdout().flush()?;
    let mut resp = String::new();
    io::stdin().read_line(&mut resp)?;
    match resp.chars().next() {
        Some(c) => {
            if c == 'y' {
                Ok(true)
            } else {
                Ok(false)
            }
        },
        None => Ok(false)
    }
}

/// Removes a file or directory
fn rm(name: &str, force: bool, recursive: bool) -> io::Result<()> {
    let md = fs::metadata(name)?;
    let go = if md.permissions().readonly() {
        let mut msg = "rm: remove readonly file ".to_string();
        msg.push_str(&name);
        msg.push_str("?");
        if confirm(&msg)? {
            true
        } else {
            false
        }
    } else {
        true
    };

    if go {
        if recursive {
            fs::remove_dir_all(name)
        } else {
            fs::remove_file(name)
        }
    } else {
        Ok(())
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let mut processing_options: bool = true;
    let mut force: bool = false;
    let mut recursive: bool = false;

    if args.len() > 1 {
        for arg in args.iter().skip(1) {
            if arg == "-f" {
                if processing_options {
                    force = true;
                    continue;
                }
            } else if arg == "-r" {
                if processing_options {
                    recursive = true;
                    continue;
                }
            } else {
                processing_options = false;
            }

            match rm(arg, force, recursive) {
                Ok(_) => {},
                Err(e) => eprintln!("{}: {}", arg, e)
            }
        }
    } else {
        eprintln!("usage: {} [-f][-r] file ...", args[0]);
    }
}
<commit_msg>rm: respect the -f command line option.<commit_after>// Copyright 2016, 2017 James Bostock. See the LICENSE file at the
// top-level directory of this distribution.

// An implementation of the rm(1) command in Rust.
// See http://man.cat-v.org/unix-6th/1/rm
use std::env;
use std::fs;
use std::io;
use std::io::Write;

#[macro_use]
mod util;

/// Prompts user for confirmation
fn confirm(msg: &str) -> io::Result<bool> {
    print!("{}: ", msg);
    io::stdout().flush()?;
    let mut resp = String::new();
    io::stdin().read_line(&mut resp)?;
    match resp.chars().next() {
        Some(c) => {
            if c == 'y' {
                Ok(true)
            } else {
                Ok(false)
            }
        },
        None => Ok(false)
    }
}

/// Removes a file or directory
fn rm(name: &str, force: bool, recursive: bool) -> io::Result<()> {
    let md = fs::metadata(name)?;
    let go = if !force && md.permissions().readonly() {
        let mut msg = "rm: remove readonly file ".to_string();
        msg.push_str(&name);
        msg.push_str("?");
        if confirm(&msg)? {
            true
        } else {
            false
        }
    } else {
        true
    };

    if go {
        if recursive {
            fs::remove_dir_all(name)
        } else {
            fs::remove_file(name)
        }
    } else {
        Ok(())
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let mut processing_options: bool = true;
    let mut force: bool = false;
    let mut recursive: bool = false;

    if args.len() > 1 {
        for arg in args.iter().skip(1) {
            if arg == "-f" {
                if processing_options {
                    force = true;
                    continue;
                }
            } else if arg == "-r" {
                if processing_options {
                    recursive = true;
                    continue;
                }
            } else {
                processing_options = false;
            }

            match rm(arg, force, recursive) {
                Ok(_) => {},
                Err(e) => eprintln!("{}: {}", arg, e)
            }
        }
    } else {
        eprintln!("usage: {} [-f][-r] file ...", args[0]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa::foundation::NSRange;

pub enum MTLBuffer {}

foreign_obj_type! {
    type CType = MTLBuffer;
    pub struct Buffer;
    pub struct BufferRef;
    type ParentType = ResourceRef;
}

impl BufferRef {
    pub fn length(&self) -> u64 {
        unsafe { msg_send![self, length] }
    }

    pub fn contents(&self) -> *mut std::ffi::c_void {
        unsafe { msg_send![self, contents] }
    }

    pub fn did_modify_range(&self, range: NSRange) {
        unsafe { msg_send![self, didModifyRange: range] }
    }

    pub fn new_texture_from_contents(
        &self,
        descriptor: &TextureDescriptorRef,
        offset: u64,
        stride: u64,
    ) -> Texture {
        unsafe {
            msg_send![self,
                newTextureWithDescriptor:descriptor
                offset:offset
                bytesPerRow:stride
            ]
        }
    }
}
<commit_msg>Add `Buffer::set_label` and `Buffer::add_debug_marker`<commit_after>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa::foundation::NSRange;

pub enum MTLBuffer {}

foreign_obj_type! {
    type CType = MTLBuffer;
    pub struct Buffer;
    pub struct BufferRef;
    type ParentType = ResourceRef;
}

impl BufferRef {
    pub fn length(&self) -> u64 {
        unsafe { msg_send![self, length] }
    }

    pub fn contents(&self) -> *mut std::ffi::c_void {
        unsafe { msg_send![self, contents] }
    }

    pub fn did_modify_range(&self, range: NSRange) {
        unsafe { msg_send![self, didModifyRange: range] }
    }

    pub fn new_texture_from_contents(
        &self,
        descriptor: &TextureDescriptorRef,
        offset: u64,
        stride: u64,
    ) -> Texture {
        unsafe {
            msg_send![self,
                newTextureWithDescriptor:descriptor
                offset:offset
                bytesPerRow:stride
            ]
        }
    }

    pub fn set_label(&self, name: &str) {
        unsafe {
            let name = crate::nsstring_from_str(name);
            msg_send![self, setLabel:name]
        }
    }

    pub fn add_debug_marker(&self, name: &str, range: NSRange) {
        unsafe {
            let name = crate::nsstring_from_str(name);
            msg_send![self, addDebugMarker:name range:range]
        }
    }
}
<|endoftext|>


<commit_before>extern crate reqwest;

#[cfg(test)]
use mockito;

use self::reqwest::Client as NetworkClient;

use error::CDCError;
use error::CDCResult;
use request::rq_get;
use std::fmt;

#[cfg(not(test))]
const LIVE_URL: &'static str = "https://media-qa.services.pbs.org/api/v1";
#[cfg(not(test))]
const QA_URL: &'static str = "https://media-qa.services.pbs.org/api/v1";

#[cfg(test)]
const LIVE_URL: &'static str = mockito::SERVER_URL;
#[cfg(test)]
const QA_URL: &'static str = mockito::SERVER_URL;

pub struct Client<'a> {
    key: &'a str,
    secret: &'a str,
    base: &'a str,
    client: NetworkClient,
}

pub type Params<'a> = Vec<(&'a str, &'a str)>;

#[derive(Debug)]
pub enum Endpoints {
    Asset,
    Changelog,
    Collection,
    Episode,
    Franchise,
    Season,
    Show,
    Special,
}

impl fmt::Display for Endpoints {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let string_form = match *self {
            Endpoints::Asset => "assets",
            Endpoints::Changelog => "changelog",
            Endpoints::Collection => "collections",
            Endpoints::Episode => "episodes",
            Endpoints::Franchise => "franchises",
            Endpoints::Season => "seasons",
            Endpoints::Show => "shows",
            Endpoints::Special => "specials",
        };

        write!(f, "{}", string_form)
    }
}

impl<'a> Client<'a> {
    pub fn new(key: &'a str, secret: &'a str) -> CDCResult<Client<'a>> {
        client_builder(key, secret, LIVE_URL)
    }

    pub fn qa(key: &'a str, secret: &'a str) -> CDCResult<Client<'a>> {
        client_builder(key, secret, QA_URL)
    }

    pub fn get(&self, endpoint: Endpoints, id: &str) -> CDCResult<String> {
        rq_get(&self.client,
               vec![self.base, "/", endpoint.to_string().as_str(), "/", id, "/"]
                   .join("")
                   .as_str(),
               vec![])
    }

    pub fn list(&self, endpoint: Endpoints, params: Params) -> CDCResult<String> {
        rq_get(&self.client,
               vec![self.base, "/", endpoint.to_string().as_str(), "/"]
                   .join("")
                   .as_str(),
               params)
    }

    pub fn url(&self, url: &str) -> CDCResult<String> {
        rq_get(&self.client, url, vec![])
    }

    // Convenience methods for the various types
    // Endpoints::Asset => "assets",
    // Endpoints::Changelog => "changelog",
    // Endpoints::Collection => "collections",
    // Endpoints::Episode => "episodes",
    // Endpoints::Franchise => "franchises",
    // Endpoints::Season => "seasons",
    // Endpoints::Show => "shows",
    // Endpoints::Special => "specials",
    pub fn asset(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Episode, id)
    }

    pub fn changelog(&self, params: Params) -> CDCResult<String> {
        self.list(Endpoints::Changelog, params)
    }

    pub fn collection(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Collection, id)
    }

    pub fn collections(&self, params: Params) -> CDCResult<String> {
        self.list(Endpoints::Collection, params)
    }

    pub fn episode(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Episode, id)
    }

    pub fn franchise(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Franchise, id)
    }

    pub fn franchises(&self, params: Params) -> CDCResult<String> {
        self.list(Endpoints::Franchise, params)
    }

    pub fn season(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Season, id)
    }

    pub fn special(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Special, id)
    }

    pub fn show(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Show, id)
    }

    pub fn shows(&self, params: Params) -> CDCResult<String> {
        self.list(Endpoints::Show, params)
    }
}

fn client_builder<'a>(key: &'a str, secret: &'a str, base: &'a str) -> CDCResult<Client<'a>> {
    NetworkClient::new().map_err(CDCError::Network).and_then(|netClient| {
        Ok(Client {
            key: key,
            secret: secret,
            base: base,
            client: netClient,
        })
    })
}
<commit_msg>Remove extraneous comments<commit_after>extern crate reqwest;

#[cfg(test)]
use mockito;

use self::reqwest::Client as NetworkClient;

use error::CDCError;
use error::CDCResult;
use request::rq_get;
use std::fmt;

#[cfg(not(test))]
const LIVE_URL: &'static str = "https://media-qa.services.pbs.org/api/v1";
#[cfg(not(test))]
const QA_URL: &'static str = "https://media-qa.services.pbs.org/api/v1";

#[cfg(test)]
const LIVE_URL: &'static str = mockito::SERVER_URL;
#[cfg(test)]
const QA_URL: &'static str = mockito::SERVER_URL;

pub struct Client<'a> {
    key: &'a str,
    secret: &'a str,
    base: &'a str,
    client: NetworkClient,
}

pub type Params<'a> = Vec<(&'a str, &'a str)>;

#[derive(Debug)]
pub enum Endpoints {
    Asset,
    Changelog,
    Collection,
    Episode,
    Franchise,
    Season,
    Show,
    Special,
}

impl fmt::Display for Endpoints {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let string_form = match *self {
            Endpoints::Asset => "assets",
            Endpoints::Changelog => "changelog",
            Endpoints::Collection => "collections",
            Endpoints::Episode => "episodes",
            Endpoints::Franchise => "franchises",
            Endpoints::Season => "seasons",
            Endpoints::Show => "shows",
            Endpoints::Special => "specials",
        };

        write!(f, "{}", string_form)
    }
}

impl<'a> Client<'a> {
    pub fn new(key: &'a str, secret: &'a str) -> CDCResult<Client<'a>> {
        client_builder(key, secret, LIVE_URL)
    }

    pub fn qa(key: &'a str, secret: &'a str) -> CDCResult<Client<'a>> {
        client_builder(key, secret, QA_URL)
    }

    pub fn get(&self, endpoint: Endpoints, id: &str) -> CDCResult<String> {
        rq_get(&self.client,
               vec![self.base, "/", endpoint.to_string().as_str(), "/", id, "/"]
                   .join("")
                   .as_str(),
               vec![])
    }

    pub fn list(&self, endpoint: Endpoints, params: Params) -> CDCResult<String> {
        rq_get(&self.client,
               vec![self.base, "/", endpoint.to_string().as_str(), "/"]
                   .join("")
                   .as_str(),
               params)
    }

    pub fn url(&self, url: &str) -> CDCResult<String> {
        rq_get(&self.client, url, vec![])
    }

    pub fn asset(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Episode, id)
    }

    pub fn changelog(&self, params: Params) -> CDCResult<String> {
        self.list(Endpoints::Changelog, params)
    }

    pub fn collection(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Collection, id)
    }

    pub fn collections(&self, params: Params) -> CDCResult<String> {
        self.list(Endpoints::Collection, params)
    }

    pub fn episode(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Episode, id)
    }

    pub fn franchise(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Franchise, id)
    }

    pub fn franchises(&self, params: Params) -> CDCResult<String> {
        self.list(Endpoints::Franchise, params)
    }

    pub fn season(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Season, id)
    }

    pub fn special(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Special, id)
    }

    pub fn show(&self, id: &str) -> CDCResult<String> {
        self.get(Endpoints::Show, id)
    }

    pub fn shows(&self, params: Params) -> CDCResult<String> {
        self.list(Endpoints::Show, params)
    }
}

fn client_builder<'a>(key: &'a str, secret: &'a str, base: &'a str) -> CDCResult<Client<'a>> {
    NetworkClient::new().map_err(CDCError::Network).and_then(|netClient| {
        Ok(Client {
            key: key,
            secret: secret,
            base: base,
            client: netClient,
        })
    })
}
<|endoftext|>