<commit_before>//! Parse incomming data
//! Currently text based CSV data
//! Will change to binary in the future

use std::str;
use std::num;
use time::{strptime, Tm};
use regex::Regex;

/// The actual data sent from each weather station
#[derive(Debug, Clone, PartialEq)]
pub struct WeatherStationData {
    pub time_stamp: Tm,
    pub air_temperature: f64,
    pub air_relative_humidity: f64,
    pub solar_radiation: f64,
    pub soil_water_content: f64,
    pub soil_temperature: f64,
    pub wind_speed: f64,
    pub wind_max: f64,
    pub wind_direction: f64,
    pub percipitation: f64,
    pub air_pressure: f64,
}

/// Wrapper type: do we have just battery data or everything else ?
#[derive(Debug, Clone, PartialEq)]
pub enum StationDataType {
    BatteryVoltage(Tm, f64),
    OtherData(WeatherStationData)
}

/// ErrorType, what can go wrong during parsing...
quick_error! {
    #[derive(Debug, Clone, PartialEq)]
    pub enum ParseError {
        EmptyBuffer {
            description("Empty buffer")
        }
        NoTimeStamp {
            description("Invalid data: no time stamp found")
        }
        WrongNumberOfColumns {
            description("Invalid data: wrong number of columns (allowed: 3 or 11)")
        }
        ParseFloatError(err: num::ParseFloatError) {
            description(err.description())
        }
        Utf8Error(err: str::Utf8Error) {
            description(err.description())
        }
    }
}

/// Parse all other data besides battery voltage
fn parse_other_data(time_stamp: &Tm, values: &Vec<&str>) -> Result<StationDataType, ParseError> {
    Err(ParseError::EmptyBuffer)
}

/// Parse all the data that is send from the weather station.
pub fn parse_data(buffer: &[u8]) -> Result<StationDataType, ParseError> {
    let line = str::from_utf8(buffer);

    match line {
        Ok(line_str) => {
            if line_str.is_empty() {
                Err(ParseError::EmptyBuffer)
            } else {
                //let line_string = line_str.as_string();
                let re = Regex::new(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}").unwrap();
                if re.is_match(line_str) {
                    // Found valid time stamp
                    let line_elements: Vec<&str> = line_str.split(',').collect();
                    // println!("time_stamp: {}", line_elements[0]);
                    // let remove_chars: &[_] = &['\x00', '\x02', '\x1E', '\x22', 'J'];
                    // println!("time_stamp_str: {}", time_stamp_str);
                    let time_stamp = strptime(line_elements[0].trim_matches(|c| c < '0' || c > '9'), "%Y-%m-%d %H:%M:%S").unwrap();

                    if line_elements.len() == 3 { // Only battery
                        let battery_voltage = line_elements[1].parse::<f64>();

                        match battery_voltage {
                            Ok(value) => {
                                Ok(StationDataType::BatteryVoltage(time_stamp, value))
                            },
                            Err(e) => {
                                Err(ParseError::ParseFloatError(e))
                            }
                        }
                    } else if line_elements.len() == 11 { // All data
                        parse_other_data(&time_stamp, &line_elements)
                    } else {
                        Err(ParseError::WrongNumberOfColumns)
                    }
                } else {
                    Err(ParseError::NoTimeStamp)
                }
            }
        },
        Err(e) => {
            Err(ParseError::Utf8Error(e))
        }
    }
}

#[cfg(test)]
mod tests {
    use time::strptime;

    use super::{parse_data, StationDataType, ParseError};

    #[test]
    fn test_parse_data_empty() {
        let result = parse_data(&[]);
        assert_eq!(result, Err(ParseError::EmptyBuffer));
    }

    #[test]
    fn test_parse_data_header1() {
        let result = parse_data(&[65, 65, 65]);
        assert_eq!(result, Err(ParseError::NoTimeStamp));
    }

    #[test]
    fn test_parse_data_header2() { // CSV header, we don't need it
        let result = parse_data(&[2, 0, 97, 34, 84, 83, 34, 44, 34, 68, 101, 103, 32, 67, 34,
            44, 34, 37, 34, 44, 34, 87, 47, 109, 66, 50, 34, 44, 34, 109, 66, 51, 47, 109, 66,
            51, 34, 44, 34, 68, 101, 103, 32, 67, 34, 44, 34, 109, 101, 116, 101, 114, 115, 47,
            115, 101, 99, 111, 110, 100, 34, 44, 34, 109, 101, 116, 101, 114, 115, 47, 115, 101,
            99, 111, 110, 100, 34, 44, 34, 100, 101, 103, 114, 101, 101, 115, 34, 44, 34, 109,
            109, 34, 44, 34, 109, 98, 97, 114, 34, 10]);
        assert_eq!(result, Err(ParseError::NoTimeStamp));
    }

    #[test]
    fn test_parse_data_correct1() { // All data from the station
        let result = parse_data(&[2, 0, 74, 34, 50, 48, 49, 54, 45, 48, 54, 45, 49, 49, 32, 48,
            57, 58, 48, 48, 58, 48, 48, 34, 44, 55, 46, 53, 54, 44, 51, 50, 46, 50, 53, 44, 49,
            46, 51, 51, 51, 44, 48, 46, 48, 50, 50, 44, 49, 53, 46, 49, 56, 44, 48, 46, 55, 56,
            50, 44, 49, 46, 55, 53, 44, 50, 53, 54, 46, 55, 44, 48, 44, 57, 53, 49, 10]);
        assert_eq!(result, Err(ParseError::EmptyBuffer));
    }

    #[test]
    fn test_parse_data_correct2() { // Only battery data
        let result = parse_data(&[2, 0, 30, 34, 50, 48, 49, 54, 45, 48, 54, 45, 49, 50, 32, 48,
            48, 58, 48, 48, 58, 48, 48, 34, 44, 49, 50, 46, 55, 51, 44, 48, 10]);
        assert_eq!(result, Ok(StationDataType::BatteryVoltage(strptime("2016-06-12 00:00:00", "%Y-%m-%d %H:%M:%S").unwrap(), 12.73)));
    }

}
<commit_msg>finish data parser<commit_after>//! Parse incomming data
//! Currently text based CSV data
//! Will change to binary in the future

use std::str;
use std::num;
use time::{strptime, Tm};
use regex::Regex;

/// The actual data sent from each weather station
#[derive(Debug, Clone, PartialEq)]
pub struct WeatherStationData {
    pub time_stamp: Tm,
    pub air_temperature: f64,
    pub air_relative_humidity: f64,
    pub solar_radiation: f64,
    pub soil_water_content: f64,
    pub soil_temperature: f64,
    pub wind_speed: f64,
    pub wind_max: f64,
    pub wind_direction: f64,
    pub percipitation: f64,
    pub air_pressure: f64,
}

/// Wrapper type: do we have just battery data or everything else ?
#[derive(Debug, Clone, PartialEq)]
pub enum StationDataType {
    BatteryVoltage(Tm, f64),
    OtherData(WeatherStationData)
}

/// ErrorType, what can go wrong during parsing...
quick_error! {
    #[derive(Debug, Clone, PartialEq)]
    pub enum ParseError {
        EmptyBuffer {
            description("Empty buffer")
        }
        NoTimeStamp {
            description("Invalid data: no time stamp found")
        }
        WrongNumberOfColumns {
            description("Invalid data: wrong number of columns (allowed: 3 or 11)")
        }
        ParseFloatError(err: num::ParseFloatError) {
            description(err.description())
        }
        Utf8Error(err: str::Utf8Error) {
            description(err.description())
        }
    }
}

impl From<num::ParseFloatError> for ParseError {
    fn from(err: num::ParseFloatError) -> ParseError {
        ParseError::ParseFloatError(err)
    }
}

/// Parse all other data besides battery voltage
fn parse_other_data(time_stamp: &Tm, line_elements: &Vec<&str>) -> Result<StationDataType, ParseError> {
    println!("line_elements: {:?}", line_elements);

    let air_temperature = try!(line_elements[1].parse::<f64>());
    let air_relative_humidity = try!(line_elements[2].parse::<f64>());
    let solar_radiation = try!(line_elements[3].parse::<f64>());
    let soil_water_content = try!(line_elements[4].parse::<f64>());
    let soil_temperature = try!(line_elements[5].parse::<f64>());
    let wind_speed = try!(line_elements[6].parse::<f64>());
    let wind_max = try!(line_elements[7].parse::<f64>());
    let wind_direction = try!(line_elements[8].parse::<f64>());
    let percipitation = try!(line_elements[9].parse::<f64>());
    let air_pressure = try!(line_elements[10].parse::<f64>());

    Ok(StationDataType::OtherData(WeatherStationData{
        time_stamp: *time_stamp,
        air_temperature: air_temperature,
        air_relative_humidity: air_relative_humidity,
        solar_radiation: solar_radiation,
        soil_water_content: soil_water_content,
        soil_temperature: soil_temperature,
        wind_speed: wind_speed,
        wind_max: wind_max,
        wind_direction: wind_direction,
        percipitation: percipitation,
        air_pressure: air_pressure
    }))
}

/// Parse all the data that is send from the weather station.
pub fn parse_data(buffer: &[u8]) -> Result<StationDataType, ParseError> {
    let line = str::from_utf8(buffer);

    match line {
        Ok(line_str) => {
            if line_str.is_empty() {
                Err(ParseError::EmptyBuffer)
            } else {
                //let line_string = line_str.as_string();
                let re = Regex::new(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}").unwrap();
                if re.is_match(line_str) {// Found valid time stamp
                    // Prepare for parsing, split line at every ','
                    let remove_junk = |c| c < '0' || c > '9';
                    let line_elements: Vec<&str> = line_str.split(',').map(|elem| elem.trim_matches(&remove_junk)).collect();
                    // println!("time_stamp: {}", line_elements[0]);
                    // let remove_chars: &[_] = &['\x00', '\x02', '\x1E', '\x22', 'J'];
                    // println!("time_stamp_str: {}", time_stamp_str);
                    let time_stamp = strptime(line_elements[0].trim_matches(&remove_junk), "%Y-%m-%d %H:%M:%S").unwrap();

                    if line_elements.len() == 3 { // Only battery
                        let battery_voltage = line_elements[1].parse::<f64>();

                        match battery_voltage {
                            Ok(value) => {
                                Ok(StationDataType::BatteryVoltage(time_stamp, value))
                            },
                            Err(e) => {
                                Err(ParseError::ParseFloatError(e))
                            }
                        }
                    } else if line_elements.len() == 11 { // All data
                        parse_other_data(&time_stamp, &line_elements)
                    } else {
                        Err(ParseError::WrongNumberOfColumns)
                    }
                } else {
                    Err(ParseError::NoTimeStamp)
                }
            }
        },
        Err(e) => {
            Err(ParseError::Utf8Error(e))
        }
    }
}

