<commit_before>use serde_json;
use sputnikvm;

use sputnikvm::{read_hex, Gas, M256, Address};
use sputnikvm::vm::{VM, Machine, Stack, PC, ExecutionError};

use super::json::{create_machine, create_block, test_machine, apply_to_block, fire_with_block};

use serde_json::{Value, Error};
use std::fs::File;
use std::path::Path;
use std::io::{BufReader, Write, stdout};
use std::str::FromStr;

use rustyline::error::ReadlineError;
use rustyline::Editor;

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    print!("Testing {} ... ", name);
    if debug {
        print!("\n");
    }
    stdout().flush();

    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    let result = fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    let out = v["out"].as_str();

    if out.is_some() {
        if result.is_ok() {
            if test_machine(v, &machine, &block, debug) {
                println!("OK");
                return true;
            } else {
                println!("Failed (result not match)");
                return false;
            }
        } else {
            println!("Failed {:?}", result.err().unwrap());
            return false;
        }
    } else {
        if result.is_err() {
            println!("OK");
            return true;
        } else {
            println!("Failed");
            return false;
        }
    }
}

pub fn debug_transaction(v: &Value) {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    let owner = machine.context().address;
    machine.commit_account(block.request_account(owner)).unwrap();
    let mut rl = Editor::<()>::new();

    loop {
        let readline = rl.readline(">> ");
        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                match line.as_ref() {
                    "step" => {
                        if machine.pc().stopped() {
                            println!("Stopped");
                        } else {
                            println!("Running {:?} ... {:?}.", machine.pc().peek_opcode(),
                                     machine.step());
                        }
                    },
                    "fire" => {
                        let result = machine.fire();
                        println!("{:?}", result);
                    },
                    "fire debug" => {
                        while !machine.pc().stopped() {
                            println!("Running {:?} ...", machine.pc().peek_opcode());
                            let gas = match machine.peek_cost() {
                                Ok(gas) => gas,
                                Err(ExecutionError::RequireAccount(address)) => {
                                    machine.commit_account(block.request_account(address)).unwrap();
                                    machine.peek_cost().unwrap()
                                },
                                _ => unimplemented!(),
                            };
                            if gas < Gas::from(u64::max_value()) {
                                let gas: u64 = gas.into();
                                println!("Cost: {}", gas);
                            } else {
                                println!("Cost: 0x{:x}", gas);
                            }
                            for i in 0..machine.stack().len() {
                                println!("{}: {:x}", i, machine.stack().peek(i).unwrap());
                            }
                            println!("Result: {:?}", machine.step());
                            print!("\n");
                        }
                    },
                    "gas" => {
                        let gas = machine.peek_cost();
                        if gas.is_ok() {
                            println!("0x{:x}", gas.unwrap());
                        } else {
                            println!("{:?}", gas);
                        }
                    }
                    "out" => {
                        let ret = machine.return_values();
                        println!("{:?}", ret);
                    }
                    "print stack" => {
                        for i in 0..machine.stack().len() {
                            println!("{}: {:x}", i, machine.stack().peek(i).unwrap());
                        }
                    },
                    _ => {
                        println!("Unknown command.");
                    }
                }
            },
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }
    }
}
<commit_msg>Problem: gaslighter crat might run indefinitely Solution: catch RequireAccount<commit_after>use serde_json;
use sputnikvm;

use sputnikvm::{read_hex, Gas, M256, Address};
use sputnikvm::vm::{VM, Machine, Stack, PC, ExecutionError};

use super::json::{create_machine, create_block, test_machine, apply_to_block, fire_with_block};

use serde_json::{Value, Error};
use std::fs::File;
use std::path::Path;
use std::io::{BufReader, Write, stdout};
use std::str::FromStr;

use rustyline::error::ReadlineError;
use rustyline::Editor;

pub fn test_transaction(name: &str, v: &Value, debug: bool) -> bool {
    print!("Testing {} ... ", name);
    if debug {
        print!("\n");
    }
    stdout().flush();

    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    let result = fire_with_block(&mut machine, &block);
    apply_to_block(&machine, &mut block);

    let out = v["out"].as_str();

    if out.is_some() {
        if result.is_ok() {
            if test_machine(v, &machine, &block, debug) {
                println!("OK");
                return true;
            } else {
                println!("Failed (result not match)");
                return false;
            }
        } else {
            println!("Failed {:?}", result.err().unwrap());
            return false;
        }
    } else {
        if result.is_err() {
            println!("OK");
            return true;
        } else {
            println!("Failed");
            return false;
        }
    }
}

pub fn debug_transaction(v: &Value) {
    let mut block = create_block(v);
    let mut machine = create_machine(v, &block);
    let owner = machine.context().address;
    machine.commit_account(block.request_account(owner)).unwrap();
    let mut rl = Editor::<()>::new();

    loop {
        let readline = rl.readline(">> ");
        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                match line.as_ref() {
                    "step" => {
                        if machine.pc().stopped() {
                            println!("Stopped");
                        } else {
                            println!("Running {:?} ... {:?}.", machine.pc().peek_opcode(),
                                     machine.step());
                        }
                    },
                    "fire" => {
                        let result = machine.fire();
                        println!("{:?}", result);
                    },
                    "fire debug" => {
                        while !machine.pc().stopped() {
                            println!("Running {:?} ...", machine.pc().peek_opcode());
                            let gas = match machine.peek_cost() {
                                Ok(gas) => gas,
                                Err(ExecutionError::RequireAccount(address)) => {
                                    machine.commit_account(block.request_account(address)).unwrap();
                                    machine.peek_cost().unwrap()
                                },
                                _ => unimplemented!(),
                            };
                            if gas < Gas::from(u64::max_value()) {
                                let gas: u64 = gas.into();
                                println!("Cost: {}", gas);
                            } else {
                                println!("Cost: 0x{:x}", gas);
                            }
                            for i in 0..machine.stack().len() {
                                println!("{}: {:x}", i, machine.stack().peek(i).unwrap());
                            }
                            println!("Result: {:?}", match machine.step() {
                                Ok(()) => (),
                                Err(ExecutionError::RequireAccount(address)) => {
                                    machine.commit_account(block.request_account(address)).unwrap();
                                    machine.step().unwrap()
                                },
                                _ => unimplemented!(),
                            });
                            print!("\n");
                        }
                    },
                    "gas" => {
                        let gas = machine.peek_cost();
                        if gas.is_ok() {
                            println!("0x{:x}", gas.unwrap());
                        } else {
                            println!("{:?}", gas);
                        }
                    }
                    "out" => {
                        let ret = machine.return_values();
                        println!("{:?}", ret);
                    }
                    "print stack" => {
                        for i in 0..machine.stack().len() {
                            println!("{}: {:x}", i, machine.stack().peek(i).unwrap());
                        }
                    },
                    _ => {
                        println!("Unknown command.");
                    }
                }
            },
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }
    }
}
<|endoftext|>


<commit_before>
use parse::Token;
use eval::{FuncError, FuncResult};

#[derive(Clone)]
pub struct FnWrapper(pub fn(Vec<Value>) -> FuncResult);

#[derive(Clone, PartialEq)]
pub enum Value {
    Number(f32),
    Bool(bool),
    Str(String),

    HardFunc(FnWrapper),

    List(Vec<Value>),
    Nil,

	Quote(Token),
}

pub trait ToLisp {
    fn to_lisp(self) -> Value;
}

pub trait FromLisp {
    fn from_lisp(Value) -> Result<Self, FuncError>;
}

impl PartialEq for FnWrapper {
    // Checks to see if the addresses of both functions are the same
    fn eq(&self, rhs: &FnWrapper) -> bool {
        let selfPtr = self as *const Self;
        let rhsPtr = rhs as *const Self;

        selfPtr == rhsPtr
    }
}

macro_rules! lisp_impl {
    ($( $t:ty: $path:path ),+) => {
        $(
            impl FromLisp for $t {
                fn from_lisp(val: Value) -> Result<$t, FuncError> {
                    match val {
                        $path(val) => Ok(val),
                        _ => Err(FuncError::InvalidType),
                    }
                }
            }

            impl ToLisp for $t {
                fn to_lisp(self) -> Value {
                    $path(self)
                }
            }
        )*
    }
}

lisp_impl!(bool: Value::Bool,
          f32: Value::Number,
          String: Value::Str,
          FnWrapper: Value::HardFunc,
          Token: Value::Quote);

impl ToLisp for () {
    fn to_lisp(self) -> Value { Value::Nil }
}

impl FromLisp for () {
    fn from_lisp(val: Value) -> Result<(), FuncError> {
        match val {
            Value::Nil => Ok(()),
            _ => Err(FuncError::InvalidType),
        }
    }
}
<commit_msg>Proper comparisons for function pointers<commit_after>
use parse::Token;
use eval::{FuncError, FuncResult};

#[derive(Clone)]
pub struct FnWrapper(pub fn(Vec<Value>) -> FuncResult);

#[derive(Clone, PartialEq)]
pub enum Value {
    Number(f32),
    Bool(bool),
    Str(String),

    HardFunc(FnWrapper),

    List(Vec<Value>),
    Nil,

	Quote(Token),
}

pub trait ToLisp {
    fn to_lisp(self) -> Value;
}

pub trait FromLisp {
    fn from_lisp(Value) -> Result<Self, FuncError>;
}

impl PartialEq for FnWrapper {
    // Checks to see if the addresses of both functions are the same
    fn eq(&self, rhs: &FnWrapper) -> bool {
        let &FnWrapper(self_f) = self;
        let &FnWrapper(rhs_f) = rhs;

        let self_ptr = (self_f as *const fn(Vec<Value>) -> FuncResult);
        let rhs_ptr = (rhs_f as *const fn(Vec<Value>) -> FuncResult);

        self_ptr == rhs_ptr
    }
}

macro_rules! lisp_impl {
    ($( $t:ty: $path:path ),+) => {
        $(
            impl FromLisp for $t {
                fn from_lisp(val: Value) -> Result<$t, FuncError> {
                    match val {
                        $path(val) => Ok(val),
                        _ => Err(FuncError::InvalidType),
                    }
                }
            }

            impl ToLisp for $t {
                fn to_lisp(self) -> Value {
                    $path(self)
                }
            }
        )*
    }
}

lisp_impl!(bool: Value::Bool,
          f32: Value::Number,
          String: Value::Str,
          FnWrapper: Value::HardFunc,
          Token: Value::Quote);

impl ToLisp for () {
    fn to_lisp(self) -> Value { Value::Nil }
}

impl FromLisp for () {
    fn from_lisp(val: Value) -> Result<(), FuncError> {
        match val {
            Value::Nil => Ok(()),
            _ => Err(FuncError::InvalidType),
        }
    }
}
<|endoftext|>


