<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use super::SubTok;

use util::ascii::is_ascii_alnum;
use std::char::{to_digit, from_u32};

#[path="../../../generated/char_ref_data.rs"]
mod data;

pub struct CharRef {
    chars: [char, ..2],
    num_chars: u8,
    parse_error: bool,
}

pub enum Status {
    Stuck,
    Progress,
    Done,
}

enum State {
    Begin,
    Octothorpe,
    Numeric(u32), // base
    NumericSemicolon,
    Named,
}

pub struct CharRefTokenizer {
    priv state: State,
    priv addnl_allowed: Option<char>,
    priv result: Option<CharRef>,

    priv num: u32,
    priv num_too_big: bool,
    priv seen_digit: bool,
    priv hex_marker: Option<char>,

    priv name_buf_opt: Option<~str>,
    priv name_match: Option<&'static [char, ..2]>,
    priv name_len: uint,
}

impl CharRefTokenizer {
    // NB: We assume that we have an additional allowed character iff we're
    // tokenizing in an attribute value.
    pub fn new(addnl_allowed: Option<char>) -> CharRefTokenizer {
        CharRefTokenizer {
            state: Begin,
            addnl_allowed: addnl_allowed,
            result: None,
            num: 0,
            num_too_big: false,
            seen_digit: false,
            hex_marker: None,
            name_buf_opt: None,
            name_match: None,
            name_len: 0,
        }
    }

    pub fn step<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        if self.result.is_some() {
            return Done;
        }

        debug!("char ref tokenizer stepping in state {:?}", self.state);
        match self.state {
            Begin => self.do_begin(tokenizer),
            Octothorpe => self.do_octothorpe(tokenizer),
            Numeric(base) => self.do_numeric(tokenizer, base),
            NumericSemicolon => self.do_numeric_semicolon(tokenizer),
            Named => self.do_named(tokenizer),
        }
    }

    // A CharRefTokenizer can only tokenize one character reference,
    // so this method consumes the tokenizer.
    pub fn get_result(self) -> CharRef {
        self.result.expect("get_result called before done")
    }

    fn name_buf<'t>(&'t mut self) -> &'t mut ~str {
        self.name_buf_opt.as_mut()
            .expect("name_buf missing in named character reference")
    }

    fn finish_none(&mut self, error: bool) -> Status {
        self.result = Some(CharRef {
            chars: ['\0', '\0'],
            num_chars: 0,
            parse_error: error,
        });
        Done
    }

    fn finish_one(&mut self, c: char, error: bool) -> Status {
        self.result = Some(CharRef {
            chars: [c, '\0'],
            num_chars: 1,
            parse_error: error,
        });
        Done
    }

    fn do_begin<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        match unwrap_or_return!(tokenizer.peek(), Stuck) {
            '\t' | '\n' | '\x0C' | ' ' | '<' | '&'
                => self.finish_none(false),
            c if Some(c) == self.addnl_allowed
                => self.finish_none(false),

            '#' => {
                tokenizer.discard_char();
                self.state = Octothorpe;
                Progress
            }

            _ => {
                self.state = Named;
                self.name_buf_opt = Some(~"");
                Progress
            }
        }
    }

    fn do_octothorpe<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        match c {
            'x' | 'X' => {
                tokenizer.discard_char();
                self.hex_marker = Some(c);
                self.state = Numeric(16);
            }

            _ => {
                self.hex_marker = None;
                self.state = Numeric(10);
            }
        }
        Progress
    }

    fn do_numeric<T: SubTok>(&mut self, tokenizer: &mut T, base: u32) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        match to_digit(c, base as uint) {
            Some(n) => {
                tokenizer.discard_char();
                self.num *= base;
                if self.num > 0x10FFFF {
                    // We might overflow, and the character is definitely invalid.
                    // We still parse digits and semicolon, but don't use the result.
                    self.num_too_big = true;
                }
                self.num += n as u32;
                self.seen_digit = true;
                Progress
            }

            None if !self.seen_digit => {
                let mut unconsume = ~"#";
                match self.hex_marker {
                    Some(c) => unconsume.push_char(c),
                    None => (),
                }

                tokenizer.unconsume(unconsume);
                self.finish_none(true)
            }

            None => {
                self.state = NumericSemicolon;
                Progress
            }
        }
    }

    fn do_numeric_semicolon<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let semi_missing = match unwrap_or_return!(tokenizer.peek(), Stuck) {
            ';' => { tokenizer.discard_char(); false }
            _   => true
        };
        self.finish_numeric(semi_missing)
    }

    fn finish_numeric(&mut self, parse_error: bool) -> Status {
        fn conv(n: u32) -> char {
            from_u32(n).expect("invalid char missed by error handling cases")
        }

        match self.num {
            n if (n > 0x10FFFF) || self.num_too_big => self.finish_one('\ufffd', true),
            0x00 | 0xD800..0xDFFF => self.finish_one('\ufffd', true),

            0x80..0x9F => match data::c1_replacements[self.num - 0x80] {
                Some(c) => self.finish_one(c, true),
                None => self.finish_one(conv(self.num), true),
            },

            0x01..0x08 | 0x0B | 0x0D..0x1F | 0x7F | 0xFDD0..0xFDEF
                => self.finish_one(conv(self.num), true),

            n if (n & 0xFFFE) == 0xFFFE
                => self.finish_one(conv(n), true),

            n => self.finish_one(conv(n), parse_error),
        }
    }

    fn do_named<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        tokenizer.discard_char();
        self.name_buf().push_char(c);
        match data::named_entities.find(&self.name_buf().as_slice()) {
            // We have either a full match or a prefix of one.
            Some(m) => {
                if m[0] != '\0' {
                    // We have a full match, but there might be a longer one to come.
                    self.name_match = Some(m);
                    self.name_len = self.name_buf().len();
                }
                // Otherwise we just have a prefix match.
                Progress
            }

            // Can't continue the match.
            None => match self.name_match {
                None => {
                    // FIXME: "if the characters after the U+0026 AMPERSAND
                    // character (&) consist of a sequence of one or more
                    // alphanumeric ASCII characters followed by a U+003B
                    // SEMICOLON character (;), then this is a parse error".

                    tokenizer.unconsume(self.name_buf_opt.take_unwrap());
                    self.finish_none(false)
                }
                Some(m) => {
                    // We have a complete match, but we've consumed at least
                    // one additional character into self.name_buf, and more
                    // in cases like
                    //
                    //     &not    => match for U+00AC
                    //     &noti   => valid prefix for &notin
                    //     &notit  => can't continue match

                    assert!(self.name_len > 0);
                    assert!(self.name_len < self.name_buf().len());
                    let last_matched = self.name_buf().char_at(self.name_len-1);
                    let next_after   = self.name_buf().char_at(self.name_len);

                    // "If the character reference is being consumed as part of
                    // an attribute, and the last character matched is not a
                    // U+003B SEMICOLON character (;), and the next character
                    // is either a U+003D EQUALS SIGN character (=) or an
                    // alphanumeric ASCII character..."
                    if self.addnl_allowed.is_some() && (last_matched != ';')
                        && ((next_after == '=') || is_ascii_alnum(next_after)) {
                        // "...all the characters that were matched after the
                        // U+0026 AMPERSAND character (&) must be unconsumed,
                        // and nothing is returned"
                        tokenizer.unconsume(self.name_buf_opt.take_unwrap());

                        // "...if this next character is in fact a U+003D
                        // EQUALS SIGN character (=), then this is a parse
                        // error"
                        self.finish_none(next_after == '=')
                    } else {
                        tokenizer.unconsume(self.name_buf().slice_from(self.name_len).to_owned());

                        self.result = Some(CharRef {
                            chars: *m,
                            num_chars: if m[1] == '\0' { 1 } else { 2 },
                            parse_error: ';' != last_matched,
                        });
                        Done
                    }
                }
            }
        }
    }

    pub fn end_of_file<T: SubTok>(&mut self, _tokenizer: &mut T) {
        match self.state {
            Begin => { self.finish_none(false); }

            // FIXME: Handling the rest of these correctly requires unconsuming
            // characters after EOF, which the main tokenizer can't handle yet.

            Numeric(_) | NumericSemicolon => {
                self.finish_numeric(true);
            }

            Named | Octothorpe => {
                self.finish_none(true);
            }
        }
    }
}
<commit_msg>Partially support named character references at EOF<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use super::SubTok;

use util::ascii::is_ascii_alnum;
use std::char::{to_digit, from_u32};

#[path="../../../generated/char_ref_data.rs"]
mod data;

pub struct CharRef {
    chars: [char, ..2],
    num_chars: u8,
    parse_error: bool,
}

pub enum Status {
    Stuck,
    Progress,
    Done,
}

enum State {
    Begin,
    Octothorpe,
    Numeric(u32), // base
    NumericSemicolon,
    Named,
}

pub struct CharRefTokenizer {
    priv state: State,
    priv addnl_allowed: Option<char>,
    priv result: Option<CharRef>,

    priv num: u32,
    priv num_too_big: bool,
    priv seen_digit: bool,
    priv hex_marker: Option<char>,

    priv name_buf_opt: Option<~str>,
    priv name_match: Option<&'static [char, ..2]>,
    priv name_len: uint,
}

impl CharRefTokenizer {
    // NB: We assume that we have an additional allowed character iff we're
    // tokenizing in an attribute value.
    pub fn new(addnl_allowed: Option<char>) -> CharRefTokenizer {
        CharRefTokenizer {
            state: Begin,
            addnl_allowed: addnl_allowed,
            result: None,
            num: 0,
            num_too_big: false,
            seen_digit: false,
            hex_marker: None,
            name_buf_opt: None,
            name_match: None,
            name_len: 0,
        }
    }

    pub fn step<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        if self.result.is_some() {
            return Done;
        }

