<commit_before>use crate::os::process::can_run_services_as_svc_user;
use nix::unistd::{setgid,
                  setuid,
                  Gid,
                  Uid};
use std::{ffi::OsStr,
          io,
          os::unix::process::CommandExt,
          process::{Command,
                    Stdio},
          result};

/// Prepare a `Command` to execute a lifecycle hook.
// TODO (CM): Ideally, `ids` would not be an `Option`, but separate
// `Uid` and `Gid` inputs. However, the `Option` interface provides
// the least disruption to other existing code for the time being.
pub fn hook_command<X, I, K, V>(executable: X, env: I, ids: Option<(Uid, Gid)>) -> Command
    where X: AsRef<OsStr>,
          I: IntoIterator<Item = (K, V)>,
          K: AsRef<OsStr>,
          V: AsRef<OsStr>
{
    let mut cmd = Command::new(executable);

    // NOTE: CommandExt::uid and CommandExt::guid should *not* be
    // called here! They are set in `with_user_and_group_information`;
    // see there for further details.
    cmd.stdin(Stdio::null())
       .stdout(Stdio::piped())
       .stderr(Stdio::piped())
       .envs(env);

    with_own_process_group(&mut cmd);
    if let Some((uid, gid)) = ids {
        with_user_and_group_information(&mut cmd, uid, gid);
    }

    cmd
}

/// Ensures that the `Command` is executed within its own process
/// group, and not that of its parent process.
///
/// This should be used when spawning all hooks. This ensures that
/// they are not the same process group as the Launcher (for `run`
/// hooks) or the Supervisor (for all other hooks). Otherwise, if a
/// child process were to send `SIGTERM`, the Launcher could be
/// terminated. Similarly, it prevents a `^C` sent to a foregrounded
/// Supervisor from terminating any hooks prematurely.
///
/// This basically ensures that all hooks are properly isolated,
/// without signaling cross-talk between them and the Launcher /
/// Supervisor.
fn with_own_process_group(cmd: &mut Command) -> &mut Command {
    unsafe {
        cmd.pre_exec(set_own_process_group);
    }
    cmd
}

/// Set the process group of the calling process to be the same as its
/// PID.
///
/// Intended for use in a
/// `std::os::unix::process::CommandExt::pre_exec` callback.
fn set_own_process_group() -> result::Result<(), io::Error> {
    unsafe {
        if libc::setpgid(0, 0) == 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    }
}
/// Sets uid, gid, and supplementary groups on command.
///
/// DO NOT call `CommandExt#uid` or `CommandExt#gid` on this command,
/// either before or after calling this function, or it will probably
/// not work like you want it to.
fn with_user_and_group_information(cmd: &mut Command, uid: Uid, gid: Gid) -> &mut Command {
    unsafe {
        cmd.pre_exec(set_supplementary_groups(uid, gid));
    }
    cmd
}

/// Stupid little private helper macro to make mapping `Nix` errors to
/// IO errors for our `pre_exec` hooks.
///
/// The format string should have a single variable placeholder for
/// the actual error.
///
/// e.g. `result.map_err(io_err!("blah blah {:?}"))`
macro_rules! io_error {
    ($format_string:tt) => {
        move |e| io::Error::new(io::ErrorKind::Other, format!($format_string, e))
    };
}

/// Returns a function that sets the supplementary group IDs of the
/// process to those that `user_id` belongs to.
///
/// Also sets the uid and gid of the process. We must do that here,
/// rather than using the `CommandExt::uid` and `CommandExt::gid`
/// methods to ensure that all the IDs are set on the process in the
/// correct order (that is, supplementary groups, gid, and finally uid).
///
/// Once https://github.com/rust-lang/rust/pull/72160 merges, we can
/// use all `CommandExt` methods, and thus simplify things a (little)
/// bit.
fn set_supplementary_groups(user_id: Uid,
                            group_id: Gid)
                            -> impl Fn() -> result::Result<(), io::Error> {
    // Note: since this function will be run a separate process that doesn't
    // inherit RUST_LOG, none of the log! macros will work actually
    // work here.

    move || {
        // Note that if we *can't* run services as another user,
        // that's OK; not an error. We just won't set supplementary
        // groups, and run all hooks as the user we currently are.
        if can_run_services_as_svc_user() {
            // These calls don't have a macOS counterpart (well, not a
            // direct one in nix, at least) and we don't need to
            // execute hooks on macOS, so it's not important to
            // implement this. Our crates aren't really factored well
            // enough to let us cut out larger chunks of code on macOS
            // at the moment, so we just won't compile this particular
            // bit for now.
            #[cfg(not(target_os = "macos"))]
            {
                use nix::unistd::{getgrouplist,
                                  setgroups,
                                  User};
                use std::ffi::CString;

                if let Some(user) = User::from_uid(user_id).map_err(io_error!("Error resolving \
                                                                               user from ID: \
                                                                               {:?}"))?
                {
                    let user = CString::new(user.name).map_err(io_error!("User name cannot \
                                                                          convert to CString!: \
                                                                          {:?}"))?;
                    let groups = getgrouplist(&user, group_id).map_err(io_error!("getgrouplist \
                                                                                failed!: {:?}"))?;
                    setgroups(&groups).map_err(io_error!("setgroups failed! {:?}"))?; // CAP_SETGID
                } else {
                    return Err(io::Error::new(io::ErrorKind::Other,
                                              "Could not find user from user ID"));
                }
            }

            // These calls replace `CommandExt::uid` and `CommandExt::gid`
            setgid(group_id).map_err(io_error!("setgid failed! {:?}"))?; // CAP_SETGID
            setuid(user_id).map_err(io_error!("setuid failed! {:?}"))?; // CAP_SETUID
        }

        Ok(())
    }
}
<commit_msg>set groups with primary group if unable to retrieve supplemental groups<commit_after>use crate::os::process::can_run_services_as_svc_user;
use nix::unistd::{setgid,
                  setuid,
                  Gid,
                  Uid};
use std::{ffi::OsStr,
          io,
          os::unix::process::CommandExt,
          process::{Command,
                    Stdio},
          result};

/// Prepare a `Command` to execute a lifecycle hook.
// TODO (CM): Ideally, `ids` would not be an `Option`, but separate
// `Uid` and `Gid` inputs. However, the `Option` interface provides
// the least disruption to other existing code for the time being.
pub fn hook_command<X, I, K, V>(executable: X, env: I, ids: Option<(Uid, Gid)>) -> Command
    where X: AsRef<OsStr>,
          I: IntoIterator<Item = (K, V)>,
          K: AsRef<OsStr>,
          V: AsRef<OsStr>
{
    let mut cmd = Command::new(executable);

    // NOTE: CommandExt::uid and CommandExt::guid should *not* be
    // called here! They are set in `with_user_and_group_information`;
    // see there for further details.
    cmd.stdin(Stdio::null())
       .stdout(Stdio::piped())
       .stderr(Stdio::piped())
       .envs(env);

    with_own_process_group(&mut cmd);
    if let Some((uid, gid)) = ids {
        with_user_and_group_information(&mut cmd, uid, gid);
    }

    cmd
}

/// Ensures that the `Command` is executed within its own process
/// group, and not that of its parent process.
///
/// This should be used when spawning all hooks. This ensures that
/// they are not the same process group as the Launcher (for `run`
/// hooks) or the Supervisor (for all other hooks). Otherwise, if a
/// child process were to send `SIGTERM`, the Launcher could be
/// terminated. Similarly, it prevents a `^C` sent to a foregrounded
/// Supervisor from terminating any hooks prematurely.
///
/// This basically ensures that all hooks are properly isolated,
/// without signaling cross-talk between them and the Launcher /
/// Supervisor.
fn with_own_process_group(cmd: &mut Command) -> &mut Command {
    unsafe {
        cmd.pre_exec(set_own_process_group);
    }
    cmd
}

/// Set the process group of the calling process to be the same as its
/// PID.
///
/// Intended for use in a
/// `std::os::unix::process::CommandExt::pre_exec` callback.
fn set_own_process_group() -> result::Result<(), io::Error> {
    unsafe {
        if libc::setpgid(0, 0) == 0 {
            Ok(())
        } else {
            Err(io::Error::last_os_error())
        }
    }
}
/// Sets uid, gid, and supplementary groups on command.
///
/// DO NOT call `CommandExt#uid` or `CommandExt#gid` on this command,
/// either before or after calling this function, or it will probably
/// not work like you want it to.
fn with_user_and_group_information(cmd: &mut Command, uid: Uid, gid: Gid) -> &mut Command {
    unsafe {
        cmd.pre_exec(set_supplementary_groups(uid, gid));
    }
    cmd
}

/// Stupid little private helper macro to make mapping `Nix` errors to
/// IO errors for our `pre_exec` hooks.
///
/// The format string should have a single variable placeholder for
/// the actual error.
///
/// e.g. `result.map_err(io_err!("blah blah {:?}"))`
macro_rules! io_error {
    ($format_string:tt) => {
        move |e| io::Error::new(io::ErrorKind::Other, format!($format_string, e))
    };
}