#[cfg(test)]
mod tests {
    use time::strptime;

    use super::{parse_data, StationDataType, ParseError, WeatherStationData};

    #[test]
    fn test_parse_data_empty() {
        let result = parse_data(&[]);
        assert_eq!(result, Err(ParseError::EmptyBuffer));
    }

    #[test]
    fn test_parse_data_header1() {
        let result = parse_data(&[65, 65, 65]);
        assert_eq!(result, Err(ParseError::NoTimeStamp));
    }

    #[test]
    fn test_parse_data_header2() { // CSV header, we don't need it
        let result = parse_data(&[2, 0, 97, 34, 84, 83, 34, 44, 34, 68, 101, 103, 32, 67, 34,
            44, 34, 37, 34, 44, 34, 87, 47, 109, 66, 50, 34, 44, 34, 109, 66, 51, 47, 109, 66,
            51, 34, 44, 34, 68, 101, 103, 32, 67, 34, 44, 34, 109, 101, 116, 101, 114, 115, 47,
            115, 101, 99, 111, 110, 100, 34, 44, 34, 109, 101, 116, 101, 114, 115, 47, 115, 101,
            99, 111, 110, 100, 34, 44, 34, 100, 101, 103, 114, 101, 101, 115, 34, 44, 34, 109,
            109, 34, 44, 34, 109, 98, 97, 114, 34, 10]);
        assert_eq!(result, Err(ParseError::NoTimeStamp));
    }

    #[test]
    fn test_parse_data_correct1() { // All data from the station
        let result = parse_data(&[2, 0, 74, 34, 50, 48, 49, 54, 45, 48, 54, 45, 49, 49, 32, 48,
            57, 58, 48, 48, 58, 48, 48, 34, 44, 55, 46, 53, 54, 44, 51, 50, 46, 50, 53, 44, 49,
            46, 51, 51, 51, 44, 48, 46, 48, 50, 50, 44, 49, 53, 46, 49, 56, 44, 48, 46, 55, 56,
            50, 44, 49, 46, 55, 53, 44, 50, 53, 54, 46, 55, 44, 48, 44, 57, 53, 49, 10]);
        assert_eq!(result, Ok(StationDataType::OtherData(WeatherStationData{
            time_stamp: strptime("2016-06-11 09:00:00", "%Y-%m-%d %H:%M:%S").unwrap(),
            air_temperature: 7.56,
            air_relative_humidity: 32.25,
            solar_radiation: 1.333,
            soil_water_content: 0.022,
            soil_temperature: 15.18,
            wind_speed: 0.782,
            wind_max: 1.75,
            wind_direction: 256.7,
            percipitation: 0.0,
            air_pressure: 951.0
        })));
    }

    #[test]
    fn test_parse_data_correct2() { // Only battery data
        let result = parse_data(&[2, 0, 30, 34, 50, 48, 49, 54, 45, 48, 54, 45, 49, 50, 32, 48,
            48, 58, 48, 48, 58, 48, 48, 34, 44, 49, 50, 46, 55, 51, 44, 48, 10]);
        assert_eq!(result, Ok(StationDataType::BatteryVoltage(strptime("2016-06-12 00:00:00", "%Y-%m-%d %H:%M:%S").unwrap(), 12.73)));
    }

    #[test]
    fn test_parse_data_wrong_columns() { // Wrong number of columns
        let result = parse_data(&[2, 0, 74, 34, 50, 48, 49, 54, 45, 48, 54, 45, 49, 49, 32, 48,
            57, 58, 48, 48, 58, 48, 48, 34, 44, 55, 46, 53, 54, 44, 51, 50, 46, 50, 53, 44, 49,
            46, 51, 51, 51, 44, 48, 46, 48, 50, 50, 44, 49, 53, 46, 49, 56, 44, 48, 46, 55]);
        assert_eq!(result, Err(ParseError::WrongNumberOfColumns));
    }

}
<|endoftext|>


<commit_before>use detect;

use rb;
use rb::{CallbackPtr, Value, RB_NIL};

// Initialize all of the Ruby-specific static variables.
lazy_static! {
  // Lookup table for Ruby Results
  static ref RUBY_RESULTS: [Value; 16] = [
    RB_NIL,                  // 0
    str2sym!("devanagari"),  // 1
    str2sym!("bengali") ,    // 2
    str2sym!("gurmukhi"),    // 3
    str2sym!("gujarati"),    // 4
    str2sym!("oriya"),       // 5
    str2sym!("tamil"),       // 6
    str2sym!("telugu"),      // 7
    str2sym!("kannada"),     // 8
    str2sym!("malayalam"),   // 9
    str2sym!("iast"),        // 10
    str2sym!("kolkata"),     // 11
    str2sym!("itrans"),      // 12
    str2sym!("slp1"),        // 13
    str2sym!("velthuis"),    // 14
    str2sym!("hk")           // 15
  ];
}

fn rbstr_detect_scheme(_rself: Value, s: Value) -> Value {
  let r_str = rbstr2str!(&s);
  let result = detect::detect_scheme(r_str);
  return RUBY_RESULTS[result];
}

#[no_mangle]
pub extern fn init_rusty_sanscript() {
  let m_sanscript = rb::define_module("Sanscript");
  let m_detect = rb::define_module_under(&m_sanscript, "Detect");
  let m_rust = rb::define_module_under(&m_sanscript, "Rust");
  let m_rust_detect = rb::define_module_under(&m_rust, "Detect");
  rb::define_method(&m_rust_detect, "rust_detect_scheme",
    rbstr_detect_scheme as CallbackPtr, 1);
  rb::extend_object(&m_detect, &m_rust_detect);
}
<commit_msg>Slim down proxy rust detect method.<commit_after>use detect;

use rb;
use rb::{CallbackPtr, Value, RB_NIL};

// Initialize all of the Ruby-specific static variables.
lazy_static! {
  // Lookup table for Ruby Results
  static ref RUBY_RESULTS: [Value; 16] = [
    RB_NIL,                  // 0
    str2sym!("devanagari"),  // 1
    str2sym!("bengali") ,    // 2
    str2sym!("gurmukhi"),    // 3
    str2sym!("gujarati"),    // 4
    str2sym!("oriya"),       // 5
    str2sym!("tamil"),       // 6
    str2sym!("telugu"),      // 7
    str2sym!("kannada"),     // 8
    str2sym!("malayalam"),   // 9
    str2sym!("iast"),        // 10
    str2sym!("kolkata"),     // 11
    str2sym!("itrans"),      // 12
    str2sym!("slp1"),        // 13
    str2sym!("velthuis"),    // 14
    str2sym!("hk")           // 15
  ];
}

fn rbstr_detect_scheme(_rself: Value, s: Value) -> Value {
  let result = detect::detect_scheme(&rbstr2str!(&s));
  return RUBY_RESULTS[result];
}

#[no_mangle]
pub extern fn init_rusty_sanscript() {
  let m_sanscript = rb::define_module("Sanscript");
  let m_detect = rb::define_module_under(&m_sanscript, "Detect");
  let m_rust = rb::define_module_under(&m_sanscript, "Rust");
  let m_rust_detect = rb::define_module_under(&m_rust, "Detect");
  rb::define_method(&m_rust_detect, "rust_detect_scheme",
    rbstr_detect_scheme as CallbackPtr, 1);
  rb::extend_object(&m_detect, &m_rust_detect);
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! e_number {
    ($e:expr) => ($crate::expr::Expr::Number($e))
}

#[macro_export]
macro_rules! e_bool {
    ($e:expr) => ($crate::expr::Expr::Bool($e))
}

#[macro_export]
macro_rules! e_string {
    ($e:expr) => ($crate::expr::Expr::String($e.to_string()))
}

#[macro_export]
macro_rules! e_symbol {
    ($e:expr) => ($crate::expr::Expr::Symbol($e.to_string()))
}

#[macro_export]
macro_rules! e_list {
    ($($e:expr),*) => ($crate::expr::Expr::List(vec![$($e),*]))
}

#[macro_export]
macro_rules! e_def {
    ($sym:expr, $e:expr) => ($crate::expr::Expr::Def {
        sym: $sym.to_string(),
        expr: Box::new($e),
    })
}

#[macro_export]
macro_rules! e_fn {
    ([$($params:expr),*], [$($e:expr),*]) => ($crate::expr::Expr::Fn {
        params: vec![$($params),*],
        body: vec![$($e),*],
    })
}

#[macro_export]
macro_rules! e_macro {
    ([$($params:expr),*], [$($e:expr),*]) => ($crate::expr::Expr::Macro {
        params: vec![$($params),*],
        body: vec![$($e),*],
    })
}

#[macro_export]
macro_rules! e_call {
    ($name:expr, $($arg:expr), *) => ($crate::expr::Expr::Call {
        name: $name.to_string(),
        args: vec![$($arg),*]
    })
}
<commit_msg>Implement eval macro<commit_after>#[macro_export]
macro_rules! e_number {
    ($e:expr) => ($crate::expr::Expr::Number($e))
}

#[macro_export]
macro_rules! e_bool {
    ($e:expr) => ($crate::expr::Expr::Bool($e))
}

#[macro_export]
macro_rules! e_string {
    ($e:expr) => ($crate::expr::Expr::String($e.to_string()))
}

#[macro_export]
macro_rules! e_symbol {
    ($e:expr) => ($crate::expr::Expr::Symbol($e.to_string()))
}

#[macro_export]
macro_rules! e_list {
    ($($e:expr),*) => ($crate::expr::Expr::List(vec![$($e),*]))
}

#[macro_export]
macro_rules! e_def {
    ($sym:expr, $e:expr) => ($crate::expr::Expr::Def {
        sym: $sym.to_string(),
        expr: Box::new($e),
    })
}

#[macro_export]
macro_rules! e_fn {
    ([$($params:expr),*], [$($e:expr),*]) => ($crate::expr::Expr::Fn {
        params: vec![$($params),*],
        body: vec![$($e),*],
    })
}

#[macro_export]
macro_rules! e_macro {
    ([$($params:expr),*], [$($e:expr),*]) => ($crate::expr::Expr::Macro {
        params: vec![$($params),*],
        body: vec![$($e),*],
    })
}

#[macro_export]
macro_rules! e_call {
    ($name:expr, $($arg:expr), *) => ($crate::expr::Expr::Call {
        name: $name.to_string(),
        args: vec![$($arg),*]
    })
}

#[macro_export]
macro_rules! eval {
    ($e:expr, $s:expr) => ($e.expand($s).and_then(|e| e.eval($s)));
}
<|endoftext|>


<commit_before>use crate::syntax::report::Errors;
use crate::syntax::Api;
use serde::Deserialize;

type Node = clang_ast::Node<Clang>;

#[derive(Deserialize)]
enum Clang {
    Unknown,
}

pub fn load(cx: &mut Errors, apis: &mut [Api]) {
    let mut variants_from_header = Vec::new();
    for api in apis {
        if let Api::Enum(enm) = api {
            if enm.variants_from_header {
                variants_from_header.push(enm);
            }
        }
    }

    if variants_from_header.is_empty() {
        return;
    }

    let _ = cx;
    unimplemented!()
}
<commit_msg>JSON deserialization based on CXX_CLANG_AST env var<commit_after>use crate::syntax::report::Errors;
use crate::syntax::Api;
use serde::Deserialize;
use std::env;
use std::fs;
use std::path::PathBuf;

const CXX_CLANG_AST: &str = "CXX_CLANG_AST";

type Node = clang_ast::Node<Clang>;

#[derive(Deserialize)]
enum Clang {
    Unknown,
}

pub fn load(cx: &mut Errors, apis: &mut [Api]) {
    let mut variants_from_header = Vec::new();
    for api in apis {
        if let Api::Enum(enm) = api {
            if enm.variants_from_header {
                variants_from_header.push(enm);
            }
        }
    }

    let span = match variants_from_header.get(0) {
        None => return,
        Some(enm) => enm.variants_from_header_attr.clone().unwrap(),
    };

    let ast_dump_path = match env::var_os(CXX_CLANG_AST) {
        Some(ast_dump_path) => PathBuf::from(ast_dump_path),
        None => {
            let msg = format!(
                "environment variable ${} has not been provided",
                CXX_CLANG_AST,
            );
            return cx.error(span, msg);
        }
    };

    let ast_dump_bytes = match fs::read(&ast_dump_path) {
        Ok(ast_dump_bytes) => ast_dump_bytes,
        Err(error) => {
            let msg = format!("failed to read {}: {}", ast_dump_path.display(), error);
            return cx.error(span, msg);
        }
    };

    let root: Node = match serde_json::from_slice(&ast_dump_bytes) {
        Ok(root) => root,
        Err(error) => {
            let msg = format!("failed to read {}: {}", ast_dump_path.display(), error);
            return cx.error(span, msg);
        }
    };

    unimplemented!()
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(rustc_diagnostic_macros)]
#![feature(stmt_expr_attributes)]
#![feature(try_blocks)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(trusted_len)]
#![feature(mem_take)]
#![feature(associated_type_bounds)]

#![recursion_limit="256"]

//! This crate contains codegen code that is used by all codegen backends (LLVM and others).
//! The backend-agnostic functions of this crate use functions defined in various traits that
//! have to be implemented by each backends.

#[macro_use] extern crate log;
#[macro_use] extern crate rustc;
#[macro_use] extern crate rustc_data_structures;
#[macro_use] extern crate syntax;

use std::path::PathBuf;
use rustc::dep_graph::WorkProduct;
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::middle::lang_items::LangItem;
use rustc::hir::def_id::CrateNum;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::svh::Svh;
use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary};
use syntax_pos::symbol::Symbol;