<commit_before>use crate::api::raii::{Publisher, Service, Subscriber};
use crate::api::resolve::get_unused_args;
use crate::api::{Delay, Parameter, Rate, Ros, SystemState, Topic};
use crate::error::{ErrorKind, Result};
use crate::rosxmlrpc::Response;
use crate::tcpros::{Client, Message, ServicePair, ServiceResult};
use crate::time::{Duration, Time};
use crate::util::FAILED_TO_LOCK;
use crossbeam::sync::ShardedLock;
use ctrlc;
use lazy_static::lazy_static;
use std::time;

lazy_static! {
    static ref ROS: ShardedLock<Option<Ros>> = ShardedLock::new(None);
}

#[inline]
pub fn init(name: &str) {
    try_init(name).expect("ROS init failed!");
}

#[inline]
pub fn try_init(name: &str) -> Result<()> {
    try_init_with_options(name, true)
}

pub fn try_init_with_options(name: &str, capture_sigint: bool) -> Result<()> {
    let mut ros = ROS.write().expect(FAILED_TO_LOCK);
    if ros.is_some() {
        bail!(ErrorKind::MultipleInitialization);
    }
    let client = Ros::new(name)?;
    if capture_sigint {
        let shutdown_sender = client.shutdown_sender();
        ctrlc::set_handler(move || {
            shutdown_sender.shutdown();
        })?;
    }
    *ros = Some(client);
    Ok(())
}

macro_rules! ros {
    () => {
        ROS.read()
            .expect(FAILED_TO_LOCK)
            .as_ref()
            .expect(UNINITIALIZED)
    };
}

#[inline]
pub fn args() -> Vec<String> {
    get_unused_args()
}

#[inline]
pub fn uri() -> String {
    ros!().uri().into()
}

#[inline]
pub fn name() -> String {
    ros!().name().into()
}

#[inline]
pub fn hostname() -> String {
    ros!().hostname().into()
}

#[inline]
pub fn now() -> Time {
    ros!().now()
}

#[inline]
pub fn delay(d: Duration) -> Delay {
    ros!().delay(d)
}

#[inline]
pub fn sleep(d: Duration) {
    delay(d).sleep();
}

#[inline]
pub fn rate(rate: f64) -> Rate {
    ros!().rate(rate)
}

#[inline]
pub fn is_ok() -> bool {
    ros!().is_ok()
}

#[inline]
pub fn spin() {
    // Spinner drop locks the thread until a kill request is received
    let _spinner = { ros!().spin() };
}

#[inline]
pub fn shutdown() {
    ros!().shutdown_sender().shutdown()
}

#[inline]
pub fn param(name: &str) -> Option<Parameter> {
    ros!().param(name)
}

#[inline]
pub fn parameters() -> Response<Vec<String>> {
    ros!().parameters()
}

#[inline]
pub fn state() -> Response<SystemState> {
    ros!().state()
}

#[inline]
pub fn topics() -> Response<Vec<Topic>> {
    ros!().topics()
}

#[inline]
pub fn client<T: ServicePair>(service: &str) -> Result<Client<T>> {
    ros!().client::<T>(service)
}

#[inline]
pub fn wait_for_service(service: &str, timeout: Option<time::Duration>) -> Result<()> {
    ros!().wait_for_service(service, timeout)
}

#[inline]
pub fn service<T, F>(service: &str, handler: F) -> Result<Service>
where
    T: ServicePair,
    F: Fn(T::Request) -> ServiceResult<T::Response> + Send + Sync + 'static,
{
    ros!().service::<T, F>(service, handler)
}

#[inline]
pub fn subscribe<T, F>(topic: &str, queue_size: usize, callback: F) -> Result<Subscriber>
where
    T: Message,
    F: Fn(T) -> () + Send + 'static,
{
    ros!().subscribe::<T, F>(topic, queue_size, callback)
}

#[inline]
pub fn publish<T>(topic: &str, queue_size: usize) -> Result<Publisher<T>>
where
    T: Message,
{
    ros!().publish::<T>(topic, queue_size)
}

#[inline]
pub fn log(level: i8, msg: String, file: &str, line: u32) {
    ros!().log(level, msg, file, line)
}

static UNINITIALIZED: &str = "ROS uninitialized. Please run ros::init(name) first!";
<commit_msg>Adds is_initialized to check for rosrust init state.<commit_after>use crate::api::raii::{Publisher, Service, Subscriber};
use crate::api::resolve::get_unused_args;
use crate::api::{Delay, Parameter, Rate, Ros, SystemState, Topic};
use crate::error::{ErrorKind, Result};
use crate::rosxmlrpc::Response;
use crate::tcpros::{Client, Message, ServicePair, ServiceResult};
use crate::time::{Duration, Time};
use crate::util::FAILED_TO_LOCK;
use crossbeam::sync::ShardedLock;
use ctrlc;
use lazy_static::lazy_static;
use std::time;

lazy_static! {
    static ref ROS: ShardedLock<Option<Ros>> = ShardedLock::new(None);
}

#[inline]
pub fn init(name: &str) {
    try_init(name).expect("ROS init failed!");
}

#[inline]
pub fn try_init(name: &str) -> Result<()> {
    try_init_with_options(name, true)
}

pub fn try_init_with_options(name: &str, capture_sigint: bool) -> Result<()> {
    let mut ros = ROS.write().expect(FAILED_TO_LOCK);
    if ros.is_some() {
        bail!(ErrorKind::MultipleInitialization);
    }
    let client = Ros::new(name)?;
    if capture_sigint {
        let shutdown_sender = client.shutdown_sender();
        ctrlc::set_handler(move || {
            shutdown_sender.shutdown();
        })?;
    }
    *ros = Some(client);
    Ok(())
}

pub fn is_initialized() -> bool {
    ROS.read().expect(FAILED_TO_LOCK).is_some()
}

macro_rules! ros {
    () => {
        ROS.read()
            .expect(FAILED_TO_LOCK)
            .as_ref()
            .expect(UNINITIALIZED)
    };
}

#[inline]
pub fn args() -> Vec<String> {
    get_unused_args()
}

#[inline]
pub fn uri() -> String {
    ros!().uri().into()
}

#[inline]
pub fn name() -> String {
    ros!().name().into()
}

#[inline]
pub fn hostname() -> String {
    ros!().hostname().into()
}

#[inline]
pub fn now() -> Time {
    ros!().now()
}

#[inline]
pub fn delay(d: Duration) -> Delay {
    ros!().delay(d)
}

#[inline]
pub fn sleep(d: Duration) {
    delay(d).sleep();
}

#[inline]
pub fn rate(rate: f64) -> Rate {
    ros!().rate(rate)
}

#[inline]
pub fn is_ok() -> bool {
    ros!().is_ok()
}

#[inline]
pub fn spin() {
    // Spinner drop locks the thread until a kill request is received
    let _spinner = { ros!().spin() };
}

#[inline]
pub fn shutdown() {
    ros!().shutdown_sender().shutdown()
}

#[inline]
pub fn param(name: &str) -> Option<Parameter> {
    ros!().param(name)
}

#[inline]
pub fn parameters() -> Response<Vec<String>> {
    ros!().parameters()
}

#[inline]
pub fn state() -> Response<SystemState> {
    ros!().state()
}

#[inline]
pub fn topics() -> Response<Vec<Topic>> {
    ros!().topics()
}

#[inline]
pub fn client<T: ServicePair>(service: &str) -> Result<Client<T>> {
    ros!().client::<T>(service)
}

#[inline]
pub fn wait_for_service(service: &str, timeout: Option<time::Duration>) -> Result<()> {
    ros!().wait_for_service(service, timeout)
}

#[inline]
pub fn service<T, F>(service: &str, handler: F) -> Result<Service>
where
    T: ServicePair,
    F: Fn(T::Request) -> ServiceResult<T::Response> + Send + Sync + 'static,
{
    ros!().service::<T, F>(service, handler)
}

#[inline]
pub fn subscribe<T, F>(topic: &str, queue_size: usize, callback: F) -> Result<Subscriber>
where
    T: Message,
    F: Fn(T) -> () + Send + 'static,
{
    ros!().subscribe::<T, F>(topic, queue_size, callback)
}

#[inline]
pub fn publish<T>(topic: &str, queue_size: usize) -> Result<Publisher<T>>
where
    T: Message,
{
    ros!().publish::<T>(topic, queue_size)
}

#[inline]
pub fn log(level: i8, msg: String, file: &str, line: u32) {
    ros!().log(level, msg, file, line)
}

static UNINITIALIZED: &str = "ROS uninitialized. Please run ros::init(name) first!";
<|endoftext|>


<commit_before>#![feature(path_ext)]
#[cfg(not(windows))]
extern crate pkg_config;
use std::fs::{self, PathExt};
use std::env;
use std::path::Path;
use std::process::Command;

#[cfg(windows)]
static FINAL_LIB:&'static str = "libjit.dll";

#[cfg(not(windows))]
static FINAL_LIB:&'static str = "libjit.a";

static MINGW:&'static str = "c:/mingw";

static INSTALL_AUTOTOOLS_MSG:&'static str = "Failed to generate configuration script. Did you forget to install autotools, bison, flex, and libtool?";

static USE_CARGO_MSG:&'static str = "Build script should be ran with Cargo";

#[cfg(windows)]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install MinGW and MSYS?";
#[cfg(not(windows))]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install gcc or clang?";

fn parse(cmd: &str) -> Command {
	let mut words = cmd.split(' ');
	let mut command = Command::new(words.next().unwrap());
	for arg in words {
		command.arg(arg);
	}
	command
}

fn main() {
	if cfg!(windows) && !Path::new(MINGW).exists() {
		panic!("{}", INSTALL_COMPILER_MSG);
	} else if pkg_config::find_library("jit").is_ok() {
		println!("Copy of LibJIT found on system - no need to build");
		return;
	}
	let out_dir = env::var("OUT_DIR").ok().expect(USE_CARGO_MSG);
	let num_jobs = env::var("NUM_JOBS").ok().expect(USE_CARGO_MSG);
	let out_dir = Path::new(&*out_dir);
	let submod_path = Path::new("libjit");
	let final_lib_dir = submod_path.join("jit/.libs");
	if !final_lib_dir.join(FINAL_LIB).exists() {
		run_wocare(&mut parse("git submodule init"));
		run(&mut parse("git submodule update"));
		if !submod_path.exists() {
			run(Command::new("git").args(&["clone", "git://git.savannah.gnu.org/libjit.git", submod_path.to_str().unwrap()]))
		}
		run_nice(parse("sh auto_gen.sh").current_dir(submod_path), INSTALL_AUTOTOOLS_MSG);
		run_nice(parse("sh configure --enable-static --disable-shared CC=clang CFLAGS=-fPIC").current_dir(submod_path), INSTALL_COMPILER_MSG);
		run(Command::new("make").arg(&format!("j{}", num_jobs)).current_dir(submod_path));
	}
	let from = final_lib_dir.join(FINAL_LIB);
	let to = out_dir.join(FINAL_LIB);
	if let Err(error) = fs::copy(&from, &to) {
		panic!("Failed to copy library from {:?} to {:?} due to {}", from, to, error)
	}
	println!("cargo:rustc-link-lib=jit");
	println!("cargo:rustc-link-search=native={:?}", out_dir);
}
fn run_nice(cmd: &mut Command, text: &str) {
	if !cmd.status().unwrap().success() {
		panic!("{:?} failed - {}", cmd, text)
	}
}
fn run(cmd: &mut Command) {
	if !cmd.status().unwrap().success() {
		panic!("{:?} failed", cmd)
	}
}
fn run_wocare(cmd: &mut Command) {
	cmd.status().unwrap();
}
<commit_msg>Use constant number of threads<commit_after>#![feature(path_ext)]
#[cfg(not(windows))]
extern crate pkg_config;
use std::fs::{self, PathExt};
use std::env;
use std::path::Path;
use std::process::Command;