/// Returns a function that sets the supplementary group IDs of the
/// process to those that `user_id` belongs to.
///
/// Also sets the uid and gid of the process. We must do that here,
/// rather than using the `CommandExt::uid` and `CommandExt::gid`
/// methods to ensure that all the IDs are set on the process in the
/// correct order (that is, supplementary groups, gid, and finally uid).
///
/// Once https://github.com/rust-lang/rust/pull/72160 merges, we can
/// use all `CommandExt` methods, and thus simplify things a (little)
/// bit.
fn set_supplementary_groups(user_id: Uid,
                            group_id: Gid)
                            -> impl Fn() -> result::Result<(), io::Error> {
    // Note: since this function will be run a separate process that doesn't
    // inherit RUST_LOG, none of the log! macros will work actually
    // work here.

    move || {
        // Note that if we *can't* run services as another user,
        // that's OK; not an error. We just won't set supplementary
        // groups, and run all hooks as the user we currently are.
        if can_run_services_as_svc_user() {
            // These calls don't have a macOS counterpart (well, not a
            // direct one in nix, at least) and we don't need to
            // execute hooks on macOS, so it's not important to
            // implement this. Our crates aren't really factored well
            // enough to let us cut out larger chunks of code on macOS
            // at the moment, so we just won't compile this particular
            // bit for now.
            #[cfg(not(target_os = "macos"))]
            {
                use nix::unistd::{getgrouplist,
                                  setgroups,
                                  User};
                use std::ffi::CString;

                if let Some(user) = User::from_uid(user_id).map_err(io_error!("Error resolving \
                                                                               user from ID: \
                                                                               {:?}"))?
                {
                    let user = CString::new(user.name).map_err(io_error!("User name cannot \
                                                                          convert to CString!: \
                                                                          {:?}"))?;

                    // There are some platforms (ex. SUSE 12 sp5) that may return
                    // EINVAL from getgrouplist. This only appears to occur from
                    // statically compiled (MUSL) executables like the hab CLI. The
                    // error has not been reproducible from a dynamic executable like
                    // the supervisor.
                    let groups = getgrouplist(&user, group_id).unwrap_or_else(|e| {
                                                                  warn!("unable to get \
                                                                         supplementary groups \
                                                                         with getgrouplist: {}",
                                                                        e);
                                                                  vec![group_id]
                                                              });
                    setgroups(&groups).map_err(io_error!("setgroups failed! {:?}"))?; // CAP_SETGID
                } else {
                    return Err(io::Error::new(io::ErrorKind::Other,
                                              "Could not find user from user ID"));
                }
            }

            // These calls replace `CommandExt::uid` and `CommandExt::gid`
            setgid(group_id).map_err(io_error!("setgid failed! {:?}"))?; // CAP_SETGID
            setuid(user_id).map_err(io_error!("setuid failed! {:?}"))?; // CAP_SETUID
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
extern crate syn;

/// Main `Template` trait; implementations are generally derived
pub trait Template {
    /// Renders the template to the given `writer` buffer
    fn render_to(&self, writer: &mut std::fmt::Write);
    /// Helper method which allocates a new `String` and renders into it
    fn render(&self) -> String {
        let mut buf = String::new();
        self.render_to(&mut buf);
        buf
    }
}

mod generator;
mod parser;
mod path;

pub mod filters;
pub use path::rerun_if_templates_changed;

// Holds metadata for the template, based on the `template()` attribute.
struct TemplateMeta {
    path: String,
    print: String,
}

// Returns a `TemplateMeta` based on the `template()` attribute data found
// in the parsed struct or enum. Will panic if it does not find the required
// template path, or if the `print` key has an unexpected value.
fn get_template_meta(ast: &syn::DeriveInput) -> TemplateMeta {
    let mut path = None;
    let mut print = "none".to_string();
    let attr = ast.attrs.iter().find(|a| a.name() == "template").unwrap();
    if let syn::MetaItem::List(_, ref inner) = attr.value {
        for nm_item in inner {
            if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
                if let syn::MetaItem::NameValue(ref key, ref val) = *item {
                    match key.as_ref() {
                        "path" => if let syn::Lit::Str(ref s, _) = *val {
                            path = Some(s.clone());
                        } else {
                            panic!("template path must be string literal");
                        },
                        "print" => if let syn::Lit::Str(ref s, _) = *val {
                            print = s.clone();
                        } else {
                            panic!("print value must be string literal");
                        },
                        _ => { panic!("unsupported annotation key found") }
                    }
                }
            }
        }
    }
    if path.is_none() {
        panic!("template path not found in struct attributes");
    }
    TemplateMeta { path: path.unwrap(), print: print }
}

/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
pub fn build_template(ast: &syn::DeriveInput) -> String {
    let meta = get_template_meta(ast);
    let mut src = path::get_template_source(&meta.path);
    if src.ends_with('\n') {
        let _ = src.pop();
    }
    let nodes = parser::parse(&src);
    if meta.print == "ast" || meta.print == "all" {
        println!("{:?}", nodes);
    }
    let code = generator::generate(ast, &meta.path, nodes);
    if meta.print == "code" || meta.print == "all" {
        println!("{}", code);
    }
    code
}
<commit_msg>Create documentation about supported template syntax<commit_after>//! Askama implements a type-safe compiler for Jinja-like templates.
//! It lets you write templates in a Jinja-like syntax,
//! which are linked to a `struct` defining the template context.
//! This is done using a custom derive implementation (implemented
//! in [askama_derive](https://crates.io/crates/askama_derive)).
//!
//! # Example template
//!
//! ```text
//! {% extends "layout.html" %}
//! {% block body %}
//!   <ul>
//!     {% for user in users %}
//!       <li><a href="{{ user.url }}">{{ user.username }}</a></li>
//!     {% endfor %}
//!   </ul>
//! {% endblock %}
//! ```
//!
//! # Feature highlights
//!
//! * Construct templates using a familiar, easy-to-use syntax
//! * Fully benefit from the safety provided by Rust's type system
//! * Templates do not perform eager conversion to strings or other types
//! * Template code is compiled into your crate for optimal performance
//! * Templates can directly access your Rust types, according to Rust's
//!   privacy rules
//! * Debugging features to assist you in template development
//! * Included filter functions will provide easy access to common functions
//! * Templates must be valid UTF-8 and produce UTF-8 when rendered
//!
//! # Creating Askama templates
//!
//! An Askama template is just a text file, in the UTF-8 encoding.
//! It can be used to generate any kind of text-based format.
//! You can use whatever extension you like.
//!
//! A template consists of **text contents**, which are passed through as-is,
//! **expressions**, which get replaced with content while being rendered, and
//! **tags**, which control the template's logic.
//! The template syntax is very similar to [Jinja](http://jinja.pocoo.org/),
//! as well as Jinja-derivatives like [Twig](http://twig.sensiolabs.org/) or
//! [Tera](https://github.com/Keats/tera).
//!
//! ## Variables
//!
//! Template variables are defined by the template context linked to the
//! template by deriving a `struct`'s implementation for `Template` from
//! a template file's contents.
//! You can use a dot (`.`) to get a variable's attributes.
//! Reading from variables is subject to the usual borrowing policies.
//! For example, `{{ name }}` will get the ``name`` field from the template
//! context,
//! while `{{ user.name }}` will get the ``name`` field of the `user`
//! ``field`` of the template context.
//!
//! ## Filters
//!
//! Values such as those obtained from variables can be post-processed
//! using **filters**.
//! Filters are applied to values using the pipe symbol (`|`) and may
//! have optional extra arguments in parentheses.
//! Filters can be chained, in which case the output from one filter
//! is passed to the next.
//!
//! For example, `{{ "{:?}"|format(name|escape) }}` will escape HTML
//! characters from the value obtained by accessing the `name` field,
//! and print the resulting string as a Rust literal.
//!
//! Consult the [filters module documentation](filters/index.html) for a list
//! of available filters. User-defined filters are currently not supported.
//!
//! ## Whitespace control
//!
//! Askama preserves all whitespace in template code by default,
//! except that final trailing newline characters are suppressed.
//! However, whitespace before and after expression and block delimiters
//! can be suppressed by writing a minus sign directly following a
//! start delimiter or leading into an end delimiter.
//! Askama considers all tabs, spaces, newlines and carriage returns to be
//! whitespace.
//!
//! ## Template inheritance
//!
//! Template inheritance allows you to build a base template with common
//! elements that can then be shared by all inheriting templates.
//! A base template defines **blocks** that child templates can then override.
//!
//! ### Base template
//!
//! ```text
//! <!DOCTYPE html>
//! <html lang="en">
//!   <head>
//!     <title>{{ block title %}{{ title }}{% endblock %} - My Site</title>
//!     {% block head %}{% endblock %}
//!   </head>
//!   <body>
//!     <div id="content">
//!       {% block content %}{% endblock %}
//!     </div>
//!   </body>
//! </html>
//! ```
//!
//! The `block` tags define three blocks that can be filled in by child
//! templates. The base template defines a default version of the block.
//!
//! ### Child template
//!
//! Here's an example child template:
//!
//! ```text
//! {% extends "base.html" %}
//!
//! {% block title %}Index{% endblock %}
//!
//! {% block head %}
//!   <style>
//!   </style>
//! {% endblock %}
//!
//! {% block content %}
//!   <h1>Index</h1>
//!   <p>Hello, world!</p>
//! {% endblock %}
//! ```
//!
//! The `extends` tag tells the code generator that this template inherits
//! from another template. It will render the top-level content from the
//! base template, and substitute blocks from the base template with those
//! from the child template. The inheriting template context `struct` must
//! have a field called `_parent` of the type used as the base template
//! context. Blocks can only refer to the context of their own template.
//!
//! ## HTML escaping
//!
//! Askama does not yet support automatic escaping. Care must be taken to
//! escape content that may contain HTML control characters. You can use
//! the `escape` filter (or its `e` alias) to escape data for use in HTML.
//!
//! ## Control structures
//!
//! ### For
//!
//! Loop over each item in an iterator. For example:
//!
//! ```text
//! <h1>Users</h1>
//! <ul>
//! {% for user in users %}
//!   <li>{{ user.name|e }}</li>
//! {% endfor %}
//! </ul>
//! ```
//!
//! Inside for-loop blocks, some useful variables are accessible:
//!
//! * *loop.index*: current loop iteration (starting from 1)
//! * *loop.index0*: current loop iteration (starting from 0)
//!
//! ### If
//!
//! The *if* statement is used as you might expect:
//!
//! ```text
//! {% if users.len() == 0 %}
//!   No users
//! {% else if users.len() == 1 %}
//!   1 user
//! {% else %}
//!   {{ users.len() }} users
//! {% endif %}
//! ```
//!
//! ## Expressions
//!
//! Askama supports string literals (`"foo"`) and integer literals (`1`).
//! It supports almost all binary operators that Rust supports,
//! including arithmetic, comparison and logic operators.
//! The same precedence order as Rust uses is applied.
//! Expressions can be grouped using parentheses.

#[macro_use]
extern crate nom;
extern crate syn;

/// Main `Template` trait; implementations are generally derived
pub trait Template {
    /// Renders the template to the given `writer` buffer
    fn render_to(&self, writer: &mut std::fmt::Write);
    /// Helper method which allocates a new `String` and renders into it
    fn render(&self) -> String {
        let mut buf = String::new();
        self.render_to(&mut buf);
        buf
    }
}

mod generator;
mod parser;
mod path;

pub mod filters;
pub use path::rerun_if_templates_changed;

// Holds metadata for the template, based on the `template()` attribute.
struct TemplateMeta {
    path: String,
    print: String,
}

// Returns a `TemplateMeta` based on the `template()` attribute data found
// in the parsed struct or enum. Will panic if it does not find the required
// template path, or if the `print` key has an unexpected value.
fn get_template_meta(ast: &syn::DeriveInput) -> TemplateMeta {
    let mut path = None;
    let mut print = "none".to_string();
    let attr = ast.attrs.iter().find(|a| a.name() == "template").unwrap();
    if let syn::MetaItem::List(_, ref inner) = attr.value {
        for nm_item in inner {
            if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
                if let syn::MetaItem::NameValue(ref key, ref val) = *item {
                    match key.as_ref() {
                        "path" => if let syn::Lit::Str(ref s, _) = *val {
                            path = Some(s.clone());
                        } else {
                            panic!("template path must be string literal");
                        },
                        "print" => if let syn::Lit::Str(ref s, _) = *val {
                            print = s.clone();
                        } else {
                            panic!("print value must be string literal");
                        },
                        _ => { panic!("unsupported annotation key found") }
                    }
                }
            }
        }
    }
    if path.is_none() {
        panic!("template path not found in struct attributes");
    }
    TemplateMeta { path: path.unwrap(), print: print }
}

/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
pub fn build_template(ast: &syn::DeriveInput) -> String {
    let meta = get_template_meta(ast);
    let mut src = path::get_template_source(&meta.path);
    if src.ends_with('\n') {
        let _ = src.pop();
    }
    let nodes = parser::parse(&src);
    if meta.print == "ast" || meta.print == "all" {
        println!("{:?}", nodes);
    }
    let code = generator::generate(ast, &meta.path, nodes);
    if meta.print == "code" || meta.print == "all" {
        println!("{}", code);
    }
    code
}
<|endoftext|>


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

use font::UsedFontStyle;
use platform::font::FontHandle;
use font_context::FontContextHandleMethods;
use platform::font_list::path_from_identifier;

use freetype::freetype::{FTErrorMethods, FT_Library};
use freetype::freetype::{FT_Done_FreeType, FT_Init_FreeType};

use std::ptr;

#[deriving(Clone)]
struct FreeTypeLibraryHandle {
    ctx: FT_Library,
}

// FIXME(ksh8281) this value have to use atomic operation for counting ref
static mut font_context_ref_count: uint = 0;
static mut ft_pointer: Option<FT_Library> = None;
pub struct FontContextHandle {
    ctx: FreeTypeLibraryHandle,
}

impl Drop for FontContextHandle {
    #[fixed_stack_segment]
    fn drop(&mut self) {
        assert!(self.ctx.ctx.is_not_null());
        unsafe {
            assert!(font_context_ref_count >= 1);
            font_context_ref_count = font_context_ref_count - 1;
            if font_context_ref_count == 0 {
                FT_Done_FreeType(self.ctx.ctx);
            }
        }
    }
}

impl FontContextHandle {
    #[fixed_stack_segment]
    pub fn new() -> FontContextHandle {
        unsafe {
            match ft_pointer {
                Some(ref ctx) => {
                    font_context_ref_count = font_context_ref_count + 1;
                    FontContextHandle {
                        ctx: FreeTypeLibraryHandle { ctx: ctx.clone() },
                    }
                },
                None => {
                    let ctx: FT_Library = ptr::null();
                    let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
                    if !result.succeeded() { fail!("Unable to initialize FreeType library"); }
                    ft_pointer = Some(ctx);
                    font_context_ref_count = font_context_ref_count + 1;
                    FontContextHandle {
                        ctx: FreeTypeLibraryHandle { ctx: ctx },
                    }
                }
            }
        }
    }
}

impl FontContextHandleMethods for FontContextHandle {
    fn clone(&self) -> FontContextHandle {
        unsafe {
            font_context_ref_count = font_context_ref_count + 1;
            FontContextHandle {
                ctx: self.ctx.clone()
            }
        }
    }

    fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle)
                                -> Result<FontHandle, ()> {
        debug!("Creating font handle for {:s}", name);
        do path_from_identifier(name, &style).and_then |file_name| {
            debug!("Opening font face {:s}", file_name);
            FontHandle::new_from_file(self, file_name.to_owned(), &style)
        }
    }
}

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