// N.B., this module needs to be declared first so diagnostics are
// registered before they are used.
mod error_codes;

pub mod common;
pub mod traits;
pub mod mir;
pub mod debuginfo;
pub mod base;
pub mod callee;
pub mod glue;
pub mod meth;
pub mod mono_item;
pub mod back;

pub struct ModuleCodegen<M> {
    /// The name of the module. When the crate may be saved between
    /// compilations, incremental compilation requires that name be
    /// unique amongst **all** crates. Therefore, it should contain
    /// something unique to this crate (e.g., a module path) as well
    /// as the crate name and disambiguator.
    /// We currently generate these names via CodegenUnit::build_cgu_name().
    pub name: String,
    pub module_llvm: M,
    pub kind: ModuleKind,
}

pub const METADATA_FILENAME: &str = "rust.metadata.bin";
pub const RLIB_BYTECODE_EXTENSION: &str = "bc.z";

impl<M> ModuleCodegen<M> {
    pub fn into_compiled_module(self,
                            emit_obj: bool,
                            emit_bc: bool,
                            emit_bc_compressed: bool,
                            outputs: &OutputFilenames) -> CompiledModule {
        let object = if emit_obj {
            Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
        } else {
            None
        };
        let bytecode = if emit_bc {
            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
        } else {
            None
        };
        let bytecode_compressed = if emit_bc_compressed {
            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
                    .with_extension(RLIB_BYTECODE_EXTENSION))
        } else {
            None
        };

        CompiledModule {
            name: self.name.clone(),
            kind: self.kind,
            object,
            bytecode,
            bytecode_compressed,
        }
    }
}

#[derive(Debug)]
pub struct CompiledModule {
    pub name: String,
    pub kind: ModuleKind,
    pub object: Option<PathBuf>,
    pub bytecode: Option<PathBuf>,
    pub bytecode_compressed: Option<PathBuf>,
}

pub struct CachedModuleCodegen {
    pub name: String,
    pub source: WorkProduct,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ModuleKind {
    Regular,
    Metadata,
    Allocator,
}

bitflags::bitflags! {
    pub struct MemFlags: u8 {
        const VOLATILE = 1 << 0;
        const NONTEMPORAL = 1 << 1;
        const UNALIGNED = 1 << 2;
    }
}

/// Misc info we load from metadata to persist beyond the tcx.
pub struct CrateInfo {
    pub panic_runtime: Option<CrateNum>,
    pub compiler_builtins: Option<CrateNum>,
    pub profiler_runtime: Option<CrateNum>,
    pub sanitizer_runtime: Option<CrateNum>,
    pub is_no_builtins: FxHashSet<CrateNum>,
    pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLibrary>>>,
    pub crate_name: FxHashMap<CrateNum, String>,
    pub used_libraries: Lrc<Vec<NativeLibrary>>,
    pub link_args: Lrc<Vec<String>>,
    pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
    pub used_crates_static: Vec<(CrateNum, LibSource)>,
    pub used_crates_dynamic: Vec<(CrateNum, LibSource)>,
    pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
    pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
}

pub struct CodegenResults {
    pub crate_name: Symbol,
    pub modules: Vec<CompiledModule>,
    pub allocator_module: Option<CompiledModule>,
    pub metadata_module: Option<CompiledModule>,
    pub crate_hash: Svh,
    pub metadata: rustc::middle::cstore::EncodedMetadata,
    pub windows_subsystem: Option<String>,
    pub linker_info: back::linker::LinkerInfo,
    pub crate_info: CrateInfo,
}

__build_diagnostic_array! { librustc_codegen_ssa, DIAGNOSTICS }
<commit_msg>Derive Debug for CrateInfo<commit_after>#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]

#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(rustc_diagnostic_macros)]
#![feature(stmt_expr_attributes)]
#![feature(try_blocks)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(trusted_len)]
#![feature(mem_take)]
#![feature(associated_type_bounds)]

#![recursion_limit="256"]

//! This crate contains codegen code that is used by all codegen backends (LLVM and others).
//! The backend-agnostic functions of this crate use functions defined in various traits that
//! have to be implemented by each backends.

#[macro_use] extern crate log;
#[macro_use] extern crate rustc;
#[macro_use] extern crate rustc_data_structures;
#[macro_use] extern crate syntax;

use std::path::PathBuf;
use rustc::dep_graph::WorkProduct;
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::middle::lang_items::LangItem;
use rustc::hir::def_id::CrateNum;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::svh::Svh;
use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary};
use syntax_pos::symbol::Symbol;

// N.B., this module needs to be declared first so diagnostics are
// registered before they are used.
mod error_codes;

pub mod common;
pub mod traits;
pub mod mir;
pub mod debuginfo;
pub mod base;
pub mod callee;
pub mod glue;
pub mod meth;
pub mod mono_item;
pub mod back;

pub struct ModuleCodegen<M> {
    /// The name of the module. When the crate may be saved between
    /// compilations, incremental compilation requires that name be
    /// unique amongst **all** crates. Therefore, it should contain
    /// something unique to this crate (e.g., a module path) as well
    /// as the crate name and disambiguator.
    /// We currently generate these names via CodegenUnit::build_cgu_name().
    pub name: String,
    pub module_llvm: M,
    pub kind: ModuleKind,
}

pub const METADATA_FILENAME: &str = "rust.metadata.bin";
pub const RLIB_BYTECODE_EXTENSION: &str = "bc.z";

impl<M> ModuleCodegen<M> {
    pub fn into_compiled_module(self,
                            emit_obj: bool,
                            emit_bc: bool,
                            emit_bc_compressed: bool,
                            outputs: &OutputFilenames) -> CompiledModule {
        let object = if emit_obj {
            Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
        } else {
            None
        };
        let bytecode = if emit_bc {
            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
        } else {
            None
        };
        let bytecode_compressed = if emit_bc_compressed {
            Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
                    .with_extension(RLIB_BYTECODE_EXTENSION))
        } else {
            None
        };

        CompiledModule {
            name: self.name.clone(),
            kind: self.kind,
            object,
            bytecode,
            bytecode_compressed,
        }
    }
}

#[derive(Debug)]
pub struct CompiledModule {
    pub name: String,
    pub kind: ModuleKind,
    pub object: Option<PathBuf>,
    pub bytecode: Option<PathBuf>,
    pub bytecode_compressed: Option<PathBuf>,
}