#[cfg(windows)]
static FINAL_LIB:&'static str = "libjit.dll";

#[cfg(not(windows))]
static FINAL_LIB:&'static str = "libjit.a";

static MINGW:&'static str = "c:/mingw";

static INSTALL_AUTOTOOLS_MSG:&'static str = "Failed to generate configuration script. Did you forget to install autotools, bison, flex, and libtool?";

static USE_CARGO_MSG:&'static str = "Build script should be ran with Cargo";

#[cfg(windows)]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install MinGW and MSYS?";
#[cfg(not(windows))]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install gcc or clang?";

fn parse(cmd: &str) -> Command {
	let mut words = cmd.split(' ');
	let mut command = Command::new(words.next().unwrap());
	for arg in words {
		command.arg(arg);
	}
	command
}

fn main() {
	if cfg!(windows) && !Path::new(MINGW).exists() {
		panic!("{}", INSTALL_COMPILER_MSG);
	} else if pkg_config::find_library("jit").is_ok() {
		println!("Copy of LibJIT found on system - no need to build");
		return;
	}
	let out_dir = env::var("OUT_DIR").ok().expect(USE_CARGO_MSG);
	let out_dir = Path::new(&*out_dir);
	let submod_path = Path::new("libjit");
	let final_lib_dir = submod_path.join("jit/.libs");
	if !final_lib_dir.join(FINAL_LIB).exists() {
		run_wocare(&mut parse("git submodule init"));
		run(&mut parse("git submodule update"));
		if !submod_path.exists() {
			run(Command::new("git").args(&["clone", "git://git.savannah.gnu.org/libjit.git", submod_path.to_str().unwrap()]))
		}
		run_nice(parse("sh auto_gen.sh").current_dir(submod_path), INSTALL_AUTOTOOLS_MSG);
		run_nice(parse("sh configure --enable-static --disable-shared CC=clang CFLAGS=-fPIC").current_dir(submod_path), INSTALL_COMPILER_MSG);
		run(Command::new("make").arg("j8").current_dir(submod_path));
	}
	let from = final_lib_dir.join(FINAL_LIB);
	let to = out_dir.join(FINAL_LIB);
	if let Err(error) = fs::copy(&from, &to) {
		panic!("Failed to copy library from {:?} to {:?} due to {}", from, to, error)
	}
	println!("cargo:rustc-link-lib=jit");
	println!("cargo:rustc-link-search=native={:?}", out_dir);
}
fn run_nice(cmd: &mut Command, text: &str) {
	if !cmd.status().unwrap().success() {
		panic!("{:?} failed - {}", cmd, text)
	}
}
fn run(cmd: &mut Command) {
	if !cmd.status().unwrap().success() {
		panic!("{:?} failed", cmd)
	}
}
fn run_wocare(cmd: &mut Command) {
	cmd.status().unwrap();
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// 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 std::fmt::Debug;
use std::rc::Rc;
use std::sync::Arc;

use super::inputs::{Input, Position};
use super::inputs_private::position;
use super::error::Error;
use super::streams_private::buffered::{buffered, BufferedSender, SendableError, SendableToken};
use super::streams_private::parser_stream;
use super::tokens::Token;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum TokenDestination {
    Stream,
    Queue,
    Lookahead
}

/// A `struct` which contains the complete state of a `Parser`.
pub struct ParserState<'a, Rule, I: Input> {
    input:           Rc<Arc<I>>,
    sender:          BufferedSender<SendableToken<Rule>, SendableError<Rule>>,
    queue:           Vec<SendableToken<Rule>>,
    dest:            TokenDestination,
    pos_lookahead:   bool,
    is_atomic:       bool,
    pos_attempts:    Vec<Rule>,
    neg_attempts:    Vec<Rule>,
    attempt_pos:     usize,
    /// Stack of captured strings
    pub stack:       Vec<&'a str>,
    /// End-of-input matched flag
    pub eoi_matched: bool
}

/// Creates a new `(ParserStream, ParserState)` tuple from an `Input`.
///
/// # Examples
///
/// ```
/// # extern crate futures;
/// # extern crate pest;
/// # use pest::inputs::StringInput;
/// # use pest::state;
/// # fn main() {
/// let input = StringInput::new("a");
///
/// let (_, _) = state::<(), _>(input);
/// # }
/// ```
pub fn state<'a, Rule: Copy + Debug + Eq + 'static, I: Input>(input: I)
    -> (ParserState<'a, Rule, I>, parser_stream::ParserStream<Rule, I>) {

    let (sender, stream) = buffered(1024);
    let input = Arc::new(input);

    let state = ParserState {
        input:         Rc::new(input.clone()),
        sender:        sender,
        queue:         vec![],
        dest:          TokenDestination::Stream,
        pos_lookahead: false,
        is_atomic:     false,
        pos_attempts:  vec![],
        neg_attempts:  vec![],
        attempt_pos:   0,
        stack:         vec![],
        eoi_matched:   false
    };

    let stream = parser_stream::new(stream, input);

    (state, stream)
}

impl<'a, Rule: Copy, I: Input> ParserState<'a, Rule, I> {
    /// Creates the initial `Position` of the state's `Input` with the value `0`.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate pest;
    /// # use pest::inputs::StringInput;
    /// # use pest::state;
    /// # fn main() {
    /// let input = StringInput::new("a");
    ///
    /// let (state, _) = state::<(), _>(input);
    ///
    /// assert_eq!(state.start().pos(), 0);
    /// # }
    /// ```
    #[inline]
    pub fn start(&self) -> Position<I> {
        position::new(self.input.clone(), 0)
    }

    #[inline]
    pub fn rule<F>(&mut self, rule: Rule, pos: Position<I>, must_match: bool, f: F)
        -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>,
                        &mut ParserState<'a, Rule, I>) -> Result<Position<I>, Position<I>> {

        let should_toggle = !must_match && self.dest == TokenDestination::Stream;
        let index = self.queue.len();

        if should_toggle {
            self.dest = TokenDestination::Queue;
        }

        self.send(Token::Start { rule: rule, pos: pos.clone() });

        let result = f(pos.clone(), self);

        if let Ok(ref pos) = result {
            self.send(Token::End { rule: rule, pos: pos.clone() });
        }

        if self.dest == TokenDestination::Queue && result.is_err() {
            self.queue.truncate(index);
        }

        if should_toggle {
            self.dest = TokenDestination::Stream;

            if result.is_ok() {
                for token in self.queue.drain(..) {
                    self.sender.send(token);
                }
            }
        }

        result
    }

    #[inline]
    fn send(&mut self, token: Token<Rule, I>) {
        #[inline]
        fn to_sendable<Rule, I: Input>(token: Token<Rule, I>) -> SendableToken<Rule> {
            match token {
                Token::Start { rule, pos } => {
                    SendableToken::Start {
                        rule: rule,
                        pos:  pos.pos()
                    }
                },
                Token::End { rule, pos } => {
                    SendableToken::End {
                        rule: rule,
                        pos:  pos.pos()
                    }
                }
            }
        }

        match token {
            Token::Start { ref rule, ref pos } => {
                let is_positive = !(self.dest == TokenDestination::Lookahead) || self.pos_lookahead;
                self.track(is_positive, *rule, pos.pos());
            },
            _ => ()
        };

        match self.dest {
            TokenDestination::Stream    => self.sender.send(to_sendable(token)),
            TokenDestination::Queue     => self.queue.push(to_sendable(token)),
            TokenDestination::Lookahead => ()
        };
    }

    /// Consumes the `ParserState` and causes the matching `ParserStream` to fail.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate pest;
    /// # use pest::inputs::StringInput;
    /// # use pest::state;
    /// # use pest::Error;
    /// # fn main() {
    /// let input = StringInput::new("");
    /// let (state, _) = state::<(), _>(input);
    /// let pos = state.start();
    ///
    /// state.fail(Error::CustomErrorPos { message: "error".to_owned(), pos: pos });
    /// # }
    /// ```
    #[inline]
    pub fn fail(&self, error: Error<Rule, I>) {
        self.sender.fail(match error {
            Error::ParsingError { positives, negatives, pos } => {
                SendableError::ParsingError {
                    positives: positives,
                    negatives: negatives,
                    pos:       pos.pos()
                }
            },
            Error::CustomErrorPos { message, pos } => {
                SendableError::CustomErrorPos {
                    message: message,
                    pos:     pos.pos()
                }
            },
            Error::CustomErrorSpan { message, span } => {
                SendableError::CustomErrorSpan {
                    message: message,
                    start:   span.start(),
                    end:     span.end()
                }
            }
        });
    }

    #[inline]
    pub fn fail_with_attempts(&mut self) {
        let positives = self.pos_attempts.drain(..).collect();
        let negatives = self.neg_attempts.drain(..).collect();

        self.fail(Error::ParsingError {
            positives: positives,
            negatives: negatives,
            pos:       position::new(self.input.clone(), self.attempt_pos)
        });
    }

    #[inline]
    pub fn lookahead<F>(&mut self, is_positive: bool, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(&mut ParserState<'a, Rule, I>) -> Result<Position<I>, Position<I>> {

        let should_toggle = self.dest != TokenDestination::Lookahead;
        let initial_dest = self.dest;

        if should_toggle {
            self.dest = TokenDestination::Lookahead;
            self.pos_lookahead = is_positive;
        }

        let result = f(self);

        if should_toggle {
            self.dest = initial_dest;
        }

        result
    }

    #[inline]
    pub fn atomic<F>(&mut self, is_atomic: bool, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(&mut ParserState<'a, Rule, I>) -> Result<Position<I>, Position<I>> {

        let should_toggle = self.is_atomic != is_atomic;

        if should_toggle {
            self.is_atomic = is_atomic;
        }

        let result = f(self);

        if should_toggle {
            self.is_atomic = !is_atomic;
        }

        result
    }

    /// Returns the state's current atomicity.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate pest;
    /// # use pest::inputs::StringInput;
    /// # use pest::state;
    /// # fn main() {
    /// let input = StringInput::new("");
    /// let (state, _) = state::<(), _>(input);
    ///
    /// assert!(!state.is_atomic());
    /// # }
    /// ```
    #[inline]
    pub fn is_atomic(&self) -> bool {
        self.is_atomic
    }

    #[inline]
    fn track(&mut self, is_positive: bool, rule: Rule, pos: usize) {
        if self.is_atomic || self.dest == TokenDestination::Lookahead {
            return;
        }

        let mut attempts = if is_positive {
            &mut self.pos_attempts
        } else {
            &mut self.neg_attempts
        };

        if attempts.is_empty() {
            attempts.push(rule);

            self.attempt_pos = pos;
        } else if pos == self.attempt_pos {
            attempts.push(rule);
        } else if pos > self.attempt_pos {
            attempts.clear();
            attempts.clear();
            attempts.push(rule);

            self.attempt_pos = pos;
        }
    }
}
<commit_msg>Simplified token sending.<commit_after>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// 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 std::fmt::Debug;
use std::rc::Rc;
use std::sync::Arc;

use super::inputs::{Input, Position};
use super::inputs_private::position;
use super::error::Error;
use super::streams_private::buffered::{buffered, BufferedSender, SendableError, SendableToken};
use super::streams_private::parser_stream;
use super::tokens::Token;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum TokenDestination {
    Stream,
    Queue,
    Lookahead
}

/// A `struct` which contains the complete state of a `Parser`.
pub struct ParserState<'a, Rule, I: Input> {
    input:           Rc<Arc<I>>,
    sender:          BufferedSender<SendableToken<Rule>, SendableError<Rule>>,
    queue:           Vec<SendableToken<Rule>>,
    dest:            TokenDestination,
    pos_lookahead:   bool,
    is_atomic:       bool,
    pos_attempts:    Vec<Rule>,
    neg_attempts:    Vec<Rule>,
    attempt_pos:     usize,
    /// Stack of captured strings
    pub stack:       Vec<&'a str>,
    /// End-of-input matched flag
    pub eoi_matched: bool
}