use font::UsedFontStyle;
use platform::font::FontHandle;
use font_context::FontContextHandleMethods;
use platform::font_list::path_from_identifier;

use freetype::freetype::{FTErrorMethods, FT_Library};
use freetype::freetype::{FT_Done_FreeType, FT_Init_FreeType};

use std::ptr;
use extra::arc::Arc;

#[deriving(Clone)]
struct FreeTypeLibraryHandle {
    ctx: FT_Library,
}

pub struct FontContextHandle {
    ctx: Arc<FreeTypeLibraryHandle>,
}

impl Drop for FreeTypeLibraryHandle {
    #[fixed_stack_segment]
    fn drop(&mut self) {
        assert!(self.ctx.is_not_null());
        unsafe { FT_Done_FreeType(self.ctx) };
    }
}

impl FontContextHandle {
    #[fixed_stack_segment]
    pub fn new() -> FontContextHandle {
        unsafe {
            let ctx: FT_Library = ptr::null();
            let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
            if !result.succeeded() { fail!("Unable to initialize FreeType library"); }
            FontContextHandle {
                ctx: Arc::new(FreeTypeLibraryHandle { ctx: ctx }),
            }
        }
    }
}

impl FontContextHandleMethods for FontContextHandle {
    fn clone(&self) -> FontContextHandle {
        FontContextHandle {
            ctx: self.ctx.clone()
        }
    }

    fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle)
                                -> Result<FontHandle, ()> {
        debug!("Creating font handle for {:s}", name);
        do path_from_identifier(name, &style).and_then |file_name| {
            debug!("Opening font face {:s}", file_name);
            FontHandle::new_from_file(self, file_name.to_owned(), &style)
        }
    }
}

<|endoftext|>


<commit_before>extern "C" {
    pub fn strfmon(s: *mut ::char_t, max: ::size_t, format: *const ::char_t,
                   ...) -> ::ssize_t;
    pub fn strfmon_l(s: *mut ::char_t, max: ::size_t, loc: ::locale::locale_t,
                     format: *const ::char_t, ...) -> ::ssize_t;
}
<commit_msg>monetary.h<commit_after>use {size_t, char_t, ssize_t};
use locale::{locale_t};

extern {
    pub fn strfmon(s: *mut char_t, max: size_t, format: *const char_t, ...) -> ssize_t;
    pub fn strfmon_l(s: *mut char_t, max: size_t, loc: locale_t, format: *const char_t,
                     ...) -> ssize_t;
}
<|endoftext|>


<commit_before>use chattium_oxide_lib::json::{FromJsonnable, ToJsonnable};
use chattium_oxide_lib::ChatMessage;
use hyper::server::{Handler, Request, Response};
use hyper::header::{ContentLength, ContentType, CacheControl, CacheDirective, ContentLanguage, Server, qitem};
use hyper::status::StatusCode;
use hyper::method::Method;
use hyper::LanguageTag;
use regex::Regex;
use time::strftime;
use std::collections::btree_map::BTreeMap;
use std::sync::RwLock;
use std::io::{Read, Write, stderr};

pub struct ClientHandler {
	messages  : RwLock<Vec<ChatMessage>>,
	message_id: RwLock<u64>,
}

impl ClientHandler {
	pub fn new() -> ClientHandler {
		ClientHandler{
			messages  : RwLock::new(Vec::new()),
			message_id: RwLock::new(1),
		}
	}

