<commit_before>use std::path::PathBuf;

use crate::externalfiles::ExternalHtml;
use crate::html::render::ensure_trailing_slash;
use crate::html::format::{Buffer, Print};

#[derive(Clone)]
pub struct Layout {
    pub logo: String,
    pub favicon: String,
    pub external_html: ExternalHtml,
    pub krate: String,
    /// The given user css file which allow to customize the generated
    /// documentation theme.
    pub css_file_extension: Option<PathBuf>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    pub generate_search_filter: bool,
}

pub struct Page<'a> {
    pub title: &'a str,
    pub css_class: &'a str,
    pub root_path: &'a str,
    pub static_root_path: Option<&'a str>,
    pub description: &'a str,
    pub keywords: &'a str,
    pub resource_suffix: &'a str,
    pub extra_scripts: &'a [&'a str],
    pub static_extra_scripts: &'a [&'a str],
}

pub fn render<T: Print, S: Print>(
    layout: &Layout,
    page: &Page<'_>,
    sidebar: S,
    t: T,
    themes: &[PathBuf],
) -> String {
    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
    format!("<!DOCTYPE html>\
\
\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <meta name=\"generator\" content=\"rustdoc\">\
    <meta name=\"description\" content=\"{description}\">\
    <meta name=\"keywords\" content=\"{keywords}\">\
    <title>{title}</title>\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
          id=\"mainThemeStyle\">\
    {themes}\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}dark{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}light{suffix}.css\" \
          id=\"themeStyle\">\
    \
    <link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\">\
    {css_extension}\
    {favicon}\
    {in_header}\
    \
\
\
    \
    {before_content}\
    \

☰
\
        {logo}\
        {sidebar}\
    \

\
        <button id=\"theme-picker\" aria-label=\"Pick another theme!\">\
            \
        </button>\

\

\
    \
    \
        <form class=\"search-form js-only\">\

\

{filter_crates}\
                    <input class=\"search-input\" name=\"search\" \
                           autocomplete=\"off\" \
                           spellcheck=\"false\" \
                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                           type=\"search\">\

\
                \
                    \
                \

\
        </form>\
    \

{content}
\

\

\
    \

\

Help
\

\

Keyboard Shortcuts
\

\

?
\

Show this help dialog
\

S
\

Focus the search field
\

↑
\

Move up in search results
\

↓
\

Move down in search results
\

↹
\

Switch tab
\

⏎
\

Go to active search result
\

+
\

Expand all sections
\

-
\

Collapse all sections
\

\

\

\

Search Tricks
\

\
                    Prefix searches with a type followed by a colon (e.g., \
                    fn:) to restrict the search to a given type.\

\

\
                    Accepted types are: fn, mod, \
                    struct, enum, \
                    trait, type, macro, \
                    and const.\

\

\
                    Search functions by type signature (e.g., \
                    vec -> usize or * -> vec)\

\

\
                    Search multiple things at once by splitting your query with comma (e.g., \
                    str,u8 or String,struct:Vec,test)\

\

\

\
    \
    {after_content}\
    \
    \
    \
    {static_extra_scripts}\
    {extra_scripts}\
    \
\
",
    css_extension = if layout.css_file_extension.is_some() {
        format!("<link rel=\"stylesheet\" \
                       type=\"text/css\" \
                       href=\"{static_root_path}theme{suffix}.css\">",
                static_root_path = static_root_path,
                suffix=page.resource_suffix)
    } else {
        String::new()
    },
    content   = Buffer::html().to_display(t),
    static_root_path = static_root_path,
    root_path = page.root_path,
    css_class = page.css_class,
    logo      = {
        let p = format!("{}{}", page.root_path, layout.krate);
        let p = ensure_trailing_slash(&p);
        if layout.logo.is_empty() {
            format!("\

\

",
                    path=p,
                    static_root_path=static_root_path,
                    suffix=page.resource_suffix)
        } else {
            format!("\

",
                    p,
                    layout.logo)
        }
    },
    title     = page.title,
    description = page.description,
    keywords = page.keywords,
    favicon   = if layout.favicon.is_empty() {
        format!(r#"<link rel="shortcut icon" href="{static_root_path}favicon{suffix}.ico">"#,
                static_root_path=static_root_path,
                suffix=page.resource_suffix)
    } else {
        format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
    },
    in_header = layout.external_html.in_header,
    before_content = layout.external_html.before_content,
    after_content = layout.external_html.after_content,
    sidebar   = Buffer::html().to_display(sidebar),
    krate     = layout.krate,
    themes = themes.iter()
                   .filter_map(|t| t.file_stem())
                   .filter_map(|t| t.to_str())
                   .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#,
                                    static_root_path,
                                    t,
                                    page.resource_suffix))
                   .collect::<String>(),
    suffix=page.resource_suffix,
    static_extra_scripts=page.static_extra_scripts.iter().map(|e| {
        format!("",
                static_root_path=static_root_path,
                extra_script=e)
    }).collect::<String>(),
    extra_scripts=page.extra_scripts.iter().map(|e| {
        format!("",
                root_path=page.root_path,
                extra_script=e)
    }).collect::<String>(),
    filter_crates=if layout.generate_search_filter {
        "<select id=\"crate-search\">\
            <option value=\"All crates\">All crates</option>\
        </select>"
    } else {
        ""
    },
    )
}

pub fn redirect(url: &str) -> String {
    //

"##,
    url = url,
    )
}
<commit_msg>Rollup merge of #65842 - GuillaumeGomez:more-search-information, r=Dylan-DPC<commit_after>use std::path::PathBuf;

use crate::externalfiles::ExternalHtml;
use crate::html::render::ensure_trailing_slash;
use crate::html::format::{Buffer, Print};

#[derive(Clone)]
pub struct Layout {
    pub logo: String,
    pub favicon: String,
    pub external_html: ExternalHtml,
    pub krate: String,
    /// The given user css file which allow to customize the generated
    /// documentation theme.
    pub css_file_extension: Option<PathBuf>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    pub generate_search_filter: bool,
}

pub struct Page<'a> {
    pub title: &'a str,
    pub css_class: &'a str,
    pub root_path: &'a str,
    pub static_root_path: Option<&'a str>,
    pub description: &'a str,
    pub keywords: &'a str,
    pub resource_suffix: &'a str,
    pub extra_scripts: &'a [&'a str],
    pub static_extra_scripts: &'a [&'a str],
}