/// Creates a new `(ParserStream, ParserState)` tuple from an `Input`.
///
/// # Examples
///
/// ```
/// # extern crate futures;
/// # extern crate pest;
/// # use pest::inputs::StringInput;
/// # use pest::state;
/// # fn main() {
/// let input = StringInput::new("a");
///
/// let (_, _) = state::<(), _>(input);
/// # }
/// ```
pub fn state<'a, Rule: Copy + Debug + Eq + 'static, I: Input>(input: I)
    -> (ParserState<'a, Rule, I>, parser_stream::ParserStream<Rule, I>) {

    let (sender, stream) = buffered(1024);
    let input = Arc::new(input);

    let state = ParserState {
        input:         Rc::new(input.clone()),
        sender:        sender,
        queue:         vec![],
        dest:          TokenDestination::Stream,
        pos_lookahead: false,
        is_atomic:     false,
        pos_attempts:  vec![],
        neg_attempts:  vec![],
        attempt_pos:   0,
        stack:         vec![],
        eoi_matched:   false
    };

    let stream = parser_stream::new(stream, input);

    (state, stream)
}

impl<'a, Rule: Copy, I: Input> ParserState<'a, Rule, I> {
    /// Creates the initial `Position` of the state's `Input` with the value `0`.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate pest;
    /// # use pest::inputs::StringInput;
    /// # use pest::state;
    /// # fn main() {
    /// let input = StringInput::new("a");
    ///
    /// let (state, _) = state::<(), _>(input);
    ///
    /// assert_eq!(state.start().pos(), 0);
    /// # }
    /// ```
    #[inline]
    pub fn start(&self) -> Position<I> {
        position::new(self.input.clone(), 0)
    }

    #[inline]
    pub fn rule<F>(&mut self, rule: Rule, pos: Position<I>, must_match: bool, f: F)
        -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>,
                        &mut ParserState<'a, Rule, I>) -> Result<Position<I>, Position<I>> {

        let should_toggle = !must_match && self.dest == TokenDestination::Stream;
        let actual_pos = pos.pos();
        let index = self.queue.len();

        if should_toggle {
            self.dest = TokenDestination::Queue;
        }

        self.send(SendableToken::Start { rule: rule, pos: actual_pos });

        let result = f(pos, self);

        if let Ok(ref pos) = result {
            self.send(SendableToken::End { rule: rule, pos: pos.pos() });
        }

        if self.dest == TokenDestination::Queue && result.is_err() {
            self.queue.truncate(index);
        }

        if should_toggle {
            self.dest = TokenDestination::Stream;

            if result.is_ok() {
                for token in self.queue.drain(..) {
                    self.sender.send(token);
                }
            }
        }