	fn compact(what: &str) -> String {
		let regices = [
			(Regex::new(r#"\s+"#).unwrap(), " "),
			(Regex::new(r#">\s<"#).unwrap(), "><"),
			(Regex::new(r#"\s/>"#).unwrap(), "/>"),
			(Regex::new(r#"\s?\{\s?"#).unwrap(), "{"),
			(Regex::new(r#"\s?\}\s?"#).unwrap(), "}"),
		];

		regices.iter().fold(what.to_string(), |curr, ref tpl| tpl.0.replace_all(&curr[..], &tpl.1[..]))
	}
}

impl Handler for ClientHandler {
	fn handle(&self, mut req: Request, mut res: Response) {
		let mut body = "".to_string();

		let mut reqbody = String::new();
		*res.status_mut() = match req.read_to_string(&mut reqbody) {
			Ok(_) =>
				match req.method {
					Method::Post =>
						match ChatMessage::from_json_string(&reqbody) {
							Ok(mut message) => {
								message.sender.fill_ip(req.remote_addr);
								message.fill_id(self.message_id.write().unwrap());
								println!("{}@{}: {} @ {} # {}", message.sender.name, req.remote_addr, message.value, strftime("%T", &message.time_posted).unwrap(),
								                                message.id);
								self.messages.write().unwrap().push(message);
								StatusCode::Ok
							},
							Err(error) => {
								let _ = stderr().write_fmt(format_args!("Couldn't process POSTed message from {}: {}\n", req.remote_addr, error));
								StatusCode::UnprocessableEntity
							},
						},
					Method::Get => {  // Web browser, probably
						println!("Serving {} HTML message to connect via client.", req.remote_addr);
						body = r#"<!DOCTYPE html>

						          	<title>chattium-oxide — please connect with chattium-oxide client</title>
						          	<meta charset="utf-8" />
						          	<meta name="application-name" content="chattium-oxide" />
						          	<meta name="author"           content="chattium-oxide server" />
						          	<meta name="description"      content="Please reconnect with chattium-oxide client" />
						          	<meta name="keywords"         content="chat,open source" />
						          	<meta name="robots"           content="index,follow" />

						          		What is Ч@O2?

						          		Ч@O2 (read: chattium oxide, as in: chemical compound) is a lightweight chat platform written in
						          		Rust with an aim for simplicity. Both the client and the
						          		server reside on GitHub.

						          		How do I connect to a Ч@O2 server?

						          		Just type in the exact URL of this page into the client, as this document is sent by the Ч@O2 server
						          		itself.

						          		Latest Windows and Ubuntu client binaries can be downloaded from the
						          		latest Ч@O2 client
						          		release page to connect to chat.

						          "#.to_string();
						res.headers_mut().set(ContentType::html());
						res.headers_mut().set(Server(concat!("chattium-oxide-server/", env!("CARGO_PKG_VERSION")).to_string()));
						res.headers_mut().set(ContentLanguage(vec![qitem(LanguageTag{
							language  : Some("en-GB".to_string()),
							extlangs  : vec![],
							script    : None,
							region    : None,
							variants  : vec![],
							extensions: BTreeMap::new(),
							privateuse: vec![],
						})]));
						res.headers_mut().set(CacheControl(vec![
							CacheDirective::Public,
							CacheDirective::MaxAge(60 * 60 * 24 * 7),
						]));
						StatusCode::Ok
					},
					Method::Trace => {
						match u64::from_json_string(&reqbody) {
							Ok(id) => {
								let messages = self.messages.read().unwrap();
								let msgs     = messages.iter().rev().take_while(|&m| m.id != id).collect::<Vec<&_>>()
								                       .iter().rev().map(|&m| m.clone()).collect::<Vec<_>>();
								match msgs.to_json_string() {
									Ok(msgs) => {
										body = msgs;
										StatusCode::Ok
									},
									Err(error) => {
										let _ = stderr().write_fmt(format_args!("Couldn't create a JSON response for {}: {}\n", req.remote_addr, error));
										body = "[]".to_string();  // Empty array
										StatusCode::Accepted
									},
								}
							},
							Err(error) => {
								let _ = stderr().write_fmt(format_args!("Couldn't process a TRACE message id ({:?}) from {}: {}\n", reqbody, req.remote_addr, error));
								StatusCode::UnprocessableEntity
							},
						}
					},
				  _ => StatusCode::ImATeapot,
				},
			Err(error) => {
				let _ = stderr().write_fmt(format_args!("Failed reading request from {}: {}\n", req.remote_addr, error));
				StatusCode::UnsupportedMediaType  // non-UTF-8
			},
		};

		res.headers_mut().set(ContentLength(body.len() as u64));
		if let Err(error) = res.start().unwrap().write_all(body.as_bytes()) {
			let _ = stderr().write_fmt(format_args!("Failed to respond to {}: {}", req.remote_addr, error));
		}
	}
}
<commit_msg>Compact and store HTML response<commit_after>use chattium_oxide_lib::json::{FromJsonnable, ToJsonnable};
use chattium_oxide_lib::ChatMessage;
use hyper::server::{Handler, Request, Response};
use hyper::header::{ContentLength, ContentType, CacheControl, CacheDirective, ContentLanguage, Server, qitem};
use hyper::status::StatusCode;
use hyper::method::Method;
use hyper::LanguageTag;
use regex::Regex;
use time::strftime;
use std::collections::btree_map::BTreeMap;
use std::sync::RwLock;
use std::io::{self, Read, Write, stderr};

pub struct ClientHandler {
	messages    : RwLock<Vec<ChatMessage>>,
	message_id  : RwLock<u64>,
	html_message: String,
}

impl ClientHandler {
	pub fn new() -> ClientHandler {
		ClientHandler{
			messages    : RwLock::new(Vec::new()),
			message_id  : RwLock::new(1),
			html_message: Self::compact(r##"<!DOCTYPE html>

			                                	<title>chattium-oxide — please connect with chattium-oxide client</title>
			                                	<meta charset="utf-8" />
			                                	<meta name="application-name" content="chattium-oxide" />
			                                	<meta name="author"           content="chattium-oxide server" />
			                                	<meta name="description"      content="Please reconnect with chattium-oxide client" />
			                                	<meta name="keywords"         content="chat,open source" />
			                                	<meta name="robots"           content="index,follow" />

			                                		What is Ч@O2?

			                                		Ч@O2 (read: chattium oxide, as in: chemical compound) is a lightweight chat
			                                		platform written in Rust with an aim for simplicity. Both the
			                                		client and the
			                                		server reside on
			                                		GitHub.

			                                		How do I connect to a Ч@O2 server?

			                                		Just type in the exact URL of this page into the client, as this document is sent by the
			                                		Ч@O2 server itself.

			                                		Latest Windows and Ubuntu client binaries can be downloaded from the
			                                		latest
			                                		Ч@O2 client release page to connect to chat.

			                                "##),
		}
	}

	fn compact(what: &str) -> String {
		let regices = [
			(Regex::new(r#"\s+"#).unwrap(), " "),
			(Regex::new(r#">\s<"#).unwrap(), "><"),
			(Regex::new(r#"\s/>"#).unwrap(), "/>"),
			(Regex::new(r#"\s?\{\s?"#).unwrap(), "{"),
			(Regex::new(r#"\s?\}\s?"#).unwrap(), "}"),
		];

		regices.iter().fold(what.to_string(), |curr, ref tpl| tpl.0.replace_all(&curr[..], &tpl.1[..]))
	}
}

impl Handler for ClientHandler {
	fn handle(&self, mut req: Request, mut res: Response) {
		let mut body_ref: Option<&String> = None;
		let mut body    : Option<String>  = None;

		let mut reqbody = String::new();
		*res.status_mut() = match req.read_to_string(&mut reqbody) {
			Ok(_) =>
				match req.method {
					Method::Post =>
						match ChatMessage::from_json_string(&reqbody) {
							Ok(mut message) => {
								message.sender.fill_ip(req.remote_addr);
								message.fill_id(self.message_id.write().unwrap());
								println!("{}@{}: {} @ {} # {}", message.sender.name, req.remote_addr, message.value, strftime("%T", &message.time_posted).unwrap(),
								                                message.id);
								self.messages.write().unwrap().push(message);
								StatusCode::Ok
							},
							Err(error) => {
								let _ = stderr().write_fmt(format_args!("Couldn't process POSTed message from {}: {}\n", req.remote_addr, error));
								StatusCode::UnprocessableEntity
							},
						},
					Method::Get => {  // Web browser, probably
						println!("Serving {} HTML message to connect via client.", req.remote_addr);
						body_ref = Some(&self.html_message);
						res.headers_mut().set(ContentType::html());
						res.headers_mut().set(Server(concat!("chattium-oxide-server/", env!("CARGO_PKG_VERSION")).to_string()));
						res.headers_mut().set(ContentLanguage(vec![qitem(LanguageTag{
							language  : Some("en-GB".to_string()),
							extlangs  : vec![],
							script    : None,
							region    : None,
							variants  : vec![],
							extensions: BTreeMap::new(),
							privateuse: vec![],
						})]));
						res.headers_mut().set(CacheControl(vec![
							CacheDirective::Public,
							CacheDirective::MaxAge(60 * 60 * 24 * 7),
						]));
						StatusCode::Ok
					},
					Method::Trace => {
						match u64::from_json_string(&reqbody) {
							Ok(id) => {
								let messages = self.messages.read().unwrap();
								let msgs     = messages.iter().rev().take_while(|&m| m.id != id).collect::<Vec<&_>>()
								                       .iter().rev().map(|&m| m.clone()).collect::<Vec<_>>();
								match msgs.to_json_string() {
									Ok(msgs) => {
										body = Some(msgs);
										StatusCode::Ok
									},
									Err(error) => {
										let _ = stderr().write_fmt(format_args!("Couldn't create a JSON response for {}: {}\n", req.remote_addr, error));
										body = Some("[]".to_string());  // Empty array
										StatusCode::Accepted
									},
								}
							},
							Err(error) => {
								let _ = stderr().write_fmt(format_args!("Couldn't process a TRACE message id ({:?}) from {}: {}\n", reqbody, req.remote_addr, error));
								StatusCode::UnprocessableEntity
							},
						}
					},
				  _ => StatusCode::ImATeapot,
				},
			Err(error) => {
				let _ = stderr().write_fmt(format_args!("Failed reading request from {}: {}\n", req.remote_addr, error));
				StatusCode::UnsupportedMediaType  // non-UTF-8
			},
		};

		let handle_error = |error: Result<(), io::Error>| {
			if let Err(error) = error {
				let _ = stderr().write_fmt(format_args!("Failed to respond to {}: {}", req.remote_addr, error));
			}
		};

		let reply = |body: &String| {
			res.headers_mut().set(ContentLength(body.len() as u64));
			handle_error(res.start().unwrap().write_all(body.as_bytes()));
		};

		match (body, body_ref) {
			(Some(body), _)     => reply(&body),
			(_, Some(ref body)) => reply(&body),
			(None, None)        => reply(&"".to_string()),
		}
	}
}
<|endoftext|>


<commit_before>use crate::prelude::*;

impl Uuid {
    /// Creates a random UUID.
    ///
    /// This uses the [`getrandom`] crate to utilise the operating system's RNG
    /// as the source of random numbers. If you'd like to use a custom generator,
    /// don't use this method: generate random bytes using your custom generator
    /// and pass them to the [`uuid::Builder::from_bytes`][from_bytes] function
    /// instead.
    ///
    /// Note that usage of this method requires the `v4` feature of this crate
    /// to be enabled.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Uuid;
    ///
    /// let uuid = Uuid::new_v4();
    /// ```
    ///
    /// [`getrandom`]: https://crates.io/crates/getrandom
    /// [from_bytes]: struct.Builder.html#method.from_bytes
    // TODO: change signature to support uuid's Error.
    pub fn new_v4() -> Result<Uuid, getrandom::Error> {
        let mut bytes = [0u8; 16];
        getrandom::getrandom(&mut bytes)?;

        let uuid = crate::Builder::from_bytes(bytes)
            .set_variant(Variant::RFC4122)
            .set_version(Version::Random)
            .build();
        Ok(uuid)
    }
}

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

    #[test]
    fn test_new() {
        let uuid = Uuid::new_v4().unwrap();

        assert_eq!(uuid.get_version(), Some(Version::Random));
        assert_eq!(uuid.get_variant(), Some(Variant::RFC4122));
    }

    #[test]
    fn test_get_version() {
        let uuid = Uuid::new_v4().unwrap();

        assert_eq!(uuid.get_version(), Some(Version::Random));
        assert_eq!(uuid.get_version_num(), 4)
    }
}
<commit_msg>un-breaking-change Uuid::new_v4<commit_after>use crate::prelude::*;

impl Uuid {
    /// Creates a random UUID.
    ///
    /// This uses the [`getrandom`] crate to utilise the operating system's RNG
    /// as the source of random numbers. If you'd like to use a custom
    /// generator, don't use this method: generate random bytes using your
    /// custom generator and pass them to the
    /// [`uuid::Builder::from_bytes`][from_bytes] function instead.
    ///
    /// Note that usage of this method requires the `v4` feature of this crate
    /// to be enabled.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Uuid;
    ///
    /// let uuid = Uuid::new_v4();
    /// ```
    ///
    /// [`getrandom`]: https://crates.io/crates/getrandom
    /// [from_bytes]: struct.Builder.html#method.from_bytes
    pub fn new_v4() -> Uuid {
        let mut bytes = [0u8; 16];
        getrandom::getrandom(&mut bytes).unwrap_or_else(|err| {
            // NB: getrandom::Error has no source; this is adequate display
            panic!("could not retreive random bytes for uuid: {}", err)
        });

        crate::Builder::from_bytes(bytes)
            .set_variant(Variant::RFC4122)
            .set_version(Version::Random)
            .build()
    }
}

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

    #[test]
    fn test_new() {
        let uuid = Uuid::new_v4();

        assert_eq!(uuid.get_version(), Some(Version::Random));
        assert_eq!(uuid.get_variant(), Some(Variant::RFC4122));
    }

    #[test]
    fn test_get_version() {
        let uuid = Uuid::new_v4();

        assert_eq!(uuid.get_version(), Some(Version::Random));
        assert_eq!(uuid.get_version_num(), 4)
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use instructions::Instruction;
const STACK_SIZE: usize = 256;
const REG_SIZE: usize = 16;

#[derive(Debug,PartialEq)]
enum VMErrorKind {
	StackError,
	ZeroDivision,
}
impl fmt::Debug for VM {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Registers: \n {:?} \n Stack Contents:\n {:?}", self.registers, self.stack)
	}
}

pub struct VM {
	stack: Vec<i32>,
	registers: [i32; REG_SIZE],
	ip: usize,
	running: bool,
	debug: bool,
}

impl VM {
	pub fn new() -> VM {
		VM { stack: Vec::with_capacity(STACK_SIZE), registers: [0; REG_SIZE], ip: 0, running: true, debug: true}
	}
	pub fn run(&mut self, program: Vec<Instruction>) {

		while self.running {
			let instruction = &program[self.ip];

			match self.eval(instruction) {
				Ok(_) => {},
				Err(e) => {

					println!("Registers: \n {:?}",self.registers);
					println!("Stack Contents:\n {:?}",self.stack);
					panic!("VMError: {:?} on ip {:?}",e, self.ip + 1);
				}
			}
			self.ip += 1;
		}
	}
	fn eval(&mut self, instruction: &Instruction) -> Result<(), VMErrorKind> {
		match instruction {
			&Instruction::OUT => {
				println!("{:?}", self.stack.last().unwrap() );
				Ok(())
			}
			&Instruction::PSH(value) => {
				self.stack.push(value);
				Ok(())
			}
			&Instruction::POP => {
				match self.stack.pop() {
					Some(val) => Ok(()),
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::ADD => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a + b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::SUB => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a - b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}

			}
			&Instruction::MUL => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a * b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::DIV => {

				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						if b == 0 {
							return Err(VMErrorKind::ZeroDivision)
						} else {
							self.stack.push(a / b);
						}
						Ok(())

					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::SET(register, value) => {
				self.registers[register as usize] = value;
				Ok(())
			}
			&Instruction::MOV(register1, register2) => {
				self.registers[register1 as usize] = self.registers[register2 as usize];
				Ok(())
			}
			&Instruction::LDR(register) => {
				self.stack.push(self.registers[register as usize] as i32 );
				Ok(())
			}
			&Instruction::STR(register) => {
				match self.stack.pop() {
					Some(value) => {
						self.registers[register as usize] = value;
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::JMP => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::JZ => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::JNZ => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::HLT => {
				self.running = false;
				Ok(())
			}
			&Instruction::NOP => {
				Ok(())
			}
		}
	}
}<commit_msg>vm tests<commit_after>use std::fmt;
use instructions::Instruction;
const STACK_SIZE: usize = 256;
const REG_SIZE: usize = 16;

#[derive(Debug,PartialEq)]
enum VMErrorKind {
	StackError,
	ZeroDivision,
}
impl fmt::Debug for VM {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Registers: \n {:?} \nStack Contents:\n {:?}", self.registers, self.stack)
	}
}

pub struct VM {
	stack: Vec<i32>,
	registers: [i32; REG_SIZE],
	ip: usize,
	running: bool,
	debug: bool,
}

impl VM {
	pub fn new() -> VM {
		VM { stack: Vec::with_capacity(STACK_SIZE), registers: [0; REG_SIZE], ip: 0, running: true, debug: true}
	}
	pub fn run(&mut self, program: Vec<Instruction>) {

		while self.running {
			let instruction = &program[self.ip];

			match self.eval(instruction) {
				Ok(_) => {},
				Err(e) => {
					println!("Registers: \n {:?}",self.registers);
					println!("Stack Contents:\n {:?}",self.stack);
					panic!("VMError: {:?} on ip {:?}", e, self.ip + 1);
				}
			}
			self.ip += 1;
		}
	}
	fn eval(&mut self, instruction: &Instruction) -> Result<(), VMErrorKind> {
		match instruction {
			&Instruction::OUT => {
				println!("{:?}", self.stack.last().unwrap() );
				Ok(())
			}
			&Instruction::PSH(value) => {
				self.stack.push(value);
				Ok(())
			}
			&Instruction::POP => {
				match self.stack.pop() {
					Some(val) => Ok(()),
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::ADD => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a + b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::SUB => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a - b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}

			}
			&Instruction::MUL => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a * b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::DIV => {

				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						if b == 0 {
							return Err(VMErrorKind::ZeroDivision)
						} else {
							self.stack.push(a / b);
						}
						Ok(())

					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::SET(register, value) => {
				self.registers[register as usize] = value;
				Ok(())
			}
			&Instruction::MOV(register1, register2) => {
				self.registers[register1 as usize] = self.registers[register2 as usize];
				Ok(())
			}
			&Instruction::LDR(register) => {
				self.stack.push(self.registers[register as usize] as i32 );
				Ok(())
			}
			&Instruction::STR(register) => {
				match self.stack.pop() {
					Some(value) => {
						self.registers[register as usize] = value;
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::JMP => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::JZ => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::JNZ => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::HLT => {
				self.running = false;
				Ok(())
			}
			&Instruction::NOP => {
				Ok(())
			}
		}
	}
}

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

	#[test]
	fn add() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::ADD, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &15);
	}
	#[test]
	fn sub() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::SUB, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &5);
	}
	#[test]
	fn mul() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::MUL, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &50);
	}
	#[test]
	fn div() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::DIV, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &2);
	}

	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn add_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::ADD, Instruction::HLT];
		vm.run(program);
		assert_eq!(vm.stack.last().unwrap(), &3);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn sub_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::SUB, Instruction::HLT];
		vm.run(program);
		assert_eq!(vm.stack.last().unwrap(), &3);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn mul_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::MUL, Instruction::HLT];
		vm.run(program);
		assert_eq!(vm.stack.last().unwrap(), &3);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn div_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::DIV, Instruction::HLT];
		vm.run(program);
		assert_eq!(vm.stack.last().unwrap(), &3);
	}
	#[test]
	#[should_panic(expected = "VMError: ZeroDivision on ip 3")]
	fn zerodivision() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(0),Instruction::PSH(10),Instruction::DIV, Instruction::HLT];
		vm.run(program);
		assert_eq!(vm.stack.last().unwrap(), &0);
	}
}

<|endoftext|>


<commit_before>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core_intrinsics,lang_items)]

extern crate hotel;
extern crate hil;
extern crate support;

pub struct Firestorm;

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            use core::mem::transmute;
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

const LED : u32 = 0;
const LED_GPIO : u16 = 1;

pub unsafe fn init<'a>() -> &'a mut Firestorm {

    use core::intrinsics::volatile_store;

    // Turn on GPIO clocks
    let pmu_periclockset0 : *mut u32 = 0x40000064 as *mut u32;
    volatile_store(pmu_periclockset0, 1 << 8);

    // Driver DIOM4 from GPIO0_0
    let pinmux_diom4_sel : *mut u16 = 0x40060020 as *mut u16;
    volatile_store(pinmux_diom4_sel, LED_GPIO);

    // Enable output on GPIO0_0
    let gpio0_outen : *mut u32 = 0x40200010 as *mut u32;
    volatile_store(gpio0_outen, 1 << LED);

    // Set GPIO0_0
    let gpio0_out : *mut u32 = 0x40200004 as *mut u32;
    volatile_store(gpio0_out, 1 << LED);

    loop {
        for _ in 0..3000000 {
            support::nop();
        }
        volatile_store(gpio0_out, 0 << LED);
        for _ in 0..3000000 {
            support::nop();
        }
        volatile_store(gpio0_out, 1 << LED);
    }

    static_init!(firestorm : Firestorm = Firestorm);
    firestorm
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        // FIXME: The wfi call from main() blocks forever if no interrupts are generated. For now,
        // pretend we have interrupts to avoid blocking.
        true
    }

    #[inline(never)]
    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {
        match driver_num {
            //1 => f(Some(self.gpio)),
            _ => f(None)
        }
    }
}

use core::fmt::Arguments;
#[cfg(not(test))]
#[lang="panic_fmt"]
#[no_mangle]
pub unsafe extern fn rust_begin_unwind(_args: &Arguments,
    _file: &'static str, _line: usize) -> ! {
    loop {}
}
<commit_msg>Tango: print string over UART<commit_after>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core_intrinsics,lang_items)]

extern crate hotel;
extern crate hil;
extern crate support;

pub struct Firestorm;

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            use core::mem::transmute;
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

const LED : u32 = 0;
const LED_GPIO : u16 = 1;

pub unsafe fn init<'a>() -> &'a mut Firestorm {
    use core::intrinsics::{volatile_load,volatile_store};

    /* ********************
     * UART
     * ********************/

    // Turn on UART0 clock
    let pmu_periclockset1 : *mut u32 = 0x4000006c as *mut u32;
    volatile_store(pmu_periclockset1, 1 << 5);

    // Drive DIOA0 from TX
    let pinmux_dioa0_sel : *mut u16 = 0x40060028 as *mut u16;
    volatile_store(pinmux_dioa0_sel, 70);

    // Setup baud rate
    let nco = 5300; // 2^20 * 115200 / 24000000
    let uart_nco : *mut u16 = 0x40600008 as *mut u16;
    volatile_store(uart_nco, nco);

    // Enable TX
    let uart_ctrl : *mut u16 = 0x4060000C as *mut u16;
    volatile_store(uart_ctrl, 1);

    unsafe fn write_char(c : char) {
        let uart_state : *mut u32 = 0x40600014 as *mut u32;
        let uart_wdata : *mut u8 = 0x40600004 as *mut u8;

        while volatile_load(uart_state) & 1 != 0 {}

        volatile_store(uart_wdata, c as u8);
    }

    unsafe fn write_str(s : &str) {
        for c in s.chars() {
            write_char(c);
        }
    }

    write_str("Hello from Rust!\n");

    /* ********************
     * Blink
     * ********************/

    // Turn on GPIO clocks
    let pmu_periclockset0 : *mut u32 = 0x40000064 as *mut u32;
    volatile_store(pmu_periclockset0, 1 << 8);

    // Driver DIOM4 from GPIO0_0
    let pinmux_diom4_sel : *mut u16 = 0x40060020 as *mut u16;
    volatile_store(pinmux_diom4_sel, LED_GPIO);

    // Enable output on GPIO0_0
    let gpio0_outen : *mut u32 = 0x40200010 as *mut u32;
    volatile_store(gpio0_outen, 1 << LED);

    // Set GPIO0_0
    let gpio0_out : *mut u32 = 0x40200004 as *mut u32;
    volatile_store(gpio0_out, 1 << LED);

    loop {
        for _ in 0..3000000 {
            support::nop();
        }
        volatile_store(gpio0_out, 0 << LED);
        for _ in 0..3000000 {
            support::nop();
        }
        volatile_store(gpio0_out, 1 << LED);
    }

    static_init!(firestorm : Firestorm = Firestorm);
    firestorm
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        // FIXME: The wfi call from main() blocks forever if no interrupts are generated. For now,
        // pretend we have interrupts to avoid blocking.
        true
    }

    #[inline(never)]
    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {
        match driver_num {
            //1 => f(Some(self.gpio)),
            _ => f(None)
        }
    }
}

use core::fmt::Arguments;
#[cfg(not(test))]
#[lang="panic_fmt"]
#[no_mangle]
pub unsafe extern fn rust_begin_unwind(_args: &Arguments,
    _file: &'static str, _line: usize) -> ! {
    loop {}
}
<|endoftext|>


<commit_before>use std::fmt;
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use std::collections::HashMap;

extern crate rustc_serialize;
use self::rustc_serialize::json::{as_json, Json, Object};

#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
pub struct Location {
    pub lineno: u32,
    pub col_start: u32,
    pub col_end: u32,
}

impl fmt::Display for Location {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        if self.col_start == self.col_end {
            write!(formatter, r#""loc":"{:05}:{}""#, self.lineno, self.col_start)
        } else {
            write!(formatter, r#""loc":"{:05}:{}-{}""#, self.lineno, self.col_start, self.col_end)
        }
    }
}

#[derive(Eq, PartialEq, PartialOrd, Ord, Debug)]
pub struct LineRange {
    pub start_lineno: u32,
    pub end_lineno: u32,
}

#[derive(Debug)]
pub struct WithLocation<T> {
    pub data: T,
    pub loc: Location,
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum AnalysisKind {
    Use,
    Def,
    Assign,
    Decl,
    Idl,
}

impl fmt::Display for AnalysisKind {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            AnalysisKind::Use => "use",
            AnalysisKind::Def => "def",
            AnalysisKind::Assign => "assign",
            AnalysisKind::Decl => "decl",
            AnalysisKind::Idl => "idl",
        };
        formatter.write_str(str)
    }
}

#[derive(Debug)]
pub struct AnalysisTarget {
    pub kind: AnalysisKind,
    pub pretty: String,
    pub sym: String,
    pub context: String,
    pub contextsym: String,
    pub peek_range: LineRange,
}

impl fmt::Display for AnalysisTarget {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter,
               r#""target":1,"kind":"{}","pretty":{},"sym":{}"#,
               self.kind,
               as_json(&self.pretty),
               as_json(&self.sym))?;
        if !self.context.is_empty() {
            write!(formatter, r#","context":{}"#, as_json(&self.context))?;
        }
        if !self.contextsym.is_empty() {
            write!(formatter, r#","contextsym":{}"#, as_json(&self.contextsym))?;
        }
        if self.peek_range.start_lineno != 0 || self.peek_range.end_lineno != 0 {
            write!(formatter,
                   r#","peekRange":"{}-{}""#,
                   self.peek_range.start_lineno,
                   self.peek_range.end_lineno)?;
        }
        Ok(())
    }
}

impl fmt::Display for WithLocation<AnalysisTarget> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{{{},{}}}", self.loc, self.data)
    }
}

#[derive(Debug)]
pub struct AnalysisSource {
    pub syntax: Vec<String>,
    pub pretty: String,
    pub sym: Vec<String>,
    pub no_crossref: bool,
}

impl AnalysisSource {
    /// Merges the `syntax` and `sym` fields from `other` into `self`.
    /// Also asserts that the `pretty` and `no_crossref` fields are
    /// the same because otherwise the merge doesn't really make sense.
    pub fn merge(&mut self, mut other: AnalysisSource) {
        assert_eq!(self.pretty, other.pretty);
        assert_eq!(self.no_crossref, other.no_crossref);
        self.syntax.append(&mut other.syntax);
        self.syntax.sort();
        self.syntax.dedup();
        self.sym.append(&mut other.sym);
        self.sym.sort();
        self.sym.dedup();
    }
}

impl fmt::Display for AnalysisSource {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter,
               r#""source":1,"syntax":{},"pretty":{},"sym":{}"#,
               as_json(&self.syntax.join(",")),
               as_json(&self.pretty),
               as_json(&self.sym.join(",")))?;
        if self.no_crossref {
            write!(formatter, r#","no_crossref":1"#)?;
        }
        Ok(())
    }
}

impl fmt::Display for WithLocation<AnalysisSource> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{{{},{}}}", self.loc, self.data)
    }
}