        debug!("char ref tokenizer stepping in state {:?}", self.state);
        match self.state {
            Begin => self.do_begin(tokenizer),
            Octothorpe => self.do_octothorpe(tokenizer),
            Numeric(base) => self.do_numeric(tokenizer, base),
            NumericSemicolon => self.do_numeric_semicolon(tokenizer),
            Named => self.do_named(tokenizer),
        }
    }

    // A CharRefTokenizer can only tokenize one character reference,
    // so this method consumes the tokenizer.
    pub fn get_result(self) -> CharRef {
        self.result.expect("get_result called before done")
    }

    fn name_buf<'t>(&'t mut self) -> &'t mut ~str {
        self.name_buf_opt.as_mut()
            .expect("name_buf missing in named character reference")
    }

    fn finish_none(&mut self, error: bool) -> Status {
        self.result = Some(CharRef {
            chars: ['\0', '\0'],
            num_chars: 0,
            parse_error: error,
        });
        Done
    }

    fn finish_one(&mut self, c: char, error: bool) -> Status {
        self.result = Some(CharRef {
            chars: [c, '\0'],
            num_chars: 1,
            parse_error: error,
        });
        Done
    }

    fn do_begin<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        match unwrap_or_return!(tokenizer.peek(), Stuck) {
            '\t' | '\n' | '\x0C' | ' ' | '<' | '&'
                => self.finish_none(false),
            c if Some(c) == self.addnl_allowed
                => self.finish_none(false),

            '#' => {
                tokenizer.discard_char();
                self.state = Octothorpe;
                Progress
            }

            _ => {
                self.state = Named;
                self.name_buf_opt = Some(~"");
                Progress
            }
        }
    }

    fn do_octothorpe<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        match c {
            'x' | 'X' => {
                tokenizer.discard_char();
                self.hex_marker = Some(c);
                self.state = Numeric(16);
            }

            _ => {
                self.hex_marker = None;
                self.state = Numeric(10);
            }
        }
        Progress
    }

    fn do_numeric<T: SubTok>(&mut self, tokenizer: &mut T, base: u32) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        match to_digit(c, base as uint) {
            Some(n) => {
                tokenizer.discard_char();
                self.num *= base;
                if self.num > 0x10FFFF {
                    // We might overflow, and the character is definitely invalid.
                    // We still parse digits and semicolon, but don't use the result.
                    self.num_too_big = true;
                }
                self.num += n as u32;
                self.seen_digit = true;
                Progress
            }

            None if !self.seen_digit => {
                let mut unconsume = ~"#";
                match self.hex_marker {
                    Some(c) => unconsume.push_char(c),
                    None => (),
                }

                tokenizer.unconsume(unconsume);
                self.finish_none(true)
            }

            None => {
                self.state = NumericSemicolon;
                Progress
            }
        }
    }

    fn do_numeric_semicolon<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let semi_missing = match unwrap_or_return!(tokenizer.peek(), Stuck) {
            ';' => { tokenizer.discard_char(); false }
            _   => true
        };
        self.finish_numeric(semi_missing)
    }

    fn finish_numeric(&mut self, parse_error: bool) -> Status {
        fn conv(n: u32) -> char {
            from_u32(n).expect("invalid char missed by error handling cases")
        }

        match self.num {
            n if (n > 0x10FFFF) || self.num_too_big => self.finish_one('\ufffd', true),
            0x00 | 0xD800..0xDFFF => self.finish_one('\ufffd', true),

            0x80..0x9F => match data::c1_replacements[self.num - 0x80] {
                Some(c) => self.finish_one(c, true),
                None => self.finish_one(conv(self.num), true),
            },

            0x01..0x08 | 0x0B | 0x0D..0x1F | 0x7F | 0xFDD0..0xFDEF
                => self.finish_one(conv(self.num), true),

            n if (n & 0xFFFE) == 0xFFFE
                => self.finish_one(conv(n), true),

            n => self.finish_one(conv(n), parse_error),
        }
    }

    fn do_named<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        let c = unwrap_or_return!(tokenizer.peek(), Stuck);
        tokenizer.discard_char();
        self.name_buf().push_char(c);
        match data::named_entities.find(&self.name_buf().as_slice()) {
            // We have either a full match or a prefix of one.
            Some(m) => {
                if m[0] != '\0' {
                    // We have a full match, but there might be a longer one to come.
                    self.name_match = Some(m);
                    self.name_len = self.name_buf().len();
                }
                // Otherwise we just have a prefix match.
                Progress
            }

            // Can't continue the match.
            None => self.finish_named(tokenizer),
        }
    }

    fn finish_named<T: SubTok>(&mut self, tokenizer: &mut T) -> Status {
        match self.name_match {
            None => {
                // FIXME: "if the characters after the U+0026 AMPERSAND
                // character (&) consist of a sequence of one or more
                // alphanumeric ASCII characters followed by a U+003B
                // SEMICOLON character (;), then this is a parse error".

                tokenizer.unconsume(self.name_buf_opt.take_unwrap());
                self.finish_none(false)
            }
            Some(m) => {
                // We have a complete match, but we may have consumed
                // additional characters into self.name_buf.  Usually
                // at least one, but several in cases like
                //
                //     &not    => match for U+00AC
                //     &noti   => valid prefix for &notin
                //     &notit  => can't continue match

                assert!(self.name_len > 0);
                let last_matched = self.name_buf().char_at(self.name_len-1);

                // There might not be a next character after the match, if
                // we had a full match and then hit EOF.
                let next_after = if self.name_len == self.name_buf().len() {
                    None
                } else {
                    Some(self.name_buf().char_at(self.name_len))
                };

                // "If the character reference is being consumed as part of an
                // attribute, and the last character matched is not a U+003B
                // SEMICOLON character (;), and the next character is either a
                // U+003D EQUALS SIGN character (=) or an alphanumeric ASCII
                // character, then, for historical reasons, all the characters
                // that were matched after the U+0026 AMPERSAND character (&)
                // must be unconsumed, and nothing is returned. However, if
                // this next character is in fact a U+003D EQUALS SIGN
                // character (=), then this is a parse error"

                let (unconsume_all, parse_error) =
                match (self.addnl_allowed, last_matched, next_after) {
                    (_, ';', _) => (false, false),
                    (Some(_), _, Some('=')) => (true, true),
                    (Some(_), _, Some(c)) if is_ascii_alnum(c) => (true, false),
                    _ => (false, true),
                };

                if unconsume_all {
                    tokenizer.unconsume(self.name_buf_opt.take_unwrap());
                    self.finish_none(parse_error)
                } else {
                    tokenizer.unconsume(self.name_buf().slice_from(self.name_len).to_owned());
                    self.result = Some(CharRef {
                        chars: *m,
                        num_chars: if m[1] == '\0' { 1 } else { 2 },
                        parse_error: parse_error,
                    });
                    Done
                }
            }
        }
    }

    pub fn end_of_file<T: SubTok>(&mut self, tokenizer: &mut T) {
        match self.state {
            Begin => self.finish_none(false),

            // FIXME: Handling the rest of these correctly requires unconsuming
            // characters after EOF, which the main tokenizer can't handle yet.

            Numeric(_) | NumericSemicolon
                => self.finish_numeric(true),

            Named => self.finish_named(tokenizer),

            Octothorpe => self.finish_none(true),
        };
    }
}
<|endoftext|>


<commit_before>use libc::{c_char, c_void};
use std::ffi::CString;

pub enum ServiceType {
    Message1,
    Capstone1,

    Message = Message1,
    Capstone = Capstone1,
}

#[repr(C)]
struct CMessageFuncs1
	info: extern "C" fn(title: *const c_char, message: *const c_char);
	error: extern "C" fn(title: *const c_char, message: *const c_char);
	warning: extern "C" fn(title: *const c_char, message: *const c_char);
}

pub struct MessageFunc {
    pub api: *mut CMessageFuncs1,
}

impl Message {
    pub fn info(&mut self, title: &str, message: &str) {
        let ts = CString::new(title).unwrap();
        let ms = CString::new(message).unwrap();
        unsafe {
            ((*self.api).info)(ts.as_ptr(), ms.as_ptr());
        }
    }
    pub fn error(&mut self, title: &str, message: &str) {
        let ts = CString::new(title).unwrap();
        let ms = CString::new(message).unwrap();
        unsafe {
            ((*self.api).error)(ts.as_ptr(), ms.as_ptr());
        }
    }
    pub fn warning(&mut self, title: &str, message: &str) {
        let ts = CString::new(title).unwrap();
        let ms = CString::new(message).unwrap();
        unsafe {
            ((*self.warning).error)(ts.as_ptr(), ms.as_ptr());
        }
    }
}

pub struct Service {
    pub service_func: extern "C" fn(data: *const c_char) -> *mut c_void,
}

impl Service {
    // TODO: Handle different versions here
    get_messages(&self _: ServiceType) -> Messages {
        unsafe {
            let api: &mut CMessageFuncs1 = &mut *((*self.service_func)(b"Dialogs 1")
                                                  as *mut CMessageFuncs1);
            Message { api: CMessageFuncs1 }
        }
    }
}
<commit_msg>Simplified message code<commit_after>use libc::{c_char, c_void};
use std::ffi::CString;

pub enum ServiceType {
    Message1,
    Capstone1,

    Message = Message1,
    Capstone = Capstone1,
}

#[repr(C)]
struct CMessageFuncs1
	info: extern "C" fn(title: *const c_char, message: *const c_char);
	error: extern "C" fn(title: *const c_char, message: *const c_char);
	warning: extern "C" fn(title: *const c_char, message: *const c_char);
}

pub struct MessageFunc {
    pub api: *mut CMessageFuncs1,
}

macro_rules! message_fun {
    ($name:ident) => {
        pub fn $name(&mut self, title: &str, message: &str) {
            let ts = CString::new(title).unwrap();
            let ms = CString::new(message).unwrap();
            unsafe {
                ((*self.api).$name)(ts.as_ptr(), ms.as_ptr());
            }
        }
    }
}

impl Message {
    message_fun!(info);
    message_fun!(error);
    message_fun!(warning);
}

pub struct Service {
    pub service_func: extern "C" fn(data: *const c_char) -> *mut c_void,
}