        result
    }

    #[inline]
    fn send(&mut self, token: SendableToken<Rule>) {
        match token {
            SendableToken::Start { rule, pos } => {
                let is_positive = !(self.dest == TokenDestination::Lookahead) || self.pos_lookahead;
                self.track(is_positive, rule, pos);
            },
            _ => ()
        };

        match self.dest {
            TokenDestination::Stream    => self.sender.send(token),
            TokenDestination::Queue     => self.queue.push(token),
            TokenDestination::Lookahead => ()
        };
    }

    /// Consumes the `ParserState` and causes the matching `ParserStream` to fail.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate pest;
    /// # use pest::inputs::StringInput;
    /// # use pest::state;
    /// # use pest::Error;
    /// # fn main() {
    /// let input = StringInput::new("");
    /// let (state, _) = state::<(), _>(input);
    /// let pos = state.start();
    ///
    /// state.fail(Error::CustomErrorPos { message: "error".to_owned(), pos: pos });
    /// # }
    /// ```
    #[inline]
    pub fn fail(&self, error: Error<Rule, I>) {
        self.sender.fail(match error {
            Error::ParsingError { positives, negatives, pos } => {
                SendableError::ParsingError {
                    positives: positives,
                    negatives: negatives,
                    pos:       pos.pos()
                }
            },
            Error::CustomErrorPos { message, pos } => {
                SendableError::CustomErrorPos {
                    message: message,
                    pos:     pos.pos()
                }
            },
            Error::CustomErrorSpan { message, span } => {
                SendableError::CustomErrorSpan {
                    message: message,
                    start:   span.start(),
                    end:     span.end()
                }
            }
        });
    }

    #[inline]
    pub fn fail_with_attempts(&mut self) {
        let positives = self.pos_attempts.drain(..).collect();
        let negatives = self.neg_attempts.drain(..).collect();

        self.fail(Error::ParsingError {
            positives: positives,
            negatives: negatives,
            pos:       position::new(self.input.clone(), self.attempt_pos)
        });
    }

    #[inline]
    pub fn lookahead<F>(&mut self, is_positive: bool, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(&mut ParserState<'a, Rule, I>) -> Result<Position<I>, Position<I>> {

        let should_toggle = self.dest != TokenDestination::Lookahead;
        let initial_dest = self.dest;

        if should_toggle {
            self.dest = TokenDestination::Lookahead;
            self.pos_lookahead = is_positive;
        }

        let result = f(self);

        if should_toggle {
            self.dest = initial_dest;
        }

        result
    }

    #[inline]
    pub fn atomic<F>(&mut self, is_atomic: bool, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(&mut ParserState<'a, Rule, I>) -> Result<Position<I>, Position<I>> {

        let should_toggle = self.is_atomic != is_atomic;

        if should_toggle {
            self.is_atomic = is_atomic;
        }

        let result = f(self);

        if should_toggle {
            self.is_atomic = !is_atomic;
        }

        result
    }

    /// Returns the state's current atomicity.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate futures;
    /// # extern crate pest;
    /// # use pest::inputs::StringInput;
    /// # use pest::state;
    /// # fn main() {
    /// let input = StringInput::new("");
    /// let (state, _) = state::<(), _>(input);
    ///
    /// assert!(!state.is_atomic());
    /// # }
    /// ```
    #[inline]
    pub fn is_atomic(&self) -> bool {
        self.is_atomic
    }

    #[inline]
    fn track(&mut self, is_positive: bool, rule: Rule, pos: usize) {
        if self.is_atomic || self.dest == TokenDestination::Lookahead {
            return;
        }

        let mut attempts = if is_positive {
            &mut self.pos_attempts
        } else {
            &mut self.neg_attempts
        };

        if attempts.is_empty() {
            attempts.push(rule);

            self.attempt_pos = pos;
        } else if pos == self.attempt_pos {
            attempts.push(rule);
        } else if pos > self.attempt_pos {
            attempts.clear();
            attempts.clear();
            attempts.push(rule);

            self.attempt_pos = pos;
        }
    }
}
<|endoftext|>


<commit_before>use cssparser::{self, Parser};
use libc;

use crate::error::*;
use crate::parsers::Parse;
use crate::parsers::ParseError;
use crate::util::utf8_cstr;

pub use cssparser::Color;

impl Parse for cssparser::Color {
    type Err = ValueErrorKind;

    fn parse(parser: &mut Parser<'_, '_>) -> Result<cssparser::Color, ValueErrorKind> {
        cssparser::Color::parse(parser)
            .map_err(|_| ValueErrorKind::Parse(ParseError::new("invalid syntax for color")))
    }
}

impl Parse for cssparser::RGBA {
    type Err = ValueErrorKind;

    fn parse(parser: &mut Parser<'_, '_>) -> Result<cssparser::RGBA, ValueErrorKind> {
        match cssparser::Color::parse(parser) {
            Ok(cssparser::Color::RGBA(rgba)) => Ok(rgba),
            Ok(cssparser::Color::CurrentColor) => Err(ValueErrorKind::Value(
                "currentColor is not allowed here".to_string(),
            )),
            _ => Err(ValueErrorKind::Parse(ParseError::new(
                "invalid syntax for color",
            ))),
        }
    }
}

// There are two quirks here:
//
// First, we need to expose the Color algebraic type *and* a parse
// error to C, but we can't repr(C) them plainly.  So, we define a
// ColorKind enum and a ColorSpec struct that can both be represented
// in C.
//
// Second, the C code in librsvg expects ARGB colors passed around as
// guint32.  However, in Rust we'd prefer to use cssparser's RGBA
// structure, which has explicit fields for red/green/blue/alpha.
// We'll do those conversions here, for the benefit of the C code, and
// then just wait until the C code gradually disappears.

// Keep this in sync with rsvg-css.h:RsvgCssColorKind
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ColorKind {
    Inherit,
    CurrentColor,
    ARGB,
    ParseError,
}

// Keep this in sync with rsvg-css.h:RsvgCssColorSpec
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct ColorSpec {
    kind: ColorKind,
    argb: u32,
}

pub fn rgba_to_argb(rgba: cssparser::RGBA) -> u32 {
    u32::from(rgba.alpha) << 24
        | u32::from(rgba.red) << 16
        | u32::from(rgba.green) << 8
        | u32::from(rgba.blue)
}

impl From<Result<Option<cssparser::Color>, ValueErrorKind>> for ColorSpec {
    fn from(result: Result<Option<cssparser::Color>, ValueErrorKind>) -> ColorSpec {
        match result {
            Ok(None) => ColorSpec {
                kind: ColorKind::Inherit,
                argb: 0,
            },

            Ok(Some(cssparser::Color::CurrentColor)) => ColorSpec {
                kind: ColorKind::CurrentColor,
                argb: 0,
            },

            Ok(Some(cssparser::Color::RGBA(rgba))) => ColorSpec {
                kind: ColorKind::ARGB,
                argb: rgba_to_argb(rgba),
            },

            _ => ColorSpec {
                kind: ColorKind::ParseError,
                argb: 0,
            },
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_css_parse_color(string: *const libc::c_char) -> ColorSpec {
    let s = unsafe { utf8_cstr(string) };

    if s == "inherit" {
        ColorSpec {
            kind: ColorKind::Inherit,
            argb: 0,
        }
    } else {
        ColorSpec::from(<Color as Parse>::parse_str(s).map(|v| Some(v)))
    }
}

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

    fn parse(s: &str) -> ColorSpec {
        rsvg_css_parse_color(s.to_glib_none().0)
    }

    #[test]
    fn parses_hash_hex_colors() {
        assert_eq!(
            parse("#AB10fa20"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0x20ab10fa,
            }
        );
        assert_eq!(
            parse("#10fa20"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff10fa20,
            }
        );
        assert_eq!(
            parse("#abcd"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xddaabbcc,
            }
        );
        assert_eq!(
            parse("#123"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff112233,
            }
        );
    }

    #[test]
    fn parses_color_keywords() {
        assert_eq!(
            parse("red"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xffff0000,
            }
        );
        assert_eq!(
            parse("lime"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff00ff00,
            }
        );
        assert_eq!(
            parse("blue"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff0000ff,
            }
        );
    }

    #[test]
    fn parses_color_functions() {
        assert_eq!(
            parse("rgb(255, 0, 0)"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xffff0000,
            }
        );
        assert_eq!(
            parse("rgb(0, 255, 0)"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff00ff00,
            }
        );
        assert_eq!(
            parse("rgb(0, 0, 255)"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff0000ff,
            }
        );
    }

    #[test]
    fn parses_current_color() {
        assert_eq!(
            parse("currentColor"),
            ColorSpec {
                kind: ColorKind::CurrentColor,
                argb: 0,
            }
        );
    }

    fn make_error() -> ColorSpec {
        ColorSpec {
            kind: ColorKind::ParseError,
            argb: 0,
        }
    }

    #[test]
    fn invalid_hash_hex_colors_yield_error() {
        assert_eq!(parse("#"), make_error());
        assert_eq!(parse("#xyz"), make_error());
        assert_eq!(parse("#112233gg"), make_error());
    }

    #[test]
    fn invalid_colors_yield_error() {
        assert_eq!(parse(""), make_error());
        assert_eq!(parse("foo"), make_error());
        assert_eq!(parse("rgb(chilaquil)"), make_error());
        assert_eq!(parse("rgb(1, 2, 3, 4, 5)"), make_error());
    }
}
<commit_msg>color: cleanup map() call<commit_after>use cssparser::{self, Parser};
use libc;

use crate::error::*;
use crate::parsers::Parse;
use crate::parsers::ParseError;
use crate::util::utf8_cstr;

pub use cssparser::Color;

impl Parse for cssparser::Color {
    type Err = ValueErrorKind;

    fn parse(parser: &mut Parser<'_, '_>) -> Result<cssparser::Color, ValueErrorKind> {
        cssparser::Color::parse(parser)
            .map_err(|_| ValueErrorKind::Parse(ParseError::new("invalid syntax for color")))
    }
}

impl Parse for cssparser::RGBA {
    type Err = ValueErrorKind;

    fn parse(parser: &mut Parser<'_, '_>) -> Result<cssparser::RGBA, ValueErrorKind> {
        match cssparser::Color::parse(parser) {
            Ok(cssparser::Color::RGBA(rgba)) => Ok(rgba),
            Ok(cssparser::Color::CurrentColor) => Err(ValueErrorKind::Value(
                "currentColor is not allowed here".to_string(),
            )),
            _ => Err(ValueErrorKind::Parse(ParseError::new(
                "invalid syntax for color",
            ))),
        }
    }
}

// There are two quirks here:
//
// First, we need to expose the Color algebraic type *and* a parse
// error to C, but we can't repr(C) them plainly.  So, we define a
// ColorKind enum and a ColorSpec struct that can both be represented
// in C.
//
// Second, the C code in librsvg expects ARGB colors passed around as
// guint32.  However, in Rust we'd prefer to use cssparser's RGBA
// structure, which has explicit fields for red/green/blue/alpha.
// We'll do those conversions here, for the benefit of the C code, and
// then just wait until the C code gradually disappears.

// Keep this in sync with rsvg-css.h:RsvgCssColorKind
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ColorKind {
    Inherit,
    CurrentColor,
    ARGB,
    ParseError,
}

// Keep this in sync with rsvg-css.h:RsvgCssColorSpec
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct ColorSpec {
    kind: ColorKind,
    argb: u32,
}

pub fn rgba_to_argb(rgba: cssparser::RGBA) -> u32 {
    u32::from(rgba.alpha) << 24
        | u32::from(rgba.red) << 16
        | u32::from(rgba.green) << 8
        | u32::from(rgba.blue)
}

impl From<Result<Option<cssparser::Color>, ValueErrorKind>> for ColorSpec {
    fn from(result: Result<Option<cssparser::Color>, ValueErrorKind>) -> ColorSpec {
        match result {
            Ok(None) => ColorSpec {
                kind: ColorKind::Inherit,
                argb: 0,
            },

            Ok(Some(cssparser::Color::CurrentColor)) => ColorSpec {
                kind: ColorKind::CurrentColor,
                argb: 0,
            },

            Ok(Some(cssparser::Color::RGBA(rgba))) => ColorSpec {
                kind: ColorKind::ARGB,
                argb: rgba_to_argb(rgba),
            },

            _ => ColorSpec {
                kind: ColorKind::ParseError,
                argb: 0,
            },
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_css_parse_color(string: *const libc::c_char) -> ColorSpec {
    let s = unsafe { utf8_cstr(string) };

    if s == "inherit" {
        ColorSpec {
            kind: ColorKind::Inherit,
            argb: 0,
        }
    } else {
        ColorSpec::from(<Color as Parse>::parse_str(s).map(Some))
    }
}

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

    fn parse(s: &str) -> ColorSpec {
        rsvg_css_parse_color(s.to_glib_none().0)
    }

    #[test]
    fn parses_hash_hex_colors() {
        assert_eq!(
            parse("#AB10fa20"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0x20ab10fa,
            }
        );
        assert_eq!(
            parse("#10fa20"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff10fa20,
            }
        );
        assert_eq!(
            parse("#abcd"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xddaabbcc,
            }
        );
        assert_eq!(
            parse("#123"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff112233,
            }
        );
    }

    #[test]
    fn parses_color_keywords() {
        assert_eq!(
            parse("red"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xffff0000,
            }
        );
        assert_eq!(
            parse("lime"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff00ff00,
            }
        );
        assert_eq!(
            parse("blue"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff0000ff,
            }
        );
    }

    #[test]
    fn parses_color_functions() {
        assert_eq!(
            parse("rgb(255, 0, 0)"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xffff0000,
            }
        );
        assert_eq!(
            parse("rgb(0, 255, 0)"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff00ff00,
            }
        );
        assert_eq!(
            parse("rgb(0, 0, 255)"),
            ColorSpec {
                kind: ColorKind::ARGB,
                argb: 0xff0000ff,
            }
        );
    }

    #[test]
    fn parses_current_color() {
        assert_eq!(
            parse("currentColor"),
            ColorSpec {
                kind: ColorKind::CurrentColor,
                argb: 0,
            }
        );
    }

    fn make_error() -> ColorSpec {
        ColorSpec {
            kind: ColorKind::ParseError,
            argb: 0,
        }
    }

    #[test]
    fn invalid_hash_hex_colors_yield_error() {
        assert_eq!(parse("#"), make_error());
        assert_eq!(parse("#xyz"), make_error());
        assert_eq!(parse("#112233gg"), make_error());
    }

    #[test]
    fn invalid_colors_yield_error() {
        assert_eq!(parse(""), make_error());
        assert_eq!(parse("foo"), make_error());
        assert_eq!(parse("rgb(chilaquil)"), make_error());
        assert_eq!(parse("rgb(1, 2, 3, 4, 5)"), make_error());
    }
}
<|endoftext|>


<commit_before><commit_msg>Add rust code for triangle case<commit_after><|endoftext|>


<commit_before><commit_msg>Re-enables the previously broken tests<commit_after><|endoftext|>


<commit_before>#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(os)]
#![feature(env)]
#![feature(path)]
#![feature(rustc_private)]

extern crate document;
extern crate xpath;
extern crate getopts;

use std::cmp::min;
use std::env;
use std::collections::HashMap;
use std::old_io::File;

use document::parser::Parser;

use xpath::nodeset::ToNode;
use xpath::{EvaluationContext,Factory,Expression};

use getopts::{reqopt,optmulti,getopts,OptGroup,usage};

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

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn build_xpath(xpath_str: &str) -> Box<Expression> {
    let factory = Factory::new();

    match factory.build(xpath_str) {
        Err(x) => panic!("Unable to compile XPath: {:?}", x),
        Ok(None) => panic!("Unable to compile XPath"),
        Ok(Some(x)) => x,
    }
}

fn load_xml(filename: &str) -> document::Package {
    let p = Parser::new();
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    }
}

fn build_functions() -> xpath::Functions {
    let mut functions = HashMap::new();
    xpath::function::register_core_functions(&mut functions);
    functions
}

fn build_variables<'a>() -> xpath::Variables<'a> {
    HashMap::new()
}

fn build_namespaces(arguments: &getopts::Matches) -> xpath::Namespaces {
    let mut namespaces = HashMap::new();
    for ns_defn in arguments.opt_strs("namespace").iter() {
        let parts: Vec<_> = ns_defn.splitn(2, ':').collect();
        if parts.len() < 2 {
            panic!("Namespace definition '{}' is malformed", ns_defn);
        }

        namespaces.insert(parts[0].to_string(), parts[1].to_string());
    }
    namespaces
}

#[allow(dead_code)]
fn main() {
    let args: Result<Vec<_>, _> = env::args().map(|a| a.into_string()).collect();
    let args = args.unwrap();

    let program_name = &args[0];

    let opts = &[
        reqopt("", "xpath", "The XPath to execute", "XPATH"),
        optmulti("", "namespace", "set namespace prefix", "PREFIX:URI"),
    ];

    let arguments = match getopts(args.tail(), opts) {
        Ok(x) => x,
        Err(x) => {
            println!("{}", x);
            print_usage(program_name, opts);
            return;
        },
    };

    let xpath_str = arguments.opt_str("xpath").unwrap();
    let xpath = build_xpath(&xpath_str);

    for filename in arguments.free.iter() {
        let package = load_xml(filename);
        let doc = package.as_document();
        let root = doc.root().to_node();

        let functions = build_functions();
        let variables = build_variables();
        let namespaces = build_namespaces(&arguments);

        let context = EvaluationContext::new(
            root,
            &functions,
            &variables,
            &namespaces,
        );

        let res = xpath.evaluate(&context);

        println!("{:?}", res);
    }
}
<commit_msg>env::args returns Strings<commit_after>#![feature(collections)]
#![feature(io)]
#![feature(env)]
#![feature(path)]
#![feature(rustc_private)]

extern crate document;
extern crate xpath;
extern crate getopts;

use std::cmp::min;
use std::env;
use std::collections::HashMap;
use std::old_io::File;

use document::parser::Parser;

use xpath::nodeset::ToNode;
use xpath::{EvaluationContext,Factory,Expression};

use getopts::{reqopt,optmulti,getopts,OptGroup,usage};

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

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn build_xpath(xpath_str: &str) -> Box<Expression> {
    let factory = Factory::new();

    match factory.build(xpath_str) {
        Err(x) => panic!("Unable to compile XPath: {:?}", x),
        Ok(None) => panic!("Unable to compile XPath"),
        Ok(Some(x)) => x,
    }
}

fn load_xml(filename: &str) -> document::Package {
    let p = Parser::new();
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    }
}

fn build_functions() -> xpath::Functions {
    let mut functions = HashMap::new();
    xpath::function::register_core_functions(&mut functions);
    functions
}

fn build_variables<'a>() -> xpath::Variables<'a> {
    HashMap::new()
}

fn build_namespaces(arguments: &getopts::Matches) -> xpath::Namespaces {
    let mut namespaces = HashMap::new();
    for ns_defn in arguments.opt_strs("namespace").iter() {
        let parts: Vec<_> = ns_defn.splitn(2, ':').collect();
        if parts.len() < 2 {
            panic!("Namespace definition '{}' is malformed", ns_defn);
        }

        namespaces.insert(parts[0].to_string(), parts[1].to_string());
    }
    namespaces
}

#[allow(dead_code)]
fn main() {
    let args: Vec<_> = env::args().collect();

    let program_name = &args[0];

    let opts = &[
        reqopt("", "xpath", "The XPath to execute", "XPATH"),
        optmulti("", "namespace", "set namespace prefix", "PREFIX:URI"),
    ];

    let arguments = match getopts(args.tail(), opts) {
        Ok(x) => x,
        Err(x) => {
            println!("{}", x);
            print_usage(program_name, opts);
            return;
        },
    };

    let xpath_str = arguments.opt_str("xpath").unwrap();
    let xpath = build_xpath(&xpath_str);

    for filename in arguments.free.iter() {
        let package = load_xml(filename);
        let doc = package.as_document();
        let root = doc.root().to_node();

        let functions = build_functions();
        let variables = build_variables();
        let namespaces = build_namespaces(&arguments);

        let context = EvaluationContext::new(
            root,
            &functions,
            &variables,
            &namespaces,
        );

        let res = xpath.evaluate(&context);

        println!("{:?}", res);
    }
}
<|endoftext|>


<commit_before>pub type in_addr_t = u32;
pub type in_port_t = u16;
pub type pthread_key_t = usize;
pub type pthread_t = usize;
pub type sa_family_t = u8;
pub type socklen_t = usize;

s! {
    pub struct addrinfo {
        pub ai_flags: ::c_int,
        pub ai_family: ::c_int,
        pub ai_socktype: ::c_int,
        pub ai_protocol: ::c_int,
        pub ai_addrlen: ::socklen_t,
        pub ai_addr: *mut ::sockaddr,
        pub ai_canonname: *mut ::c_char,
        pub ai_next: *mut addrinfo,
    }

    pub struct in_addr {
        pub s_addr: in_addr_t,
    }

    pub struct in6_addr {
        pub s6_addr: [u8; 16],
    }

    pub struct pthread_attr_t {
        __detachstate: ::c_int,
        __stacksize: usize,
    }

    pub struct sockaddr {
        pub sa_family: sa_family_t,
        pub sa_data: [::c_char; 0],
    }

    pub struct sockaddr_in {
        pub sin_family: ::sa_family_t,
        pub sin_port: ::in_port_t,
        pub sin_addr: ::in_addr,
    }

    pub struct sockaddr_in6 {
        pub sin6_family: sa_family_t,
        pub sin6_port: ::in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }

    pub struct sockaddr_storage {
        pub ss_family: ::sa_family_t,
        __ss_data: [u8; 32],
    }
}

pub const _SC_PAGESIZE: ::c_int = 54;

pub const AF_INET: ::c_int = 1;
pub const AF_INET6: ::c_int = 2;

pub const EACCES: ::c_int = 2;
pub const EADDRINUSE: ::c_int = 3;
pub const EADDRNOTAVAIL: ::c_int = 4;
pub const EAGAIN: ::c_int = 6;
pub const ECONNABORTED: ::c_int = 13;
pub const ECONNREFUSED: ::c_int = 14;
pub const ECONNRESET: ::c_int = 15;
pub const EEXIST: ::c_int = 20;
pub const EINTR: ::c_int = 27;
pub const EINVAL: ::c_int = 28;
pub const ENOENT: ::c_int = 44;
pub const ENOTCONN: ::c_int = 53;
pub const EPERM: ::c_int = 63;
pub const EPIPE: ::c_int = 64;
pub const ETIMEDOUT: ::c_int = 73;
pub const EWOULDBLOCK: ::c_int = EAGAIN;

pub const EAI_SYSTEM: ::c_int = 9;

pub const PTHREAD_STACK_MIN: ::size_t = 1024;

pub const SOCK_DGRAM: ::c_int = 128;
pub const SOCK_STREAM: ::c_int = 130;

extern {
    pub fn freeaddrinfo(res: *mut addrinfo);
    pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char;
    pub fn getaddrinfo(
        node: *const c_char,
        service: *const c_char,
        hints: *const addrinfo,
        res: *mut *mut addrinfo,
    ) -> ::c_int;
    pub fn getsockopt(
        sockfd: ::c_int,
        level: ::c_int,
        optname: ::c_int,
        optval: *mut ::c_void,
        optlen: *mut ::socklen_t,
    ) -> ::c_int;
    pub fn posix_memalign(
        memptr: *mut *mut ::c_void,
        align: ::size_t,
        size: ::size_t,
    ) -> ::c_int;
    pub fn pthread_attr_destroy(attr: *mut ::pthread_attr_t) -> ::c_int;
    pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int;
    pub fn pthread_attr_setstacksize(
        attr: *mut ::pthread_attr_t,
        stack_size: ::size_t,
    ) -> ::c_int;
    pub fn pthread_create(
        native: *mut ::pthread_t,
        attr: *const ::pthread_attr_t,
        f: extern fn(*mut ::c_void) -> *mut ::c_void,
        value: *mut ::c_void,
    ) -> ::c_int;
    pub fn pthread_detach(thread: ::pthread_t) -> ::c_int;
    pub fn pthread_getspecific(key: pthread_key_t) -> *mut ::c_void;
    pub fn pthread_join(
        native: ::pthread_t,
        value: *mut *mut ::c_void,
    ) -> ::c_int;
    pub fn pthread_key_create(
        key: *mut pthread_key_t,
        dtor: Option<unsafe extern fn(*mut ::c_void)>,
    ) -> ::c_int;
    pub fn pthread_key_delete(key: pthread_key_t) -> ::c_int;
    pub fn pthread_setspecific(
        key: pthread_key_t,
        value: *const ::c_void,
    ) -> ::c_int;
    pub fn send(
        socket: ::c_int,
        buf: *const ::c_void,
        len: ::size_t,
        flags: ::c_int,
    ) -> ::ssize_t;
    pub fn sysconf(name: ::c_int) -> ::c_long;
}

cfg_if! {
    if #[cfg(target_arch = "aarch64")] {
        mod aarch64;
        pub use self::aarch64::*;
    } else if #[cfg(any(target_arch = "x86"))] {
        mod x86;
        pub use self::x86::*;
    } else if #[cfg(any(target_arch = "x86_64"))] {
        mod x86_64;
        pub use self::x86_64::*;
    } else {
        // Unknown target_arch
    }
}
<commit_msg>Add arc4random_buf() for PRNG access.<commit_after>pub type in_addr_t = u32;
pub type in_port_t = u16;
pub type pthread_key_t = usize;
pub type pthread_t = usize;
pub type sa_family_t = u8;
pub type socklen_t = usize;