impl fmt::Display for WithLocation<Vec<AnalysisSource>> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let locstr = format!("{}", self.loc);
        for src in &self.data {
            writeln!(formatter, "{{{},{}}}", locstr, src)?;
        }
        Ok(())
    }
}

pub fn parse_location(loc: &str) -> Location {
    let v : Vec<&str> = loc.split(":").collect();
    let lineno = v[0].parse::<u32>().unwrap();
    let (col_start, col_end) = if v[1].contains("-") {
        let v : Vec<&str> = v[1].split("-").collect();
        (v[0], v[1])
    } else {
        (v[1], v[1])
    };
    let col_start = col_start.parse::<u32>().unwrap();
    let col_end = col_end.parse::<u32>().unwrap();
    Location { lineno: lineno, col_start: col_start, col_end: col_end }
}

fn parse_line_range(range: &str) -> LineRange {
    let v : Vec<&str> = range.split("-").collect();
    let start_lineno = v[0].parse::<u32>().unwrap();
    let end_lineno = v[1].parse::<u32>().unwrap();
    LineRange { start_lineno: start_lineno, end_lineno: end_lineno }
}

pub fn read_analysis<T>(filename: &str, filter: &mut FnMut(&Object) -> Option<T>) -> Vec<WithLocation<Vec<T>>> {
    read_analyses(&vec![filename], filter)
}