pub struct CachedModuleCodegen {
    pub name: String,
    pub source: WorkProduct,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ModuleKind {
    Regular,
    Metadata,
    Allocator,
}

bitflags::bitflags! {
    pub struct MemFlags: u8 {
        const VOLATILE = 1 << 0;
        const NONTEMPORAL = 1 << 1;
        const UNALIGNED = 1 << 2;
    }
}

/// Misc info we load from metadata to persist beyond the tcx.
#[derive(Debug)]
pub struct CrateInfo {
    pub panic_runtime: Option<CrateNum>,
    pub compiler_builtins: Option<CrateNum>,
    pub profiler_runtime: Option<CrateNum>,
    pub sanitizer_runtime: Option<CrateNum>,
    pub is_no_builtins: FxHashSet<CrateNum>,
    pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLibrary>>>,
    pub crate_name: FxHashMap<CrateNum, String>,
    pub used_libraries: Lrc<Vec<NativeLibrary>>,
    pub link_args: Lrc<Vec<String>>,
    pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
    pub used_crates_static: Vec<(CrateNum, LibSource)>,
    pub used_crates_dynamic: Vec<(CrateNum, LibSource)>,
    pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
    pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
}

pub struct CodegenResults {
    pub crate_name: Symbol,
    pub modules: Vec<CompiledModule>,
    pub allocator_module: Option<CompiledModule>,
    pub metadata_module: Option<CompiledModule>,
    pub crate_hash: Svh,
    pub metadata: rustc::middle::cstore::EncodedMetadata,
    pub windows_subsystem: Option<String>,
    pub linker_info: back::linker::LinkerInfo,
    pub crate_info: CrateInfo,
}

__build_diagnostic_array! { librustc_codegen_ssa, DIAGNOSTICS }
<|endoftext|>


<commit_before>use piston_window::PistonWindow;
use piston_window::Texture;
use piston_window::TextureSettings;
use piston_window::Flip;
use std::path::PathBuf;
use gfx_device_gl::Resources;
use update_component::UpdateComponent;
use std::mem;

pub struct GameObject {
    pub x : f64,
    pub y : f64,
    pub rot : f64,
    pub texture : Texture<Resources>,
    update_components : Vec<Box<UpdateComponent>>,
    updated_components: Vec<Box<UpdateComponent>>,
}

impl GameObject {
    pub fn new(window : &mut PistonWindow) -> GameObject {
        GameObject{
            x : 0.0,
            y : 0.0,
            rot : 0.0,
            update_components : Vec::new(),
            updated_components : Vec::new(),
            texture : Texture::empty(&mut window.factory)
                .expect("Bro it's an empty texture.  How could this fail?"),
        }
    }

    pub fn update(&mut self, delta_time : f64) {
        self.updated_components = Vec::new();
        let mut pop_result = self.update_components.pop();
        while let Some(mut component) = pop_result {
            component.update(self, delta_time);
            self.updated_components.push(component);
            pop_result = self.update_components.pop();
        }
        self.update_components = mem::replace(&mut self.updated_components, Vec::new());
    }

    pub fn add_update_component(&mut self, component : Box<UpdateComponent>)
    {
        self.update_components.push(component);
    }

    pub fn set_texture(&mut self, window : &mut PistonWindow, texture_name : &str) {
        let mut texture_path = PathBuf::from("assets");
        texture_path.push("textures");
        texture_path.push(texture_name);
        let result = Texture::from_path(&mut window.factory, texture_path, Flip::None, &TextureSettings::new());
        match result {
            Ok(texture) => {
                self.texture = texture;
            }
            Err(err) => {
                println!("Unable to load texture, {} Error: {:?}", texture_name, err);
            }
        }
    }
}
<commit_msg>Optimized update loop a bit.<commit_after>use piston_window::PistonWindow;
use piston_window::Texture;
use piston_window::TextureSettings;
use piston_window::Flip;
use std::path::PathBuf;
use gfx_device_gl::Resources;
use update_component::UpdateComponent;
use std::mem;

pub struct GameObject {
    pub x : f64,
    pub y : f64,
    pub rot : f64,
    pub texture : Texture<Resources>,
    update_components : Vec<Box<UpdateComponent>>, //These have not had update run this frame (yet).
    updated_components: Vec<Box<UpdateComponent>>, //These have had update run this frame.
}

impl GameObject {
    pub fn new(window : &mut PistonWindow) -> GameObject {
        GameObject{
            x : 0.0,
            y : 0.0,
            rot : 0.0,
            update_components : Vec::new(),
            updated_components : Vec::new(),
            texture : Texture::empty(&mut window.factory)
                .expect("Bro it's an empty texture.  How could this fail?"),
        }
    }

    pub fn update(&mut self, delta_time : f64) {
        let mut pop_result = self.update_components.pop();
        while let Some(mut component) = pop_result {
            component.update(self, delta_time);
            self.updated_components.push(component);
            pop_result = self.update_components.pop();
        }
        assert_eq!(self.update_components.len(), 0);
        mem::swap(&mut self.update_components, &mut self.updated_components);
    }

    pub fn add_update_component(&mut self, component : Box<UpdateComponent>)
    {
        self.update_components.push(component);
    }

    pub fn set_texture(&mut self, window : &mut PistonWindow, texture_name : &str) {
        let mut texture_path = PathBuf::from("assets");
        texture_path.push("textures");
        texture_path.push(texture_name);
        let result = Texture::from_path(&mut window.factory, texture_path, Flip::None, &TextureSettings::new());
        match result {
            Ok(texture) => {
                self.texture = texture;
            }
            Err(err) => {
                println!("Unable to load texture, {} Error: {:?}", texture_name, err);
            }
        }
    }
}
<|endoftext|>


<commit_before>pub mod cpu;
mod mmu;
pub mod ppu;
pub mod cartridge;
pub mod instructions;
pub mod timer;
pub mod joypad;
pub mod debugger;
pub mod assembly;
mod serial;
mod oam_dma;
mod util;

use std::time::Duration;
use std::sync::mpsc::{Sender, Receiver};

use gameboy::mmu::Mmu;
use gameboy::cpu::CPU;
use gameboy::cpu::registers::Register;
use gameboy::ppu::PPU;
use gameboy::ppu::dmg_ppu::DmgPpu;
//use gameboy::ppu::cgb_ppu::CgbPpu;
use gameboy::timer::Timer;
use gameboy::cartridge::{Cartridge, VirtualCartridge};
use gameboy::joypad::Joypad;
use gameboy::debugger::{Debugger, DebuggerInterface};
use gameboy::cpu::interrupts::Interrupt;
use gameboy::oam_dma::{OamDmaState, OamDmaController};
use gameboy::serial::Serial;
pub use gameboy::joypad::Key;

const IO_SIZE: usize = 128;

const WRAM_BANK_SIZE: usize = 4096;
const WRAM_NUM_BANKS: usize = 8;

#[derive(Debug, Clone, Copy)]
pub enum Mode {
	DMG, CGB,
}

pub struct Gameboy {
	pub cpu: CPU,
	pub timer: Timer,
	pub ppu: Box<PPU + Send>,
	pub serial: Serial,
	pub joypad: Joypad,
	pub cart: Box<Cartridge + Send>,
	pub io: Box<[u8]>,
	pub wram: Box<[u8]>,
	pub mode: Mode,
	pub debugger: Debugger,
	pub oam_dma_state: OamDmaState,
}

#[allow(dead_code)]
impl Gameboy {
	pub fn new(rom: Box<[u8]>, ram: Option<Box<[u8]>>) -> Result<Gameboy, & 'static str> {
		let cart = Box::new(try!(VirtualCartridge::new(rom, ram)));
		let mode: Mode = match cart.get_cart_info().cgb {
			true => Mode::CGB,
			false => Mode::DMG,
		};
		let ppu: Box<PPU + Send> = match mode {
			_ => Box::new(DmgPpu::new()) as Box<PPU + Send>,
		};

		/* initialize io memory to what it should be at the end of the bootrom if
		   no boot rom is loaded
		   TODO: allow the loading of a boot rom
		 */
		let io: [u8; IO_SIZE] = match mode {
			Mode::DMG => {
				[
					0xCF, 0x00, 0x7E, 0xFF, 0x19, 0x00, 0x00, 0xF8, //ff00
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, //ff08
					0x80, 0xBF, 0xF3, 0xFF, 0xBF, 0xFF, 0x3F, 0x00, //ff10
					0xFF, 0xBF, 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, 0xFF, //ff18
					0xFF, 0x00, 0x00, 0xBF, 0x77, 0xF3, 0xF1, 0xFF, //ff20
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff28
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff30
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff38
					0x91, 0x83, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFC, //ff40
					0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, //ff48
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff50
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff58
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff60
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff68
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff70
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff78
				]
			},
			Mode::CGB => {
				//TODO: cgb bootrom values
				[0; IO_SIZE]
			},
		};

		let gameboy = Gameboy {
			cpu: CPU::new(),
			timer: Timer::new(),
			ppu: ppu,
			serial: Serial::new(),
			joypad: Joypad::new(),
			cart: cart,
			io: Box::new(io),
			wram: Box::new([0; WRAM_BANK_SIZE * WRAM_NUM_BANKS]),
			mode: mode,
			debugger: Debugger::new(),
			oam_dma_state: OamDmaState::new(),
		};
		Ok(gameboy)
	}

	pub fn emulate(&mut self, time: Duration) {
		let clock_cycles = ((time.as_secs() * 4_194_304) + ((time.subsec_nanos() as u64 * 4_194_304) / 1_000_000_000)) as usize;
		let mut counter = 0;
		while counter < clock_cycles {
			let start = self.cpu.cycle_counter;
			self.interrupt_service_routine();
			if self.debugger.enabled() {
				if let Some(breakpoint) = self.breakpoint_lookahead() {
					self.debugger.breakpoint_callback(breakpoint);
					return;
				}
				self.execute();
			}
			let end = self.cpu.cycle_counter;
			counter += if self.cpu.double_speed_mode {
				(end - start) / 2
			}
			else {
				end - start
			};
		}
	}

	/// Emulate a variable number of t cycles (usually 4 at a time)
	fn emulate_hardware(&mut self, mut t_cycles: usize) {
		use gameboy::cpu::interrupts::InterruptLine;

		while t_cycles > 0 {
			self.service_oam_dma_transfer();
			let mut interrupt_line = InterruptLine::new(&mut self.cpu.interrupt_flag, &mut self.cpu.halt, &mut self.cpu.stop);
			self.timer.emulate_hardware(&mut interrupt_line);
			self.ppu.emulate_hardware(&mut interrupt_line);
			self.serial.emulate_hardware(&mut interrupt_line);
			self.cpu.cycle_counter += 1;

			t_cycles -= 1;
		}
	}

	fn request_interrupt(&mut self, req_int: Interrupt) {
		self.cpu.interrupt_flag.request_interrupt(req_int);
		self.cpu.stop = false;
		self.cpu.halt = false;
	}