pub fn render<T: Print, S: Print>(
    layout: &Layout,
    page: &Page<'_>,
    sidebar: S,
    t: T,
    themes: &[PathBuf],
) -> String {
    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
    format!("<!DOCTYPE html>\
\
\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <meta name=\"generator\" content=\"rustdoc\">\
    <meta name=\"description\" content=\"{description}\">\
    <meta name=\"keywords\" content=\"{keywords}\">\
    <title>{title}</title>\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
          id=\"mainThemeStyle\">\
    {themes}\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}dark{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}light{suffix}.css\" \
          id=\"themeStyle\">\
    \
    <link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\">\
    {css_extension}\
    {favicon}\
    {in_header}\
    \
\
\
    \
    {before_content}\
    \

☰
\
        {logo}\
        {sidebar}\
    \

\
        <button id=\"theme-picker\" aria-label=\"Pick another theme!\">\
            \
        </button>\

\

\
    \
    \
        <form class=\"search-form js-only\">\

\

{filter_crates}\
                    <input class=\"search-input\" name=\"search\" \
                           autocomplete=\"off\" \
                           spellcheck=\"false\" \
                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                           type=\"search\">\

\
                \
                    \
                \

\
        </form>\
    \

{content}
\

\

\
    \

\

Help
\

\

Keyboard Shortcuts
\

\

?
\

Show this help dialog
\

S
\

Focus the search field
\

↑
\

Move up in search results
\

↓
\

Move down in search results
\

↹
\

Switch tab
\

⏎
\

Go to active search result
\

+
\

Expand all sections
\

-
\

Collapse all sections
\

\

\

\

Search Tricks
\

\
                    Prefix searches with a type followed by a colon (e.g., \
                    fn:) to restrict the search to a given type.\

\

\
                    Accepted types are: fn, mod, \
                    struct, enum, \
                    trait, type, macro, \
                    and const.\

\

\
                    Search functions by type signature (e.g., \
                    vec -> usize or * -> vec)\

\

\
                    Search multiple things at once by splitting your query with comma (e.g., \
                    str,u8 or String,struct:Vec,test)\

\

\
                    You can look for items with an exact name by putting double quotes around \
                    your request: \"string\"\

\

\
                    Look for items inside another one by searching for a path: \
                    vec::Vec\

\

\

\
    \
    {after_content}\
    \
    \
    \
    {static_extra_scripts}\
    {extra_scripts}\
    \
\
",
    css_extension = if layout.css_file_extension.is_some() {
        format!("<link rel=\"stylesheet\" \
                       type=\"text/css\" \
                       href=\"{static_root_path}theme{suffix}.css\">",
                static_root_path = static_root_path,
                suffix=page.resource_suffix)
    } else {
        String::new()
    },
    content   = Buffer::html().to_display(t),
    static_root_path = static_root_path,
    root_path = page.root_path,
    css_class = page.css_class,
    logo      = {
        let p = format!("{}{}", page.root_path, layout.krate);
        let p = ensure_trailing_slash(&p);
        if layout.logo.is_empty() {
            format!("\

\

",
                    path=p,
                    static_root_path=static_root_path,
                    suffix=page.resource_suffix)
        } else {
            format!("\

",
                    p,
                    layout.logo)
        }
    },
    title     = page.title,
    description = page.description,
    keywords = page.keywords,
    favicon   = if layout.favicon.is_empty() {
        format!(r#"<link rel="shortcut icon" href="{static_root_path}favicon{suffix}.ico">"#,
                static_root_path=static_root_path,
                suffix=page.resource_suffix)
    } else {
        format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
    },
    in_header = layout.external_html.in_header,
    before_content = layout.external_html.before_content,
    after_content = layout.external_html.after_content,
    sidebar   = Buffer::html().to_display(sidebar),
    krate     = layout.krate,
    themes = themes.iter()
                   .filter_map(|t| t.file_stem())
                   .filter_map(|t| t.to_str())
                   .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#,
                                    static_root_path,
                                    t,
                                    page.resource_suffix))
                   .collect::<String>(),
    suffix=page.resource_suffix,
    static_extra_scripts=page.static_extra_scripts.iter().map(|e| {
        format!("",
                static_root_path=static_root_path,
                extra_script=e)
    }).collect::<String>(),
    extra_scripts=page.extra_scripts.iter().map(|e| {
        format!("",
                root_path=page.root_path,
                extra_script=e)
    }).collect::<String>(),
    filter_crates=if layout.generate_search_filter {
        "<select id=\"crate-search\">\
            <option value=\"All crates\">All crates</option>\
        </select>"
    } else {
        ""
    },
    )
}

pub fn redirect(url: &str) -> String {
    //

"##,
    url = url,
    )
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

//! iced-x86 JavaScript bindings

#![allow(unknown_lints)]
#![warn(absolute_paths_not_starting_with_crate)]
#![warn(anonymous_parameters)]
#![warn(elided_lifetimes_in_paths)]
#![warn(explicit_outlives_requirements)]
#![warn(invalid_html_tags)]
#![warn(keyword_idents)]
#![warn(macro_use_extern_crate)]
#![warn(meta_variable_misuse)]
#![warn(missing_docs)]
#![warn(non_ascii_idents)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_lifetimes)]
#![warn(unused_must_use)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::collapsible_if)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::manual_range_contains)]
#![allow(clippy::match_ref_pats)]
#![allow(clippy::ptr_eq)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::unused_unit)] // wasm-bindgen 0.2.79 https://github.com/rustwasm/wasm-bindgen/issues/2774
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::wrong_self_convention)]
#![warn(clippy::cloned_instead_of_copied)]
#![warn(clippy::dbg_macro)]
#![warn(clippy::debug_assert_with_mut_call)]
#![warn(clippy::default_trait_access)]
#![warn(clippy::doc_markdown)]
#![warn(clippy::empty_line_after_outer_attr)]
#![warn(clippy::expect_used)]
#![warn(clippy::explicit_into_iter_loop)]
#![warn(clippy::explicit_iter_loop)]
#![warn(clippy::fallible_impl_from)]
#![warn(clippy::get_unwrap)]
#![warn(clippy::implicit_saturating_sub)]
#![warn(clippy::large_digit_groups)]
#![warn(clippy::let_unit_value)]
#![warn(clippy::match_bool)]
#![warn(clippy::match_on_vec_items)]
#![warn(clippy::match_wild_err_arm)]
#![warn(clippy::missing_errors_doc)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
#![warn(clippy::rc_buffer)]
#![warn(clippy::redundant_closure)]
#![warn(clippy::redundant_closure_for_method_calls)]
#![warn(clippy::same_functions_in_if_condition)]
#![warn(clippy::todo)]
#![warn(clippy::unimplemented)]
#![warn(clippy::unreadable_literal)]
#![warn(clippy::unused_self)]
#![warn(clippy::unwrap_in_result)]
#![warn(clippy::unwrap_used)]
#![warn(clippy::used_underscore_binding)]
#![warn(clippy::useless_let_if_seq)]
#![warn(clippy::useless_transmute)]
#![warn(clippy::zero_sized_map_values)]

#[cfg(all(feature = "encoder", feature = "block_encoder"))]
mod block_encoder;
#[cfg(all(feature = "encoder", feature = "block_encoder"))]
mod block_encoder_options;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod cc;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info"), feature = "instr_create"))]
mod code;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod code_ext;
#[cfg(feature = "instr_api")]
mod code_size;
#[cfg(feature = "instr_info")]
#[cfg(feature = "instr_api")]
mod condition_code;
#[cfg(any(feature = "encoder", all(feature = "decoder", feature = "instr_info")))]
mod constant_offsets;
#[cfg(feature = "instr_info")]
mod cpuid_feature;
#[cfg(feature = "decoder")]
mod decoder;
#[cfg(feature = "decoder")]
mod decoder_error;
#[cfg(feature = "decoder")]
mod decoder_options;
#[cfg(feature = "encoder")]
mod encoder;
#[cfg(any(feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
mod encoding_kind;
#[cfg(any(feature = "decoder", feature = "instr_info", feature = "encoder", feature = "instr_api", feature = "instr_create"))]
mod ex_utils;
#[cfg(feature = "fast_fmt")]
mod fast_fmt;
#[cfg(any(feature = "instr_info", all(feature = "instr_info", feature = "instr_api")))]
mod flow_control;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod format_mnemonic_options;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod formatter;
#[cfg(feature = "instr_info")]
mod info;
mod instruction;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod mandatory_prefix;
#[cfg(feature = "instr_create")]
mod memory_operand;
#[cfg(any(feature = "instr_api", feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
mod memory_size;
#[cfg(feature = "instr_info")]
mod memory_size_ext;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod memory_size_options;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info")))]
mod mnemonic;
#[cfg(feature = "mvex")]
mod mvex_cvt_fn;
#[cfg(feature = "mvex")]
mod mvex_eh_bit;
#[cfg(feature = "mvex")]
mod mvex_rm_conv;
#[cfg(feature = "mvex")]
mod mvex_tt_lut;
#[cfg(feature = "instr_info")]
mod op_access;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_info;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_operand_kind;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_table_kind;
#[cfg(feature = "instr_api")]
mod op_kind;
#[cfg(any(feature = "instr_api", feature = "instr_info", feature = "instr_create"))]
mod register;
#[cfg(feature = "instr_info")]
mod register_ext;
#[cfg(feature = "instr_create")]
mod rep_prefix_kind;
#[cfg(feature = "instr_info")]
mod rflags_bits;
#[cfg(feature = "instr_api")]
mod rounding_control;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod tuple_type;