impl Service {
    // TODO: Handle different versions here
    get_messages(&self,  _: ServiceType) -> Messages {
        unsafe {
            let api: &mut CMessageFuncs1 = &mut *((*self.service_func)(b"Dialogs 1")
                                                  as *mut CMessageFuncs1);
            Message { api: CMessageFuncs1 }
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate docopt;
extern crate env_logger;
extern crate jemallocator;
extern crate log;
extern crate rand;
extern crate sled;

use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use docopt::Docopt;
use rand::{thread_rng, Rng};

#[cfg_attr(not(feature = "no_jemalloc"), global_allocator)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);
static SEQ: AtomicUsize = AtomicUsize::new(0);

const USAGE: &'static str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 1].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 75].
    --set-prop=<p>     The relative proportion of set requests [default: 5].
    --del-prop=<p>     The relative proportion of del requests [default: 5].
    --cas-prop=<p>     The relative proportion of cas requests [default: 5].
    --scan-prop=<p>    The relative proportion of scan requests [default: 5].
    --merge-prop=<p>   The relative proportion of merge requests [default: 5].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random [default: false].
";

#[derive(Deserialize, Clone)]
struct Args {
    flag_threads: usize,
    flag_burn_in: bool,
    flag_duration: u64,
    flag_key_len: usize,
    flag_val_len: usize,
    flag_get_prop: usize,
    flag_set_prop: usize,
    flag_del_prop: usize,
    flag_cas_prop: usize,
    flag_scan_prop: usize,
    flag_merge_prop: usize,
    flag_entries: usize,
    flag_sequential: bool,
}

// defaults will be applied later based on USAGE above
static mut ARGS: Args = Args {
    flag_threads: 0,
    flag_burn_in: false,
    flag_duration: 0,
    flag_key_len: 0,
    flag_val_len: 0,
    flag_get_prop: 0,
    flag_set_prop: 0,
    flag_del_prop: 0,
    flag_cas_prop: 0,
    flag_scan_prop: 0,
    flag_merge_prop: 0,
    flag_entries: 0,
    flag_sequential: false,
};

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!("did {} ops", total - last);

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret =
        old_value.map(|ov| ov.to_vec()).unwrap_or_else(|| vec![]);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(tree: Arc<sled::Tree>, shutdown: Arc<AtomicBool>) {
    let args = unsafe { ARGS.clone() };

    let get_max = args.flag_get_prop;
    let set_max = get_max + args.flag_set_prop;
    let del_max = set_max + args.flag_del_prop;
    let cas_max = del_max + args.flag_cas_prop;
    let scan_max = cas_max + args.flag_scan_prop;
    let merge_max = scan_max + args.flag_merge_prop;

    let bytes = |len| -> Vec<u8> {
        let i = if args.flag_sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.flag_entries;

        let i_bytes: [u8; std::mem::size_of::<usize>()] =
            unsafe { std::mem::transmute(i) };

        i_bytes.into_iter().cycle().take(len).cloned().collect()
    };
    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        TOTAL.fetch_add(1, Ordering::Release);
        let key = bytes(args.flag_key_len);
        let choice = rng.gen_range(0, merge_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get(&key).unwrap();
            }
            v if v > get_max && v <= set_max => {
                tree.set(&key, bytes(args.flag_val_len)).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.del(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old_k = bytes(args.flag_val_len);

                let old = if rng.gen::<bool>() {
                    Some(old_k.as_slice())
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    Some(bytes(args.flag_val_len))
                } else {
                    None
                };

                match tree.cas(&key, old, new) {
                    Ok(_) | Err(sled::Error::CasFailed(_)) => {}
                    other => panic!("operational error: {:?}", other),
                }
            }
            v if v > cas_max && v <= scan_max => {
                let _ = tree
                    .scan(&key)
                    .take(rng.gen_range(0, 15))
                    .map(|res| res.unwrap())
                    .collect::<Vec<_>>();
            }
            _ => {
                tree.merge(&key, bytes(args.flag_val_len)).unwrap();
            }
        }
    }
}

fn main() {
    setup_logger();

    let args = unsafe {
        ARGS = Docopt::new(USAGE)
            .and_then(|d| {
                d.argv(std::env::args().into_iter()).deserialize()
            })
            .unwrap_or_else(|e| e.exit());
        ARGS.clone()
    };

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::ConfigBuilder::new()
        .io_bufs(2)
        .io_buf_size(8_000_000)
        .blink_node_split_size(4096)
        .page_consolidation_threshold(10)
        .cache_bits(6)
        .cache_capacity(1_000_000_000)
        .flush_every_ms(Some(10))
        .snapshot_after_ops(100_000)
        .print_profile_on_drop(true)
        .merge_operator(concatenate_merge)
        .build();

    let tree = Arc::new(sled::Tree::start(config).unwrap());

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.flag_threads;

    for i in 0..n_threads + 1 {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::spawn(move || report(shutdown))
        } else {
            thread::spawn(move || run(tree, shutdown))
        };

        threads.push(t);
    }

    if !args.flag_burn_in {
        thread::sleep(std::time::Duration::from_secs(unsafe {
            ARGS.flag_duration
        }));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }

    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}

pub fn setup_logger() {
    use std::io::Write;

    fn tn() -> String {
        std::thread::current()
            .name()
            .unwrap_or("unknown")
            .to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record
                    .module_path()
                    .unwrap()
                    .split("::")
                    .last()
                    .unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<commit_msg>Update main.rs<commit_after>#[macro_use]
extern crate serde_derive;
extern crate docopt;
extern crate env_logger;
extern crate jemallocator;
extern crate log;
extern crate rand;
extern crate sled;

use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use docopt::Docopt;
use rand::{thread_rng, Rng};

#[cfg_attr(not(feature = "no_jemalloc"), global_allocator)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);
static SEQ: AtomicUsize = AtomicUsize::new(0);

const USAGE: &'static str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 1].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 75].
    --set-prop=<p>     The relative proportion of set requests [default: 5].
    --del-prop=<p>     The relative proportion of del requests [default: 5].
    --cas-prop=<p>     The relative proportion of cas requests [default: 5].
    --scan-prop=<p>    The relative proportion of scan requests [default: 5].
    --merge-prop=<p>   The relative proportion of merge requests [default: 5].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random [default: false
";

#[derive(Deserialize, Clone)]
struct Args {
    flag_threads: usize,
    flag_burn_in: bool,
    flag_duration: u64,
    flag_key_len: usize,
    flag_val_len: usize,
    flag_get_prop: usize,
    flag_set_prop: usize,
    flag_del_prop: usize,
    flag_cas_prop: usize,
    flag_scan_prop: usize,
    flag_merge_prop: usize,
    flag_entries: usize,
    flag_sequential: bool,
}

// defaults will be applied later based on USAGE above
static mut ARGS: Args = Args {
    flag_threads: 0,
    flag_burn_in: false,
    flag_duration: 0,
    flag_key_len: 0,
    flag_val_len: 0,
    flag_get_prop: 0,
    flag_set_prop: 0,
    flag_del_prop: 0,
    flag_cas_prop: 0,
    flag_scan_prop: 0,
    flag_merge_prop: 0,
    flag_entries: 0,
    flag_sequential: false,
};

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!("did {} ops", total - last);

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret =
        old_value.map(|ov| ov.to_vec()).unwrap_or_else(|| vec![]);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(tree: Arc<sled::Tree>, shutdown: Arc<AtomicBool>) {
    let args = unsafe { ARGS.clone() };

    let get_max = args.flag_get_prop;
    let set_max = get_max + args.flag_set_prop;
    let del_max = set_max + args.flag_del_prop;
    let cas_max = del_max + args.flag_cas_prop;
    let scan_max = cas_max + args.flag_scan_prop;
    let merge_max = scan_max + args.flag_merge_prop;

    let bytes = |len| -> Vec<u8> {
        let i = if args.flag_sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.flag_entries;

        let i_bytes: [u8; std::mem::size_of::<usize>()] =
            unsafe { std::mem::transmute(i) };

        i_bytes.into_iter().cycle().take(len).cloned().collect()
    };
    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        TOTAL.fetch_add(1, Ordering::Release);
        let key = bytes(args.flag_key_len);
        let choice = rng.gen_range(0, merge_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get(&key).unwrap();
            }
            v if v > get_max && v <= set_max => {
                tree.set(&key, bytes(args.flag_val_len)).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.del(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old_k = bytes(args.flag_val_len);

                let old = if rng.gen::<bool>() {
                    Some(old_k.as_slice())
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    Some(bytes(args.flag_val_len))
                } else {
                    None
                };

                match tree.cas(&key, old, new) {
                    Ok(_) | Err(sled::Error::CasFailed(_)) => {}
                    other => panic!("operational error: {:?}", other),
                }
            }
            v if v > cas_max && v <= scan_max => {
                let _ = tree
                    .scan(&key)
                    .take(rng.gen_range(0, 15))
                    .map(|res| res.unwrap())
                    .collect::<Vec<_>>();
            }
            _ => {
                tree.merge(&key, bytes(args.flag_val_len)).unwrap();
            }
        }
    }
}

fn main() {
    setup_logger();

    let args = unsafe {
        ARGS = Docopt::new(USAGE)
            .and_then(|d| {
                d.argv(std::env::args().into_iter()).deserialize()
            })
            .unwrap_or_else(|e| e.exit());
        ARGS.clone()
    };

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::ConfigBuilder::new()
        .io_bufs(2)
        .io_buf_size(8_000_000)
        .blink_node_split_size(4096)
        .page_consolidation_threshold(10)
        .cache_bits(6)
        .cache_capacity(1_000_000_000)
        .flush_every_ms(Some(10))
        .snapshot_after_ops(100_000)
        .print_profile_on_drop(true)
        .merge_operator(concatenate_merge)
        .build();

    let tree = Arc::new(sled::Tree::start(config).unwrap());

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.flag_threads;

    for i in 0..n_threads + 1 {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::spawn(move || report(shutdown))
        } else {
            thread::spawn(move || run(tree, shutdown))
        };

        threads.push(t);
    }

    if !args.flag_burn_in {
        thread::sleep(std::time::Duration::from_secs(unsafe {
            ARGS.flag_duration
        }));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }

    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops,
        time,
        (ops * 1_000) / (time * 1_000)
    );
}

pub fn setup_logger() {
    use std::io::Write;

    fn tn() -> String {
        std::thread::current()
            .name()
            .unwrap_or("unknown")
            .to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record
                    .module_path()
                    .unwrap()
                    .split("::")
                    .last()
                    .unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if std::env::var("RUST_LOG").is_ok() {
        builder.parse(&std::env::var("RUST_LOG").unwrap());
    }

    let _r = builder.try_init();
}
<|endoftext|>


<commit_before>extern crate tiny_http;

#[cfg(not(feature = "ssl"))]
fn main() { println!("This example requires the `ssl` feature to be enabled"); }

#[cfg(feature = "ssl")]
fn main() {
    use tiny_http::{Server, Response};

    let server = Server::https("0.0.0.0:8000", tiny_http::SslConfig {
        certificate: include_bytes!("ssl-cert.pem").to_vec(),
        private_key: include_bytes!("ssl-key.pem").to_vec(),
    }).unwrap();

    for request in server.incoming_requests() {
        println!("received request! method: {:?}, url: {:?}, headers: {:?}",
            request.method(),
            request.url(),
            request.headers()
        );

        let response = Response::from_string("hello world");
        request.respond(response);
    }
}
<commit_msg>Add small note about certificate in example<commit_after>extern crate tiny_http;

#[cfg(not(feature = "ssl"))]
fn main() { println!("This example requires the `ssl` feature to be enabled"); }

#[cfg(feature = "ssl")]
fn main() {
    use tiny_http::{Server, Response};

    let server = Server::https("0.0.0.0:8000", tiny_http::SslConfig {
        certificate: include_bytes!("ssl-cert.pem").to_vec(),
        private_key: include_bytes!("ssl-key.pem").to_vec(),
    }).unwrap();

    println!("Note: connecting to this server will likely give you a warning from your browser
              because the connection is unsecure. This is because the certificate used by this
              example is self-signed. With a real certificate, you wouldn't get this warning.");

    for request in server.incoming_requests() {
        println!("received request! method: {:?}, url: {:?}, headers: {:?}",
            request.method(),
            request.url(),
            request.headers()
        );

        let response = Response::from_string("hello world");
        request.respond(response);
    }
}
<|endoftext|>


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

// ignore-cross-compile

// error-pattern:expected expression, found statement (`let`)

#![feature(quote, rustc_private)]

extern crate syntax;

use syntax::ast;
use syntax::codemap;
use syntax::parse;
use syntax::print::pprust;
use syntax_pos::DUMMY_SP;

fn main() {
    let ps = syntax::parse::ParseSess::new();
    let mut loader = syntax::ext::base::DummyMacroLoader;
    let mut cx = syntax::ext::base::ExtCtxt::new(
        &ps, vec![],
        syntax::ext::expand::ExpansionConfig::default("qquote".to_string()),
        &mut loader);
    cx.bt_push(syntax::codemap::ExpnInfo {
        call_site: DUMMY_SP,
        callee: syntax::codemap::NameAndSpan {
            format: syntax::codemap::MacroBang(parse::token::intern("")),
            allow_internal_unstable: false,
            span: None,
        }
    });
    let cx = &mut cx;

    assert_eq!(pprust::expr_to_string(&*quote_expr!(&cx, 23)), "23");

    let expr = quote_expr!(&cx, let x isize = 20;);
    assert_eq!(pprust::expr_to_string(&*expr), "let x isize = 20;");
}
<commit_msg>Fix rfail test missing import<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-cross-compile

// error-pattern:expected expression, found statement (`let`)

#![feature(quote, rustc_private)]

extern crate syntax;
extern crate syntax_pos;

use syntax::ast;
use syntax::codemap;
use syntax::parse;
use syntax::print::pprust;
use syntax_pos::DUMMY_SP;

fn main() {
    let ps = syntax::parse::ParseSess::new();
    let mut loader = syntax::ext::base::DummyMacroLoader;
    let mut cx = syntax::ext::base::ExtCtxt::new(
        &ps, vec![],
        syntax::ext::expand::ExpansionConfig::default("qquote".to_string()),
        &mut loader);
    cx.bt_push(syntax::codemap::ExpnInfo {
        call_site: DUMMY_SP,
        callee: syntax::codemap::NameAndSpan {
            format: syntax::codemap::MacroBang(parse::token::intern("")),
            allow_internal_unstable: false,
            span: None,
        }
    });
    let cx = &mut cx;

    assert_eq!(pprust::expr_to_string(&*quote_expr!(&cx, 23)), "23");

    let expr = quote_expr!(&cx, let x isize = 20;);
    assert_eq!(pprust::expr_to_string(&*expr), "let x isize = 20;");
}
<|endoftext|>


<commit_before>macro_rules! pop {
    ( $machine:expr, $( $x:ident ),* ) => (
        $(
            let $x = $machine.stack.pop().unwrap();
        )*
    );
    ( $machine:expr, $( $x:ident : $t: ty ),* ) => (
        $(
            let $x: $t = $machine.stack.pop().unwrap().into();
        )*
    );
}

macro_rules! push {
    ( $machine:expr, $( $x:expr ),* ) => (
        $(
            $machine.stack.push($x).unwrap();
        )*
    )
}

macro_rules! op2 {
    ( $machine:expr, $op:ident ) => ({
        pop!($machine, op1, op2);
        push!($machine, op1.$op(op2).into());
    });
    ( $machine:expr, $op:ident, $t:ty ) => ({
        pop!($machine, op1:$t, op2:$t);
        push!($machine, op1.$op(op2).into());
    });
}

macro_rules! op2_ref {
    ( $machine:expr, $op:ident ) => ({
        pop!($machine, op1, op2);
        push!($machine, op1.$op(&op2).into());
    });
    ( $machine:expr, $op:ident, $t:ty ) => ({
        pop!($machine, op1:$t, op2:$t);
        push!($machine, op1.$op(&op2).into());
    });
}

mod arithmetic;
mod bitwise;
mod flow;
mod environment;
mod system;

use utils::gas::Gas;
use utils::bigint::{M256, MI256};
use utils::address::Address;
use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor};
use vm::{Memory, Storage, Instruction};
use super::{State, Control};
use super::utils::{copy_from_memory, copy_into_memory};

#[allow(unused_variables)]
pub fn run_opcode<M: Memory + Default, S: Storage + Default + Clone>(pc: (Instruction, usize), state: &mut State<M, S>, stipend_gas: Gas, after_gas: Gas) -> Option<Control> {
    match pc.0 {
        Instruction::STOP => { Some(Control::Stop) },
        Instruction::ADD => { op2!(state, add); None },
        Instruction::MUL => { op2!(state, mul); None },
        Instruction::SUB => { op2!(state, sub); None },
        Instruction::DIV => { op2!(state, div); None },
        Instruction::SDIV => { op2!(state, div, MI256); None },
        Instruction::MOD => { op2!(state, rem); None },
        Instruction::SMOD => { op2!(state, rem, MI256); None },
        Instruction::ADDMOD => { arithmetic::addmod(state); None },
        Instruction::MULMOD => { arithmetic::mulmod(state); None },
        Instruction::EXP => { arithmetic::exp(state); None },
        Instruction::SIGNEXTEND => { arithmetic::signextend(state); None },

        Instruction::LT => { op2_ref!(state, lt); None },
        Instruction::GT => { op2_ref!(state, gt); None },
        Instruction::SLT => { op2_ref!(state, lt, MI256); None },
        Instruction::SGT => { op2_ref!(state, gt, MI256); None },
        Instruction::EQ => { op2_ref!(state, eq); None },
        Instruction::ISZERO => { bitwise::iszero(state); None },
        Instruction::AND => { op2!(state, bitand); None },
        Instruction::OR => { op2!(state, bitor); None },
        Instruction::XOR => { op2!(state, bitxor); None },
        Instruction::NOT => { bitwise::not(state); None },
        Instruction::BYTE => { bitwise::byte(state); None },

        Instruction::SHA3 => unimplemented!(),

        Instruction::ADDRESS => { push!(state, state.context.address.into()); None },
        Instruction::BALANCE => { pop!(state, address: Address);
                                  push!(state, state.account_state.balance(address).unwrap().into());
                                  None },
        Instruction::ORIGIN => { push!(state, state.context.origin.into()); None },
        Instruction::CALLER => { push!(state, state.context.caller.into()); None },
        Instruction::CALLVALUE => { push!(state, state.context.value.into()); None },
        Instruction::CALLDATALOAD => { environment::calldataload(state); None },
        Instruction::CALLDATASIZE => { push!(state, state.context.data.len().into()); None },
        Instruction::CALLDATACOPY => { pop!(state, memory_index, data_index, len);
                                       copy_into_memory(&mut state.memory,
                                                        state.context.data.as_slice(),
                                                        memory_index, data_index, len);
                                       None },
        Instruction::CODESIZE => { push!(state, state.context.code.len().into()); None },
        Instruction::CODECOPY => { pop!(state, memory_index, code_index, len);
                                   copy_into_memory(&mut state.memory,
                                                    state.context.code.as_slice(),
                                                    memory_index, code_index, len);
                                   None },
        Instruction::GASPRICE => { push!(state, state.context.gas_price.into()); None },
        Instruction::EXTCODESIZE => { pop!(state, address: Address);
                                      push!(state,
                                            state.account_state.code(address).unwrap().len().into());
                                      None },
        Instruction::EXTCODECOPY => { pop!(state, address: Address);
                                      pop!(state, memory_index, code_index, len);
                                      copy_into_memory(&mut state.memory,
                                                       state.account_state.code(address).unwrap(),
                                                       memory_index, code_index, len);
                                      None },

        Instruction::BLOCKHASH => { pop!(state, number);
                                    let current_number = state.block.number;
                                    if !(number >= current_number || current_number - number > M256::from(256u64)) {
                                        push!(state, state.blockhash_state.get(number).unwrap());
                                    } else {
                                        push!(state, M256::zero());
                                    }
                                    None },
        Instruction::COINBASE => { push!(state, state.block.coinbase.into()); None },
        Instruction::TIMESTAMP => { push!(state, state.block.timestamp); None },
        Instruction::NUMBER => { push!(state, state.block.number); None },
        Instruction::DIFFICULTY => { push!(state, state.block.difficulty); None },
        Instruction::GASLIMIT => { push!(state, state.block.gas_limit.into()); None },

        Instruction::POP => { state.stack.pop().unwrap(); None },
        Instruction::MLOAD => { flow::mload(state); None },
        Instruction::MSTORE => { flow::mstore(state); None },
        Instruction::MSTORE8 => { flow::mstore8(state); None },
        Instruction::SLOAD => { flow::sload(state); None },
        Instruction::SSTORE => { flow::sstore(state); None },
        Instruction::JUMP => { pop!(state, dest); Some(Control::Jump(dest)) }
        Instruction::JUMPI => { pop!(state, dest, value);
                                if value != M256::zero() {
                                    Some(Control::Jump(dest))
                                } else {
                                    None
                                } },
        Instruction::PC => { push!(state, pc.1.into()); None },
        Instruction::MSIZE => { push!(state, state.memory_cost.into()); None },
        Instruction::GAS => { push!(state, after_gas.into()); None },
        Instruction::JUMPDEST => None,

        Instruction::PUSH(v) => { push!(state, v); None }

        Instruction::DUP(v) => { let val = state.stack.peek(v-1).unwrap();
                                 push!(state, val);
                                 None },
        Instruction::SWAP(v) => { let val1 = state.stack.peek(0).unwrap();
                                  let val2 = state.stack.peek(v).unwrap();
                                  state.stack.set(0, val2).unwrap();
                                  state.stack.set(v, val1).unwrap();
                                  None },
        Instruction::LOG(v) => unimplemented!(),

        Instruction::CREATE => unimplemented!(),
        Instruction::CALL => unimplemented!(),
        Instruction::CALLCODE => unimplemented!(),
        Instruction::RETURN => { pop!(state, start, len);
                                 state.out = copy_from_memory(&mut state.memory, start, len);
                                 Some(Control::Stop) },
        Instruction::DELEGATECALL => unimplemented!(),
        Instruction::SUICIDE => { system::suicide(state); Some(Control::Stop) },
    }
}
<commit_msg>Problem: MSIZE is incorrect Solution: *32<commit_after>macro_rules! pop {
    ( $machine:expr, $( $x:ident ),* ) => (
        $(
            let $x = $machine.stack.pop().unwrap();
        )*
    );
    ( $machine:expr, $( $x:ident : $t: ty ),* ) => (
        $(
            let $x: $t = $machine.stack.pop().unwrap().into();
        )*
    );
}

macro_rules! push {
    ( $machine:expr, $( $x:expr ),* ) => (
        $(
            $machine.stack.push($x).unwrap();
        )*
    )
}

macro_rules! op2 {
    ( $machine:expr, $op:ident ) => ({
        pop!($machine, op1, op2);
        push!($machine, op1.$op(op2).into());
    });
    ( $machine:expr, $op:ident, $t:ty ) => ({
        pop!($machine, op1:$t, op2:$t);
        push!($machine, op1.$op(op2).into());
    });
}

macro_rules! op2_ref {
    ( $machine:expr, $op:ident ) => ({
        pop!($machine, op1, op2);
        push!($machine, op1.$op(&op2).into());
    });
    ( $machine:expr, $op:ident, $t:ty ) => ({
        pop!($machine, op1:$t, op2:$t);
        push!($machine, op1.$op(&op2).into());
    });
}

mod arithmetic;
mod bitwise;
mod flow;
mod environment;
mod system;

use utils::gas::Gas;
use utils::bigint::{M256, MI256};
use utils::address::Address;
use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor};
use vm::{Memory, Storage, Instruction};
use super::{State, Control};
use super::utils::{copy_from_memory, copy_into_memory};

#[allow(unused_variables)]
pub fn run_opcode<M: Memory + Default, S: Storage + Default + Clone>(pc: (Instruction, usize), state: &mut State<M, S>, stipend_gas: Gas, after_gas: Gas) -> Option<Control> {
    match pc.0 {
        Instruction::STOP => { Some(Control::Stop) },
        Instruction::ADD => { op2!(state, add); None },
        Instruction::MUL => { op2!(state, mul); None },
        Instruction::SUB => { op2!(state, sub); None },
        Instruction::DIV => { op2!(state, div); None },
        Instruction::SDIV => { op2!(state, div, MI256); None },
        Instruction::MOD => { op2!(state, rem); None },
        Instruction::SMOD => { op2!(state, rem, MI256); None },
        Instruction::ADDMOD => { arithmetic::addmod(state); None },
        Instruction::MULMOD => { arithmetic::mulmod(state); None },
        Instruction::EXP => { arithmetic::exp(state); None },
        Instruction::SIGNEXTEND => { arithmetic::signextend(state); None },

        Instruction::LT => { op2_ref!(state, lt); None },
        Instruction::GT => { op2_ref!(state, gt); None },
        Instruction::SLT => { op2_ref!(state, lt, MI256); None },
        Instruction::SGT => { op2_ref!(state, gt, MI256); None },
        Instruction::EQ => { op2_ref!(state, eq); None },
        Instruction::ISZERO => { bitwise::iszero(state); None },
        Instruction::AND => { op2!(state, bitand); None },
        Instruction::OR => { op2!(state, bitor); None },
        Instruction::XOR => { op2!(state, bitxor); None },
        Instruction::NOT => { bitwise::not(state); None },
        Instruction::BYTE => { bitwise::byte(state); None },

        Instruction::SHA3 => unimplemented!(),

        Instruction::ADDRESS => { push!(state, state.context.address.into()); None },
        Instruction::BALANCE => { pop!(state, address: Address);
                                  push!(state, state.account_state.balance(address).unwrap().into());
                                  None },
        Instruction::ORIGIN => { push!(state, state.context.origin.into()); None },
        Instruction::CALLER => { push!(state, state.context.caller.into()); None },
        Instruction::CALLVALUE => { push!(state, state.context.value.into()); None },
        Instruction::CALLDATALOAD => { environment::calldataload(state); None },
        Instruction::CALLDATASIZE => { push!(state, state.context.data.len().into()); None },
        Instruction::CALLDATACOPY => { pop!(state, memory_index, data_index, len);
                                       copy_into_memory(&mut state.memory,
                                                        state.context.data.as_slice(),
                                                        memory_index, data_index, len);
                                       None },
        Instruction::CODESIZE => { push!(state, state.context.code.len().into()); None },
        Instruction::CODECOPY => { pop!(state, memory_index, code_index, len);
                                   copy_into_memory(&mut state.memory,
                                                    state.context.code.as_slice(),
                                                    memory_index, code_index, len);
                                   None },
        Instruction::GASPRICE => { push!(state, state.context.gas_price.into()); None },
        Instruction::EXTCODESIZE => { pop!(state, address: Address);
                                      push!(state,
                                            state.account_state.code(address).unwrap().len().into());
                                      None },
        Instruction::EXTCODECOPY => { pop!(state, address: Address);
                                      pop!(state, memory_index, code_index, len);
                                      copy_into_memory(&mut state.memory,
                                                       state.account_state.code(address).unwrap(),
                                                       memory_index, code_index, len);
                                      None },

        Instruction::BLOCKHASH => { pop!(state, number);
                                    let current_number = state.block.number;
                                    if !(number >= current_number || current_number - number > M256::from(256u64)) {
                                        push!(state, state.blockhash_state.get(number).unwrap());
                                    } else {
                                        push!(state, M256::zero());
                                    }
                                    None },
        Instruction::COINBASE => { push!(state, state.block.coinbase.into()); None },
        Instruction::TIMESTAMP => { push!(state, state.block.timestamp); None },
        Instruction::NUMBER => { push!(state, state.block.number); None },
        Instruction::DIFFICULTY => { push!(state, state.block.difficulty); None },
        Instruction::GASLIMIT => { push!(state, state.block.gas_limit.into()); None },

        Instruction::POP => { state.stack.pop().unwrap(); None },
        Instruction::MLOAD => { flow::mload(state); None },
        Instruction::MSTORE => { flow::mstore(state); None },
        Instruction::MSTORE8 => { flow::mstore8(state); None },
        Instruction::SLOAD => { flow::sload(state); None },
        Instruction::SSTORE => { flow::sstore(state); None },
        Instruction::JUMP => { pop!(state, dest); Some(Control::Jump(dest)) }
        Instruction::JUMPI => { pop!(state, dest, value);
                                if value != M256::zero() {
                                    Some(Control::Jump(dest))
                                } else {
                                    None
                                } },
        Instruction::PC => { push!(state, pc.1.into()); None },
        Instruction::MSIZE => { push!(state, (state.memory_cost * Gas::from(32u64)).into()); None },
        Instruction::GAS => { push!(state, after_gas.into()); None },
        Instruction::JUMPDEST => None,

        Instruction::PUSH(v) => { push!(state, v); None }

        Instruction::DUP(v) => { let val = state.stack.peek(v-1).unwrap();
                                 push!(state, val);
                                 None },
        Instruction::SWAP(v) => { let val1 = state.stack.peek(0).unwrap();
                                  let val2 = state.stack.peek(v).unwrap();
                                  state.stack.set(0, val2).unwrap();
                                  state.stack.set(v, val1).unwrap();
                                  None },
        Instruction::LOG(v) => unimplemented!(),

        Instruction::CREATE => unimplemented!(),
        Instruction::CALL => unimplemented!(),
        Instruction::CALLCODE => unimplemented!(),
        Instruction::RETURN => { pop!(state, start, len);
                                 state.out = copy_from_memory(&mut state.memory, start, len);
                                 Some(Control::Stop) },
        Instruction::DELEGATECALL => unimplemented!(),
        Instruction::SUICIDE => { system::suicide(state); Some(Control::Stop) },
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 The Kythe Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use kythe_rust_extractor::generate_analysis;
use std::env;
use std::fs::File;
use std::path::{Path, PathBuf};

use tempdir::TempDir;

#[test]
fn empty_args_fails() {
    let args: Vec<String> = Vec::new();
    let temp_dir = TempDir::new("extractor_test").expect("Could not create temporary directory");
    let analysis_directory = PathBuf::new().join(temp_dir.path());
    let result = generate_analysis(args, analysis_directory);
    assert_eq!(result.unwrap_err(), "Arguments vector should not be empty".to_string());
}

#[test]
fn nonempty_string_first_fails() {
    let args: Vec<String> = vec!["nonempty".to_string()];
    let temp_dir = TempDir::new("extractor_test").expect("Could not create temporary directory");
    let analysis_directory = PathBuf::new().join(temp_dir.path());
    let result = generate_analysis(args, analysis_directory);
    assert_eq!(result.unwrap_err(), "The first argument must be an empty string".to_string());
}

#[test]
fn correct_arguments_succeed() {
    // Get location of test file to be compiled
    let test_file = env::var("TEST_FILE").expect("TEST_FILE variable not set");

    // Get sysroot location
    let sysroot = env::var("SYSROOT").expect("SYSROOT variable not set");

    // Generate the save_analysis
    let temp_dir = TempDir::new("extractor_test").expect("Could not create temporary directory");
    let args: Vec<String> = vec![
        "".to_string(),
        test_file.to_string(),
        format!("-L{}", sysroot),
        "--crate-name=test_crate".to_string(),
        format!("--out-dir={:?}", temp_dir.path()),
    ];
    let analysis_directory = PathBuf::new().join(temp_dir.path());
    let result = generate_analysis(args, analysis_directory);
    assert_eq!(result.unwrap(), (), "generate_analysis result wasn't void");

    // Ensure the save_analysis file exists
    let _ = File::open(Path::new(temp_dir.path()).join("save-analysis/test_crate.json"))
        .expect("save_analysis did not exist in the expected path");
}
<commit_msg>fix(rust_extractor): fix --out-dir path (#4993)<commit_after>// Copyright 2020 The Kythe Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use kythe_rust_extractor::generate_analysis;
use std::env;
use std::fs::File;
use std::path::{Path, PathBuf};

use tempdir::TempDir;

#[test]
fn empty_args_fails() {
    let args: Vec<String> = Vec::new();
    let temp_dir = TempDir::new("extractor_test").expect("Could not create temporary directory");
    let analysis_directory = PathBuf::new().join(temp_dir.path());
    let result = generate_analysis(args, analysis_directory);
    assert_eq!(result.unwrap_err(), "Arguments vector should not be empty".to_string());
}

#[test]
fn nonempty_string_first_fails() {
    let args: Vec<String> = vec!["nonempty".to_string()];
    let temp_dir = TempDir::new("extractor_test").expect("Could not create temporary directory");
    let analysis_directory = PathBuf::new().join(temp_dir.path());
    let result = generate_analysis(args, analysis_directory);
    assert_eq!(result.unwrap_err(), "The first argument must be an empty string".to_string());
}

#[test]
fn correct_arguments_succeed() {
    // Get location of test file to be compiled
    let test_file = env::var("TEST_FILE").expect("TEST_FILE variable not set");

    // Get sysroot location
    let sysroot = env::var("SYSROOT").expect("SYSROOT variable not set");

    // Generate the save_analysis
    let temp_dir = TempDir::new("extractor_test").expect("Could not create temporary directory");
    let args: Vec<String> = vec![
        "".to_string(),
        test_file.to_string(),
        format!("-L{}", sysroot),
        "--crate-name=test_crate".to_string(),
        format!("--out-dir={}", temp_dir.path().to_str().unwrap()),
    ];
    let analysis_directory = PathBuf::new().join(temp_dir.path());
    let result = generate_analysis(args, analysis_directory);
    assert_eq!(result.unwrap(), (), "generate_analysis result wasn't void");

    // Ensure the save_analysis file exists
    let _ = File::open(Path::new(temp_dir.path()).join("save-analysis/test_crate.json"))
        .expect("save_analysis did not exist in the expected path");
}
<|endoftext|>


<commit_before>// this is just a test binary that can be hooked up to Instruments
extern crate lonlat_bng;
use lonlat_bng::{convert_to_bng_threaded, Array};

extern crate rand;
use rand::distributions::{IndependentSample, Range};

extern crate libc;

fn main() {
    let num_coords = 1000000;
    let between_lon = Range::new(-6.379880, 1.768960);
    let between_lat = Range::new(49.871159, 55.811741);
    let mut rng = rand::thread_rng();
    let lon_vec = vec![between_lon.ind_sample(&mut rng) as f32; num_coords];
    let lat_vec = vec![between_lat.ind_sample(&mut rng) as f32; num_coords];
    let lon_arr = Array {
        data: lon_vec.as_ptr() as *const libc::c_void,
        len: lon_vec.len() as libc::size_t,
    };
    let lat_arr = Array {
        data: lat_vec.as_ptr() as *const libc::c_void,
        len: lat_vec.len() as libc::size_t,
    };

    convert_to_bng_threaded(lon_arr, lat_arr);
}
<commit_msg>Import OSGB36 function in anticipation of testing<commit_after>// this is just a test binary that can be hooked up to Instruments
extern crate lonlat_bng;
use lonlat_bng::{convert_to_bng_threaded, convert_to_osgb36_threaded, Array};

extern crate rand;
use rand::distributions::{IndependentSample, Range};

extern crate libc;

fn main() {
    let num_coords = 1000000;
    let between_lon = Range::new(-6.379880, 1.768960);
    let between_lat = Range::new(49.871159, 55.811741);
    let mut rng = rand::thread_rng();
    let lon_vec = vec![between_lon.ind_sample(&mut rng) as f32; num_coords];
    let lat_vec = vec![between_lat.ind_sample(&mut rng) as f32; num_coords];
    let lon_arr = Array {
        data: lon_vec.as_ptr() as *const libc::c_void,
        len: lon_vec.len() as libc::size_t,
    };
    let lat_arr = Array {
        data: lat_vec.as_ptr() as *const libc::c_void,
        len: lat_vec.len() as libc::size_t,
    };

    convert_to_bng_threaded(lon_arr, lat_arr);
    // convert_to_osgb36_threaded(lon_arr, lat_arr);
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate rustc_middle;
extern crate rustc_driver;
extern crate rustc_hir;
extern crate rustc_interface;
extern crate rustc_session;

use std::convert::TryFrom;
use std::env;
use std::str::FromStr;

use hex::FromHexError;
use log::debug;

use rustc_session::CtfeBacktrace;
use rustc_driver::Compilation;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::TyCtxt;

struct MiriCompilerCalls {
    miri_config: miri::MiriConfig,
}

impl rustc_driver::Callbacks for MiriCompilerCalls {
    fn after_analysis<'tcx>(
        &mut self,
        compiler: &rustc_interface::interface::Compiler,
        queries: &'tcx rustc_interface::Queries<'tcx>,
    ) -> Compilation {
        compiler.session().abort_if_errors();

        queries.global_ctxt().unwrap().peek_mut().enter(|tcx| {
            init_late_loggers(tcx);
            let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
            let mut config = self.miri_config.clone();

            // Add filename to `miri` arguments.
            config.args.insert(0, compiler.input().filestem().to_string());

            if let Some(return_code) = miri::eval_main(tcx, entry_def_id.to_def_id(), config) {
                std::process::exit(
                    i32::try_from(return_code).expect("Return value was too large!"),
                );
            }
        });

        compiler.session().abort_if_errors();

        Compilation::Stop
    }
}

fn init_early_loggers() {
    // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
    // initialize them both, and we always initialize `miri`'s first.
    let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE");
    env_logger::init_from_env(env);
    // We only initialize `rustc` if the env var is set (so the user asked for it).
    // If it is not set, we avoid initializing now so that we can initialize
    // later with our custom settings, and *not* log anything for what happens before
    // `miri` gets started.
    if env::var_os("RUSTC_LOG").is_some() {
        rustc_driver::init_rustc_env_logger();
    }
}

fn init_late_loggers(tcx: TyCtxt<'_>) {
    // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG`
    // env var if it is not set, control it based on `MIRI_LOG`.
    // (FIXME: use `var_os`, but then we need to manually concatenate instead of `format!`.)
    if let Ok(var) = env::var("MIRI_LOG") {
        if env::var_os("RUSTC_LOG").is_none() {
            // We try to be a bit clever here: if `MIRI_LOG` is just a single level
            // used for everything, we only apply it to the parts of rustc that are
            // CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`.
            // This way, if you set `MIRI_LOG=trace`, you get only the right parts of
            // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_mir::interpret=debug`.
            if log::Level::from_str(&var).is_ok() {
                env::set_var(
                    "RUSTC_LOG",
                    &format!("rustc_middle::mir::interpret={0},rustc_mir::interpret={0}", var),
                );
            } else {
                env::set_var("RUSTC_LOG", &var);
            }
            rustc_driver::init_rustc_env_logger();
        }
    }

    // If `MIRI_BACKTRACE` is set and `RUSTC_CTFE_BACKTRACE` is not, set `RUSTC_CTFE_BACKTRACE`.
    // Do this late, so we ideally only apply this to Miri's errors.
    if let Some(val) = env::var_os("MIRI_BACKTRACE") {
        let ctfe_backtrace = match &*val.to_string_lossy() {
            "immediate" => CtfeBacktrace::Immediate,
            "0" => CtfeBacktrace::Disabled,
            _ => CtfeBacktrace::Capture,
        };
        *tcx.sess.ctfe_backtrace.borrow_mut() = ctfe_backtrace;
    }
}

/// Returns the "default sysroot" that Miri will use if no `--sysroot` flag is set.
/// Should be a compile-time constant.
fn compile_time_sysroot() -> Option<String> {
    if option_env!("RUSTC_STAGE").is_some() {
        // This is being built as part of rustc, and gets shipped with rustup.
        // We can rely on the sysroot computation in librustc_session.
        return None;
    }
    // For builds outside rustc, we need to ensure that we got a sysroot
    // that gets used as a default.  The sysroot computation in librustc_session would
    // end up somewhere in the build dir (see `get_or_default_sysroot`).
    // Taken from PR <https://github.com/Manishearth/rust-clippy/pull/911>.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    Some(match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("To build Miri without rustup, set the `RUST_SYSROOT` env var at build time")
            .to_owned(),
    })
}

/// Execute a compiler with the given CLI arguments and callbacks.
fn run_compiler(mut args: Vec<String>, callbacks: &mut (dyn rustc_driver::Callbacks + Send)) -> ! {
    // Make sure we use the right default sysroot. The default sysroot is wrong,
    // because `get_or_default_sysroot` in `librustc_session` bases that on `current_exe`.
    //
    // Make sure we always call `compile_time_sysroot` as that also does some sanity-checks
    // of the environment we were built in.
    // FIXME: Ideally we'd turn a bad build env into a compile-time error via CTFE or so.
    if let Some(sysroot) = compile_time_sysroot() {
        let sysroot_flag = "--sysroot";
        if !args.iter().any(|e| e == sysroot_flag) {
            // We need to overwrite the default that librustc_session would compute.
            args.push(sysroot_flag.to_owned());
            args.push(sysroot);
        }
    }

    // Some options have different defaults in Miri than in plain rustc; apply those by making
    // them the first arguments after the binary name (but later arguments can overwrite them).
    args.splice(1..1, miri::miri_default_args().iter().map(ToString::to_string));

    // Invoke compiler, and handle return code.
    let exit_code = rustc_driver::catch_with_exit_code(move || {
        rustc_driver::run_compiler(&args, callbacks, None, None)
    });
    std::process::exit(exit_code)
}

fn main() {
    rustc_driver::install_ice_hook();

    // If the environment asks us to actually be rustc, then do that.
    if env::var_os("MIRI_BE_RUSTC").is_some() {
        rustc_driver::init_rustc_env_logger();
        // We cannot use `rustc_driver::main` as we need to adjust the CLI arguments.
        let mut callbacks = rustc_driver::TimePassesCallbacks::default();
        run_compiler(env::args().collect(), &mut callbacks)
    }

    // Init loggers the Miri way.
    init_early_loggers();

    // Parse our arguments and split them across `rustc` and `miri`.
    let mut validate = true;
    let mut stacked_borrows = true;
    let mut check_alignment = true;
    let mut communicate = false;
    let mut ignore_leaks = false;
    let mut seed: Option<u64> = None;
    let mut tracked_pointer_tag: Option<miri::PtrId> = None;
    let mut tracked_alloc_id: Option<miri::AllocId> = None;
    let mut rustc_args = vec![];
    let mut crate_args = vec![];
    let mut after_dashdash = false;
    let mut excluded_env_vars = vec![];
    for arg in env::args() {
        if rustc_args.is_empty() {
            // Very first arg: binary name.
            rustc_args.push(arg);
        } else if after_dashdash {
            // Everything that comes after `--` is forwarded to the interpreted crate.
            crate_args.push(arg);
        } else {
            match arg.as_str() {
                "-Zmiri-disable-validation" => {
                    validate = false;
                }
                "-Zmiri-disable-stacked-borrows" => {
                    stacked_borrows = false;
                }
                "-Zmiri-disable-alignment-check" => {
                    check_alignment = false;
                }
                "-Zmiri-disable-isolation" => {
                    communicate = true;
                }
                "-Zmiri-ignore-leaks" => {
                    ignore_leaks = true;
                }
                "--" => {
                    after_dashdash = true;
                }
                arg if arg.starts_with("-Zmiri-seed=") => {
                    if seed.is_some() {
                        panic!("Cannot specify -Zmiri-seed multiple times!");
                    }
                    let seed_raw = hex::decode(arg.trim_start_matches("-Zmiri-seed="))
                        .unwrap_or_else(|err| match err {
                            FromHexError::InvalidHexCharacter { .. } => panic!(
                                "-Zmiri-seed should only contain valid hex digits [0-9a-fA-F]"
                            ),
                            FromHexError::OddLength =>
                                panic!("-Zmiri-seed should have an even number of digits"),
                            err => panic!("Unknown error decoding -Zmiri-seed as hex: {:?}", err),
                        });
                    if seed_raw.len() > 8 {
                        panic!(format!(
                            "-Zmiri-seed must be at most 8 bytes, was {}",
                            seed_raw.len()
                        ));
                    }

                    let mut bytes = [0; 8];
                    bytes[..seed_raw.len()].copy_from_slice(&seed_raw);
                    seed = Some(u64::from_be_bytes(bytes));
                }
                arg if arg.starts_with("-Zmiri-env-exclude=") => {
                    excluded_env_vars
                        .push(arg.trim_start_matches("-Zmiri-env-exclude=").to_owned());
                }
                arg if arg.starts_with("-Zmiri-track-pointer-tag=") => {
                    let id: u64 = match arg.trim_start_matches("-Zmiri-track-pointer-tag=").parse()
                    {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-pointer-tag requires a valid `u64` as the argument: {}",
                            err
                        ),
                    };
                    if let Some(id) = miri::PtrId::new(id) {
                        tracked_pointer_tag = Some(id);
                    } else {
                        panic!("-Zmiri-track-pointer-tag must be a nonzero id");
                    }
                }
                arg if arg.starts_with("-Zmiri-track-alloc-id=") => {
                    let id: u64 = match arg.trim_start_matches("-Zmiri-track-alloc-id=").parse()
                    {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-alloc-id requires a valid `u64` as the argument: {}",
                            err
                        ),
                    };
                    tracked_alloc_id = Some(miri::AllocId(id));
                }
                _ => {
                    // Forward to rustc.
                    rustc_args.push(arg);
                }
            }
        }
    }