pub fn read_analyses<T>(filenames: &[&str], filter: &mut FnMut(&Object) -> Option<T>) -> Vec<WithLocation<Vec<T>>> {
    let mut result = Vec::new();
    for filename in filenames {
        let file = match File::open(filename) {
            Ok(f) => f,
            Err(_) => continue,
        };
        let reader = BufReader::new(&file);
        let mut lineno = 0;
        for line in reader.lines() {
            let line = line.unwrap();
            lineno += 1;
            let data = Json::from_str(&line);
            let data = match data {
                Ok(data) => data,
                Err(e) => {
                    warn!("Error [{}] trying to read analysis from file [{}] line [{}]: [{}]", e, filename, lineno, &line);
                    continue;
                }
            };
            let obj = data.as_object().unwrap();
            match filter(obj) {
                Some(v) => {
                    let loc = parse_location(obj.get("loc").unwrap().as_string().unwrap());
                    result.push(WithLocation { data: v, loc: loc })
                }
                None => {}
            }
        }
    }

    result.sort_by(|x1, x2| {
        x1.loc.cmp(&x2.loc)
    });

    let mut result2 = Vec::new();
    let mut last_loc = None;
    let mut last_vec = Vec::new();
    for r in result {
        match last_loc {
            Some(ll) => {
                if ll == r.loc {
                    last_loc = Some(ll);
                } else {
                    result2.push(WithLocation { loc: ll, data: last_vec });
                    last_vec = Vec::new();
                    last_loc = Some(r.loc);
                }
            },
            None => {
                last_loc = Some(r.loc);
            }
        }
        last_vec.push(r.data);
    }

    match last_loc {
        Some(ll) => result2.push(WithLocation { loc: ll, data: last_vec }),
        None => {},
    }

    result2
}

pub fn read_target(obj : &Object) -> Option<AnalysisTarget> {
    if !obj.contains_key("target") {
        return None;
    }

    let kindstr = obj.get("kind").unwrap().as_string().unwrap();
    let kind = match kindstr {
        "use" => AnalysisKind::Use,
        "def" => AnalysisKind::Def,
        "assign" => AnalysisKind::Assign,
        "decl" => AnalysisKind::Decl,
        "idl" => AnalysisKind::Idl,
        _ => panic!("bad target kind")
    };

    let pretty = match obj.get("pretty") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let context = match obj.get("context") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let contextsym = match obj.get("contextsym") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let peek_range = match obj.get("peekRange") {
        Some(json) => parse_line_range(json.as_string().unwrap()),
        None => LineRange { start_lineno: 0, end_lineno: 0 }
    };
    let sym = obj.get("sym").unwrap().as_string().unwrap().to_string();

    Some(AnalysisTarget { kind: kind, pretty: pretty, sym: sym, context: context,
                          contextsym: contextsym, peek_range: peek_range })
}

pub fn read_source(obj : &Object) -> Option<AnalysisSource> {
    if !obj.contains_key("source") {
        return None;
    }

    let syntax = match obj.get("syntax") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let mut syntax : Vec<String> = syntax.split(',').map(str::to_string).collect();
    syntax.sort();
    syntax.dedup();

    let pretty = match obj.get("pretty") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let mut sym : Vec<String> = obj.get("sym").unwrap().as_string().unwrap().to_string().split(',').map(str::to_string).collect();
    sym.sort();
    sym.dedup();

    let no_crossref = match obj.get("no_crossref") {
        Some(_) => true,
        None => false,
    };

    Some(AnalysisSource { pretty: pretty, sym: sym, syntax: syntax, no_crossref: no_crossref })
}