#[cfg(all(feature = "encoder", feature = "block_encoder"))]
pub use block_encoder::*;
#[cfg(all(feature = "encoder", feature = "block_encoder"))]
pub use block_encoder_options::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use cc::*;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info"), feature = "instr_create"))]
pub use code::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use code_ext::*;
#[cfg(feature = "instr_api")]
pub use code_size::*;
#[cfg(feature = "instr_info")]
#[cfg(feature = "instr_api")]
pub use condition_code::*;
#[cfg(any(feature = "encoder", all(feature = "decoder", feature = "instr_info")))]
pub use constant_offsets::*;
#[cfg(feature = "instr_info")]
pub use cpuid_feature::*;
#[cfg(feature = "decoder")]
pub use decoder::*;
#[cfg(feature = "decoder")]
pub use decoder_error::*;
#[cfg(feature = "decoder")]
pub use decoder_options::*;
#[cfg(feature = "encoder")]
pub use encoder::*;
#[cfg(any(feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
pub use encoding_kind::*;
#[cfg(feature = "fast_fmt")]
pub use fast_fmt::*;
#[cfg(any(feature = "instr_info", all(feature = "instr_info", feature = "instr_api")))]
pub use flow_control::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use format_mnemonic_options::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use formatter::*;
#[cfg(feature = "instr_info")]
pub use info::*;
pub use instruction::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use mandatory_prefix::*;
#[cfg(feature = "instr_create")]
pub use memory_operand::*;
#[cfg(any(feature = "instr_api", feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
pub use memory_size::*;
#[cfg(feature = "instr_info")]
pub use memory_size_ext::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use memory_size_options::*;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info")))]
pub use mnemonic::*;
#[cfg(feature = "mvex")]
pub use mvex_cvt_fn::*;
#[cfg(feature = "mvex")]
pub use mvex_eh_bit::*;
#[cfg(feature = "mvex")]
pub use mvex_rm_conv::*;
#[cfg(feature = "mvex")]
pub use mvex_tt_lut::*;
#[cfg(feature = "instr_info")]
pub use op_access::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_info::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_operand_kind::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_table_kind::*;
#[cfg(feature = "instr_api")]
pub use op_kind::*;
#[cfg(any(feature = "instr_api", feature = "instr_info", feature = "instr_create"))]
pub use register::*;
#[cfg(feature = "instr_info")]
pub use register_ext::*;
#[cfg(feature = "instr_create")]
pub use rep_prefix_kind::*;
#[cfg(feature = "instr_info")]
pub use rflags_bits::*;
#[cfg(feature = "instr_api")]
pub use rounding_control::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use tuple_type::*;
use wasm_bindgen::prelude::*;

/// Gets feature flags.
///
/// Flag | Value
/// -----|-------
/// 0x01 | `VEX`
/// 0x02 | `EVEX`
/// 0x04 | `XOP`
/// 0x08 | `3DNow!`
/// 0x10 | `MVEX`
#[wasm_bindgen(js_name = "getIcedFeatures")]
pub fn get_iced_features() -> u32 {
	#[allow(unused_mut)]
	let mut flags = 0;
	#[cfg(not(feature = "no_vex"))]
	{
		flags |= 1;
	}
	#[cfg(not(feature = "no_evex"))]
	{
		flags |= 2;
	}
	#[cfg(not(feature = "no_xop"))]
	{
		flags |= 4;
	}
	#[cfg(not(feature = "no_d3now"))]
	{
		flags |= 8;
	}
	#[cfg(feature = "mvex")]
	{
		flags |= 0x10;
	}
	flags
}
<commit_msg>Disable the new `clippy::return_self_not_must_use` lint<commit_after>// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

//! iced-x86 JavaScript bindings

#![allow(unknown_lints)]
#![warn(absolute_paths_not_starting_with_crate)]
#![warn(anonymous_parameters)]
#![warn(elided_lifetimes_in_paths)]
#![warn(explicit_outlives_requirements)]
#![warn(invalid_html_tags)]
#![warn(keyword_idents)]
#![warn(macro_use_extern_crate)]
#![warn(meta_variable_misuse)]
#![warn(missing_docs)]
#![warn(non_ascii_idents)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_lifetimes)]
#![warn(unused_must_use)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::collapsible_if)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::manual_range_contains)]
#![allow(clippy::match_ref_pats)]
#![allow(clippy::ptr_eq)]
#![allow(clippy::return_self_not_must_use)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::unused_unit)] // wasm-bindgen 0.2.79 https://github.com/rustwasm/wasm-bindgen/issues/2774
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::wrong_self_convention)]
#![warn(clippy::cloned_instead_of_copied)]
#![warn(clippy::dbg_macro)]
#![warn(clippy::debug_assert_with_mut_call)]
#![warn(clippy::default_trait_access)]
#![warn(clippy::doc_markdown)]
#![warn(clippy::empty_line_after_outer_attr)]
#![warn(clippy::expect_used)]
#![warn(clippy::explicit_into_iter_loop)]
#![warn(clippy::explicit_iter_loop)]
#![warn(clippy::fallible_impl_from)]
#![warn(clippy::get_unwrap)]
#![warn(clippy::implicit_saturating_sub)]
#![warn(clippy::large_digit_groups)]
#![warn(clippy::let_unit_value)]
#![warn(clippy::match_bool)]
#![warn(clippy::match_on_vec_items)]
#![warn(clippy::match_wild_err_arm)]
#![warn(clippy::missing_errors_doc)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
#![warn(clippy::rc_buffer)]
#![warn(clippy::redundant_closure)]
#![warn(clippy::redundant_closure_for_method_calls)]
#![warn(clippy::same_functions_in_if_condition)]
#![warn(clippy::todo)]
#![warn(clippy::unimplemented)]
#![warn(clippy::unreadable_literal)]
#![warn(clippy::unused_self)]
#![warn(clippy::unwrap_in_result)]
#![warn(clippy::unwrap_used)]
#![warn(clippy::used_underscore_binding)]
#![warn(clippy::useless_let_if_seq)]
#![warn(clippy::useless_transmute)]
#![warn(clippy::zero_sized_map_values)]

#[cfg(all(feature = "encoder", feature = "block_encoder"))]
mod block_encoder;
#[cfg(all(feature = "encoder", feature = "block_encoder"))]
mod block_encoder_options;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod cc;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info"), feature = "instr_create"))]
mod code;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod code_ext;
#[cfg(feature = "instr_api")]
mod code_size;
#[cfg(feature = "instr_info")]
#[cfg(feature = "instr_api")]
mod condition_code;
#[cfg(any(feature = "encoder", all(feature = "decoder", feature = "instr_info")))]
mod constant_offsets;
#[cfg(feature = "instr_info")]
mod cpuid_feature;
#[cfg(feature = "decoder")]
mod decoder;
#[cfg(feature = "decoder")]
mod decoder_error;
#[cfg(feature = "decoder")]
mod decoder_options;
#[cfg(feature = "encoder")]
mod encoder;
#[cfg(any(feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
mod encoding_kind;
#[cfg(any(feature = "decoder", feature = "instr_info", feature = "encoder", feature = "instr_api", feature = "instr_create"))]
mod ex_utils;
#[cfg(feature = "fast_fmt")]
mod fast_fmt;
#[cfg(any(feature = "instr_info", all(feature = "instr_info", feature = "instr_api")))]
mod flow_control;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod format_mnemonic_options;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod formatter;
#[cfg(feature = "instr_info")]
mod info;
mod instruction;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod mandatory_prefix;
#[cfg(feature = "instr_create")]
mod memory_operand;
#[cfg(any(feature = "instr_api", feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
mod memory_size;
#[cfg(feature = "instr_info")]
mod memory_size_ext;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod memory_size_options;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info")))]
mod mnemonic;
#[cfg(feature = "mvex")]
mod mvex_cvt_fn;
#[cfg(feature = "mvex")]
mod mvex_eh_bit;
#[cfg(feature = "mvex")]
mod mvex_rm_conv;
#[cfg(feature = "mvex")]
mod mvex_tt_lut;
#[cfg(feature = "instr_info")]
mod op_access;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_info;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_operand_kind;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_table_kind;
#[cfg(feature = "instr_api")]
mod op_kind;
#[cfg(any(feature = "instr_api", feature = "instr_info", feature = "instr_create"))]
mod register;
#[cfg(feature = "instr_info")]
mod register_ext;
#[cfg(feature = "instr_create")]
mod rep_prefix_kind;
#[cfg(feature = "instr_info")]
mod rflags_bits;
#[cfg(feature = "instr_api")]
mod rounding_control;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod tuple_type;