    debug!("rustc arguments: {:?}", rustc_args);
    debug!("crate arguments: {:?}", crate_args);
    let miri_config = miri::MiriConfig {
        validate,
        stacked_borrows,
        check_alignment,
        communicate,
        ignore_leaks,
        excluded_env_vars,
        seed,
        args: crate_args,
        tracked_pointer_tag,
        tracked_alloc_id,
    };
    run_compiler(rustc_args, &mut MiriCompilerCalls { miri_config })
}
<commit_msg>use strip_prefix where it makes sense<commit_after>#![feature(rustc_private)]
#![feature(str_strip)]

extern crate rustc_middle;
extern crate rustc_driver;
extern crate rustc_hir;
extern crate rustc_interface;
extern crate rustc_session;

use std::convert::TryFrom;
use std::env;
use std::str::FromStr;

use hex::FromHexError;
use log::debug;

use rustc_session::CtfeBacktrace;
use rustc_driver::Compilation;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::TyCtxt;

struct MiriCompilerCalls {
    miri_config: miri::MiriConfig,
}

impl rustc_driver::Callbacks for MiriCompilerCalls {
    fn after_analysis<'tcx>(
        &mut self,
        compiler: &rustc_interface::interface::Compiler,
        queries: &'tcx rustc_interface::Queries<'tcx>,
    ) -> Compilation {
        compiler.session().abort_if_errors();

        queries.global_ctxt().unwrap().peek_mut().enter(|tcx| {
            init_late_loggers(tcx);
            let (entry_def_id, _) = tcx.entry_fn(LOCAL_CRATE).expect("no main function found!");
            let mut config = self.miri_config.clone();

            // Add filename to `miri` arguments.
            config.args.insert(0, compiler.input().filestem().to_string());

            if let Some(return_code) = miri::eval_main(tcx, entry_def_id.to_def_id(), config) {
                std::process::exit(
                    i32::try_from(return_code).expect("Return value was too large!"),
                );
            }
        });

        compiler.session().abort_if_errors();

        Compilation::Stop
    }
}