	///Handles interupts
	///If an interrupt is requested in IF (FF0F), and it is enabled in IE (FFFF), and
	///interrupts are enabled by IME (cpu flag),
	///Servicing an interrupt consumes 5 M-Cycles (same as CALL I think)
	///The order than interrupts are serviced is as follows:
	///1. V-Blank
	///2. LCD Stat
	///3. Timer
	///4. Serial
	///5. Joypad
	fn interrupt_service_routine(&mut self) {
		if self.cpu.ime {
			let interrupt_flag: u8 = self.cpu.interrupt_flag.read();
			let interrupt_enable: u8 = self.cpu.interrupt_enable.read();

			//only service requests where it's requested in IF and enabled in IE
			let interrupts = interrupt_flag & interrupt_enable;

			let mut interrupt: Option<Interrupt> = None;

			if (interrupts & (Interrupt::VBlank).mask()) == (Interrupt::VBlank).mask() {
				interrupt = Some(Interrupt::VBlank);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::VBlank); //reset the v-blank bit in IF
			}
			else if (interrupts & (Interrupt::LcdStat).mask()) == (Interrupt::LcdStat).mask() {
				interrupt = Some(Interrupt::LcdStat);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::LcdStat); //reset the lcd-stat bit in IF
			}
			else if (interrupts & (Interrupt::Timer).mask()) == (Interrupt::Timer).mask() {
				interrupt = Some(Interrupt::Timer);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::Timer); //reset the lcd-stat bit in IF
			}
			else if (interrupts & (Interrupt::Serial).mask()) == (Interrupt::Serial).mask() {
				interrupt = Some(Interrupt::Serial);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::Serial); //reset the lcd-stat bit in IF
			}
			else if (interrupts & (Interrupt::Joypad).mask()) == (Interrupt::Joypad).mask() {
				interrupt = Some(Interrupt::Joypad);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::Joypad); //reset the lcd-stat bit in IF
			}

			if let Some(interrupt) = interrupt {
				//Interrupts are enabled, so service this interrupt
				//Nested interrupts are disabled unless the interrupt handler re enables them
				self.cpu.next_ime_state = false;

				//2 cycle delay
				self.emulate_hardware(4);
				self.emulate_hardware(4);

				//wake the processor
				self.cpu.halt = false;

				//Service the interrupt
				let new_pc = interrupt.address();

				let old_pc = self.cpu.registers.pc;
				let sp: u16 = self.cpu.registers.sp;

				//TODO: if there is an oam dma transfer and sp doesn't point
				//to hram, can this be put on the stack?

				//push pc onto stack
				let high: u8 = (old_pc >> 8) as u8;
				self.write_byte_cpu(sp - 1, high);
				self.emulate_hardware(4);

				//push low byte of pc onto stack
				let low: u8 = (old_pc & 0xFF) as u8;
				self.write_byte_cpu(sp - 2, low);
				self.emulate_hardware(4);

				//sub 2 from sp because we pushed a word onto the stack
				self.cpu.registers.sp -= 2;

				//jump to interrupt handler
				self.cpu.registers.pc = new_pc;
				self.emulate_hardware(4);	//1 cycle delay when setting pc
			}
		}
	}

	/*
	///This is only really here for test roms that output results as text through the
	///serial port (blarggs test roms)
	fn print_serial(&mut self) {
		let sc: u8 = self.io[0x02];	//Serial Control Register
		if (sc & 128) == 128 && (sc & 1) == 1 {
			//if bit 7 (transfer start) and bit 0 (internal clock) are set, start transfer
			let sb = self.io[0x01];	//Serial Transfer Data Register
			print!("{}", sb as char);

			//reset sc bit 7
			self.io[0x02] &= 127;
			self.request_interrupt(Interrupt::Serial);
		}
	}*/

	pub fn keydown(&mut self, key: Key) {
		self.joypad.keydown(key);
		self.request_interrupt(Interrupt::Joypad);
	}

	pub fn keyup(&mut self, key: Key) {
		self.joypad.keyup(key);
	}

	pub fn get_framebuffer(&self) -> &[u32] {
		self.ppu.get_framebuffer()
	}

	/* If for some reason you want to write directly to the framebuffer */
	pub fn get_framebuffer_mut(&mut self) -> &mut[u32] {
		self.ppu.get_framebuffer_mut()
	}

	pub fn get_frame_counter(&self) -> usize {
		self.ppu.get_frame_counter()
	}

	/// Create channels to handle async serial transfers.
	pub fn create_serial_channels(&mut self) -> (Sender<u8>, Receiver<u8>) {
		self.serial.create_channels()
	}
}
<commit_msg>Fixed a bug where Gameboy::emulate would get stuck in an infinite loop when the debugger wasn't active.<commit_after>pub mod cpu;
mod mmu;
pub mod ppu;
pub mod cartridge;
pub mod instructions;
pub mod timer;
pub mod joypad;
pub mod debugger;
pub mod assembly;
mod serial;
mod oam_dma;
mod util;

use std::time::Duration;
use std::sync::mpsc::{Sender, Receiver};

use gameboy::mmu::Mmu;
use gameboy::cpu::CPU;
use gameboy::cpu::registers::Register;
use gameboy::ppu::PPU;
use gameboy::ppu::dmg_ppu::DmgPpu;
//use gameboy::ppu::cgb_ppu::CgbPpu;
use gameboy::timer::Timer;
use gameboy::cartridge::{Cartridge, VirtualCartridge};
use gameboy::joypad::Joypad;
use gameboy::debugger::{Debugger, DebuggerInterface};
use gameboy::cpu::interrupts::Interrupt;
use gameboy::oam_dma::{OamDmaState, OamDmaController};
use gameboy::serial::Serial;
pub use gameboy::joypad::Key;

const IO_SIZE: usize = 128;

const WRAM_BANK_SIZE: usize = 4096;
const WRAM_NUM_BANKS: usize = 8;

#[derive(Debug, Clone, Copy)]
pub enum Mode {
	DMG, CGB,
}

pub struct Gameboy {
	pub cpu: CPU,
	pub timer: Timer,
	pub ppu: Box<PPU + Send>,
	pub serial: Serial,
	pub joypad: Joypad,
	pub cart: Box<Cartridge + Send>,
	pub io: Box<[u8]>,
	pub wram: Box<[u8]>,
	pub mode: Mode,
	pub debugger: Debugger,
	pub oam_dma_state: OamDmaState,
}

#[allow(dead_code)]
impl Gameboy {
	pub fn new(rom: Box<[u8]>, ram: Option<Box<[u8]>>) -> Result<Gameboy, & 'static str> {
		let cart = Box::new(try!(VirtualCartridge::new(rom, ram)));
		let mode: Mode = match cart.get_cart_info().cgb {
			true => Mode::CGB,
			false => Mode::DMG,
		};
		let ppu: Box<PPU + Send> = match mode {
			_ => Box::new(DmgPpu::new()) as Box<PPU + Send>,
		};

		/* initialize io memory to what it should be at the end of the bootrom if
		   no boot rom is loaded
		   TODO: allow the loading of a boot rom
		 */
		let io: [u8; IO_SIZE] = match mode {
			Mode::DMG => {
				[
					0xCF, 0x00, 0x7E, 0xFF, 0x19, 0x00, 0x00, 0xF8, //ff00
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, //ff08
					0x80, 0xBF, 0xF3, 0xFF, 0xBF, 0xFF, 0x3F, 0x00, //ff10
					0xFF, 0xBF, 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, 0xFF, //ff18
					0xFF, 0x00, 0x00, 0xBF, 0x77, 0xF3, 0xF1, 0xFF, //ff20
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff28
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff30
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff38
					0x91, 0x83, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFC, //ff40
					0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, //ff48
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff50
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff58
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff60
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff68
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff70
					0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //ff78
				]
			},
			Mode::CGB => {
				//TODO: cgb bootrom values
				[0; IO_SIZE]
			},
		};

		let gameboy = Gameboy {
			cpu: CPU::new(),
			timer: Timer::new(),
			ppu: ppu,
			serial: Serial::new(),
			joypad: Joypad::new(),
			cart: cart,
			io: Box::new(io),
			wram: Box::new([0; WRAM_BANK_SIZE * WRAM_NUM_BANKS]),
			mode: mode,
			debugger: Debugger::new(),
			oam_dma_state: OamDmaState::new(),
		};
		Ok(gameboy)
	}

	pub fn emulate(&mut self, time: Duration) {
		let clock_cycles = ((time.as_secs() * 4_194_304) + ((time.subsec_nanos() as u64 * 4_194_304) / 1_000_000_000)) as usize;
		let mut counter = 0;
		while counter < clock_cycles {
			let start = self.cpu.cycle_counter;
			self.interrupt_service_routine();
			if self.debugger.enabled() {
				if let Some(breakpoint) = self.breakpoint_lookahead() {
					self.debugger.breakpoint_callback(breakpoint);
					return;
				}
				self.execute();
			}
			else {
				self.execute();
			}
			let end = self.cpu.cycle_counter;
			counter += if self.cpu.double_speed_mode {
				(end - start) / 2
			}
			else {
				end - start
			};
		}
	}

	/// Emulate a variable number of t cycles (usually 4 at a time)
	fn emulate_hardware(&mut self, mut t_cycles: usize) {
		use gameboy::cpu::interrupts::InterruptLine;

		while t_cycles > 0 {
			self.service_oam_dma_transfer();
			let mut interrupt_line = InterruptLine::new(&mut self.cpu.interrupt_flag, &mut self.cpu.halt, &mut self.cpu.stop);
			self.timer.emulate_hardware(&mut interrupt_line);
			self.ppu.emulate_hardware(&mut interrupt_line);
			self.serial.emulate_hardware(&mut interrupt_line);
			self.cpu.cycle_counter += 1;

			t_cycles -= 1;
		}
	}

	fn request_interrupt(&mut self, req_int: Interrupt) {
		self.cpu.interrupt_flag.request_interrupt(req_int);
		self.cpu.stop = false;
		self.cpu.halt = false;
	}

	///Handles interupts
	///If an interrupt is requested in IF (FF0F), and it is enabled in IE (FFFF), and
	///interrupts are enabled by IME (cpu flag),
	///Servicing an interrupt consumes 5 M-Cycles (same as CALL I think)
	///The order than interrupts are serviced is as follows:
	///1. V-Blank
	///2. LCD Stat
	///3. Timer
	///4. Serial
	///5. Joypad
	fn interrupt_service_routine(&mut self) {
		if self.cpu.ime {
			let interrupt_flag: u8 = self.cpu.interrupt_flag.read();
			let interrupt_enable: u8 = self.cpu.interrupt_enable.read();

			//only service requests where it's requested in IF and enabled in IE
			let interrupts = interrupt_flag & interrupt_enable;

			let mut interrupt: Option<Interrupt> = None;

			if (interrupts & (Interrupt::VBlank).mask()) == (Interrupt::VBlank).mask() {
				interrupt = Some(Interrupt::VBlank);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::VBlank); //reset the v-blank bit in IF
			}
			else if (interrupts & (Interrupt::LcdStat).mask()) == (Interrupt::LcdStat).mask() {
				interrupt = Some(Interrupt::LcdStat);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::LcdStat); //reset the lcd-stat bit in IF
			}
			else if (interrupts & (Interrupt::Timer).mask()) == (Interrupt::Timer).mask() {
				interrupt = Some(Interrupt::Timer);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::Timer); //reset the lcd-stat bit in IF
			}
			else if (interrupts & (Interrupt::Serial).mask()) == (Interrupt::Serial).mask() {
				interrupt = Some(Interrupt::Serial);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::Serial); //reset the lcd-stat bit in IF
			}
			else if (interrupts & (Interrupt::Joypad).mask()) == (Interrupt::Joypad).mask() {
				interrupt = Some(Interrupt::Joypad);
				self.cpu.interrupt_flag.clear_interrupt(Interrupt::Joypad); //reset the lcd-stat bit in IF
			}

			if let Some(interrupt) = interrupt {
				//Interrupts are enabled, so service this interrupt
				//Nested interrupts are disabled unless the interrupt handler re enables them
				self.cpu.next_ime_state = false;

				//2 cycle delay
				self.emulate_hardware(4);
				self.emulate_hardware(4);

				//wake the processor
				self.cpu.halt = false;

				//Service the interrupt
				let new_pc = interrupt.address();

				let old_pc = self.cpu.registers.pc;
				let sp: u16 = self.cpu.registers.sp;

				//TODO: if there is an oam dma transfer and sp doesn't point
				//to hram, can this be put on the stack?

				//push pc onto stack
				let high: u8 = (old_pc >> 8) as u8;
				self.write_byte_cpu(sp - 1, high);
				self.emulate_hardware(4);

				//push low byte of pc onto stack
				let low: u8 = (old_pc & 0xFF) as u8;
				self.write_byte_cpu(sp - 2, low);
				self.emulate_hardware(4);

				//sub 2 from sp because we pushed a word onto the stack
				self.cpu.registers.sp -= 2;

				//jump to interrupt handler
				self.cpu.registers.pc = new_pc;
				self.emulate_hardware(4);	//1 cycle delay when setting pc
			}
		}
	}

	/*
	///This is only really here for test roms that output results as text through the
	///serial port (blarggs test roms)
	fn print_serial(&mut self) {
		let sc: u8 = self.io[0x02];	//Serial Control Register
		if (sc & 128) == 128 && (sc & 1) == 1 {
			//if bit 7 (transfer start) and bit 0 (internal clock) are set, start transfer
			let sb = self.io[0x01];	//Serial Transfer Data Register
			print!("{}", sb as char);

			//reset sc bit 7
			self.io[0x02] &= 127;
			self.request_interrupt(Interrupt::Serial);
		}
	}*/

	pub fn keydown(&mut self, key: Key) {
		self.joypad.keydown(key);
		self.request_interrupt(Interrupt::Joypad);
	}

	pub fn keyup(&mut self, key: Key) {
		self.joypad.keyup(key);
	}

	pub fn get_framebuffer(&self) -> &[u32] {
		self.ppu.get_framebuffer()
	}

	/* If for some reason you want to write directly to the framebuffer */
	pub fn get_framebuffer_mut(&mut self) -> &mut[u32] {
		self.ppu.get_framebuffer_mut()
	}

	pub fn get_frame_counter(&self) -> usize {
		self.ppu.get_frame_counter()
	}

	/// Create channels to handle async serial transfers.
	pub fn create_serial_channels(&mut self) -> (Sender<u8>, Receiver<u8>) {
		self.serial.create_channels()
	}
}
<|endoftext|>