#[cfg(all(feature = "encoder", feature = "block_encoder"))]
pub use block_encoder::*;
#[cfg(all(feature = "encoder", feature = "block_encoder"))]
pub use block_encoder_options::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use cc::*;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info"), feature = "instr_create"))]
pub use code::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use code_ext::*;
#[cfg(feature = "instr_api")]
pub use code_size::*;
#[cfg(feature = "instr_info")]
#[cfg(feature = "instr_api")]
pub use condition_code::*;
#[cfg(any(feature = "encoder", all(feature = "decoder", feature = "instr_info")))]
pub use constant_offsets::*;
#[cfg(feature = "instr_info")]
pub use cpuid_feature::*;
#[cfg(feature = "decoder")]
pub use decoder::*;
#[cfg(feature = "decoder")]
pub use decoder_error::*;
#[cfg(feature = "decoder")]
pub use decoder_options::*;
#[cfg(feature = "encoder")]
pub use encoder::*;
#[cfg(any(feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
pub use encoding_kind::*;
#[cfg(feature = "fast_fmt")]
pub use fast_fmt::*;
#[cfg(any(feature = "instr_info", all(feature = "instr_info", feature = "instr_api")))]
pub use flow_control::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use format_mnemonic_options::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use formatter::*;
#[cfg(feature = "instr_info")]
pub use info::*;
pub use instruction::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use mandatory_prefix::*;
#[cfg(feature = "instr_create")]
pub use memory_operand::*;
#[cfg(any(feature = "instr_api", feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
pub use memory_size::*;
#[cfg(feature = "instr_info")]
pub use memory_size_ext::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use memory_size_options::*;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info")))]
pub use mnemonic::*;
#[cfg(feature = "mvex")]
pub use mvex_cvt_fn::*;
#[cfg(feature = "mvex")]
pub use mvex_eh_bit::*;
#[cfg(feature = "mvex")]
pub use mvex_rm_conv::*;
#[cfg(feature = "mvex")]
pub use mvex_tt_lut::*;
#[cfg(feature = "instr_info")]
pub use op_access::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_info::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_operand_kind::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_table_kind::*;
#[cfg(feature = "instr_api")]
pub use op_kind::*;
#[cfg(any(feature = "instr_api", feature = "instr_info", feature = "instr_create"))]
pub use register::*;
#[cfg(feature = "instr_info")]
pub use register_ext::*;
#[cfg(feature = "instr_create")]
pub use rep_prefix_kind::*;
#[cfg(feature = "instr_info")]
pub use rflags_bits::*;
#[cfg(feature = "instr_api")]
pub use rounding_control::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use tuple_type::*;
use wasm_bindgen::prelude::*;

/// Gets feature flags.
///
/// Flag | Value
/// -----|-------
/// 0x01 | `VEX`
/// 0x02 | `EVEX`
/// 0x04 | `XOP`
/// 0x08 | `3DNow!`
/// 0x10 | `MVEX`
#[wasm_bindgen(js_name = "getIcedFeatures")]
pub fn get_iced_features() -> u32 {
	#[allow(unused_mut)]
	let mut flags = 0;
	#[cfg(not(feature = "no_vex"))]
	{
		flags |= 1;
	}
	#[cfg(not(feature = "no_evex"))]
	{
		flags |= 2;
	}
	#[cfg(not(feature = "no_xop"))]
	{
		flags |= 4;
	}
	#[cfg(not(feature = "no_d3now"))]
	{
		flags |= 8;
	}
	#[cfg(feature = "mvex")]
	{
		flags |= 0x10;
	}
	flags
}
<|endoftext|>


<commit_before>fn largest<T>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

fn main() {
    let numbers = vec![1, 3, 2, 5, 0];

    let result = largest(&numbers);

    println!("The largest number is {}", result);
}
<commit_msg>Example of method that uses different types than struct definitions<commit_after>fn largest<T>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

struct Point<T, U> {
    x: T,
    y: U,
}

impl<T, U> Point<T, U> {
    fn x(&self) -> &T {
        &self.x
    }
}

impl<T, U> Point<T, U> {
    fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
        Point {
            x: self.x,
            y: other.y
        }
    }
}

fn main() {
    let numbers = vec![1, 3, 2, 5, 0];

    let result = largest(&numbers);

    println!("The largest number is {}", result);
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(core)]
#![feature(scoped)]

#![allow(dead_code)]

extern crate core;
extern crate test;
extern crate columnar;
extern crate byteorder;
extern crate timely;

extern crate docopt;
use docopt::Docopt;

use test::Bencher;
use std::thread;
use std::hash::Hash;
use core::fmt::Debug;

use columnar::Columnar;

use timely::progress::Scope;
use timely::progress::nested::Summary::Local;
use timely::progress::nested::product::Product;
use timely::communication::{ThreadCommunicator, ProcessCommunicator, Communicator};
use timely::communication::channels::Data;
use timely::networking::initialize_networking;

use timely::example_static::*;

static USAGE: &'static str = "
Usage: timely distinct [options] [<arguments>...]
       timely barrier [options] [<arguments>...]
       timely command [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
";

fn main() {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Hello, world!");
    println!("Starting timely with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");
        let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
        let communicators = initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking");
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        let communicators = ProcessCommunicator::new_vector(workers);
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    }
    else {
        println!("Initializing ThreadCommunicator");
        let communicators = vec![ThreadCommunicator];
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    };
}

#[bench]
fn distinct_bench(bencher: &mut Bencher) { _distinct(ProcessCommunicator::new_vector(1).swap_remove(0), Some(bencher)); }
fn _distinct_multi<C: Communicator+Send>(communicators: Vec<C>) {
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        guards.push(thread::Builder::new().name(format!("worker thread {}", communicator.index()))
                                          .scoped(move || _distinct(communicator, None))
                                          .unwrap());
    }
}

// #[bench]
// fn command_bench(bencher: &mut Bencher) { _command(ProcessCommunicator::new_vector(1).swap_remove(0).unwrap(), Some(bencher)); }
fn _command_multi<C: Communicator+Send>(_communicators: Vec<C>) {
    println!("command currently disabled awaiting io reform");
    // let mut guards = Vec::new();
    // for communicator in communicators.into_iter() {
    //     guards.push(thread::scoped(move || _command(communicator, None)));
    // }
}

#[bench]
fn barrier_bench(bencher: &mut Bencher) { _barrier(ProcessCommunicator::new_vector(1).swap_remove(0), Some(bencher)); }
fn _barrier_multi<C: Communicator+Send>(communicators: Vec<C>) {
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        guards.push(thread::scoped(move || _barrier(communicator, None)));
    }
}

fn create_subgraph<G: GraphBuilder, D>(builder: &mut G,
                                        source1: &Stream<G::Timestamp, D>,
                                        source2: &Stream<G::Timestamp, D>) ->
                                            (Stream<G::Timestamp, D>, Stream<G::Timestamp, D>)
where D: Data+Hash+Eq+Debug+Columnar {

    let mut subgraph = builder.new_subgraph::<u64>();

    ((&mut subgraph).enter(source1).distinct().leave(),
     (&mut subgraph).enter(source2).leave())
}

fn _distinct<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {

    let mut root = GraphRoot::new(communicator);

    let (mut input1, mut input2) = {

        // allocate a new graph builder
        let mut graph = root.new_subgraph();

        // try building some input scopes
        let (input1, stream1) = graph.new_input::<u64>();
        let (input2, stream2) = graph.new_input::<u64>();

        // prepare some feedback edges
        let (loop1_source, loop1) = graph.loop_variable(Product::new((), 100), Local(1));
        let (loop2_source, loop2) = graph.loop_variable(Product::new((), 100), Local(1));

        let concat1 = (&mut graph).concatenate(vec![stream1, loop1]).disable();
        let concat2 = (&mut graph).concatenate(vec![stream2, loop2]).disable();

        // build up a subgraph using the concatenated inputs/feedbacks
        let (egress1, egress2) = create_subgraph(&mut graph, &concat1, &concat2);

        // connect feedback sources. notice that we have swapped indices ...
        egress1.enable(&mut graph).connect_loop(loop2_source);
        egress2.enable(&mut graph).connect_loop(loop1_source);

        (input1, input2)
    };

    root.step();

    // move some data into the dataflow graph.
    input1.send_messages(&Product::new((), 0), vec![1u64]);
    input2.send_messages(&Product::new((), 0), vec![2u64]);

    // see what everyone thinks about that ...
    root.step();

    input1.advance(&Product::new((), 0), &Product::new((), 1000000));
    input2.advance(&Product::new((), 0), &Product::new((), 1000000));
    input1.close_at(&Product::new((), 1000000));
    input2.close_at(&Product::new((), 1000000));

    // spin
    match bencher {
        Some(b) => b.iter(|| { root.step(); }),
        None    => while root.step() { }
    }
}