fn init_early_loggers() {
    // Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
    // initialize them both, and we always initialize `miri`'s first.
    let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE");
    env_logger::init_from_env(env);
    // We only initialize `rustc` if the env var is set (so the user asked for it).
    // If it is not set, we avoid initializing now so that we can initialize
    // later with our custom settings, and *not* log anything for what happens before
    // `miri` gets started.
    if env::var_os("RUSTC_LOG").is_some() {
        rustc_driver::init_rustc_env_logger();
    }
}

fn init_late_loggers(tcx: TyCtxt<'_>) {
    // We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG`
    // env var if it is not set, control it based on `MIRI_LOG`.
    // (FIXME: use `var_os`, but then we need to manually concatenate instead of `format!`.)
    if let Ok(var) = env::var("MIRI_LOG") {
        if env::var_os("RUSTC_LOG").is_none() {
            // We try to be a bit clever here: if `MIRI_LOG` is just a single level
            // used for everything, we only apply it to the parts of rustc that are
            // CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`.
            // This way, if you set `MIRI_LOG=trace`, you get only the right parts of
            // rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_mir::interpret=debug`.
            if log::Level::from_str(&var).is_ok() {
                env::set_var(
                    "RUSTC_LOG",
                    &format!("rustc_middle::mir::interpret={0},rustc_mir::interpret={0}", var),
                );
            } else {
                env::set_var("RUSTC_LOG", &var);
            }
            rustc_driver::init_rustc_env_logger();
        }
    }

    // If `MIRI_BACKTRACE` is set and `RUSTC_CTFE_BACKTRACE` is not, set `RUSTC_CTFE_BACKTRACE`.
    // Do this late, so we ideally only apply this to Miri's errors.
    if let Some(val) = env::var_os("MIRI_BACKTRACE") {
        let ctfe_backtrace = match &*val.to_string_lossy() {
            "immediate" => CtfeBacktrace::Immediate,
            "0" => CtfeBacktrace::Disabled,
            _ => CtfeBacktrace::Capture,
        };
        *tcx.sess.ctfe_backtrace.borrow_mut() = ctfe_backtrace;
    }
}