<commit_before>#![feature(raw)]
extern crate elf;
extern crate getopts;

use getopts::Options;
use std::env;
use std::path::Path;
use std::fs::File;
use std::io;
use std::io::Write;

#[repr(C,packed)]
#[derive(Debug)]
struct LoadInfo {
    rel_data_size: u32,
    entry_loc: u32,        /* Entry point for user application */
    init_data_loc: u32,    /* Data initialization information in flash */
    init_data_size: u32,   /* Size of initialization information */
    got_start_offset: u32, /* Offset in memory to start of GOT */
    got_end_offset: u32,   /* Offset in memory to end of GOT */
    bss_start_offset: u32, /* Offset in memory to start of BSS */
    bss_end_offset: u32    /* Offset in memory to end of BSS */
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "OUTFILE");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    let path = Path::new(&input);
    let file = match elf::File::open_path(&path) {
        Ok(f) => f,
        Err(e) => panic!("Error: {:?}", e),
    };

    match output {
        None => {
            let mut out = io::stdout();
            do_work(&file, &mut out)
        }
        Some(name) => match File::create(Path::new(&name)) {
            Ok(mut f) => do_work(&file, &mut f),
            Err(e) => panic!("Error: {:?}", e),
        }
    };

}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [-o OUTFILE] FILE", program);
    print!("{}", opts.usage(&brief));
}

fn get_section<'a>(input: &'a elf::File, name: &str) -> &'a elf::Section {
    match input.get_section(name) {
        Some(s) => {
            s
        },
        None => panic!("Failed to look up {} section", name),
    }
}

fn do_work(input: &elf::File, output: &mut Write) {
    let (rel_data_size, rel_data) = match input.sections.iter()
            .find(|section| section.shdr.name == ".rel.data".as_ref()) {
        Some(section) => {
            (section.shdr.size, section.data.as_ref())
        },
        None => (0 as u64, &[] as &[u8])

    };
    let text = get_section(input, ".text");
    let got = get_section(input, ".got");
    let data = get_section(input, ".data");
    let bss = get_section(input, ".bss");

    let load_info = LoadInfo {
        rel_data_size: rel_data_size as u32,
        entry_loc: (input.ehdr.entry ^ 0x80000000) as u32,
        init_data_loc: text.shdr.size as u32,
        init_data_size: (data.shdr.size + got.shdr.size) as u32,
        got_start_offset: 0,
        got_end_offset: got.shdr.size as u32,
        bss_start_offset: bss.shdr.addr as u32,
        bss_end_offset: (bss.shdr.addr + bss.shdr.size) as u32
    };

    let load_info_bytes : &[u8] = unsafe {
        std::mem::transmute(std::raw::Slice {
            data: &load_info,
            len: std::mem::size_of::<LoadInfo>()
        })
    };

    let mut total_len : u32 =
        (std::mem::size_of::<u32>() +
        load_info_bytes.as_ref().len() +
        rel_data.len() +
        text.data.len() +
        got.data.len() +
        data.data.len()) as u32;
    let pad = (4 - (total_len % 4)) % 4;
    total_len = total_len + pad;

    let total_len_buf : &[u8; 4] = unsafe {
        std::mem::transmute(&total_len)
    };

    let _ = output.write(total_len_buf);

    let _ = output.write(load_info_bytes);

    let _ = output.write(rel_data.as_ref());

    let _ = output.write(text.data.as_ref());
    let _ = output.write(got.data.as_ref());
    let _ = output.write(data.data.as_ref());

    for _ in 0..pad {
        let _ = output.write(&[0]);
    }
}

<commit_msg>Pad app binaries to nearest power of 2<commit_after>#![feature(raw)]
extern crate elf;
extern crate getopts;

use getopts::Options;
use std::env;
use std::path::Path;
use std::fs::File;
use std::io;
use std::io::Write;

#[repr(C,packed)]
#[derive(Debug)]
struct LoadInfo {
    rel_data_size: u32,
    entry_loc: u32,        /* Entry point for user application */
    init_data_loc: u32,    /* Data initialization information in flash */
    init_data_size: u32,   /* Size of initialization information */
    got_start_offset: u32, /* Offset in memory to start of GOT */
    got_end_offset: u32,   /* Offset in memory to end of GOT */
    bss_start_offset: u32, /* Offset in memory to start of BSS */
    bss_end_offset: u32    /* Offset in memory to end of BSS */
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "OUTFILE");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    let path = Path::new(&input);
    let file = match elf::File::open_path(&path) {
        Ok(f) => f,
        Err(e) => panic!("Error: {:?}", e),
    };

    match output {
        None => {
            let mut out = io::stdout();
            do_work(&file, &mut out)
        }
        Some(name) => match File::create(Path::new(&name)) {
            Ok(mut f) => do_work(&file, &mut f),
            Err(e) => panic!("Error: {:?}", e),
        }
    };

}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [-o OUTFILE] FILE", program);
    print!("{}", opts.usage(&brief));
}

fn get_section<'a>(input: &'a elf::File, name: &str) -> &'a elf::Section {
    match input.get_section(name) {
        Some(s) => {
            s
        },
        None => panic!("Failed to look up {} section", name),
    }
}

fn do_work(input: &elf::File, output: &mut Write) {
    let (rel_data_size, rel_data) = match input.sections.iter()
            .find(|section| section.shdr.name == ".rel.data".as_ref()) {
        Some(section) => {
            (section.shdr.size, section.data.as_ref())
        },
        None => (0 as u64, &[] as &[u8])

    };
    let text = get_section(input, ".text");
    let got = get_section(input, ".got");
    let data = get_section(input, ".data");
    let bss = get_section(input, ".bss");

    let load_info = LoadInfo {
        rel_data_size: rel_data_size as u32,
        entry_loc: (input.ehdr.entry ^ 0x80000000) as u32,
        init_data_loc: text.shdr.size as u32,
        init_data_size: (data.shdr.size + got.shdr.size) as u32,
        got_start_offset: 0,
        got_end_offset: got.shdr.size as u32,
        bss_start_offset: bss.shdr.addr as u32,
        bss_end_offset: (bss.shdr.addr + bss.shdr.size) as u32
    };

    let load_info_bytes : &[u8] = unsafe {
        std::mem::transmute(std::raw::Slice {
            data: &load_info,
            len: std::mem::size_of::<LoadInfo>()
        })
    };

    let mut total_len : u32 =
        (std::mem::size_of::<u32>() +
        load_info_bytes.as_ref().len() +
        rel_data.len() +
        text.data.len() +
        got.data.len() +
        data.data.len()) as u32;

    let pad = if total_len.count_ones() > 1 {
        let power2len = 1 << (32 - total_len.leading_zeros());
        power2len - total_len
    } else {
        0
    };
    total_len = total_len + pad;

    let total_len_buf : &[u8; 4] = unsafe {
        std::mem::transmute(&total_len)
    };

    let _ = output.write(total_len_buf);

    let _ = output.write(load_info_bytes);

    let _ = output.write(rel_data.as_ref());

    let _ = output.write(text.data.as_ref());
    let _ = output.write(got.data.as_ref());
    let _ = output.write(data.data.as_ref());

    for _ in 0..pad {
        let _ = output.write(&[0]);
    }
}

<|endoftext|>


<commit_before>//! Providing auxiliary information for signals.

use std::io::Error;
use std::mem;
use std::ptr;

use libc::{c_int, EINVAL};
#[cfg(not(windows))]
use libc::{sigset_t, SIG_UNBLOCK};

use crate::consts::signal::*;
use crate::low_level;

#[derive(Clone, Copy, Debug)]
enum DefaultKind {
    Ignore,
    #[cfg(not(windows))]
    Stop,
    Term,
}

struct Details {
    signal: c_int,
    name: &'static str,
    default_kind: DefaultKind,
}