// fn _command<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {
//     let communicator = Rc::new(RefCell::new(communicator));
//
//     // no "base scopes" yet, so the root pretends to be a subscope of some parent with a () timestamp type.
//     let mut graph = new_graph(Progcaster::new(&mut (*communicator.borrow_mut())));
//     let mut input = graph.new_input::<u64>(communicator);
//     let mut feedback = input.1.feedback(((), 1000), Local(1));
//     let mut result: Stream<_, u64, _> = input.1.concat(&mut feedback.1)
//                                                .command("./target/release/command".to_string());
//
//     feedback.0.connect_input(&mut result);
//
//     // start things up!
//     graph.borrow_mut().get_internal_summary();
//     graph.borrow_mut().set_external_summary(Vec::new(), &mut []);
//     graph.borrow_mut().push_external_progress(&mut []);
//
//     input.0.close_at(&((), 0));
//
//     // spin
//     match bencher {
//         Some(b) => b.iter(|| { graph.borrow_mut().pull_internal_progress(&mut [], &mut [], &mut []); }),
//         None    => while graph.borrow_mut().pull_internal_progress(&mut [], &mut [], &mut []) { },
//     }
// }

fn _barrier<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {

    let mut root = GraphRoot::new(communicator);
    //
    // {
    //     let borrow = root.builder();
    //     let mut graph = SubgraphBuilder::new(&borrow);
    //
    //     let peers = graph.with_communicator(|x| x.peers());
    //     {
    //         let builder = &graph.builder();
    //
    //         builder.borrow_mut().add_scope(BarrierScope { epoch: 0, ready: true, degree: peers, ttl: 1000000 });
    //         builder.borrow_mut().connect(ScopeOutput(0, 0), ScopeInput(0, 0));
    //     }
    //
    //     graph.seal();
    // }
    //
    // // spin
    match bencher {
        Some(b) => b.iter(|| { root.step(); }),
        None    => while root.step() { },
    }
}
<commit_msg>simplified<commit_after>#![feature(test)]
#![feature(core)]
#![feature(scoped)]

#![allow(dead_code)]

extern crate core;
extern crate test;
extern crate columnar;
extern crate byteorder;
extern crate timely;

extern crate docopt;
use docopt::Docopt;

use test::Bencher;
use std::thread;
use std::hash::Hash;
use core::fmt::Debug;

use columnar::Columnar;

use timely::progress::Scope;
use timely::progress::nested::Summary::Local;
use timely::progress::nested::product::Product;
use timely::communication::{ThreadCommunicator, ProcessCommunicator, Communicator};
use timely::communication::channels::Data;
use timely::networking::initialize_networking;

use timely::example_static::*;

static USAGE: &'static str = "
Usage: timely distinct [options] [<arguments>...]
       timely barrier [options] [<arguments>...]
       timely command [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
";

fn main() {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Hello, world!");
    println!("Starting timely with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");
        let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
        let communicators = initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking");
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        let communicators = ProcessCommunicator::new_vector(workers);
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    }
    else {
        println!("Initializing ThreadCommunicator");
        let communicators = vec![ThreadCommunicator];
        if args.get_bool("distinct") { _distinct_multi(communicators); }
        else if args.get_bool("barrier") { _barrier_multi(communicators); }
        else if args.get_bool("command") { _command_multi(communicators); }
    };
}

#[bench]
fn distinct_bench(bencher: &mut Bencher) { _distinct(ProcessCommunicator::new_vector(1).swap_remove(0), Some(bencher)); }
fn _distinct_multi<C: Communicator+Send>(communicators: Vec<C>) {
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        guards.push(thread::Builder::new().name(format!("worker thread {}", communicator.index()))
                                          .scoped(move || _distinct(communicator, None))
                                          .unwrap());
    }
}

// #[bench]
// fn command_bench(bencher: &mut Bencher) { _command(ProcessCommunicator::new_vector(1).swap_remove(0).unwrap(), Some(bencher)); }
fn _command_multi<C: Communicator+Send>(_communicators: Vec<C>) {
    println!("command currently disabled awaiting io reform");
    // let mut guards = Vec::new();
    // for communicator in communicators.into_iter() {
    //     guards.push(thread::scoped(move || _command(communicator, None)));
    // }
}

#[bench]
fn barrier_bench(bencher: &mut Bencher) { _barrier(ProcessCommunicator::new_vector(1).swap_remove(0), Some(bencher)); }
fn _barrier_multi<C: Communicator+Send>(communicators: Vec<C>) {
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        guards.push(thread::scoped(move || _barrier(communicator, None)));
    }
}

fn create_subgraph<G: GraphBuilder, D>(builder: &mut G,
                                        source1: &Stream<G::Timestamp, D>,
                                        source2: &Stream<G::Timestamp, D>) ->
                                            (Stream<G::Timestamp, D>, Stream<G::Timestamp, D>)
where D: Data+Hash+Eq+Debug+Columnar {

    let mut subgraph = builder.new_subgraph::<u64>();

    (subgraph.enter(source1).distinct().leave(),
     subgraph.enter(source2).leave())
}

fn _distinct<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {

    let mut root = GraphRoot::new(communicator);

    let (mut input1, mut input2) = {

        // allocate a new graph builder
        let mut graph = root.new_subgraph();

        // try building some input scopes
        let (input1, stream1) = graph.new_input::<u64>();
        let (input2, stream2) = graph.new_input::<u64>();

        // prepare some feedback edges
        let (loop1_source, loop1) = graph.loop_variable(Product::new((), 100), Local(1));
        let (loop2_source, loop2) = graph.loop_variable(Product::new((), 100), Local(1));

        let concat1 = (&mut graph).concatenate(vec![stream1, loop1]).disable();
        let concat2 = (&mut graph).concatenate(vec![stream2, loop2]).disable();

        // build up a subgraph using the concatenated inputs/feedbacks
        let (egress1, egress2) = create_subgraph(&mut graph, &concat1, &concat2);

        // connect feedback sources. notice that we have swapped indices ...
        egress1.enable(&mut graph).connect_loop(loop2_source);
        egress2.enable(&mut graph).connect_loop(loop1_source);

        (input1, input2)
    };

    root.step();

    // move some data into the dataflow graph.
    input1.send_messages(&Product::new((), 0), vec![1u64]);
    input2.send_messages(&Product::new((), 0), vec![2u64]);

    // see what everyone thinks about that ...
    root.step();

    input1.advance(&Product::new((), 0), &Product::new((), 1000000));
    input2.advance(&Product::new((), 0), &Product::new((), 1000000));
    input1.close_at(&Product::new((), 1000000));
    input2.close_at(&Product::new((), 1000000));

    // spin
    match bencher {
        Some(b) => b.iter(|| { root.step(); }),
        None    => while root.step() { }
    }
}

// fn _command<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {
//     let communicator = Rc::new(RefCell::new(communicator));
//
//     // no "base scopes" yet, so the root pretends to be a subscope of some parent with a () timestamp type.
//     let mut graph = new_graph(Progcaster::new(&mut (*communicator.borrow_mut())));
//     let mut input = graph.new_input::<u64>(communicator);
//     let mut feedback = input.1.feedback(((), 1000), Local(1));
//     let mut result: Stream<_, u64, _> = input.1.concat(&mut feedback.1)
//                                                .command("./target/release/command".to_string());
//
//     feedback.0.connect_input(&mut result);
//
//     // start things up!
//     graph.borrow_mut().get_internal_summary();
//     graph.borrow_mut().set_external_summary(Vec::new(), &mut []);
//     graph.borrow_mut().push_external_progress(&mut []);
//
//     input.0.close_at(&((), 0));
//
//     // spin
//     match bencher {
//         Some(b) => b.iter(|| { graph.borrow_mut().pull_internal_progress(&mut [], &mut [], &mut []); }),
//         None    => while graph.borrow_mut().pull_internal_progress(&mut [], &mut [], &mut []) { },
//     }
// }

fn _barrier<C: Communicator>(communicator: C, bencher: Option<&mut Bencher>) {

    let mut root = GraphRoot::new(communicator);
    //
    // {
    //     let borrow = root.builder();
    //     let mut graph = SubgraphBuilder::new(&borrow);
    //
    //     let peers = graph.with_communicator(|x| x.peers());
    //     {
    //         let builder = &graph.builder();
    //
    //         builder.borrow_mut().add_scope(BarrierScope { epoch: 0, ready: true, degree: peers, ttl: 1000000 });
    //         builder.borrow_mut().connect(ScopeOutput(0, 0), ScopeInput(0, 0));
    //     }
    //
    //     graph.seal();
    // }
    //
    // // spin
    match bencher {
        Some(b) => b.iter(|| { root.step(); }),
        None    => while root.step() { },
    }
}
<|endoftext|>