/// Returns the "default sysroot" that Miri will use if no `--sysroot` flag is set.
/// Should be a compile-time constant.
fn compile_time_sysroot() -> Option<String> {
    if option_env!("RUSTC_STAGE").is_some() {
        // This is being built as part of rustc, and gets shipped with rustup.
        // We can rely on the sysroot computation in librustc_session.
        return None;
    }
    // For builds outside rustc, we need to ensure that we got a sysroot
    // that gets used as a default.  The sysroot computation in librustc_session would
    // end up somewhere in the build dir (see `get_or_default_sysroot`).
    // Taken from PR <https://github.com/Manishearth/rust-clippy/pull/911>.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    Some(match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("To build Miri without rustup, set the `RUST_SYSROOT` env var at build time")
            .to_owned(),
    })
}

/// Execute a compiler with the given CLI arguments and callbacks.
fn run_compiler(mut args: Vec<String>, callbacks: &mut (dyn rustc_driver::Callbacks + Send)) -> ! {
    // Make sure we use the right default sysroot. The default sysroot is wrong,
    // because `get_or_default_sysroot` in `librustc_session` bases that on `current_exe`.
    //
    // Make sure we always call `compile_time_sysroot` as that also does some sanity-checks
    // of the environment we were built in.
    // FIXME: Ideally we'd turn a bad build env into a compile-time error via CTFE or so.
    if let Some(sysroot) = compile_time_sysroot() {
        let sysroot_flag = "--sysroot";
        if !args.iter().any(|e| e == sysroot_flag) {
            // We need to overwrite the default that librustc_session would compute.
            args.push(sysroot_flag.to_owned());
            args.push(sysroot);
        }
    }

    // Some options have different defaults in Miri than in plain rustc; apply those by making
    // them the first arguments after the binary name (but later arguments can overwrite them).
    args.splice(1..1, miri::miri_default_args().iter().map(ToString::to_string));

    // Invoke compiler, and handle return code.
    let exit_code = rustc_driver::catch_with_exit_code(move || {
        rustc_driver::run_compiler(&args, callbacks, None, None)
    });
    std::process::exit(exit_code)
}