s! {
    pub struct addrinfo {
        pub ai_flags: ::c_int,
        pub ai_family: ::c_int,
        pub ai_socktype: ::c_int,
        pub ai_protocol: ::c_int,
        pub ai_addrlen: ::socklen_t,
        pub ai_addr: *mut ::sockaddr,
        pub ai_canonname: *mut ::c_char,
        pub ai_next: *mut addrinfo,
    }

    pub struct in_addr {
        pub s_addr: in_addr_t,
    }

    pub struct in6_addr {
        pub s6_addr: [u8; 16],
    }

    pub struct pthread_attr_t {
        __detachstate: ::c_int,
        __stacksize: usize,
    }

    pub struct sockaddr {
        pub sa_family: sa_family_t,
        pub sa_data: [::c_char; 0],
    }

    pub struct sockaddr_in {
        pub sin_family: ::sa_family_t,
        pub sin_port: ::in_port_t,
        pub sin_addr: ::in_addr,
    }

    pub struct sockaddr_in6 {
        pub sin6_family: sa_family_t,
        pub sin6_port: ::in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }

    pub struct sockaddr_storage {
        pub ss_family: ::sa_family_t,
        __ss_data: [u8; 32],
    }
}

pub const _SC_PAGESIZE: ::c_int = 54;

pub const AF_INET: ::c_int = 1;
pub const AF_INET6: ::c_int = 2;

pub const EACCES: ::c_int = 2;
pub const EADDRINUSE: ::c_int = 3;
pub const EADDRNOTAVAIL: ::c_int = 4;
pub const EAGAIN: ::c_int = 6;
pub const ECONNABORTED: ::c_int = 13;
pub const ECONNREFUSED: ::c_int = 14;
pub const ECONNRESET: ::c_int = 15;
pub const EEXIST: ::c_int = 20;
pub const EINTR: ::c_int = 27;
pub const EINVAL: ::c_int = 28;
pub const ENOENT: ::c_int = 44;
pub const ENOTCONN: ::c_int = 53;
pub const EPERM: ::c_int = 63;
pub const EPIPE: ::c_int = 64;
pub const ETIMEDOUT: ::c_int = 73;
pub const EWOULDBLOCK: ::c_int = EAGAIN;

pub const EAI_SYSTEM: ::c_int = 9;

pub const PTHREAD_STACK_MIN: ::size_t = 1024;

pub const SOCK_DGRAM: ::c_int = 128;
pub const SOCK_STREAM: ::c_int = 130;