<commit_before>import std::io;
import std::str;
import std::option;
import std::fs;
import std::os;
import std::vec;
import std::test;

import common::mode_run_pass;
import common::mode_run_fail;
import common::mode_compile_fail;
import common::mode_pretty;
import common::cx;
import common::config;
import header::load_props;
import header::test_props;
import util::logv;

export run;

fn run(cx: cx, -_testfile: [u8]) {
    let testfile = str::unsafe_from_bytes(_testfile);
    if cx.config.verbose {
        // We're going to be dumping a lot of info. Start on a new line.
        io::stdout().write_str("\n\n");
    }
    log #fmt["running %s", testfile];
    let props = load_props(testfile);
    alt cx.config.mode {
      mode_compile_fail. { run_cfail_test(cx, props, testfile); }
      mode_run_fail. { run_rfail_test(cx, props, testfile); }
      mode_run_pass. { run_rpass_test(cx, props, testfile); }
      mode_pretty. { run_pretty_test(cx, props, testfile); }
    }
}

fn run_cfail_test(cx: cx, props: test_props, testfile: str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status == 0 {
        fatal_procres("compile-fail test compiled successfully!", procres);
    }

    check_error_patterns(props, testfile, procres);
}

fn run_rfail_test(cx: cx, props: test_props, testfile: str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status != 0 { fatal_procres("compilation failed!", procres); }

    procres = exec_compiled_test(cx, props, testfile);

    // The value our Makefile configures valgrind to return on failure
    const valgrind_err: int = 100;
    if procres.status == valgrind_err {
        fatal_procres("run-fail test isn't valgrind-clean!", procres);
    }

    // The value the rust runtime returns on failure
    const rust_err: int = 101;
    if procres.status != rust_err {
        fatal_procres(
            #fmt("run-fail test produced the wrong error code: %d",
                 procres.status),
            procres);
    }

    check_error_patterns(props, testfile, procres);
}

fn run_rpass_test(cx: cx, props: test_props, testfile: str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status != 0 { fatal_procres("compilation failed!", procres); }

    procres = exec_compiled_test(cx, props, testfile);

    if procres.status != 0 { fatal_procres("test run failed!", procres); }
}

fn run_pretty_test(cx: cx, props: test_props, testfile: str) {
    if option::is_some(props.pp_exact) {
        logv(cx.config, "testing for exact pretty-printing");
    } else { logv(cx.config, "testing for converging pretty-printing"); }

    let rounds =
        alt props.pp_exact { option::some(_) { 1 } option::none. { 2 } };

    let srcs = [io::read_whole_file_str(testfile)];

    let round = 0;
    while round < rounds {
        logv(cx.config, #fmt["pretty-printing round %d", round]);
        let procres = print_source(cx, testfile, srcs[round]);

        if procres.status != 0 {
            fatal_procres(#fmt["pretty-printing failed in round %d", round],
                          procres);
        }

        srcs += [procres.stdout];
        round += 1;
    }

    let expected =
        alt props.pp_exact {
          option::some(file) {
            let filepath = fs::connect(fs::dirname(testfile), file);
            io::read_whole_file_str(filepath)
          }
          option::none. { srcs[vec::len(srcs) - 2u] }
        };
    let actual = srcs[vec::len(srcs) - 1u];

    if option::is_some(props.pp_exact) {
        // Now we have to care about line endings
        let cr = "\r";
        check (str::is_not_empty(cr));
        actual = str::replace(actual, cr, "");
        expected = str::replace(expected, cr, "");
    }

    compare_source(expected, actual);

    // Finally, let's make sure it actually appears to remain valid code
    let procres = typecheck_source(cx, testfile, actual);

    if procres.status != 0 {
        fatal_procres("pretty-printed source does not typecheck", procres);
    }

    ret;

    fn print_source(cx: cx, testfile: str, src: str) -> procres {
        compose_and_run(cx, testfile, make_pp_args,
                        cx.config.compile_lib_path, option::some(src))
    }

    fn make_pp_args(config: config, _testfile: str) -> procargs {
        let prog = config.rustc_path;
        let args = ["-", "--pretty", "normal"];
        ret {prog: prog, args: args};
    }

    fn compare_source(expected: str, actual: str) {
        if expected != actual {
            error("pretty-printed source does match expected source");
            let msg =
                #fmt["\n\
expected:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
actual:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
\n",
                     expected, actual];
            io::stdout().write_str(msg);
            fail;
        }
    }

    fn typecheck_source(cx: cx, testfile: str, src: str) -> procres {
        compose_and_run(cx, testfile, make_typecheck_args,
                        cx.config.compile_lib_path, option::some(src))
    }

    fn make_typecheck_args(config: config, _testfile: str) -> procargs {
        let prog = config.rustc_path;
        let args = ["-", "--no-trans", "--lib"];
        ret {prog: prog, args: args};
    }
}

fn check_error_patterns(props: test_props, testfile: str, procres: procres) {
    if vec::is_empty(props.error_patterns) {
        fatal("no error pattern specified in " + testfile);
    }

    if procres.status == 0 {
        fatal("process did not return an error status");
    }

    let next_err_idx = 0u;
    let next_err_pat = props.error_patterns[next_err_idx];
    for line: str in str::split(procres.stdout, '\n' as u8) {
        if str::find(line, next_err_pat) > 0 {
            log #fmt["found error pattern %s", next_err_pat];
            next_err_idx += 1u;
            if next_err_idx == vec::len(props.error_patterns) {
                log "found all error patterns";
                ret;
            }
            next_err_pat = props.error_patterns[next_err_idx];
        }
    }

    let missing_patterns =
        vec::slice(props.error_patterns, next_err_idx,
                   vec::len(props.error_patterns));
    if vec::len(missing_patterns) == 1u {
        fatal_procres(#fmt["error pattern '%s' not found!",
                           missing_patterns[0]], procres);
    } else {
        for pattern: str in missing_patterns {
            error(#fmt["error pattern '%s' not found!", pattern]);
        }
        fatal_procres("multiple error patterns not found", procres);
    }
}

type procargs = {prog: str, args: [str]};

type procres = {status: int, stdout: str, stderr: str, cmdline: str};

fn compile_test(cx: cx, props: test_props, testfile: str) -> procres {
    compose_and_run(cx, testfile, bind make_compile_args(_, props, _),
                    cx.config.compile_lib_path, option::none)
}

fn exec_compiled_test(cx: cx, props: test_props, testfile: str) -> procres {
    compose_and_run(cx, testfile, bind make_run_args(_, props, _),
                    cx.config.run_lib_path, option::none)
}

fn compose_and_run(cx: cx, testfile: str,
                   make_args: fn(config, str) -> procargs, lib_path: str,
                   input: option::t<str>) -> procres {
    let procargs = make_args(cx.config, testfile);
    ret program_output(cx, testfile, lib_path, procargs.prog, procargs.args,
                       input);
}

fn make_compile_args(config: config, props: test_props, testfile: str) ->
   procargs {
    let prog = config.rustc_path;
    let args = [testfile, "-o", make_exe_name(config, testfile)];
    let rustcflags =
        alt config.rustcflags {
          option::some(s) { option::some(s) }
          option::none. { option::none }
        };
    args += split_maybe_args(rustcflags);
    args += split_maybe_args(props.compile_flags);
    ret {prog: prog, args: args};
}

fn make_exe_name(config: config, testfile: str) -> str {
    output_base_name(config, testfile) + os::exec_suffix()
}

fn make_run_args(config: config, _props: test_props, testfile: str) ->
   procargs {
    let toolargs = {
            // If we've got another tool to run under (valgrind),
            // then split apart its command
            let runtool =
                alt config.runtool {
                  option::some(s) { option::some(s) }
                  option::none. { option::none }
                };
            split_maybe_args(runtool)
        };

    let args = toolargs + [make_exe_name(config, testfile)];
    ret {prog: args[0], args: vec::slice(args, 1u, vec::len(args))};
}