fn main() {
    rustc_driver::install_ice_hook();

    // If the environment asks us to actually be rustc, then do that.
    if env::var_os("MIRI_BE_RUSTC").is_some() {
        rustc_driver::init_rustc_env_logger();
        // We cannot use `rustc_driver::main` as we need to adjust the CLI arguments.
        let mut callbacks = rustc_driver::TimePassesCallbacks::default();
        run_compiler(env::args().collect(), &mut callbacks)
    }

    // Init loggers the Miri way.
    init_early_loggers();

    // Parse our arguments and split them across `rustc` and `miri`.
    let mut validate = true;
    let mut stacked_borrows = true;
    let mut check_alignment = true;
    let mut communicate = false;
    let mut ignore_leaks = false;
    let mut seed: Option<u64> = None;
    let mut tracked_pointer_tag: Option<miri::PtrId> = None;
    let mut tracked_alloc_id: Option<miri::AllocId> = None;
    let mut rustc_args = vec![];
    let mut crate_args = vec![];
    let mut after_dashdash = false;
    let mut excluded_env_vars = vec![];
    for arg in env::args() {
        if rustc_args.is_empty() {
            // Very first arg: binary name.
            rustc_args.push(arg);
        } else if after_dashdash {
            // Everything that comes after `--` is forwarded to the interpreted crate.
            crate_args.push(arg);
        } else {
            match arg.as_str() {
                "-Zmiri-disable-validation" => {
                    validate = false;
                }
                "-Zmiri-disable-stacked-borrows" => {
                    stacked_borrows = false;
                }
                "-Zmiri-disable-alignment-check" => {
                    check_alignment = false;
                }
                "-Zmiri-disable-isolation" => {
                    communicate = true;
                }
                "-Zmiri-ignore-leaks" => {
                    ignore_leaks = true;
                }
                "--" => {
                    after_dashdash = true;
                }
                arg if arg.starts_with("-Zmiri-seed=") => {
                    if seed.is_some() {
                        panic!("Cannot specify -Zmiri-seed multiple times!");
                    }
                    let seed_raw = hex::decode(arg.strip_prefix("-Zmiri-seed=").unwrap())
                        .unwrap_or_else(|err| match err {
                            FromHexError::InvalidHexCharacter { .. } => panic!(
                                "-Zmiri-seed should only contain valid hex digits [0-9a-fA-F]"
                            ),
                            FromHexError::OddLength =>
                                panic!("-Zmiri-seed should have an even number of digits"),
                            err => panic!("Unknown error decoding -Zmiri-seed as hex: {:?}", err),
                        });
                    if seed_raw.len() > 8 {
                        panic!(format!(
                            "-Zmiri-seed must be at most 8 bytes, was {}",
                            seed_raw.len()
                        ));
                    }

                    let mut bytes = [0; 8];
                    bytes[..seed_raw.len()].copy_from_slice(&seed_raw);
                    seed = Some(u64::from_be_bytes(bytes));
                }
                arg if arg.starts_with("-Zmiri-env-exclude=") => {
                    excluded_env_vars
                        .push(arg.strip_prefix("-Zmiri-env-exclude=").unwrap().to_owned());
                }
                arg if arg.starts_with("-Zmiri-track-pointer-tag=") => {
                    let id: u64 = match arg.strip_prefix("-Zmiri-track-pointer-tag=").unwrap().parse()
                    {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-pointer-tag requires a valid `u64` as the argument: {}",
                            err
                        ),
                    };
                    if let Some(id) = miri::PtrId::new(id) {
                        tracked_pointer_tag = Some(id);
                    } else {
                        panic!("-Zmiri-track-pointer-tag must be a nonzero id");
                    }
                }
                arg if arg.starts_with("-Zmiri-track-alloc-id=") => {
                    let id: u64 = match arg.strip_prefix("-Zmiri-track-alloc-id=").unwrap().parse()
                    {
                        Ok(id) => id,
                        Err(err) => panic!(
                            "-Zmiri-track-alloc-id requires a valid `u64` as the argument: {}",
                            err
                        ),
                    };
                    tracked_alloc_id = Some(miri::AllocId(id));
                }
                _ => {
                    // Forward to rustc.
                    rustc_args.push(arg);
                }
            }
        }
    }

    debug!("rustc arguments: {:?}", rustc_args);
    debug!("crate arguments: {:?}", crate_args);
    let miri_config = miri::MiriConfig {
        validate,
        stacked_borrows,
        check_alignment,
        communicate,
        ignore_leaks,
        excluded_env_vars,
        seed,
        args: crate_args,
        tracked_pointer_tag,
        tracked_alloc_id,
    };
    run_compiler(rustc_args, &mut MiriCompilerCalls { miri_config })
}
<|endoftext|>