extern {
    pub fn arc4random_buf(buf: *const ::c_void, len: ::size_t);
    pub fn freeaddrinfo(res: *mut addrinfo);
    pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char;
    pub fn getaddrinfo(
        node: *const c_char,
        service: *const c_char,
        hints: *const addrinfo,
        res: *mut *mut addrinfo,
    ) -> ::c_int;
    pub fn getsockopt(
        sockfd: ::c_int,
        level: ::c_int,
        optname: ::c_int,
        optval: *mut ::c_void,
        optlen: *mut ::socklen_t,
    ) -> ::c_int;
    pub fn posix_memalign(
        memptr: *mut *mut ::c_void,
        align: ::size_t,
        size: ::size_t,
    ) -> ::c_int;
    pub fn pthread_attr_destroy(attr: *mut ::pthread_attr_t) -> ::c_int;
    pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int;
    pub fn pthread_attr_setstacksize(
        attr: *mut ::pthread_attr_t,
        stack_size: ::size_t,
    ) -> ::c_int;
    pub fn pthread_create(
        native: *mut ::pthread_t,
        attr: *const ::pthread_attr_t,
        f: extern fn(*mut ::c_void) -> *mut ::c_void,
        value: *mut ::c_void,
    ) -> ::c_int;
    pub fn pthread_detach(thread: ::pthread_t) -> ::c_int;
    pub fn pthread_getspecific(key: pthread_key_t) -> *mut ::c_void;
    pub fn pthread_join(
        native: ::pthread_t,
        value: *mut *mut ::c_void,
    ) -> ::c_int;
    pub fn pthread_key_create(
        key: *mut pthread_key_t,
        dtor: Option<unsafe extern fn(*mut ::c_void)>,
    ) -> ::c_int;
    pub fn pthread_key_delete(key: pthread_key_t) -> ::c_int;
    pub fn pthread_setspecific(
        key: pthread_key_t,
        value: *const ::c_void,
    ) -> ::c_int;
    pub fn send(
        socket: ::c_int,
        buf: *const ::c_void,
        len: ::size_t,
        flags: ::c_int,
    ) -> ::ssize_t;
    pub fn sysconf(name: ::c_int) -> ::c_long;
}

cfg_if! {
    if #[cfg(target_arch = "aarch64")] {
        mod aarch64;
        pub use self::aarch64::*;
    } else if #[cfg(any(target_arch = "x86"))] {
        mod x86;
        pub use self::x86::*;
    } else if #[cfg(any(target_arch = "x86_64"))] {
        mod x86_64;
        pub use self::x86_64::*;
    } else {
        // Unknown target_arch
    }
}
<|endoftext|>


<commit_before>use std::cmp;

use ast::*;
use ast::Stmt::*;
use ast::Expr::*;
use ast::visit::*;

use codegen::expr::is_leaf;
use codegen::x64::reg::*;
use ctxt::Context;

use mem;

use sym::BuiltinType;

pub fn generate<'a, 'ast>(ctxt: &'a Context<'a, 'ast>, fct: &'ast Function) -> Info {
    InfoGenerator::new(ctxt, fct).generate()
}

pub struct Info {
    pub localsize: u32,
    pub tempsize: u32,
    pub fct_call: bool,
}

impl Info {
    pub fn stacksize(&self) -> u32 {
        self.localsize + self.tempsize
    }
}

impl Default for Info {
    fn default() -> Info {
        Info {
            localsize: 0,
            tempsize: 0,
            fct_call: false,
        }
    }
}

struct InfoGenerator<'a, 'ast: 'a> {
    ctxt: &'a Context<'a, 'ast>,
    fct: &'ast Function,

    localsize: u32,
    max_tempsize: u32,
    cur_tempsize: u32,

    param_offset: i32,
    fct_call: bool,
}

impl<'a, 'ast> InfoGenerator<'a, 'ast> {
    fn new(ctxt: &'a Context<'a, 'ast>, fct: &'ast Function) -> InfoGenerator<'a, 'ast> {
        InfoGenerator {
            ctxt: ctxt,
            fct: fct,

            localsize: 0,
            max_tempsize: 0,
            cur_tempsize: 0,

            // first param offset to rbp is +16,
            // rbp+0 -> saved rbp
            // rbp+8 -> return address
            param_offset: 16,

            fct_call: false,
        }
    }

    fn generate(mut self) -> Info {
        self.visit_fct(self.fct);

        Info {
            localsize: self.localsize,
            tempsize: self.max_tempsize,
            fct_call: self.fct_call,
        }
    }

    fn increase_stack(&mut self, id: NodeId) {
        self.ctxt.var_mut(id, |v, _| {
            let ty_size = v.data_type.size();
            self.localsize = mem::align(self.localsize + ty_size, ty_size);
            v.offset = -(self.localsize as i32);
        });
    }
}

impl<'a, 'ast> Visitor<'ast> for InfoGenerator<'a, 'ast> {
    fn visit_param(&mut self, p: &'ast Param) {
        // on x64 only the first 6 parameters are stored in registers
        if (p.idx as usize) < REG_PARAMS.len() {
            self.increase_stack(p.id);

        // the rest of the parameters need to be stored in the callers stack
        } else {
            self.ctxt.var_mut(p.id, |v, _| { v.offset = self.param_offset; });

            // all params on stack need size of 8
            self.param_offset += 8;
        }
    }

    fn visit_stmt(&mut self, s: &'ast Stmt) {
        if let StmtVar(ref var) = *s {
            self.increase_stack(var.id);
        }

        visit::walk_stmt(self, s);
    }

    fn visit_expr_top(&mut self, e: &'ast Expr) {
        self.cur_tempsize = 0;
        self.visit_expr(e);
        self.max_tempsize = cmp::max(self.cur_tempsize, self.max_tempsize);
    }

    fn visit_expr(&mut self, e: &'ast Expr) {
        match *e {
            ExprCall(_) => {
                self.fct_call = true;
            }

            ExprBin(ref expr) => {
                if !is_leaf(&expr.rhs) {
                    self.cur_tempsize += BuiltinType::Int.size();
                }
            }

            _ => {}
        }

        visit::walk_expr(self, e);
    }
}

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

    use ctxt::*;
    use test;

    fn info<F>(code: &'static str, f: F) where F: FnOnce(&Context, &FctInfo, Info) {
        test::parse(code, |ctxt| {
            let fct = ctxt.ast.elements[0].to_function().unwrap();
            let info = generate(ctxt, fct);

            ctxt.fct_info(fct.id, |fct| {
                f(ctxt, fct, info);
            });
        });
    }

    #[test]
    fn test_tempsize() {
        info("fn f() { 1+2*3; }", |_, _, info| { assert_eq!(4, info.tempsize); });
        info("fn f() { 2*3+4+5; }", |_, _, info| { assert_eq!(0, info.tempsize); });
    }

    #[test]
    fn test_invocation_flag() {
        info("fn f() { g(); } fn g() { }", |_, _, info| {
            assert!(info.fct_call);
        });

        info("fn f() { }", |_, _, info| {
            assert!(!info.fct_call);
        });
    }

    #[test]
    fn test_param_offset() {
        info("fn f(a: bool, b: int) { var c = 1; }", |ctxt, fct, info| {
            assert_eq!(12, info.localsize);

            for (varid, offset) in fct.vars.iter().zip(&[-1, -8, -12]) {
                assert_eq!(*offset, ctxt.var_infos.borrow()[varid.0].offset);
            }
        });
    }

    #[test]
    fn test_params_over_6_offset() {
        info("fn f(a: int, b: int, c: int, d: int,
                   e: int, f: int, g: int, h: int) {
                  var i : int = 1;
              }", |ctxt, fct, info| {
            assert_eq!(28, info.localsize);
            let offsets = [-4, -8, -12, -16, -20, -24, 16, 24, -28];

            for (varid, offset) in fct.vars.iter().zip(&offsets) {
                assert_eq!(*offset, ctxt.var_infos.borrow()[varid.0].offset);
            }
        });
    }

    #[test]
    fn test_var_offset() {
        info("fn f() { var a = true; var b = false; var c = 2; var d = \"abc\"; }", |ctxt, fct, info| {
            assert_eq!(16, info.localsize);

            for (varid, offset) in fct.vars.iter().zip(&[-1, -2, -8, -16]) {
                assert_eq!(*offset, ctxt.var_infos.borrow()[varid.0].offset);
            }
        });
    }
}
<commit_msg>codegen: added test case for tempsize<commit_after>use std::cmp;

use ast::*;
use ast::Stmt::*;
use ast::Expr::*;
use ast::visit::*;

use codegen::expr::is_leaf;
use codegen::x64::reg::*;
use ctxt::Context;

use mem;

use sym::BuiltinType;

pub fn generate<'a, 'ast>(ctxt: &'a Context<'a, 'ast>, fct: &'ast Function) -> Info {
    InfoGenerator::new(ctxt, fct).generate()
}

pub struct Info {
    pub localsize: u32,
    pub tempsize: u32,
    pub fct_call: bool,
}

impl Info {
    pub fn stacksize(&self) -> u32 {
        self.localsize + self.tempsize
    }
}

impl Default for Info {
    fn default() -> Info {
        Info {
            localsize: 0,
            tempsize: 0,
            fct_call: false,
        }
    }
}

struct InfoGenerator<'a, 'ast: 'a> {
    ctxt: &'a Context<'a, 'ast>,
    fct: &'ast Function,

    localsize: u32,
    max_tempsize: u32,
    cur_tempsize: u32,

    param_offset: i32,
    fct_call: bool,
}

impl<'a, 'ast> InfoGenerator<'a, 'ast> {
    fn new(ctxt: &'a Context<'a, 'ast>, fct: &'ast Function) -> InfoGenerator<'a, 'ast> {
        InfoGenerator {
            ctxt: ctxt,
            fct: fct,

            localsize: 0,
            max_tempsize: 0,
            cur_tempsize: 0,

            // first param offset to rbp is +16,
            // rbp+0 -> saved rbp
            // rbp+8 -> return address
            param_offset: 16,

            fct_call: false,
        }
    }

    fn generate(mut self) -> Info {
        self.visit_fct(self.fct);

        Info {
            localsize: self.localsize,
            tempsize: self.max_tempsize,
            fct_call: self.fct_call,
        }
    }

    fn increase_stack(&mut self, id: NodeId) {
        self.ctxt.var_mut(id, |v, _| {
            let ty_size = v.data_type.size();
            self.localsize = mem::align(self.localsize + ty_size, ty_size);
            v.offset = -(self.localsize as i32);
        });
    }
}