macro_rules! s {
    ($name: expr, $kind: ident) => {
        Details {
            signal: $name,
            name: stringify!($name),
            default_kind: DefaultKind::$kind,
        }
    };
}

#[cfg(not(windows))]
const DETAILS: &[Details] = &[
    s!(SIGABRT, Term),
    s!(SIGALRM, Term),
    s!(SIGBUS, Term),
    s!(SIGCHLD, Ignore),
    // Technically, continue the process... but this is not done *by* the process.
    s!(SIGCONT, Ignore),
    s!(SIGFPE, Term),
    s!(SIGHUP, Term),
    s!(SIGILL, Term),
    s!(SIGINT, Term),
    s!(SIGIO, Ignore),
    // Can't override anyway, but...
    s!(SIGKILL, Term),
    s!(SIGPIPE, Term),
    s!(SIGPROF, Term),
    s!(SIGQUIT, Term),
    s!(SIGSEGV, Term),
    // Can't override anyway, but...
    s!(SIGSTOP, Stop),
    s!(SIGSYS, Term),
    s!(SIGTERM, Term),
    s!(SIGTRAP, Term),
    s!(SIGTSTP, Stop),
    s!(SIGTTIN, Stop),
    s!(SIGTTOU, Stop),
    s!(SIGURG, Ignore),
    s!(SIGUSR1, Term),
    s!(SIGUSR2, Term),
    s!(SIGVTALRM, Term),
    s!(SIGWINCH, Ignore),
    s!(SIGXCPU, Term),
    s!(SIGXFSZ, Term),
];

#[cfg(windows)]
const DETAILS: &[Details] = &[
    s!(SIGABRT, Term),
    s!(SIGFPE, Term),
    s!(SIGILL, Term),
    s!(SIGINT, Term),
    s!(SIGSEGV, Term),
    s!(SIGTERM, Term),
];

/// Provides a human-readable name of a signal.
///
/// Note that the name does not have to be known (in case it is some less common, or non-standard
/// signal).
///
/// # Examples
///
/// ```
/// # use signal_hook::low_level::signal_name;
/// assert_eq!("SIGKILL", signal_name(9).unwrap());
/// assert!(signal_name(142).is_none());
/// ```
pub fn signal_name(signal: c_int) -> Option<&'static str> {
    DETAILS.iter().find(|d| d.signal == signal).map(|d| d.name)
}

#[cfg(not(windows))]
fn restore_default(signal: c_int) -> Result<(), Error> {
    unsafe {
        // A C structure, supposed to be memset to 0 before use.
        let mut action: libc::sigaction = mem::zeroed();
        action.sa_sigaction = libc::SIG_DFL as _;
        if libc::sigaction(signal, &action, ptr::null_mut()) == 0 {
            Ok(())
        } else {
            Err(Error::last_os_error())
        }
    }
}

#[cfg(windows)]
fn restore_default(signal: c_int) -> Result<(), Error> {
    unsafe {
        // SIG_DFL = 0, but not in libc :-(
        if libc::signal(signal, 0) == 0 {
            Ok(())
        } else {
            Err(Error::last_os_error())
        }
    }
}

// Some android versions don't have the sigemptyset and sigaddset. Unfortunately, we don't have
// an access to the android _version_. We just know that 64bit versions are all OK, so this is a
// best-effort guess.
//
// For the affected/guessed versions, we provide our own implementation. We hope it to be correct
// (it's inspired by a libc implementation and we assume the kernel uses the same format ‒ it's
// unlikely to be different both because of compatibility and because there's really nothing to
// invent about a bitarray).
//
// We use the proper way for other systems.
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
unsafe fn prepare_sigset(set: *mut sigset_t, mut signal: c_int) {
    signal -= 1;
    let set_raw: *mut libc::c_ulong = set.cast();
    let size = mem::size_of::<libc::c_ulong>();
    assert_eq!(set_raw as usize % mem::align_of::<libc::c_ulong>(), 0);
    let pos = signal as usize / size;
    assert!(pos < mem::size_of::<sigset_t>() / size);
    let bit = 1 << (signal as usize % size);
    set_raw.add(pos).write(bit);
}

#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
unsafe fn prepare_sigset(set: *mut sigset_t, signal: c_int) {
    libc::sigemptyset(set);
    libc::sigaddset(set, signal);
}