<commit_before>#![deny(warnings)]

use std::process;

const MAN_PAGE: &'static str = /* @MANSTART{true} */ r#"
NAME
    true - do nothing, successfully

SYNOPSIS
    true

DESCRIPTION
    Exit with a status code indicating success.
"#; /* @MANEND */
fn main() {
    process::exit(0);
}
<commit_msg>:tada: Newline. The best commit :tada:<commit_after>#![deny(warnings)]

use std::process;

const MAN_PAGE: &'static str = /* @MANSTART{true} */ r#"
NAME
    true - do nothing, successfully

SYNOPSIS
    true

DESCRIPTION
    Exit with a status code indicating success.
"#; /* @MANEND */

fn main() {
    process::exit(0);
}
<|endoftext|>


<commit_before>use data::Value;
use data::RuntimeError::*;
use scope::GlobalScope;

pub fn load(env: &mut GlobalScope)
{
    env.set_builtin("quote", false, |args, _| {
        args.iter().next().ok_or(InvalidArgNum(1))
    });

    env.set_builtin("set", true, |args, env| {
        let mut iter = args.iter();
        let key = try!(iter.next().ok_or(InvalidArgNum(2)));
        let val = try!(iter.next().ok_or(InvalidArgNum(2)));
        match key {
            Value::Symbol(name) => {
                env.set(&name, val.clone());
                Ok(val)
            },
            other => Err(InvalidArgType("Symbol", other.type_name())),
        }
    });

    env.set_builtin("+", true, |args, _| {
        let mut acc = 0.0;
        let mut iter = args.iter();
        while let Some(val) = iter.next()
        {
            acc += match val {
                Value::Number(n) => n,
                other => return Err(InvalidArgType("Number", other.type_name())),
            };
        }
        Ok(Value::Number(acc))
    });
}
<commit_msg>changed builtin 'set' to only eval the second arg<commit_after>use data::Value;
use data::RuntimeError::*;
use scope::GlobalScope;

pub fn load(env: &mut GlobalScope)
{
    env.set_builtin("quote", false, |args, _| {
        args.iter().next().ok_or(InvalidArgNum(1))
    });

    env.set_builtin("set", false, |args, env| {
        let mut iter = args.iter();
        let key = try!(iter.next().ok_or(InvalidArgNum(2)));
        let val = try!(iter.next().ok_or(InvalidArgNum(2)));
        match key {
            Value::Symbol(name) => {
                let ev = try!(val.eval(env));
                env.set(&name, ev.clone());
                Ok(ev)
            },
            other => Err(InvalidArgType("Symbol", other.type_name())),
        }
    });

    env.set_builtin("+", true, |args, _| {
        let mut acc = 0.0;
        let mut iter = args.iter();
        while let Some(val) = iter.next()
        {
            acc += match val {
                Value::Number(n) => n,
                other => return Err(InvalidArgType("Number", other.type_name())),
            };
        }
        Ok(Value::Number(acc))
    });
}
<|endoftext|>