fn split_maybe_args(argstr: option::t<str>) -> [str] {
    fn rm_whitespace(v: [str]) -> [str] {
        fn flt(s: str) -> option::t<str> {
            if !is_whitespace(s) { option::some(s) } else { option::none }
        }

        // FIXME: This should be in std
        fn is_whitespace(s: str) -> bool {
            for c: u8 in s { if c != ' ' as u8 { ret false; } }
            ret true;
        }
        vec::filter_map(flt, v)
    }

    alt argstr {
      option::some(s) { rm_whitespace(str::split(s, ' ' as u8)) }
      option::none. { [] }
    }
}

fn program_output(cx: cx, testfile: str, lib_path: str, prog: str,
                  args: [str], input: option::t<str>) -> procres {
    let cmdline =
        {
            let cmdline = make_cmdline(lib_path, prog, args);
            logv(cx.config, #fmt["executing %s", cmdline]);
            cmdline
        };
    let res = procsrv::run(cx.procsrv, lib_path, prog, args, input);
    dump_output(cx.config, testfile, res.out, res.err);
    ret {status: res.status,
         stdout: res.out,
         stderr: res.err,
         cmdline: cmdline};
}

fn make_cmdline(libpath: str, prog: str, args: [str]) -> str {
    #fmt["%s %s %s", lib_path_cmd_prefix(libpath), prog,
         str::connect(args, " ")]
}

// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
// for diagnostic purposes
fn lib_path_cmd_prefix(path: str) -> str {
    #fmt["%s=\"%s\"", util::lib_path_env_var(), util::make_new_path(path)]
}

fn dump_output(config: config, testfile: str, out: str, err: str) {
    dump_output_file(config, testfile, out, "out");
    dump_output_file(config, testfile, err, "err");
    maybe_dump_to_stdout(config, out, err);
}

#[cfg(target_os = "win32")]
#[cfg(target_os = "linux")]
fn dump_output_file(config: config, testfile: str, out: str, extension: str) {
    let outfile = make_out_name(config, testfile, extension);
    let writer = io::file_writer(outfile, [io::create, io::truncate]);
    writer.write_str(out);
}

// FIXME (726): Can't use file_writer on mac
#[cfg(target_os = "macos")]
fn dump_output_file(config: config, testfile: str, out: str, extension: str) {
}

fn make_out_name(config: config, testfile: str, extension: str) -> str {
    output_base_name(config, testfile) + "." + extension
}

fn output_base_name(config: config, testfile: str) -> str {
    let base = config.build_base;
    let filename =
        {
            let parts = str::split(fs::basename(testfile), '.' as u8);
            parts = vec::slice(parts, 0u, vec::len(parts) - 1u);
            str::connect(parts, ".")
        };
    #fmt["%s%s.%s", base, filename, config.stage_id]
}

fn maybe_dump_to_stdout(config: config, out: str, err: str) {
    if config.verbose {
        let sep1 = #fmt["------%s------------------------------", "stdout"];
        let sep2 = #fmt["------%s------------------------------", "stderr"];
        let sep3 = "------------------------------------------";
        io::stdout().write_line(sep1);
        io::stdout().write_line(out);
        io::stdout().write_line(sep2);
        io::stdout().write_line(err);
        io::stdout().write_line(sep3);
    }
}

fn error(err: str) { io::stdout().write_line(#fmt["\nerror: %s", err]); }

fn fatal(err: str) -> ! { error(err); fail; }

fn fatal_procres(err: str, procres: procres) -> ! {
    let msg =
        #fmt["\n\
error: %s\n\
command: %s\n\
stdout:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
stderr:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
\n",
             err, procres.cmdline, procres.stdout, procres.stderr];
    io::stdout().write_str(msg);
    fail;
}
<commit_msg>Check for the correct exit code on cfail tests. Closes #938<commit_after>import std::io;
import std::str;
import std::option;
import std::fs;
import std::os;
import std::vec;
import std::test;

import common::mode_run_pass;
import common::mode_run_fail;
import common::mode_compile_fail;
import common::mode_pretty;
import common::cx;
import common::config;
import header::load_props;
import header::test_props;
import util::logv;

export run;

fn run(cx: cx, -_testfile: [u8]) {
    let testfile = str::unsafe_from_bytes(_testfile);
    if cx.config.verbose {
        // We're going to be dumping a lot of info. Start on a new line.
        io::stdout().write_str("\n\n");
    }
    log #fmt["running %s", testfile];
    let props = load_props(testfile);
    alt cx.config.mode {
      mode_compile_fail. { run_cfail_test(cx, props, testfile); }
      mode_run_fail. { run_rfail_test(cx, props, testfile); }
      mode_run_pass. { run_rpass_test(cx, props, testfile); }
      mode_pretty. { run_pretty_test(cx, props, testfile); }
    }
}

fn run_cfail_test(cx: cx, props: test_props, testfile: str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status == 0 {
        fatal_procres("compile-fail test compiled successfully!", procres);
    }

    check_correct_failure_status(procres);
    check_error_patterns(props, testfile, procres);
}

fn run_rfail_test(cx: cx, props: test_props, testfile: str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status != 0 { fatal_procres("compilation failed!", procres); }

    procres = exec_compiled_test(cx, props, testfile);

    // The value our Makefile configures valgrind to return on failure
    const valgrind_err: int = 100;
    if procres.status == valgrind_err {
        fatal_procres("run-fail test isn't valgrind-clean!", procres);
    }

    check_correct_failure_status(procres);
    check_error_patterns(props, testfile, procres);
}

fn check_correct_failure_status(procres: procres) {
    // The value the rust runtime returns on failure
    const rust_err: int = 101;
    if procres.status != rust_err {
        fatal_procres(
            #fmt("failure produced the wrong error code: %d",
                 procres.status),
            procres);
    }
}

fn run_rpass_test(cx: cx, props: test_props, testfile: str) {
    let procres = compile_test(cx, props, testfile);

    if procres.status != 0 { fatal_procres("compilation failed!", procres); }

    procres = exec_compiled_test(cx, props, testfile);

    if procres.status != 0 { fatal_procres("test run failed!", procres); }
}

fn run_pretty_test(cx: cx, props: test_props, testfile: str) {
    if option::is_some(props.pp_exact) {
        logv(cx.config, "testing for exact pretty-printing");
    } else { logv(cx.config, "testing for converging pretty-printing"); }

    let rounds =
        alt props.pp_exact { option::some(_) { 1 } option::none. { 2 } };

    let srcs = [io::read_whole_file_str(testfile)];

    let round = 0;
    while round < rounds {
        logv(cx.config, #fmt["pretty-printing round %d", round]);
        let procres = print_source(cx, testfile, srcs[round]);

        if procres.status != 0 {
            fatal_procres(#fmt["pretty-printing failed in round %d", round],
                          procres);
        }

        srcs += [procres.stdout];
        round += 1;
    }

    let expected =
        alt props.pp_exact {
          option::some(file) {
            let filepath = fs::connect(fs::dirname(testfile), file);
            io::read_whole_file_str(filepath)
          }
          option::none. { srcs[vec::len(srcs) - 2u] }
        };
    let actual = srcs[vec::len(srcs) - 1u];

    if option::is_some(props.pp_exact) {
        // Now we have to care about line endings
        let cr = "\r";
        check (str::is_not_empty(cr));
        actual = str::replace(actual, cr, "");
        expected = str::replace(expected, cr, "");
    }

    compare_source(expected, actual);

    // Finally, let's make sure it actually appears to remain valid code
    let procres = typecheck_source(cx, testfile, actual);

    if procres.status != 0 {
        fatal_procres("pretty-printed source does not typecheck", procres);
    }

    ret;

    fn print_source(cx: cx, testfile: str, src: str) -> procres {
        compose_and_run(cx, testfile, make_pp_args,
                        cx.config.compile_lib_path, option::some(src))
    }

    fn make_pp_args(config: config, _testfile: str) -> procargs {
        let prog = config.rustc_path;
        let args = ["-", "--pretty", "normal"];
        ret {prog: prog, args: args};
    }

    fn compare_source(expected: str, actual: str) {
        if expected != actual {
            error("pretty-printed source does match expected source");
            let msg =
                #fmt["\n\
expected:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
actual:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
\n",
                     expected, actual];
            io::stdout().write_str(msg);
            fail;
        }
    }

    fn typecheck_source(cx: cx, testfile: str, src: str) -> procres {
        compose_and_run(cx, testfile, make_typecheck_args,
                        cx.config.compile_lib_path, option::some(src))
    }

    fn make_typecheck_args(config: config, _testfile: str) -> procargs {
        let prog = config.rustc_path;
        let args = ["-", "--no-trans", "--lib"];
        ret {prog: prog, args: args};
    }
}