impl<'a, 'ast> Visitor<'ast> for InfoGenerator<'a, 'ast> {
    fn visit_param(&mut self, p: &'ast Param) {
        // on x64 only the first 6 parameters are stored in registers
        if (p.idx as usize) < REG_PARAMS.len() {
            self.increase_stack(p.id);

        // the rest of the parameters need to be stored in the callers stack
        } else {
            self.ctxt.var_mut(p.id, |v, _| { v.offset = self.param_offset; });

            // all params on stack need size of 8
            self.param_offset += 8;
        }
    }

    fn visit_stmt(&mut self, s: &'ast Stmt) {
        if let StmtVar(ref var) = *s {
            self.increase_stack(var.id);
        }

        visit::walk_stmt(self, s);
    }

    fn visit_expr_top(&mut self, e: &'ast Expr) {
        self.cur_tempsize = 0;
        self.visit_expr(e);
        self.max_tempsize = cmp::max(self.cur_tempsize, self.max_tempsize);
    }

    fn visit_expr(&mut self, e: &'ast Expr) {
        match *e {
            ExprCall(_) => {
                self.fct_call = true;
            }

            ExprBin(ref expr) => {
                if !is_leaf(&expr.rhs) {
                    self.cur_tempsize += BuiltinType::Int.size();
                }
            }

            _ => {}
        }

        visit::walk_expr(self, e);
    }
}

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

    use ctxt::*;
    use test;

    fn info<F>(code: &'static str, f: F) where F: FnOnce(&Context, &FctInfo, Info) {
        test::parse(code, |ctxt| {
            let fct = ctxt.ast.elements[0].to_function().unwrap();
            let info = generate(ctxt, fct);

            ctxt.fct_info(fct.id, |fct| {
                f(ctxt, fct, info);
            });
        });
    }

    #[test]
    fn test_tempsize() {
        info("fn f() { 1+2*3; }", |_, _, info| { assert_eq!(4, info.tempsize); });
        info("fn f() { 2*3+4+5; }", |_, _, info| { assert_eq!(0, info.tempsize); });
        info("fn f() { 1+(2+(3+4)); }", |_, _, info| { assert_eq!(8, info.tempsize); })
    }

    #[test]
    fn test_invocation_flag() {
        info("fn f() { g(); } fn g() { }", |_, _, info| {
            assert!(info.fct_call);
        });

        info("fn f() { }", |_, _, info| {
            assert!(!info.fct_call);
        });
    }

    #[test]
    fn test_param_offset() {
        info("fn f(a: bool, b: int) { var c = 1; }", |ctxt, fct, info| {
            assert_eq!(12, info.localsize);

            for (varid, offset) in fct.vars.iter().zip(&[-1, -8, -12]) {
                assert_eq!(*offset, ctxt.var_infos.borrow()[varid.0].offset);
            }
        });
    }

    #[test]
    fn test_params_over_6_offset() {
        info("fn f(a: int, b: int, c: int, d: int,
                   e: int, f: int, g: int, h: int) {
                  var i : int = 1;
              }", |ctxt, fct, info| {
            assert_eq!(28, info.localsize);
            let offsets = [-4, -8, -12, -16, -20, -24, 16, 24, -28];

            for (varid, offset) in fct.vars.iter().zip(&offsets) {
                assert_eq!(*offset, ctxt.var_infos.borrow()[varid.0].offset);
            }
        });
    }

    #[test]
    fn test_var_offset() {
        info("fn f() { var a = true; var b = false; var c = 2; var d = \"abc\"; }", |ctxt, fct, info| {
            assert_eq!(16, info.localsize);

            for (varid, offset) in fct.vars.iter().zip(&[-1, -2, -8, -16]) {
                assert_eq!(*offset, ctxt.var_infos.borrow()[varid.0].offset);
            }
        });
    }
}
<|endoftext|>


<commit_before>use crate::discord_client::CommandHandler;
use reqwest;
use serde_derive::Deserialize;

#[derive(Deserialize)]
pub struct DanbooruApiResponse {
    file_url: String,
}

pub struct PicCommand;

impl CommandHandler for PicCommand {
    fn process_command(
        &self,
        command: &str,
        send_message_callback: &Fn(&str) -> (),
    ) -> Result<(), Box<std::error::Error>> {
        let parameters = get_search_parameters(command);
        let parameters = format_search_parameters(parameters);

        let request_uri: String = format!(
            "https://danbooru.donmai.us/posts.json?search&random=true&limit=1&tags={}",
            parameters
        );
        let response_body: String = reqwest::get(&request_uri)?.text()?;

        let response_model: Vec<DanbooruApiResponse> =
            serde_json::from_str(&response_body).unwrap();

        let result = match response_model.first() {
            Some(picture) => &picture.file_url,
            None => "No images with those tags found",
        };

        send_message_callback(result);

        Ok(())
    }
}

fn format_search_parameters(parameters: Vec<&str>) -> String {
    parameters.join("+")
}

fn get_search_parameters(command: &str) -> Vec<&str> {
    let mut result: Vec<&str> = Vec::new();

    let paramaters: Vec<&str> = command.split_whitespace().collect();
    for word in paramaters.iter().skip(1) {
        result.push(word);
    }

    result
}
<commit_msg>Adds basic unit tests for the parsing code<commit_after>use crate::discord_client::CommandHandler;
use reqwest;
use serde_derive::Deserialize;

#[derive(Deserialize)]
pub struct DanbooruApiResponse {
    file_url: String,
}

pub struct PicCommand;

impl CommandHandler for PicCommand {
    fn process_command(
        &self,
        command: &str,
        send_message_callback: &Fn(&str) -> (),
    ) -> Result<(), Box<std::error::Error>> {
        let parameters = get_search_parameters(command);
        let parameters = format_search_parameters(parameters);

        let request_uri: String = format!(
            "https://danbooru.donmai.us/posts.json?search&random=true&limit=1&tags={}",
            parameters
        );
        let response_body: String = reqwest::get(&request_uri)?.text()?;

        let response_model: Vec<DanbooruApiResponse> =
            serde_json::from_str(&response_body).unwrap();

        let result = match response_model.first() {
            Some(picture) => &picture.file_url,
            None => "No images with those tags found",
        };

        send_message_callback(result);

        Ok(())
    }
}

fn format_search_parameters(parameters: Vec<&str>) -> String {
    parameters.join("+")
}

fn get_search_parameters(command: &str) -> Vec<&str> {
    let mut result: Vec<&str> = Vec::new();

    let paramaters: Vec<&str> = command.split_whitespace().collect();
    for word in paramaters.iter().skip(1) {
        result.push(word);
    }

    result
}

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

    #[test]
    fn test_get_search_parameters() {
        let empty_vec: Vec<&str> = Vec::new();
        assert_eq!(empty_vec, get_search_parameters("pic"));
        assert_eq!(vec!["tag1", "tag2", "tag3"], get_search_parameters("pic tag1 tag2 tag3"));
        assert_eq!(vec!["一番", "に", "サン"], get_search_parameters("pic 一番 に サン"));
    }

    #[test]
    fn test_format_search_parameters() {
        let empty_vec: Vec<&str> = Vec::new();
        assert_eq!("", format_search_parameters(empty_vec));
        assert_eq!("tag1+tag2+tag3", format_search_parameters(vec!["tag1", "tag2", "tag3"]));
        assert_eq!("一番+に+サン", format_search_parameters(vec!["一番", "に", "サン"]));
    }
}
<|endoftext|>


<commit_before>
use error::{StoreError, StoreErrorKind};
use std::path::{Path, PathBuf};
use std::fs::{File, OpenOptions};

pub enum LazyFile {
    Absent(PathBuf),
    File(File)
}

fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).open(p)
}

fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).create(true).open(p)
}

impl LazyFile {
    pub fn new(p: PathBuf) -> LazyFile {
        LazyFile::Absent(p)
    }
    pub fn new_with_file(f: File) -> LazyFile {
        LazyFile::File(f)
    }

    pub fn get_file(&mut self) -> Result<&File, StoreError> {
        let file = match *self {
            LazyFile::File(ref f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))

            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    pub fn get_file_mut(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    pub fn create_file(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(create_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::LazyFile;
    use std::io::{Read, Write};
    use std::path::PathBuf;
    use std::fs::File;
    use tempdir::TempDir;

    fn get_dir() -> TempDir {
        TempDir::new("test-image").unwrap()
    }

    #[test]
    fn lazy_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test1");
        let mut lf = LazyFile::new(path);

        write!(lf.create_file().unwrap(), "Hello World").unwrap();
        dir.close().unwrap();
    }

    #[test]
    fn lazy_file_with_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test2");
        let mut lf = LazyFile::new(path);
        let mut file = lf.create_file().unwrap();

        file.write(b"Hello World").unwrap();
        file.sync_all().unwrap();
        let mut s = Vec::new();
        file.read_to_end(&mut s).unwrap();
        assert_eq!(s, "Hello World".to_string().into_bytes());

        dir.close().unwrap();
    }
}
<commit_msg>Fix test: lazy_file_with_file<commit_after>
use error::{StoreError, StoreErrorKind};
use std::path::{Path, PathBuf};
use std::fs::{File, OpenOptions};

pub enum LazyFile {
    Absent(PathBuf),
    File(File)
}

fn open_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).open(p)
}

fn create_file<A: AsRef<Path>>(p: A) -> ::std::io::Result<File> {
    OpenOptions::new().write(true).read(true).create(true).open(p)
}

impl LazyFile {
    pub fn new(p: PathBuf) -> LazyFile {
        LazyFile::Absent(p)
    }
    pub fn new_with_file(f: File) -> LazyFile {
        LazyFile::File(f)
    }

    pub fn get_file(&mut self) -> Result<&File, StoreError> {
        let file = match *self {
            LazyFile::File(ref f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))

            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    pub fn get_file_mut(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(open_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }

    pub fn create_file(&mut self) -> Result<&mut File, StoreError> {
        let file = match *self {
            LazyFile::File(ref mut f) => return Ok(f),
            LazyFile::Absent(ref p) => {
                try!(create_file(p).map_err(|e| {
                    StoreError::new(StoreErrorKind::FileNotFound,
                                    Some(Box::new(e)))
                }))
            }
        };
        *self = LazyFile::File(file);
        if let LazyFile::File(ref mut f) = *self {
            return Ok(f);
        }
        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::LazyFile;
    use std::io::{Read, Write};
    use std::path::PathBuf;
    use std::fs::File;
    use tempdir::TempDir;

    fn get_dir() -> TempDir {
        TempDir::new("test-image").unwrap()
    }

    #[test]
    fn lazy_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test1");
        let mut lf = LazyFile::new(path);

        write!(lf.create_file().unwrap(), "Hello World").unwrap();
        dir.close().unwrap();
    }

    #[test]
    fn lazy_file_with_file() {
        let dir = get_dir();
        let mut path = PathBuf::from(dir.path());
        path.set_file_name("test2");

        {
            let mut lf = LazyFile::new(path.clone());
            let mut file = lf.create_file().unwrap();

            file.write(b"Hello World").unwrap();
            file.sync_all().unwrap();
        }

        {
            let mut lf = LazyFile::new(path);
            let mut file = lf.create_file().unwrap();

            let mut s = Vec::new();
            file.read_to_end(&mut s).unwrap();
            assert_eq!(s, "Hello World".to_string().into_bytes());
        }

        dir.close().unwrap();
    }
}
<|endoftext|>