pub struct Jump {
    pub id: String,
    pub path: String,
    pub lineno: u64,
    pub pretty: String,
}

pub fn read_jumps(filename: &str) -> HashMap<String, Jump> {
    let file = File::open(filename).unwrap();
    let reader = BufReader::new(&file);
    let mut result = HashMap::new();
    let mut lineno = 1;
    for line in reader.lines() {
        let line = line.unwrap();
        let data = Json::from_str(&line);
        let data = match data {
            Ok(data) => data,
            Err(_) => panic!("error on line {}: {}", lineno, &line),
        };
        lineno += 1;

        let array = data.as_array().unwrap();
        let id = array[0].as_string().unwrap().to_string();
        let data = Jump {
            id: id.clone(),
            path: array[1].as_string().unwrap().to_string(),
            lineno: array[2].as_u64().unwrap(),
            pretty: array[3].as_string().unwrap().to_string(),
        };

        result.insert(id, data);
    }
    result
}
<commit_msg>Bug 1503547 - Allow merging records with different no_crossref values<commit_after>use std::fmt;
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use std::collections::HashMap;

extern crate rustc_serialize;
use self::rustc_serialize::json::{as_json, Json, Object};

#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
pub struct Location {
    pub lineno: u32,
    pub col_start: u32,
    pub col_end: u32,
}

impl fmt::Display for Location {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        if self.col_start == self.col_end {
            write!(formatter, r#""loc":"{:05}:{}""#, self.lineno, self.col_start)
        } else {
            write!(formatter, r#""loc":"{:05}:{}-{}""#, self.lineno, self.col_start, self.col_end)
        }
    }
}

#[derive(Eq, PartialEq, PartialOrd, Ord, Debug)]
pub struct LineRange {
    pub start_lineno: u32,
    pub end_lineno: u32,
}

#[derive(Debug)]
pub struct WithLocation<T> {
    pub data: T,
    pub loc: Location,
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum AnalysisKind {
    Use,
    Def,
    Assign,
    Decl,
    Idl,
}

impl fmt::Display for AnalysisKind {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let str = match self {
            AnalysisKind::Use => "use",
            AnalysisKind::Def => "def",
            AnalysisKind::Assign => "assign",
            AnalysisKind::Decl => "decl",
            AnalysisKind::Idl => "idl",
        };
        formatter.write_str(str)
    }
}

#[derive(Debug)]
pub struct AnalysisTarget {
    pub kind: AnalysisKind,
    pub pretty: String,
    pub sym: String,
    pub context: String,
    pub contextsym: String,
    pub peek_range: LineRange,
}

impl fmt::Display for AnalysisTarget {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter,
               r#""target":1,"kind":"{}","pretty":{},"sym":{}"#,
               self.kind,
               as_json(&self.pretty),
               as_json(&self.sym))?;
        if !self.context.is_empty() {
            write!(formatter, r#","context":{}"#, as_json(&self.context))?;
        }
        if !self.contextsym.is_empty() {
            write!(formatter, r#","contextsym":{}"#, as_json(&self.contextsym))?;
        }
        if self.peek_range.start_lineno != 0 || self.peek_range.end_lineno != 0 {
            write!(formatter,
                   r#","peekRange":"{}-{}""#,
                   self.peek_range.start_lineno,
                   self.peek_range.end_lineno)?;
        }
        Ok(())
    }
}

impl fmt::Display for WithLocation<AnalysisTarget> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{{{},{}}}", self.loc, self.data)
    }
}

#[derive(Debug)]
pub struct AnalysisSource {
    pub syntax: Vec<String>,
    pub pretty: String,
    pub sym: Vec<String>,
    pub no_crossref: bool,
}

impl AnalysisSource {
    /// Merges the `syntax`, `sym`, and `no_crossref` fields from `other`
    /// into `self`. The `no_crossref` field can be different sometimes
    /// with different versions of clang being used across different
    /// platforms; in this case we only set `no_crossref` if all the versions
    /// being merged have the `no_crossref` field set.
    /// Also asserts that the `pretty` field is the same because otherwise
    /// the merge doesn't really make sense.
    pub fn merge(&mut self, mut other: AnalysisSource) {
        assert_eq!(self.pretty, other.pretty);
        self.no_crossref &= other.no_crossref;
        self.syntax.append(&mut other.syntax);
        self.syntax.sort();
        self.syntax.dedup();
        self.sym.append(&mut other.sym);
        self.sym.sort();
        self.sym.dedup();
    }
}

impl fmt::Display for AnalysisSource {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter,
               r#""source":1,"syntax":{},"pretty":{},"sym":{}"#,
               as_json(&self.syntax.join(",")),
               as_json(&self.pretty),
               as_json(&self.sym.join(",")))?;
        if self.no_crossref {
            write!(formatter, r#","no_crossref":1"#)?;
        }
        Ok(())
    }
}

impl fmt::Display for WithLocation<AnalysisSource> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{{{},{}}}", self.loc, self.data)
    }
}

impl fmt::Display for WithLocation<Vec<AnalysisSource>> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let locstr = format!("{}", self.loc);
        for src in &self.data {
            writeln!(formatter, "{{{},{}}}", locstr, src)?;
        }
        Ok(())
    }
}

pub fn parse_location(loc: &str) -> Location {
    let v : Vec<&str> = loc.split(":").collect();
    let lineno = v[0].parse::<u32>().unwrap();
    let (col_start, col_end) = if v[1].contains("-") {
        let v : Vec<&str> = v[1].split("-").collect();
        (v[0], v[1])
    } else {
        (v[1], v[1])
    };
    let col_start = col_start.parse::<u32>().unwrap();
    let col_end = col_end.parse::<u32>().unwrap();
    Location { lineno: lineno, col_start: col_start, col_end: col_end }
}

fn parse_line_range(range: &str) -> LineRange {
    let v : Vec<&str> = range.split("-").collect();
    let start_lineno = v[0].parse::<u32>().unwrap();
    let end_lineno = v[1].parse::<u32>().unwrap();
    LineRange { start_lineno: start_lineno, end_lineno: end_lineno }
}

pub fn read_analysis<T>(filename: &str, filter: &mut FnMut(&Object) -> Option<T>) -> Vec<WithLocation<Vec<T>>> {
    read_analyses(&vec![filename], filter)
}

pub fn read_analyses<T>(filenames: &[&str], filter: &mut FnMut(&Object) -> Option<T>) -> Vec<WithLocation<Vec<T>>> {
    let mut result = Vec::new();
    for filename in filenames {
        let file = match File::open(filename) {
            Ok(f) => f,
            Err(_) => continue,
        };
        let reader = BufReader::new(&file);
        let mut lineno = 0;
        for line in reader.lines() {
            let line = line.unwrap();
            lineno += 1;
            let data = Json::from_str(&line);
            let data = match data {
                Ok(data) => data,
                Err(e) => {
                    warn!("Error [{}] trying to read analysis from file [{}] line [{}]: [{}]", e, filename, lineno, &line);
                    continue;
                }
            };
            let obj = data.as_object().unwrap();
            match filter(obj) {
                Some(v) => {
                    let loc = parse_location(obj.get("loc").unwrap().as_string().unwrap());
                    result.push(WithLocation { data: v, loc: loc })
                }
                None => {}
            }
        }
    }

    result.sort_by(|x1, x2| {
        x1.loc.cmp(&x2.loc)
    });

    let mut result2 = Vec::new();
    let mut last_loc = None;
    let mut last_vec = Vec::new();
    for r in result {
        match last_loc {
            Some(ll) => {
                if ll == r.loc {
                    last_loc = Some(ll);
                } else {
                    result2.push(WithLocation { loc: ll, data: last_vec });
                    last_vec = Vec::new();
                    last_loc = Some(r.loc);
                }
            },
            None => {
                last_loc = Some(r.loc);
            }
        }
        last_vec.push(r.data);
    }

    match last_loc {
        Some(ll) => result2.push(WithLocation { loc: ll, data: last_vec }),
        None => {},
    }

    result2
}

pub fn read_target(obj : &Object) -> Option<AnalysisTarget> {
    if !obj.contains_key("target") {
        return None;
    }

    let kindstr = obj.get("kind").unwrap().as_string().unwrap();
    let kind = match kindstr {
        "use" => AnalysisKind::Use,
        "def" => AnalysisKind::Def,
        "assign" => AnalysisKind::Assign,
        "decl" => AnalysisKind::Decl,
        "idl" => AnalysisKind::Idl,
        _ => panic!("bad target kind")
    };

    let pretty = match obj.get("pretty") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let context = match obj.get("context") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let contextsym = match obj.get("contextsym") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let peek_range = match obj.get("peekRange") {
        Some(json) => parse_line_range(json.as_string().unwrap()),
        None => LineRange { start_lineno: 0, end_lineno: 0 }
    };
    let sym = obj.get("sym").unwrap().as_string().unwrap().to_string();

    Some(AnalysisTarget { kind: kind, pretty: pretty, sym: sym, context: context,
                          contextsym: contextsym, peek_range: peek_range })
}

pub fn read_source(obj : &Object) -> Option<AnalysisSource> {
    if !obj.contains_key("source") {
        return None;
    }

    let syntax = match obj.get("syntax") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let mut syntax : Vec<String> = syntax.split(',').map(str::to_string).collect();
    syntax.sort();
    syntax.dedup();

    let pretty = match obj.get("pretty") {
        Some(json) => json.as_string().unwrap().to_string(),
        None => "".to_string()
    };
    let mut sym : Vec<String> = obj.get("sym").unwrap().as_string().unwrap().to_string().split(',').map(str::to_string).collect();
    sym.sort();
    sym.dedup();

    let no_crossref = match obj.get("no_crossref") {
        Some(_) => true,
        None => false,
    };

    Some(AnalysisSource { pretty: pretty, sym: sym, syntax: syntax, no_crossref: no_crossref })
}

pub struct Jump {
    pub id: String,
    pub path: String,
    pub lineno: u64,
    pub pretty: String,
}