fn check_error_patterns(props: test_props, testfile: str, procres: procres) {
    if vec::is_empty(props.error_patterns) {
        fatal("no error pattern specified in " + testfile);
    }

    if procres.status == 0 {
        fatal("process did not return an error status");
    }

    let next_err_idx = 0u;
    let next_err_pat = props.error_patterns[next_err_idx];
    for line: str in str::split(procres.stdout, '\n' as u8) {
        if str::find(line, next_err_pat) > 0 {
            log #fmt["found error pattern %s", next_err_pat];
            next_err_idx += 1u;
            if next_err_idx == vec::len(props.error_patterns) {
                log "found all error patterns";
                ret;
            }
            next_err_pat = props.error_patterns[next_err_idx];
        }
    }

    let missing_patterns =
        vec::slice(props.error_patterns, next_err_idx,
                   vec::len(props.error_patterns));
    if vec::len(missing_patterns) == 1u {
        fatal_procres(#fmt["error pattern '%s' not found!",
                           missing_patterns[0]], procres);
    } else {
        for pattern: str in missing_patterns {
            error(#fmt["error pattern '%s' not found!", pattern]);
        }
        fatal_procres("multiple error patterns not found", procres);
    }
}

type procargs = {prog: str, args: [str]};

type procres = {status: int, stdout: str, stderr: str, cmdline: str};

fn compile_test(cx: cx, props: test_props, testfile: str) -> procres {
    compose_and_run(cx, testfile, bind make_compile_args(_, props, _),
                    cx.config.compile_lib_path, option::none)
}

fn exec_compiled_test(cx: cx, props: test_props, testfile: str) -> procres {
    compose_and_run(cx, testfile, bind make_run_args(_, props, _),
                    cx.config.run_lib_path, option::none)
}

fn compose_and_run(cx: cx, testfile: str,
                   make_args: fn(config, str) -> procargs, lib_path: str,
                   input: option::t<str>) -> procres {
    let procargs = make_args(cx.config, testfile);
    ret program_output(cx, testfile, lib_path, procargs.prog, procargs.args,
                       input);
}

fn make_compile_args(config: config, props: test_props, testfile: str) ->
   procargs {
    let prog = config.rustc_path;
    let args = [testfile, "-o", make_exe_name(config, testfile)];
    let rustcflags =
        alt config.rustcflags {
          option::some(s) { option::some(s) }
          option::none. { option::none }
        };
    args += split_maybe_args(rustcflags);
    args += split_maybe_args(props.compile_flags);
    ret {prog: prog, args: args};
}

fn make_exe_name(config: config, testfile: str) -> str {
    output_base_name(config, testfile) + os::exec_suffix()
}

fn make_run_args(config: config, _props: test_props, testfile: str) ->
   procargs {
    let toolargs = {
            // If we've got another tool to run under (valgrind),
            // then split apart its command
            let runtool =
                alt config.runtool {
                  option::some(s) { option::some(s) }
                  option::none. { option::none }
                };
            split_maybe_args(runtool)
        };

    let args = toolargs + [make_exe_name(config, testfile)];
    ret {prog: args[0], args: vec::slice(args, 1u, vec::len(args))};
}

fn split_maybe_args(argstr: option::t<str>) -> [str] {
    fn rm_whitespace(v: [str]) -> [str] {
        fn flt(s: str) -> option::t<str> {
            if !is_whitespace(s) { option::some(s) } else { option::none }
        }

        // FIXME: This should be in std
        fn is_whitespace(s: str) -> bool {
            for c: u8 in s { if c != ' ' as u8 { ret false; } }
            ret true;
        }
        vec::filter_map(flt, v)
    }

    alt argstr {
      option::some(s) { rm_whitespace(str::split(s, ' ' as u8)) }
      option::none. { [] }
    }
}

fn program_output(cx: cx, testfile: str, lib_path: str, prog: str,
                  args: [str], input: option::t<str>) -> procres {
    let cmdline =
        {
            let cmdline = make_cmdline(lib_path, prog, args);
            logv(cx.config, #fmt["executing %s", cmdline]);
            cmdline
        };
    let res = procsrv::run(cx.procsrv, lib_path, prog, args, input);
    dump_output(cx.config, testfile, res.out, res.err);
    ret {status: res.status,
         stdout: res.out,
         stderr: res.err,
         cmdline: cmdline};
}

fn make_cmdline(libpath: str, prog: str, args: [str]) -> str {
    #fmt["%s %s %s", lib_path_cmd_prefix(libpath), prog,
         str::connect(args, " ")]
}

// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
// for diagnostic purposes
fn lib_path_cmd_prefix(path: str) -> str {
    #fmt["%s=\"%s\"", util::lib_path_env_var(), util::make_new_path(path)]
}

fn dump_output(config: config, testfile: str, out: str, err: str) {
    dump_output_file(config, testfile, out, "out");
    dump_output_file(config, testfile, err, "err");
    maybe_dump_to_stdout(config, out, err);
}

#[cfg(target_os = "win32")]
#[cfg(target_os = "linux")]
fn dump_output_file(config: config, testfile: str, out: str, extension: str) {
    let outfile = make_out_name(config, testfile, extension);
    let writer = io::file_writer(outfile, [io::create, io::truncate]);
    writer.write_str(out);
}

// FIXME (726): Can't use file_writer on mac
#[cfg(target_os = "macos")]
fn dump_output_file(config: config, testfile: str, out: str, extension: str) {
}

fn make_out_name(config: config, testfile: str, extension: str) -> str {
    output_base_name(config, testfile) + "." + extension
}

fn output_base_name(config: config, testfile: str) -> str {
    let base = config.build_base;
    let filename =
        {
            let parts = str::split(fs::basename(testfile), '.' as u8);
            parts = vec::slice(parts, 0u, vec::len(parts) - 1u);
            str::connect(parts, ".")
        };
    #fmt["%s%s.%s", base, filename, config.stage_id]
}

fn maybe_dump_to_stdout(config: config, out: str, err: str) {
    if config.verbose {
        let sep1 = #fmt["------%s------------------------------", "stdout"];
        let sep2 = #fmt["------%s------------------------------", "stderr"];
        let sep3 = "------------------------------------------";
        io::stdout().write_line(sep1);
        io::stdout().write_line(out);
        io::stdout().write_line(sep2);
        io::stdout().write_line(err);
        io::stdout().write_line(sep3);
    }
}

fn error(err: str) { io::stdout().write_line(#fmt["\nerror: %s", err]); }

fn fatal(err: str) -> ! { error(err); fail; }

fn fatal_procres(err: str, procres: procres) -> ! {
    let msg =
        #fmt["\n\
error: %s\n\
command: %s\n\
stdout:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
stderr:\n\
------------------------------------------\n\
%s\n\
------------------------------------------\n\
\n",
             err, procres.cmdline, procres.stdout, procres.stderr];
    io::stdout().write_str(msg);
    fail;
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

// GetLastError doesn't seem to work with stack switching
// xfail-test

#[cfg(target_os = "win32")]
extern "stdcall" mod kernel32 {
    fn SetLastError(err: uint);
    fn GetLastError() -> uint;
}

#[cfg(target_os = "win32")]
pub fn main() {
    unsafe {
        let expected = 1234u;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        log(error, actual);
        assert_eq!(expected, actual);
    }
}

#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
pub fn main() { }
<commit_msg>auto merge of #10363 : astrieanna/rust/fix-x86stdcall, r=huonw<commit_after>// Copyright 2012-2013 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.

// GetLastError doesn't seem to work with stack switching

#[cfg(windows)]
mod kernel32 {
  extern "system" {
    pub fn SetLastError(err: uint);
    pub fn GetLastError() -> uint;
  }
}

#[cfg(windows)]
pub fn main() {
    unsafe {
        let expected = 1234u;
        kernel32::SetLastError(expected);
        let actual = kernel32::GetLastError();
        info!("actual = {}", actual);
        assert_eq!(expected, actual);
    }
}

#[cfg(target_os = "macos")]
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
pub fn main() { }
<|endoftext|>