/// Emulates the behaviour of a default handler for the provided signal.
///
/// This function does its best to provide the same action as the default handler would do, without
/// disrupting the rest of the handling of such signal in the application. It is also
/// async-signal-safe.
///
/// This function necessarily looks up the appropriate action in a table. That means it is possible
/// your system has a signal that is not known to this function. In such case an error is returned
/// (equivalent of `EINVAL`).
///
/// See also the [`register_conditional_default`][crate::flag::register_conditional_default].
///
/// # Warning
///
/// There's a short race condition in case of signals that terminate (either with or without a core
/// dump). The emulation first resets the signal handler back to default (as the application is
/// going to end, it's not a problem) and invokes it. But if some other thread installs a signal
/// handler in the meantime (without assistance from `signal-hook`), it can happen this will be
/// invoked by the re-raised signal.
///
/// This function will still terminate the application (there's a fallback on `abort`), the risk is
/// invoking the newly installed signal handler. Note that manipulating the low-level signals is
/// always racy in a multi-threaded program, therefore the described situation is already
/// discouraged.
///
/// If you are uneasy about such race condition, the recommendation is to run relevant termination
/// routine manually ([`exit`][super::exit] or [`abort`][super::abort]); they always do what they
/// say, but slightly differ in externally observable behaviour from termination by a signal (the
/// exit code will specify that the application exited, not that it terminated with a signal in the
/// first case, and `abort` terminates on `SIGABRT`, so the detected termination signal may be
/// different).
pub fn emulate_default_handler(signal: c_int) -> Result<(), Error> {
    #[cfg(not(windows))]
    {
        if signal == SIGSTOP || signal == SIGKILL {
            return low_level::raise(signal);
        }
    }
    let kind = DETAILS
        .iter()
        .find(|d| d.signal == signal)
        .map(|d| d.default_kind)
        .ok_or_else(|| Error::from_raw_os_error(EINVAL))?;
    match kind {
        DefaultKind::Ignore => Ok(()),
        #[cfg(not(windows))]
        DefaultKind::Stop => low_level::raise(SIGSTOP),
        DefaultKind::Term => {
            if let Ok(()) = restore_default(signal) {
                #[cfg(not(windows))]
                unsafe {
                    #[allow(deprecated)]
                    let mut newsigs: sigset_t = mem::zeroed();
                    prepare_sigset(&mut newsigs, signal);
                    // Ignore the result, if it doesn't work, we try anyway
                    // Also, sigprocmask is unspecified, but available on more systems. And we want
                    // to just enable _something_. And if it doesn't work, we'll terminate
                    // anyway... It's not UB, so we are good.
                    libc::sigprocmask(SIG_UNBLOCK, &newsigs, ptr::null_mut());
                }
                let _ = low_level::raise(signal);
            }
            // Fallback if anything failed or someone managed to put some other action in in
            // between.
            unsafe { libc::abort() }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn existing() {
        assert_eq!("SIGTERM", signal_name(SIGTERM).unwrap());
    }

    #[test]
    fn unknown() {
        assert!(signal_name(128).is_none());
    }
}
<commit_msg>cargo fmt<commit_after>//! Providing auxiliary information for signals.

use std::io::Error;
use std::mem;
use std::ptr;

use libc::{c_int, EINVAL};
#[cfg(not(windows))]
use libc::{sigset_t, SIG_UNBLOCK};

use crate::consts::signal::*;
use crate::low_level;

#[derive(Clone, Copy, Debug)]
enum DefaultKind {
    Ignore,
    #[cfg(not(windows))]
    Stop,
    Term,
}

struct Details {
    signal: c_int,
    name: &'static str,
    default_kind: DefaultKind,
}

macro_rules! s {
    ($name: expr, $kind: ident) => {
        Details {
            signal: $name,
            name: stringify!($name),
            default_kind: DefaultKind::$kind,
        }
    };
}

#[cfg(not(windows))]
const DETAILS: &[Details] = &[
    s!(SIGABRT, Term),
    s!(SIGALRM, Term),
    s!(SIGBUS, Term),
    s!(SIGCHLD, Ignore),
    // Technically, continue the process... but this is not done *by* the process.
    s!(SIGCONT, Ignore),
    s!(SIGFPE, Term),
    s!(SIGHUP, Term),
    s!(SIGILL, Term),
    s!(SIGINT, Term),
    s!(SIGIO, Ignore),
    // Can't override anyway, but...
    s!(SIGKILL, Term),
    s!(SIGPIPE, Term),
    s!(SIGPROF, Term),
    s!(SIGQUIT, Term),
    s!(SIGSEGV, Term),
    // Can't override anyway, but...
    s!(SIGSTOP, Stop),
    s!(SIGSYS, Term),
    s!(SIGTERM, Term),
    s!(SIGTRAP, Term),
    s!(SIGTSTP, Stop),
    s!(SIGTTIN, Stop),
    s!(SIGTTOU, Stop),
    s!(SIGURG, Ignore),
    s!(SIGUSR1, Term),
    s!(SIGUSR2, Term),
    s!(SIGVTALRM, Term),
    s!(SIGWINCH, Ignore),
    s!(SIGXCPU, Term),
    s!(SIGXFSZ, Term),
];

#[cfg(windows)]
const DETAILS: &[Details] = &[
    s!(SIGABRT, Term),
    s!(SIGFPE, Term),
    s!(SIGILL, Term),
    s!(SIGINT, Term),
    s!(SIGSEGV, Term),
    s!(SIGTERM, Term),
];

/// Provides a human-readable name of a signal.
///
/// Note that the name does not have to be known (in case it is some less common, or non-standard
/// signal).
///
/// # Examples
///
/// ```
/// # use signal_hook::low_level::signal_name;
/// assert_eq!("SIGKILL", signal_name(9).unwrap());
/// assert!(signal_name(142).is_none());
/// ```
pub fn signal_name(signal: c_int) -> Option<&'static str> {
    DETAILS.iter().find(|d| d.signal == signal).map(|d| d.name)
}

#[cfg(not(windows))]
fn restore_default(signal: c_int) -> Result<(), Error> {
    unsafe {
        // A C structure, supposed to be memset to 0 before use.
        let mut action: libc::sigaction = mem::zeroed();
        action.sa_sigaction = libc::SIG_DFL as _;
        if libc::sigaction(signal, &action, ptr::null_mut()) == 0 {
            Ok(())
        } else {
            Err(Error::last_os_error())
        }
    }
}

#[cfg(windows)]
fn restore_default(signal: c_int) -> Result<(), Error> {
    unsafe {
        // SIG_DFL = 0, but not in libc :-(
        if libc::signal(signal, 0) == 0 {
            Ok(())
        } else {
            Err(Error::last_os_error())
        }
    }
}

// Some android versions don't have the sigemptyset and sigaddset. Unfortunately, we don't have
// an access to the android _version_. We just know that 64bit versions are all OK, so this is a
// best-effort guess.
//
// For the affected/guessed versions, we provide our own implementation. We hope it to be correct
// (it's inspired by a libc implementation and we assume the kernel uses the same format ‒ it's
// unlikely to be different both because of compatibility and because there's really nothing to
// invent about a bitarray).
//
// We use the proper way for other systems.
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
unsafe fn prepare_sigset(set: *mut sigset_t, mut signal: c_int) {
    signal -= 1;
    let set_raw: *mut libc::c_ulong = set.cast();
    let size = mem::size_of::<libc::c_ulong>();
    assert_eq!(set_raw as usize % mem::align_of::<libc::c_ulong>(), 0);
    let pos = signal as usize / size;
    assert!(pos < mem::size_of::<sigset_t>() / size);
    let bit = 1 << (signal as usize % size);
    set_raw.add(pos).write(bit);
}

#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
unsafe fn prepare_sigset(set: *mut sigset_t, signal: c_int) {
    libc::sigemptyset(set);
    libc::sigaddset(set, signal);
}

/// Emulates the behaviour of a default handler for the provided signal.
///
/// This function does its best to provide the same action as the default handler would do, without
/// disrupting the rest of the handling of such signal in the application. It is also
/// async-signal-safe.
///
/// This function necessarily looks up the appropriate action in a table. That means it is possible
/// your system has a signal that is not known to this function. In such case an error is returned
/// (equivalent of `EINVAL`).
///
/// See also the [`register_conditional_default`][crate::flag::register_conditional_default].
///
/// # Warning
///
/// There's a short race condition in case of signals that terminate (either with or without a core
/// dump). The emulation first resets the signal handler back to default (as the application is
/// going to end, it's not a problem) and invokes it. But if some other thread installs a signal
/// handler in the meantime (without assistance from `signal-hook`), it can happen this will be
/// invoked by the re-raised signal.
///
/// This function will still terminate the application (there's a fallback on `abort`), the risk is
/// invoking the newly installed signal handler. Note that manipulating the low-level signals is
/// always racy in a multi-threaded program, therefore the described situation is already
/// discouraged.
///
/// If you are uneasy about such race condition, the recommendation is to run relevant termination
/// routine manually ([`exit`][super::exit] or [`abort`][super::abort]); they always do what they
/// say, but slightly differ in externally observable behaviour from termination by a signal (the
/// exit code will specify that the application exited, not that it terminated with a signal in the
/// first case, and `abort` terminates on `SIGABRT`, so the detected termination signal may be
/// different).
pub fn emulate_default_handler(signal: c_int) -> Result<(), Error> {
    #[cfg(not(windows))]
    {
        if signal == SIGSTOP || signal == SIGKILL {
            return low_level::raise(signal);
        }
    }
    let kind = DETAILS
        .iter()
        .find(|d| d.signal == signal)
        .map(|d| d.default_kind)
        .ok_or_else(|| Error::from_raw_os_error(EINVAL))?;
    match kind {
        DefaultKind::Ignore => Ok(()),
        #[cfg(not(windows))]
        DefaultKind::Stop => low_level::raise(SIGSTOP),
        DefaultKind::Term => {
            if let Ok(()) = restore_default(signal) {
                #[cfg(not(windows))]
                unsafe {
                    #[allow(deprecated)]
                    let mut newsigs: sigset_t = mem::zeroed();
                    prepare_sigset(&mut newsigs, signal);
                    // Ignore the result, if it doesn't work, we try anyway
                    // Also, sigprocmask is unspecified, but available on more systems. And we want
                    // to just enable _something_. And if it doesn't work, we'll terminate
                    // anyway... It's not UB, so we are good.
                    libc::sigprocmask(SIG_UNBLOCK, &newsigs, ptr::null_mut());
                }
                let _ = low_level::raise(signal);
            }
            // Fallback if anything failed or someone managed to put some other action in in
            // between.
            unsafe { libc::abort() }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn existing() {
        assert_eq!("SIGTERM", signal_name(SIGTERM).unwrap());
    }

    #[test]
    fn unknown() {
        assert!(signal_name(128).is_none());
    }
}
<|endoftext|>


<commit_before>extern crate pq_sys;
extern crate openssl; // needed to avoid link errors even if we don't use it directly

fn main() {
    unsafe{ pq_sys::PQinitSSL(1); }
}
<commit_msg>speculative fix build<commit_after>extern crate openssl; // needed to avoid link errors even if we don't use it directly
extern crate pq_sys;

fn main() {
    unsafe{ pq_sys::PQinitSSL(1); }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate regex;

use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;

use regex::Regex;
use clap::{App,Arg};

fn main() {
    let args = App::new("grep-lite")
        .version("0.1")
        .about("searches for patterns")
        .arg(Arg::with_name("pattern")
             .help("the pattern to search for")
             .takes_value(true)
             .required(true))
        .arg(Arg::with_name("input")
             .help("File to search")
             .takes_value(true)
             .required(true))
        .get_matches();

    let pattern = args.value_of("pattern").unwrap();
    let re = Regex::new(pattern).unwrap();

    let input = args.value_of("input").unwrap();
    let f = File::open(input).unwrap();
    let reader = BufReader::new(f);

    // PARAMETERS
    let context_lines = 2;
    let needle = "oo";
    let haystack = "Every face, every shop,
    bedroom window, public-house, and
    dark square is a picture
    feverishly turned--in search of what?
    It is the same with books.
    what do we seek
    through millions of pages?";

    // INITIALIZATINO
    let mut tags: Vec<usize> = Vec::new();
    let mut ctx: Vec<Vec<(usize, String)>> = Vec::new();

    // PASS 1
    for (i, line) in haystack.lines().enumerate() {
        if line.contains(needle) {
            tags.push(i);

            let v = Vec::with_capacity(2*context_lines + 1);
            ctx.push(v)
        }
    }

    if tags.len() == 0 {
        return;
    }

    // PASS 2
    for (i, line) in haystack.lines().enumerate() {
        for (j, tag) in tags.iter().enumerate() {
            let lower_bound = tag.saturating_sub(context_lines);
            let upper_bound = tag + context_lines;

            if (i >= lower_bound) && (i <= upper_bound) {
                let line_as_string = String::from(line);
                let local_ctx = (i, line_as_string);
                ctx[j].push(local_ctx);
            }
        }
    }

    // OUTPUT
    for local_ctx in ctx.iter() {
        for &(i, ref line) in local_ctx.iter() {
            let line_num = i + 1;
            println!("{}: {}", line_num, line);
        }
    }
    println!();

    let mut idx = 0;
    for line_ in reader.lines() {
        let line = line_.unwrap();
        match re.find(&line) {
            Some(_) => {
                let line_num = idx + 1;
                println!("{}: {}", line_num, line);
            },
            None => (),
        }
        idx = idx + 1;
    }
}
<commit_msg>allow for reading stdin<commit_after>extern crate clap;
extern crate regex;

use std::fs::File;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use regex::Regex;
use clap::{App,Arg};

fn process_lines<T: BufRead + Sized>(reader: T, re: Regex) {
    let mut idx = 0;
    for line_ in reader.lines() {
        let line = line_.unwrap();
        match re.find(&line) {
            Some(_) => {
                let line_num = idx + 1;
                println!("{}: {}", line_num, line);
            },
            None => (),
        }
        idx = idx + 1;
    }

}

fn main() {
    let args = App::new("grep-lite")
        .version("0.1")
        .about("searches for patterns")
        .arg(Arg::with_name("pattern")
             .help("the pattern to search for")
             .takes_value(true)
             .required(true))
        .arg(Arg::with_name("input")
             .help("File to search")
             .takes_value(true)
             .required(true))
        .get_matches();

    let pattern = args.value_of("pattern").unwrap();
    let re = Regex::new(pattern).unwrap();

    let input = args.value_of("input").unwrap_or("-");

    if input == "-" {
        let stdin = io::stdin();
        let reader = stdin.lock();
        process_lines(reader, re);
    } else {
        let f = File::open(input).unwrap();
        let reader = BufReader::new(f);
        process_lines(reader, re);
    }
    println!();

    // PARAMETERS
    let context_lines = 2;
    let needle = "oo";
    let haystack = "Every face, every shop,
    bedroom window, public-house, and
    dark square is a picture
    feverishly turned--in search of what?
    It is the same with books.
    what do we seek
    through millions of pages?";

    // INITIALIZATINO
    let mut tags: Vec<usize> = Vec::new();
    let mut ctx: Vec<Vec<(usize, String)>> = Vec::new();

    // PASS 1
    for (i, line) in haystack.lines().enumerate() {
        if line.contains(needle) {
            tags.push(i);

            let v = Vec::with_capacity(2*context_lines + 1);
            ctx.push(v)
        }
    }

    if tags.len() == 0 {
        return;
    }

    // PASS 2
    for (i, line) in haystack.lines().enumerate() {
        for (j, tag) in tags.iter().enumerate() {
            let lower_bound = tag.saturating_sub(context_lines);
            let upper_bound = tag + context_lines;

            if (i >= lower_bound) && (i <= upper_bound) {
                let line_as_string = String::from(line);
                let local_ctx = (i, line_as_string);
                ctx[j].push(local_ctx);
            }
        }
    }

    // OUTPUT
    for local_ctx in ctx.iter() {
        for &(i, ref line) in local_ctx.iter() {
            let line_num = i + 1;
            println!("{}: {}", line_num, line);
        }
    }
}
<|endoftext|>


<commit_before>extern crate cmake;

use cmake::Config;

fn main() {
    let mut dst = Config::new("civetweb")
                         .define("CMAKE_BUILD_TYPE", "Release")
                         .build();
    dst.push("lib");
    println!("cargo:rustc-link-search=native={}", dst.display());
    println!("cargo:rustc-link-lib=static=civetweb");
}
<commit_msg>Allow warnings when compiling, also don't build tests<commit_after>extern crate cmake;

use cmake::Config;

fn main() {
    let mut dst = Config::new("civetweb")
                         .define("CMAKE_BUILD_TYPE", "Release")
                         .define("BUILD_TESTING", "OFF")
                         .define("CIVETWEB_ALLOW_WARNINGS", "ON")
                         .build();
    dst.push("lib");
    println!("cargo:rustc-link-search=native={}", dst.display());
    println!("cargo:rustc-link-lib=static=civetweb");
}
<|endoftext|>