pub fn read_jumps(filename: &str) -> HashMap<String, Jump> {
    let file = File::open(filename).unwrap();
    let reader = BufReader::new(&file);
    let mut result = HashMap::new();
    let mut lineno = 1;
    for line in reader.lines() {
        let line = line.unwrap();
        let data = Json::from_str(&line);
        let data = match data {
            Ok(data) => data,
            Err(_) => panic!("error on line {}: {}", lineno, &line),
        };
        lineno += 1;

        let array = data.as_array().unwrap();
        let id = array[0].as_string().unwrap().to_string();
        let data = Jump {
            id: id.clone(),
            path: array[1].as_string().unwrap().to_string(),
            lineno: array[2].as_u64().unwrap(),
            pretty: array[3].as_string().unwrap().to_string(),
        };

        result.insert(id, data);
    }
    result
}
<|endoftext|>


<commit_before>mod mtl_device;

pub use self::mtl_device::MTLDevice;
<commit_msg>Re-export Block types<commit_after>mod mtl_device;

pub use self::mtl_device::MTLDevice;
pub use self::mtl_device::{MTLNewComputePipelineStateCompletionHandler,
                           MTLNewComputePipelineStateWithReflectionCompletionHandler, MTLNewLibraryCompletionHandler,
                           MTLNewRenderPipelineStateWithReflectionCompletionHandler,
                           MTLNewRenderPipleineStateCompletionHandler};
<|endoftext|>


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

use self::InternalDebugLocation::*;

use super::utils::{debug_context, span_start};
use super::metadata::UNKNOWN_COLUMN_NUMBER;
use super::FunctionDebugContext;

use llvm;
use llvm::debuginfo::DIScope;
use builder::Builder;

use libc::c_uint;
use std::ptr;
use syntax_pos::{Span, Pos};

/// Sets the current debug location at the beginning of the span.
///
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...).
pub fn set_source_location(
    debug_context: &FunctionDebugContext, bx: &Builder, scope: DIScope, span: Span
) {
    let function_debug_context = match *debug_context {
        FunctionDebugContext::DebugInfoDisabled => return,
        FunctionDebugContext::FunctionWithoutDebugInfo => {
            set_debug_location(bx, UnknownLocation);
            return;
        }
        FunctionDebugContext::RegularContext(ref data) => data
    };

    let dbg_loc = if function_debug_context.source_locations_enabled.get() {
        debug!("set_source_location: {}", bx.sess().codemap().span_to_string(span));
        let loc = span_start(bx.cx, span);
        InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
    } else {
        UnknownLocation
    };
    set_debug_location(bx, dbg_loc);
}

/// Enables emitting source locations for the given functions.
///
/// Since we don't want source locations to be emitted for the function prelude,
/// they are disabled when beginning to codegen a new function. This functions
/// switches source location emitting on and must therefore be called before the
/// first real statement/expression of the function is codegened.
pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) {
    match *dbg_context {
        FunctionDebugContext::RegularContext(ref data) => {
            data.source_locations_enabled.set(true)
        },
        _ => { /* safe to ignore */ }
    }
}

#[derive(Copy, Clone, PartialEq)]
pub enum InternalDebugLocation {
    KnownLocation { scope: DIScope, line: usize, col: usize },
    UnknownLocation
}

impl InternalDebugLocation {
    pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
        KnownLocation {
            scope,
            line,
            col,
        }
    }
}

pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
    let metadata_node = match debug_location {
        KnownLocation { scope, line, .. } => {
            // Always set the column to zero like Clang and GCC
            let col = UNKNOWN_COLUMN_NUMBER;
            debug!("setting debug location to {} {}", line, col);

            unsafe {
                llvm::LLVMRustDIBuilderCreateDebugLocation(
                    debug_context(bx.cx).llcontext,
                    line as c_uint,
                    col as c_uint,
                    scope,
                    ptr::null_mut())
            }
        }
        UnknownLocation => {
            debug!("clearing debug location ");
            ptr::null_mut()
        }
    };

    unsafe {
        llvm::LLVMSetCurrentDebugLocation(bx.llbuilder, metadata_node);
    }
}
<commit_msg>Emit column info in debuginfo for non msvc like targets<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use self::InternalDebugLocation::*;

use super::utils::{debug_context, span_start};
use super::metadata::UNKNOWN_COLUMN_NUMBER;
use super::FunctionDebugContext;

use llvm;
use llvm::debuginfo::DIScope;
use builder::Builder;

use libc::c_uint;
use std::ptr;
use syntax_pos::{Span, Pos};

/// Sets the current debug location at the beginning of the span.
///
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...).
pub fn set_source_location(
    debug_context: &FunctionDebugContext, bx: &Builder, scope: DIScope, span: Span
) {
    let function_debug_context = match *debug_context {
        FunctionDebugContext::DebugInfoDisabled => return,
        FunctionDebugContext::FunctionWithoutDebugInfo => {
            set_debug_location(bx, UnknownLocation);
            return;
        }
        FunctionDebugContext::RegularContext(ref data) => data
    };

    let dbg_loc = if function_debug_context.source_locations_enabled.get() {
        debug!("set_source_location: {}", bx.sess().codemap().span_to_string(span));
        let loc = span_start(bx.cx, span);
        InternalDebugLocation::new(scope, loc.line, loc.col.to_usize())
    } else {
        UnknownLocation
    };
    set_debug_location(bx, dbg_loc);
}

/// Enables emitting source locations for the given functions.
///
/// Since we don't want source locations to be emitted for the function prelude,
/// they are disabled when beginning to codegen a new function. This functions
/// switches source location emitting on and must therefore be called before the
/// first real statement/expression of the function is codegened.
pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) {
    match *dbg_context {
        FunctionDebugContext::RegularContext(ref data) => {
            data.source_locations_enabled.set(true)
        },
        _ => { /* safe to ignore */ }
    }
}

#[derive(Copy, Clone, PartialEq)]
pub enum InternalDebugLocation {
    KnownLocation { scope: DIScope, line: usize, col: usize },
    UnknownLocation
}

impl InternalDebugLocation {
    pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
        KnownLocation {
            scope,
            line,
            col,
        }
    }
}

pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) {
    let metadata_node = match debug_location {
        KnownLocation { scope, line, col } => {
            // For MSVC, set the column number to zero.
            // Otherwise, emit it. This mimics clang behaviour.
            // See discussion in https://github.com/rust-lang/rust/issues/42921
            let col_used =  if bx.cx.sess().target.target.options.is_like_msvc {
                UNKNOWN_COLUMN_NUMBER
            } else {
                col as c_uint
            };
            debug!("setting debug location to {} {}", line, col);

            unsafe {
                llvm::LLVMRustDIBuilderCreateDebugLocation(
                    debug_context(bx.cx).llcontext,
                    line as c_uint,
                    col_used,
                    scope,
                    ptr::null_mut())
            }
        }
        UnknownLocation => {
            debug!("clearing debug location ");
            ptr::null_mut()
        }
    };

    unsafe {
        llvm::LLVMSetCurrentDebugLocation(bx.llbuilder, metadata_node);
    }
}
<|endoftext|>


<commit_before>fn main() {
    loop {
        println!("Hello, world!");
        break;
    }

    let mut number = 3;
    while number != 0 {
        println!("{}", number);
        number = number - 1;
    }

    println!("LIFTOFF!!!");

    let a = [10, 20, 30, 40, 50];
    // both safety & no overhead compare to maintain index of
    // array by while
    for element in a.iter() {
        println!("the value is {}", element);
    }

    // for is most commonly used, replace while:
    for count in (1..4).rev() {
        println!("{}!", count);
    }
    println!("LIFTOFF!!!");

    for n in 1..10 {
        println!("fib {} is {}", n, fib(n));
    }
    let mut f_fib = make_fib();
    for n in 1..10 {
        println!("f_fib {} is {}", n, f_fib(n));
    }
    for n in 1..10 {
        println!("f_fib {} is {}", n, f_fib(n));
    }
}

fn fib(n: i32) -> i32 {
    let mut cur = 1;
    let mut nxt = 1;
    let mut res = 0;

    for _ in 0..n {
        res = cur;
        cur = nxt;
        nxt = res + nxt;
    }

    res
}

// Just a try before know anything about borrow
// help from compiler's hint
fn make_fib() -> Box<FnMut(i32) -> i32> {
    let mut rec = vec![1, 1];
    let mut sz = 2;
    Box::new(move |n| {
        if n <= sz {
            println!("hit!");
            rec[(n - 1) as usize]
        } else {
            println!("miss!");
            for i in sz..n {
                let p2 = rec[(i - 2) as usize];
                let p1 = rec[(i - 1) as usize];
                rec.push(p1 + p2);
                sz = sz + 1;
            }
            rec[(n - 1) as usize]
        }
    })
}
<commit_msg>Try directly return closure.<commit_after>fn main() {
    loop {
        println!("Hello, world!");
        break;
    }

    let mut number = 3;
    while number != 0 {
        println!("{}", number);
        number = number - 1;
    }

    println!("LIFTOFF!!!");

    let a = [10, 20, 30, 40, 50];
    // both safety & no overhead compare to maintain index of
    // array by while
    for element in a.iter() {
        println!("the value is {}", element);
    }

    // for is most commonly used, replace while:
    for count in (1..4).rev() {
        println!("{}!", count);
    }
    println!("LIFTOFF!!!");

    for n in 1..10 {
        println!("fib {} is {}", n, fib(n));
    }
    let mut f_fib = make_fib();
    for n in (1..10).rev() {
        println!("f_fib {} is {}", n, f_fib(n));
    }

    // let f_fib2 = make_fib2();
    // for n in (1..10).rev() {
    //     println!("f_fib2 {} is {}", n, f_fib2(n));
    // }
}

fn fib(n: i32) -> i32 {
    let mut cur = 1;
    let mut nxt = 1;
    let mut res = 0;

    for _ in 0..n {
        res = cur;
        cur = nxt;
        nxt = res + nxt;
    }

    res
}

// Just a try before know anything about borrow
// help from compiler's hint
fn make_fib() -> Box<FnMut(i32) -> i32> {
    let mut rec = vec![1, 1];
    let mut sz = 2;
    Box::new(move |n| {
        if n <= sz {
            println!("hit!");
            rec[(n - 1) as usize]
        } else {
            println!("miss!");
            for i in sz..n {
                let p2 = rec[(i - 2) as usize];
                let p1 = rec[(i - 1) as usize];
                rec.push(p1 + p2);
                sz = sz + 1;
            }
            rec[(n - 1) as usize]
        }
    })
}
/* will not compile. know not how much space to store closure
fn make_fib2() -> Fn(i32) -> i32 {
    let y = 0;
    |x| x + y
}
*/
<|endoftext|>