<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/. */

//! Utilities for tracing JS-managed values.
//!
//! The lifetime of DOM objects is managed by the SpiderMonkey Garbage
//! Collector. A rooted DOM object implementing the interface `Foo` is traced
//! as follows:
//!
//! 1. The GC calls `_trace` defined in `FooBinding` during the marking
//!    phase. (This happens through `JSClass.trace` for non-proxy bindings, and
//!    through `ProxyTraps.trace` otherwise.)
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
//!    This is typically derived via a `#[dom_struct]` (implies `#[jstraceable]`) annotation.
//!    Non-JS-managed types have an empty inline `trace()` method,
//!    achieved via `no_jsmanaged_fields!` or similar.
//! 3. For all fields, `Foo::trace()`
//!    calls `trace()` on the field.
//!    For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
//!    `trace_reflector()`.
//! 4. `trace_reflector()` calls `trace_object()` with the `JSObject` for the
//!    reflector.
//! 5. `trace_object()` calls `JS_CallTracer()` to notify the GC, which will
//!    add the object to the graph, and will trace that object as well.
//! 6. When the GC finishes tracing, it [`finalizes`](../index.html#destruction)
//!    any reflectors that were not reachable.
//!
//! The `no_jsmanaged_fields!()` macro adds an empty implementation of `JSTraceable` to
//! a datatype.

use dom::bindings::js::JS;
use dom::bindings::refcounted::Trusted;
use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler};
use script_task::ScriptChan;

use canvas::canvas_paint_task::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle};
use cssparser::RGBA;
use encoding::types::EncodingRef;
use geom::matrix2d::Matrix2D;
use geom::rect::Rect;
use html5ever::tree_builder::QuirksMode;
use hyper::header::Headers;
use hyper::method::Method;
use js::jsapi::{JSObject, JSTracer, JS_CallTracer, JSGCTraceKind};
use js::jsval::JSVal;
use js::rust::{Cx, rt};
use layout_interface::{LayoutRPC, LayoutChan};
use libc;
use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData};
use net::image_cache_task::ImageCacheTask;
use net::storage_task::StorageType;
use script_traits::ScriptControlChan;
use script_traits::UntrustedNodeAddress;
use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::ConstellationChan;
use util::smallvec::{SmallVec1, SmallVec};
use util::str::{LengthOrPercentageOrAuto};
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::collections::hash_state::HashState;
use std::ffi::CString;
use std::hash::{Hash, Hasher};
use std::old_io::timer::Timer;
use std::rc::Rc;
use std::sync::mpsc::{Receiver, Sender};
use string_cache::{Atom, Namespace};
use style::properties::PropertyDeclarationBlock;
use url::Url;

/// A trait to allow tracing (only) DOM objects.
pub trait JSTraceable {
    /// Trace `self`.
    fn trace(&self, trc: *mut JSTracer);
}

impl<T: Reflectable> JSTraceable for JS<T> {
    fn trace(&self, trc: *mut JSTracer) {
        trace_reflector(trc, "", self.reflector());
    }
}

no_jsmanaged_fields!(EncodingRef);

no_jsmanaged_fields!(Reflector);

/// Trace a `JSVal`.
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: JSVal) {
    if !val.is_markable() {
        return;
    }

    unsafe {
        let name = CString::new(description).unwrap();
        (*tracer).debugPrinter = None;
        (*tracer).debugPrintIndex = -1;
        (*tracer).debugPrintArg = name.as_ptr() as *const libc::c_void;
        debug!("tracing value {}", description);
        JS_CallTracer(tracer, val.to_gcthing(), val.trace_kind());
    }
}

/// Trace the `JSObject` held by `reflector`.
#[allow(unrooted_must_root)]
pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Reflector) {
    trace_object(tracer, description, reflector.get_jsobject())
}

/// Trace a `JSObject`.
pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: *mut JSObject) {
    unsafe {
        let name = CString::new(description).unwrap();
        (*tracer).debugPrinter = None;
        (*tracer).debugPrintIndex = -1;
        (*tracer).debugPrintArg = name.as_ptr() as *const libc::c_void;
        debug!("tracing {}", description);
        JS_CallTracer(tracer, obj as *mut libc::c_void, JSGCTraceKind::JSTRACE_OBJECT);
    }
}

impl<T: JSTraceable> JSTraceable for RefCell<T> {
    fn trace(&self, trc: *mut JSTracer) {
        self.borrow().trace(trc)
    }
}

impl<T: JSTraceable> JSTraceable for Rc<T> {
    fn trace(&self, trc: *mut JSTracer) {
        (**self).trace(trc)
    }
}

impl<T: JSTraceable> JSTraceable for Box<T> {
    fn trace(&self, trc: *mut JSTracer) {
        (**self).trace(trc)
    }
}

impl<T: JSTraceable+Copy> JSTraceable for Cell<T> {
    fn trace(&self, trc: *mut JSTracer) {
        self.get().trace(trc)
    }
}

impl JSTraceable for *mut JSObject {
    fn trace(&self, trc: *mut JSTracer) {
        trace_object(trc, "object", *self);
    }
}

impl JSTraceable for JSVal {
    fn trace(&self, trc: *mut JSTracer) {
        trace_jsval(trc, "val", *self);
    }
}

// XXXManishearth Check if the following three are optimized to no-ops
// if e.trace() is a no-op (e.g it is an no_jsmanaged_fields type)
impl<T: JSTraceable> JSTraceable for Vec<T> {
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        for e in self.iter() {
            e.trace(trc);
        }
    }
}

// XXXManishearth Check if the following three are optimized to no-ops
// if e.trace() is a no-op (e.g it is an no_jsmanaged_fields type)
impl<T: JSTraceable + 'static> JSTraceable for SmallVec1<T> {
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        for e in self.iter() {
            e.trace(trc);
        }
    }
}

impl<T: JSTraceable> JSTraceable for Option<T> {
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        self.as_ref().map(|e| e.trace(trc));
    }
}

impl<K,V,S> JSTraceable for HashMap<K, V, S>
    where K: Hash + Eq + JSTraceable,
          V: JSTraceable,
          S: HashState,
          <S as HashState>::Hasher: Hasher,
{
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        for (k, v) in self.iter() {
            k.trace(trc);
            v.trace(trc);
        }
    }
}

impl<A: JSTraceable, B: JSTraceable> JSTraceable for (A, B) {
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        let (ref a, ref b) = *self;
        a.trace(trc);
        b.trace(trc);
    }
}

no_jsmanaged_fields!(bool, f32, f64, String, Url);
no_jsmanaged_fields!(usize, u8, u16, u32, u64);
no_jsmanaged_fields!(isize, i8, i16, i32, i64);
no_jsmanaged_fields!(Sender<T>);
no_jsmanaged_fields!(Receiver<T>);
no_jsmanaged_fields!(Rect<T>);
no_jsmanaged_fields!(ImageCacheTask, ScriptControlChan);
no_jsmanaged_fields!(Atom, Namespace, Timer);
no_jsmanaged_fields!(Trusted<T>);
no_jsmanaged_fields!(PropertyDeclarationBlock);
// These three are interdependent, if you plan to put jsmanaged data
// in one of these make sure it is propagated properly to containing structs
no_jsmanaged_fields!(SubpageId, WindowSizeData, PipelineId);
no_jsmanaged_fields!(QuirksMode);
no_jsmanaged_fields!(Cx);
no_jsmanaged_fields!(rt);
no_jsmanaged_fields!(Headers, Method);
no_jsmanaged_fields!(ConstellationChan);
no_jsmanaged_fields!(LayoutChan);
no_jsmanaged_fields!(WindowProxyHandler);
no_jsmanaged_fields!(UntrustedNodeAddress);
no_jsmanaged_fields!(LengthOrPercentageOrAuto);
no_jsmanaged_fields!(RGBA);
no_jsmanaged_fields!(Matrix2D<T>);
no_jsmanaged_fields!(StorageType);
no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);

impl JSTraceable for Box<ScriptChan+Send> {
    #[inline]
    fn trace(&self, _trc: *mut JSTracer) {
        // Do nothing
    }
}

impl<'a> JSTraceable for &'a str {
    #[inline]
    fn trace(&self, _: *mut JSTracer) {
        // Do nothing
    }
}

impl<A,B> JSTraceable for fn(A) -> B {
    #[inline]
    fn trace(&self, _: *mut JSTracer) {
        // Do nothing
    }
}

impl JSTraceable for Box<ScriptListener+'static> {
    #[inline]
    fn trace(&self, _: *mut JSTracer) {
        // Do nothing
    }
}

impl JSTraceable for Box<LayoutRPC+'static> {
    #[inline]
    fn trace(&self, _: *mut JSTracer) {
        // Do nothing
    }
}
<commit_msg>auto merge of #5389 : Manishearth/servo/trace_raw, r=jdm<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/. */

//! Utilities for tracing JS-managed values.
//!
//! The lifetime of DOM objects is managed by the SpiderMonkey Garbage
//! Collector. A rooted DOM object implementing the interface `Foo` is traced
//! as follows:
//!
//! 1. The GC calls `_trace` defined in `FooBinding` during the marking
//!    phase. (This happens through `JSClass.trace` for non-proxy bindings, and
//!    through `ProxyTraps.trace` otherwise.)
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
//!    This is typically derived via a `#[dom_struct]` (implies `#[jstraceable]`) annotation.
//!    Non-JS-managed types have an empty inline `trace()` method,
//!    achieved via `no_jsmanaged_fields!` or similar.
//! 3. For all fields, `Foo::trace()`
//!    calls `trace()` on the field.
//!    For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
//!    `trace_reflector()`.
//! 4. `trace_reflector()` calls `trace_object()` with the `JSObject` for the
//!    reflector.
//! 5. `trace_object()` calls `JS_CallTracer()` to notify the GC, which will
//!    add the object to the graph, and will trace that object as well.
//! 6. When the GC finishes tracing, it [`finalizes`](../index.html#destruction)
//!    any reflectors that were not reachable.
//!
//! The `no_jsmanaged_fields!()` macro adds an empty implementation of `JSTraceable` to
//! a datatype.

use dom::bindings::js::JS;
use dom::bindings::refcounted::Trusted;
use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler};
use script_task::ScriptChan;

use canvas::canvas_paint_task::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle};
use cssparser::RGBA;
use encoding::types::EncodingRef;
use geom::matrix2d::Matrix2D;
use geom::rect::Rect;
use html5ever::tree_builder::QuirksMode;
use hyper::header::Headers;
use hyper::method::Method;
use js::jsapi::{JSObject, JSTracer, JS_CallTracer, JSGCTraceKind};
use js::jsval::JSVal;
use js::rust::{Cx, rt};
use layout_interface::{LayoutRPC, LayoutChan};
use libc;
use msg::constellation_msg::{PipelineId, SubpageId, WindowSizeData};
use net::image_cache_task::ImageCacheTask;
use net::storage_task::StorageType;
use script_traits::ScriptControlChan;
use script_traits::UntrustedNodeAddress;
use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::ConstellationChan;
use util::smallvec::{SmallVec1, SmallVec};
use util::str::{LengthOrPercentageOrAuto};
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::collections::hash_state::HashState;
use std::ffi::CString;
use std::hash::{Hash, Hasher};
use std::old_io::timer::Timer;
use std::rc::Rc;
use std::sync::mpsc::{Receiver, Sender};
use string_cache::{Atom, Namespace};
use style::properties::PropertyDeclarationBlock;
use url::Url;

/// A trait to allow tracing (only) DOM objects.
pub trait JSTraceable {
    /// Trace `self`.
    fn trace(&self, trc: *mut JSTracer);
}

impl<T: Reflectable> JSTraceable for JS<T> {
    fn trace(&self, trc: *mut JSTracer) {
        trace_reflector(trc, "", self.reflector());
    }
}

no_jsmanaged_fields!(EncodingRef);

no_jsmanaged_fields!(Reflector);

/// Trace a `JSVal`.
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: JSVal) {
    if !val.is_markable() {
        return;
    }

    unsafe {
        let name = CString::new(description).unwrap();
        (*tracer).debugPrinter = None;
        (*tracer).debugPrintIndex = -1;
        (*tracer).debugPrintArg = name.as_ptr() as *const libc::c_void;
        debug!("tracing value {}", description);
        JS_CallTracer(tracer, val.to_gcthing(), val.trace_kind());
    }
}

/// Trace the `JSObject` held by `reflector`.
#[allow(unrooted_must_root)]
pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Reflector) {
    trace_object(tracer, description, reflector.get_jsobject())
}

/// Trace a `JSObject`.
pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: *mut JSObject) {
    unsafe {
        let name = CString::new(description).unwrap();
        (*tracer).debugPrinter = None;
        (*tracer).debugPrintIndex = -1;
        (*tracer).debugPrintArg = name.as_ptr() as *const libc::c_void;
        debug!("tracing {}", description);
        JS_CallTracer(tracer, obj as *mut libc::c_void, JSGCTraceKind::JSTRACE_OBJECT);
    }
}

impl<T: JSTraceable> JSTraceable for RefCell<T> {
    fn trace(&self, trc: *mut JSTracer) {
        self.borrow().trace(trc)
    }
}

impl<T: JSTraceable> JSTraceable for Rc<T> {
    fn trace(&self, trc: *mut JSTracer) {
        (**self).trace(trc)
    }
}

impl<T: JSTraceable> JSTraceable for Box<T> {
    fn trace(&self, trc: *mut JSTracer) {
        (**self).trace(trc)
    }
}

impl<T: JSTraceable> JSTraceable for *const T {
    fn trace(&self, trc: *mut JSTracer) {
        if !self.is_null() {
            unsafe {
                (**self).trace(trc)
            }
        }
    }
}

impl<T: JSTraceable> JSTraceable for *mut T {
    fn trace(&self, trc: *mut JSTracer) {
        if !self.is_null() {
            unsafe {
                (**self).trace(trc)
            }
        }
    }
}

impl<T: JSTraceable+Copy> JSTraceable for Cell<T> {
    fn trace(&self, trc: *mut JSTracer) {
        self.get().trace(trc)
    }
}

impl JSTraceable for *mut JSObject {
    fn trace(&self, trc: *mut JSTracer) {
        trace_object(trc, "object", *self);
    }
}

impl JSTraceable for JSVal {
    fn trace(&self, trc: *mut JSTracer) {
        trace_jsval(trc, "val", *self);
    }
}

// XXXManishearth Check if the following three are optimized to no-ops
// if e.trace() is a no-op (e.g it is an no_jsmanaged_fields type)
impl<T: JSTraceable> JSTraceable for Vec<T> {
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        for e in self.iter() {
            e.trace(trc);
        }
    }
}

// XXXManishearth Check if the following three are optimized to no-ops
// if e.trace() is a no-op (e.g it is an no_jsmanaged_fields type)
impl<T: JSTraceable + 'static> JSTraceable for SmallVec1<T> {
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        for e in self.iter() {
            e.trace(trc);
        }
    }
}

impl<T: JSTraceable> JSTraceable for Option<T> {
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        self.as_ref().map(|e| e.trace(trc));
    }
}

impl<K,V,S> JSTraceable for HashMap<K, V, S>
    where K: Hash + Eq + JSTraceable,
          V: JSTraceable,
          S: HashState,
          <S as HashState>::Hasher: Hasher,
{
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        for (k, v) in self.iter() {
            k.trace(trc);
            v.trace(trc);
        }
    }
}

impl<A: JSTraceable, B: JSTraceable> JSTraceable for (A, B) {
    #[inline]
    fn trace(&self, trc: *mut JSTracer) {
        let (ref a, ref b) = *self;
        a.trace(trc);
        b.trace(trc);
    }
}

no_jsmanaged_fields!(bool, f32, f64, String, Url);
no_jsmanaged_fields!(usize, u8, u16, u32, u64);
no_jsmanaged_fields!(isize, i8, i16, i32, i64);
no_jsmanaged_fields!(Sender<T>);
no_jsmanaged_fields!(Receiver<T>);
no_jsmanaged_fields!(Rect<T>);
no_jsmanaged_fields!(ImageCacheTask, ScriptControlChan);
no_jsmanaged_fields!(Atom, Namespace, Timer);
no_jsmanaged_fields!(Trusted<T>);
no_jsmanaged_fields!(PropertyDeclarationBlock);
// These three are interdependent, if you plan to put jsmanaged data
// in one of these make sure it is propagated properly to containing structs
no_jsmanaged_fields!(SubpageId, WindowSizeData, PipelineId);
no_jsmanaged_fields!(QuirksMode);
no_jsmanaged_fields!(Cx);
no_jsmanaged_fields!(rt);
no_jsmanaged_fields!(Headers, Method);
no_jsmanaged_fields!(ConstellationChan);
no_jsmanaged_fields!(LayoutChan);
no_jsmanaged_fields!(WindowProxyHandler);
no_jsmanaged_fields!(UntrustedNodeAddress);
no_jsmanaged_fields!(LengthOrPercentageOrAuto);
no_jsmanaged_fields!(RGBA);
no_jsmanaged_fields!(Matrix2D<T>);
no_jsmanaged_fields!(StorageType);
no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);

impl JSTraceable for Box<ScriptChan+Send> {
    #[inline]
    fn trace(&self, _trc: *mut JSTracer) {
        // Do nothing
    }
}

impl<'a> JSTraceable for &'a str {
    #[inline]
    fn trace(&self, _: *mut JSTracer) {
        // Do nothing
    }
}

impl<A,B> JSTraceable for fn(A) -> B {
    #[inline]
    fn trace(&self, _: *mut JSTracer) {
        // Do nothing
    }
}

impl JSTraceable for Box<ScriptListener+'static> {
    #[inline]
    fn trace(&self, _: *mut JSTracer) {
        // Do nothing
    }
}

impl JSTraceable for Box<LayoutRPC+'static> {
    #[inline]
    fn trace(&self, _: *mut JSTracer) {
        // Do nothing
    }
}
<|endoftext|>


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

use driver::session::NoDebugInfo;
use driver::session::Session;
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
use lib::llvm::{llvm, TargetData, TypeNames};
use lib::llvm::mk_target_data;
use metadata::common::LinkMeta;
use middle::astencode;
use middle::resolve;
use middle::trans::adt;
use middle::trans::base;
use middle::trans::builder::Builder;
use middle::trans::common::{C_i32, C_null};
use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
use middle::trans::debuginfo;
use middle::trans::type_::Type;
use middle::ty;
use util::sha2::Sha256;
use util::nodemap::{NodeMap, NodeSet, DefIdMap};

use std::cell::{Cell, RefCell};
use std::c_str::ToCStr;
use std::libc::c_uint;
use std::ptr;
use collections::{HashMap, HashSet};
use syntax::ast;
use syntax::parse::token::InternedString;

pub struct CrateContext {
    pub llmod: ModuleRef,
    pub llcx: ContextRef,
    pub metadata_llmod: ModuleRef,
    pub td: TargetData,
    pub tn: TypeNames,
    pub externs: RefCell<ExternMap>,
    pub intrinsics: HashMap<&'static str, ValueRef>,
    pub item_vals: RefCell<NodeMap<ValueRef>>,
    pub exp_map2: resolve::ExportMap2,
    pub reachable: NodeSet,
    pub item_symbols: RefCell<NodeMap<~str>>,
    pub link_meta: LinkMeta,
    pub drop_glues: RefCell<HashMap<ty::t, ValueRef>>,
    pub tydescs: RefCell<HashMap<ty::t, @tydesc_info>>,
    // Set when running emit_tydescs to enforce that no more tydescs are
    // created.
    pub finished_tydescs: Cell<bool>,
    // Track mapping of external ids to local items imported for inlining
    pub external: RefCell<DefIdMap<Option<ast::NodeId>>>,
    // Backwards version of the `external` map (inlined items to where they
    // came from)
    pub external_srcs: RefCell<NodeMap<ast::DefId>>,
    // A set of static items which cannot be inlined into other crates. This
    // will pevent in IIItem() structures from being encoded into the metadata
    // that is generated
    pub non_inlineable_statics: RefCell<NodeSet>,
    // Cache instances of monomorphized functions
    pub monomorphized: RefCell<HashMap<mono_id, ValueRef>>,
    pub monomorphizing: RefCell<DefIdMap<uint>>,
    // Cache generated vtables
    pub vtables: RefCell<HashMap<(ty::t, mono_id), ValueRef>>,
    // Cache of constant strings,
    pub const_cstr_cache: RefCell<HashMap<InternedString, ValueRef>>,

    // Reverse-direction for const ptrs cast from globals.
    // Key is an int, cast from a ValueRef holding a *T,
    // Val is a ValueRef holding a *[T].
    //
    // Needed because LLVM loses pointer->pointee association
    // when we ptrcast, and we have to ptrcast during translation
    // of a [T] const because we form a slice, a [*T,int] pair, not
    // a pointer to an LLVM array type.
    pub const_globals: RefCell<HashMap<int, ValueRef>>,

    // Cache of emitted const values
    pub const_values: RefCell<NodeMap<ValueRef>>,

    // Cache of external const values
    pub extern_const_values: RefCell<DefIdMap<ValueRef>>,

    pub impl_method_cache: RefCell<HashMap<(ast::DefId, ast::Name), ast::DefId>>,

    // Cache of closure wrappers for bare fn's.
    pub closure_bare_wrapper_cache: RefCell<HashMap<ValueRef, ValueRef>>,

    pub lltypes: RefCell<HashMap<ty::t, Type>>,
    pub llsizingtypes: RefCell<HashMap<ty::t, Type>>,
    pub adt_reprs: RefCell<HashMap<ty::t, @adt::Repr>>,
    pub symbol_hasher: RefCell<Sha256>,
    pub type_hashcodes: RefCell<HashMap<ty::t, ~str>>,
    pub all_llvm_symbols: RefCell<HashSet<~str>>,
    pub tcx: ty::ctxt,
    pub maps: astencode::Maps,
    pub stats: @Stats,
    pub int_type: Type,
    pub opaque_vec_type: Type,
    pub builder: BuilderRef_res,
    // Set when at least one function uses GC. Needed so that
    // decl_gc_metadata knows whether to link to the module metadata, which
    // is not emitted by LLVM's GC pass when no functions use GC.
    pub uses_gc: bool,
    pub dbg_cx: Option<debuginfo::CrateDebugContext>,
}

impl CrateContext {
    pub fn new(name: &str,
               tcx: ty::ctxt,
               emap2: resolve::ExportMap2,
               maps: astencode::Maps,
               symbol_hasher: Sha256,
               link_meta: LinkMeta,
               reachable: NodeSet)
               -> CrateContext {
        unsafe {
            let llcx = llvm::LLVMContextCreate();
            let llmod = name.with_c_str(|buf| {
                llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
            });
            let metadata_llmod = format!("{}_metadata", name).with_c_str(|buf| {
                llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
            });
            tcx.sess.targ_cfg.target_strs.data_layout.with_c_str(|buf| {
                llvm::LLVMSetDataLayout(llmod, buf);
                llvm::LLVMSetDataLayout(metadata_llmod, buf);
            });
            tcx.sess.targ_cfg.target_strs.target_triple.with_c_str(|buf| {
                llvm::LLVMRustSetNormalizedTarget(llmod, buf);
                llvm::LLVMRustSetNormalizedTarget(metadata_llmod, buf);
            });

            let td = mk_target_data(tcx.sess.targ_cfg.target_strs.data_layout);

            let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
                Some(debuginfo::CrateDebugContext::new(llmod))
            } else {
                None
            };

            let mut ccx = CrateContext {
                llmod: llmod,
                llcx: llcx,
                metadata_llmod: metadata_llmod,
                td: td,
                tn: TypeNames::new(),
                externs: RefCell::new(HashMap::new()),
                intrinsics: HashMap::new(),
                item_vals: RefCell::new(NodeMap::new()),
                exp_map2: emap2,
                reachable: reachable,
                item_symbols: RefCell::new(NodeMap::new()),
                link_meta: link_meta,
                drop_glues: RefCell::new(HashMap::new()),
                tydescs: RefCell::new(HashMap::new()),
                finished_tydescs: Cell::new(false),
                external: RefCell::new(DefIdMap::new()),
                external_srcs: RefCell::new(NodeMap::new()),
                non_inlineable_statics: RefCell::new(NodeSet::new()),
                monomorphized: RefCell::new(HashMap::new()),
                monomorphizing: RefCell::new(DefIdMap::new()),
                vtables: RefCell::new(HashMap::new()),
                const_cstr_cache: RefCell::new(HashMap::new()),
                const_globals: RefCell::new(HashMap::new()),
                const_values: RefCell::new(NodeMap::new()),
                extern_const_values: RefCell::new(DefIdMap::new()),
                impl_method_cache: RefCell::new(HashMap::new()),
                closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
                lltypes: RefCell::new(HashMap::new()),
                llsizingtypes: RefCell::new(HashMap::new()),
                adt_reprs: RefCell::new(HashMap::new()),
                symbol_hasher: RefCell::new(symbol_hasher),
                type_hashcodes: RefCell::new(HashMap::new()),
                all_llvm_symbols: RefCell::new(HashSet::new()),
                tcx: tcx,
                maps: maps,
                stats: @Stats {
                    n_static_tydescs: Cell::new(0u),
                    n_glues_created: Cell::new(0u),
                    n_null_glues: Cell::new(0u),
                    n_real_glues: Cell::new(0u),
                    n_fns: Cell::new(0u),
                    n_monos: Cell::new(0u),
                    n_inlines: Cell::new(0u),
                    n_closures: Cell::new(0u),
                    n_llvm_insns: Cell::new(0u),
                    llvm_insns: RefCell::new(HashMap::new()),
                    fn_stats: RefCell::new(Vec::new()),
                },
                int_type: Type::from_ref(ptr::null()),
                opaque_vec_type: Type::from_ref(ptr::null()),
                builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
                uses_gc: false,
                dbg_cx: dbg_cx,
            };

            ccx.int_type = Type::int(&ccx);
            ccx.opaque_vec_type = Type::opaque_vec(&ccx);

            ccx.tn.associate_type("tydesc", &Type::tydesc(&ccx));

            let mut str_slice_ty = Type::named_struct(&ccx, "str_slice");
            str_slice_ty.set_struct_body([Type::i8p(&ccx), ccx.int_type], false);
            ccx.tn.associate_type("str_slice", &str_slice_ty);

            base::declare_intrinsics(&mut ccx);

            if ccx.sess().count_llvm_insns() {
                base::init_insn_ctxt()
            }

            ccx
        }
    }

    pub fn tcx<'a>(&'a self) -> &'a ty::ctxt {
        &self.tcx
    }

    pub fn sess<'a>(&'a self) -> &'a Session {
        &self.tcx.sess
    }

    pub fn builder<'a>(&'a self) -> Builder<'a> {
        Builder::new(self)
    }

    pub fn const_inbounds_gepi(&self,
                               pointer: ValueRef,
                               indices: &[uint]) -> ValueRef {
        debug!("const_inbounds_gepi: pointer={} indices={:?}",
               self.tn.val_to_str(pointer), indices);
        let v: Vec<ValueRef> =
            indices.iter().map(|i| C_i32(self, *i as i32)).collect();
        unsafe {
            llvm::LLVMConstInBoundsGEP(pointer,
                                       v.as_ptr(),
                                       indices.len() as c_uint)
        }
    }

    pub fn offsetof_gep(&self,
                        llptr_ty: Type,
                        indices: &[uint]) -> ValueRef {
        /*!
         * Returns the offset of applying the given GEP indices
         * to an instance of `llptr_ty`. Similar to `offsetof` in C,
         * except that `llptr_ty` must be a pointer type.
         */

        unsafe {
            let null = C_null(llptr_ty);
            llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
                                    self.int_type.to_ref())
        }
    }

    pub fn tydesc_type(&self) -> Type {
        self.tn.find_type("tydesc").unwrap()
    }
}
<commit_msg>rustc: make comments on CrateContext doc comments<commit_after>// Copyright 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.

use driver::session::NoDebugInfo;
use driver::session::Session;
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
use lib::llvm::{llvm, TargetData, TypeNames};
use lib::llvm::mk_target_data;
use metadata::common::LinkMeta;
use middle::astencode;
use middle::resolve;
use middle::trans::adt;
use middle::trans::base;
use middle::trans::builder::Builder;
use middle::trans::common::{C_i32, C_null};
use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
use middle::trans::debuginfo;
use middle::trans::type_::Type;
use middle::ty;
use util::sha2::Sha256;
use util::nodemap::{NodeMap, NodeSet, DefIdMap};

use std::cell::{Cell, RefCell};
use std::c_str::ToCStr;
use std::libc::c_uint;
use std::ptr;
use collections::{HashMap, HashSet};
use syntax::ast;
use syntax::parse::token::InternedString;

pub struct CrateContext {
    pub llmod: ModuleRef,
    pub llcx: ContextRef,
    pub metadata_llmod: ModuleRef,
    pub td: TargetData,
    pub tn: TypeNames,
    pub externs: RefCell<ExternMap>,
    pub intrinsics: HashMap<&'static str, ValueRef>,
    pub item_vals: RefCell<NodeMap<ValueRef>>,
    pub exp_map2: resolve::ExportMap2,
    pub reachable: NodeSet,
    pub item_symbols: RefCell<NodeMap<~str>>,
    pub link_meta: LinkMeta,
    pub drop_glues: RefCell<HashMap<ty::t, ValueRef>>,
    pub tydescs: RefCell<HashMap<ty::t, @tydesc_info>>,
    /// Set when running emit_tydescs to enforce that no more tydescs are
    /// created.
    pub finished_tydescs: Cell<bool>,
    /// Track mapping of external ids to local items imported for inlining
    pub external: RefCell<DefIdMap<Option<ast::NodeId>>>,
    /// Backwards version of the `external` map (inlined items to where they
    /// came from)
    pub external_srcs: RefCell<NodeMap<ast::DefId>>,
    /// A set of static items which cannot be inlined into other crates. This
    /// will pevent in IIItem() structures from being encoded into the metadata
    /// that is generated
    pub non_inlineable_statics: RefCell<NodeSet>,
    /// Cache instances of monomorphized functions
    pub monomorphized: RefCell<HashMap<mono_id, ValueRef>>,
    pub monomorphizing: RefCell<DefIdMap<uint>>,
    /// Cache generated vtables
    pub vtables: RefCell<HashMap<(ty::t, mono_id), ValueRef>>,
    /// Cache of constant strings,
    pub const_cstr_cache: RefCell<HashMap<InternedString, ValueRef>>,

    /// Reverse-direction for const ptrs cast from globals.
    /// Key is an int, cast from a ValueRef holding a *T,
    /// Val is a ValueRef holding a *[T].
    ///
    /// Needed because LLVM loses pointer->pointee association
    /// when we ptrcast, and we have to ptrcast during translation
    /// of a [T] const because we form a slice, a [*T,int] pair, not
    /// a pointer to an LLVM array type.
    pub const_globals: RefCell<HashMap<int, ValueRef>>,

    /// Cache of emitted const values
    pub const_values: RefCell<NodeMap<ValueRef>>,

    /// Cache of external const values
    pub extern_const_values: RefCell<DefIdMap<ValueRef>>,

    pub impl_method_cache: RefCell<HashMap<(ast::DefId, ast::Name), ast::DefId>>,

    /// Cache of closure wrappers for bare fn's.
    pub closure_bare_wrapper_cache: RefCell<HashMap<ValueRef, ValueRef>>,

    pub lltypes: RefCell<HashMap<ty::t, Type>>,
    pub llsizingtypes: RefCell<HashMap<ty::t, Type>>,
    pub adt_reprs: RefCell<HashMap<ty::t, @adt::Repr>>,
    pub symbol_hasher: RefCell<Sha256>,
    pub type_hashcodes: RefCell<HashMap<ty::t, ~str>>,
    pub all_llvm_symbols: RefCell<HashSet<~str>>,
    pub tcx: ty::ctxt,
    pub maps: astencode::Maps,
    pub stats: @Stats,
    pub int_type: Type,
    pub opaque_vec_type: Type,
    pub builder: BuilderRef_res,
    /// Set when at least one function uses GC. Needed so that
    /// decl_gc_metadata knows whether to link to the module metadata, which
    /// is not emitted by LLVM's GC pass when no functions use GC.
    pub uses_gc: bool,
    pub dbg_cx: Option<debuginfo::CrateDebugContext>,
}

impl CrateContext {
    pub fn new(name: &str,
               tcx: ty::ctxt,
               emap2: resolve::ExportMap2,
               maps: astencode::Maps,
               symbol_hasher: Sha256,
               link_meta: LinkMeta,
               reachable: NodeSet)
               -> CrateContext {
        unsafe {
            let llcx = llvm::LLVMContextCreate();
            let llmod = name.with_c_str(|buf| {
                llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
            });
            let metadata_llmod = format!("{}_metadata", name).with_c_str(|buf| {
                llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
            });
            tcx.sess.targ_cfg.target_strs.data_layout.with_c_str(|buf| {
                llvm::LLVMSetDataLayout(llmod, buf);
                llvm::LLVMSetDataLayout(metadata_llmod, buf);
            });
            tcx.sess.targ_cfg.target_strs.target_triple.with_c_str(|buf| {
                llvm::LLVMRustSetNormalizedTarget(llmod, buf);
                llvm::LLVMRustSetNormalizedTarget(metadata_llmod, buf);
            });

            let td = mk_target_data(tcx.sess.targ_cfg.target_strs.data_layout);

            let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
                Some(debuginfo::CrateDebugContext::new(llmod))
            } else {
                None
            };

            let mut ccx = CrateContext {
                llmod: llmod,
                llcx: llcx,
                metadata_llmod: metadata_llmod,
                td: td,
                tn: TypeNames::new(),
                externs: RefCell::new(HashMap::new()),
                intrinsics: HashMap::new(),
                item_vals: RefCell::new(NodeMap::new()),
                exp_map2: emap2,
                reachable: reachable,
                item_symbols: RefCell::new(NodeMap::new()),
                link_meta: link_meta,
                drop_glues: RefCell::new(HashMap::new()),
                tydescs: RefCell::new(HashMap::new()),
                finished_tydescs: Cell::new(false),
                external: RefCell::new(DefIdMap::new()),
                external_srcs: RefCell::new(NodeMap::new()),
                non_inlineable_statics: RefCell::new(NodeSet::new()),
                monomorphized: RefCell::new(HashMap::new()),
                monomorphizing: RefCell::new(DefIdMap::new()),
                vtables: RefCell::new(HashMap::new()),
                const_cstr_cache: RefCell::new(HashMap::new()),
                const_globals: RefCell::new(HashMap::new()),
                const_values: RefCell::new(NodeMap::new()),
                extern_const_values: RefCell::new(DefIdMap::new()),
                impl_method_cache: RefCell::new(HashMap::new()),
                closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
                lltypes: RefCell::new(HashMap::new()),
                llsizingtypes: RefCell::new(HashMap::new()),
                adt_reprs: RefCell::new(HashMap::new()),
                symbol_hasher: RefCell::new(symbol_hasher),
                type_hashcodes: RefCell::new(HashMap::new()),
                all_llvm_symbols: RefCell::new(HashSet::new()),
                tcx: tcx,
                maps: maps,
                stats: @Stats {
                    n_static_tydescs: Cell::new(0u),
                    n_glues_created: Cell::new(0u),
                    n_null_glues: Cell::new(0u),
                    n_real_glues: Cell::new(0u),
                    n_fns: Cell::new(0u),
                    n_monos: Cell::new(0u),
                    n_inlines: Cell::new(0u),
                    n_closures: Cell::new(0u),
                    n_llvm_insns: Cell::new(0u),
                    llvm_insns: RefCell::new(HashMap::new()),
                    fn_stats: RefCell::new(Vec::new()),
                },
                int_type: Type::from_ref(ptr::null()),
                opaque_vec_type: Type::from_ref(ptr::null()),
                builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
                uses_gc: false,
                dbg_cx: dbg_cx,
            };

            ccx.int_type = Type::int(&ccx);
            ccx.opaque_vec_type = Type::opaque_vec(&ccx);

            ccx.tn.associate_type("tydesc", &Type::tydesc(&ccx));

            let mut str_slice_ty = Type::named_struct(&ccx, "str_slice");
            str_slice_ty.set_struct_body([Type::i8p(&ccx), ccx.int_type], false);
            ccx.tn.associate_type("str_slice", &str_slice_ty);

            base::declare_intrinsics(&mut ccx);

            if ccx.sess().count_llvm_insns() {
                base::init_insn_ctxt()
            }

            ccx
        }
    }

    pub fn tcx<'a>(&'a self) -> &'a ty::ctxt {
        &self.tcx
    }

    pub fn sess<'a>(&'a self) -> &'a Session {
        &self.tcx.sess
    }

    pub fn builder<'a>(&'a self) -> Builder<'a> {
        Builder::new(self)
    }

    pub fn const_inbounds_gepi(&self,
                               pointer: ValueRef,
                               indices: &[uint]) -> ValueRef {
        debug!("const_inbounds_gepi: pointer={} indices={:?}",
               self.tn.val_to_str(pointer), indices);
        let v: Vec<ValueRef> =
            indices.iter().map(|i| C_i32(self, *i as i32)).collect();
        unsafe {
            llvm::LLVMConstInBoundsGEP(pointer,
                                       v.as_ptr(),
                                       indices.len() as c_uint)
        }
    }

    pub fn offsetof_gep(&self,
                        llptr_ty: Type,
                        indices: &[uint]) -> ValueRef {
        /*!
         * Returns the offset of applying the given GEP indices
         * to an instance of `llptr_ty`. Similar to `offsetof` in C,
         * except that `llptr_ty` must be a pointer type.
         */

        unsafe {
            let null = C_null(llptr_ty);
            llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
                                    self.int_type.to_ref())
        }
    }

    pub fn tydesc_type(&self) -> Type {
        self.tn.find_type("tydesc").unwrap()
    }
}
<|endoftext|>


<commit_before><commit_msg>generic bounds<commit_after>use std::fmt::Debug;

trait HasArea {
    fn  area(&self) -> f64;
}

#[derive(Debug)]
struct Rectangle { length: f64, height: f64}

#[allow(dead_code)]
struct Triangle { length: f64, height: f64}

impl HasArea for Rectangle {

    fn area(&self) -> f64 {
        self.length * self.height
    }
}

fn print_debug<T: Debug>(t: &T) { // allows only Ts implementing Debug
    println!("{:?}",t);
}

fn area<T: HasArea>(t: &T) -> f64 {
    t.area()
}

fn main() {

    let rect = Rectangle { length: 5.0, height: 4.0};

    let tri = Triangle { length: 6.0, height: 7.0 };

    print_debug(&rect);
    println!("Area: {}", area(&rect));

    // fails
    // print_debug(&tri); // the trait `std::fmt::Debug` is not implemented for `Triangle`
    // println!("Area: {}", area(&tri));// the trait `HasArea` is not implemented for `Triangle`

}
<|endoftext|>


<commit_before><commit_msg>Added FileWatcher::from( FileIndex ).<commit_after><|endoftext|>


<commit_before><commit_msg>Added an example [skip ci]<commit_after>extern crate gravity;

use std::mem;
use std::ffi::CString;
use gravity::*;

// Source code for the Gravity application
static SRC: &'static str = "func main(){ \
                                return 11 + 4; \
                            }";

extern "C" fn report_error(error_type: error_type_t,
                           _: *const std::os::raw::c_char,
                           error_desc: error_desc_t,
                           _: *mut std::os::raw::c_void){
    panic!("Error {:?}: {:?}", error_type, error_desc);
}

fn main(){
    let source = CString::new(SRC).unwrap();

    unsafe{
        // Configure a VM delegate
        let mut delegate: gravity_delegate_t = mem::zeroed();
        delegate.error_callback = Some(report_error);

        // Compile source into a closure
        let compiler = gravity_compiler_create(&mut delegate);
        let closure = gravity_compiler_run(compiler, source.as_ptr(), SRC.len(), 0, true);

        if closure.is_null() {
            panic!("Failed to compile source into a closure");
        }

        // Create a new VM
        let vm = gravity_vm_new(&mut delegate);

        // Transfer memory from the compiler to the VM, then free the compiler
        gravity_compiler_transfer(compiler, vm);
        gravity_compiler_free(compiler);

        // Execute the previously compiled closure
        if gravity_vm_runmain(vm, closure){
            let result = gravity_vm_result(vm);
            let time = gravity_vm_time(vm);

            println!("Result: {} (in {} ms)", result.__bindgen_anon_1.bindgen_union_field, time);
        }

        // Free the VM and the core classes
        gravity_vm_free(vm);
        gravity_core_free();
    }
}
<|endoftext|>


<commit_before><commit_msg>add regression test for #30225<commit_after>// Copyright 2016 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.

// Regression test for #30225, which was an ICE that would trigger as
// a result of a poor interaction between trait result caching and
// type inference. Specifically, at that time, unification could cause
// unrelated type variables to become instantiated, if subtyping
// relationships existed. These relationships are now propagated
// through obligations and hence everything works out fine.

trait Foo<U,V> : Sized {
    fn foo(self, u: Option<U>, v: Option<V>) {}
}

struct A;
struct B;

impl Foo<A, B> for () {}      // impl A
impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity

fn toxic() {
    // cache the resolution <() as Foo<$0,$1>> = impl A
    let u = None;
    let v = None;
    Foo::foo((), u, v);
}

fn bomb() {
    let mut u = None; // type is Option<$0>
    let mut v = None; // type is Option<$1>
    let mut x = None; // type is Option<$2>

    Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
    u = v; // mark $0 and $1 in a subtype relationship
    //~^ ERROR mismatched types
    x = Some(()); // set $2 = (), allowing impl selection
                  // to proceed for <() as Foo<$0, $1>> = impl A.
                  // kaboom, this *used* to trigge an ICE
}

fn main() {}
<|endoftext|>


<commit_before><commit_msg>Add another test using projection types in impls.<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.

// Test where the impl self type uses a projection from a constant type.

trait Int
{
    type T;
}

trait NonZero
{
    fn non_zero(self) -> bool;
}

impl Int for i32 { type T = i32; }
impl Int for i64 { type T = i64; }
impl Int for u32 { type T = u32; }
impl Int for u64 { type T = u64; }

impl NonZero for <i32 as Int>::T { fn non_zero(self) -> bool { self != 0 } }
impl NonZero for <i64 as Int>::T { fn non_zero(self) -> bool { self != 0 } }
impl NonZero for <u32 as Int>::T { fn non_zero(self) -> bool { self != 0 } }
impl NonZero for <u64 as Int>::T { fn non_zero(self) -> bool { self != 0 } }

fn main ()
{
    assert!(NonZero::non_zero(22_i32));
    assert!(NonZero::non_zero(22_i64));
    assert!(NonZero::non_zero(22_u32));
    assert!(NonZero::non_zero(22_u64));

    assert!(!NonZero::non_zero(0_i32));
    assert!(!NonZero::non_zero(0_i64));
    assert!(!NonZero::non_zero(0_u32));
    assert!(!NonZero::non_zero(0_u64));
}
<|endoftext|>


<commit_before><commit_msg>add container.rs<commit_after>extern crate libc;
extern crate x11;

use x11::xlib;
use std::ffi;
use std::ptr;
use std::mem;
use std::rc::{ Rc, Weak };
use std::cell::RefCell;
use std::boxed::Box;
use super::layout;
use super::super::libx;

const CWX: libc::c_uint = 1<<0;
const CWY: libc::c_uint = 1<<1;
const CWWidth: libc::c_uint = 1<<2;
const CWHeight: libc::c_uint = 1<<3;
const CWBorderWidth: libc::c_uint = 1<<4;
const CWSibling: libc::c_uint =	1<<5;
const CWStackMode: libc::c_uint = 1<<6;

pub const TITLE_HEIGHT: libc::c_int = 20;

pub struct Container {
    pub id: xlib::Window,
    pub visible: bool,
    pub titlebar_height: usize,
    pub pid: Option<xlib::Window>,
    pub clients: Vec<Container>,
    pub context: libx::Context,
    layout: Box<layout::Layout>,
}

impl PartialEq for Container {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Container {
    pub fn new(context: libx::Context, parent: Option<xlib::Window>) -> Container{
        let pid = match parent {
            Some(c) => {
                c
            }
            None => {
                context.root
            }
        };
        let attrs = libx::get_window_attributes(context, pid);

        let id = libx::create_window(context, pid,
                                     attrs.x, attrs.y,
                                     attrs.width as libc::c_uint,
                                     attrs.height as libc::c_uint);
        libx::select_input(context, id, xlib::SubstructureNotifyMask | xlib::SubstructureRedirectMask);
        let mut c = Container::from_id(context, id);
        c.pid = Some(pid);
        c
    }

    pub fn from_id(context: libx::Context, id: xlib::Window) -> Container {
        Container {
            context: context,
            clients: Vec::new(),
            pid: None,
            visible: false,
            id: id,
            titlebar_height: 0,
            layout: Box::new(layout::TilingLayout::new(layout::Direction::Horizontal))
        }
    }

    pub fn print_tree(&self, indent: i32) {
        for i in 0..indent {
            print!(" ");
        }
        let attrs = libx::get_window_attributes(self.context, self.id);
        println!("C {} pid:{} x:{} y:{} w:{} h:{}", self.id, self.pid.unwrap_or(0), attrs.x, attrs.y, attrs.width, attrs.height);
        for client in self.clients.iter() {
            client.print_tree(indent+4);
        }
    }

    // pub fn is_top(&self) -> bool {
    //     let top = self.get_top();
    //     match top {
    //         Some(w) => {
    //             w.id == self.id
    //         }
    //         Noen => false
    //     }
    // }

    pub fn is_empty(&self) -> bool{
        self.clients.is_empty()
    }

    pub fn size(&self) -> usize {
        self.clients.len()
    }
    pub fn add(&mut self, mut client: Container) {
        if client.pid.is_none() || client.pid.unwrap() != self.id {
            libx::reparent(self.context, client.id, self.id, 0, 0);
            client.pid = Some(self.id);
        }
        self.clients.push(client);
    }

    pub fn remove(&mut self, id: xlib::Window) -> Option<Container>{
        let res = self.contain(id);
        match res {
            Some(index) => {
                let r = self.clients.remove(index);
                Some(r)
            }
            None => {
                for c in self.clients.iter_mut() {
                    let r = c.remove(id);
                    if r.is_some(){
                        return r;
                    }
                }
                None
            }
        }
    }

    pub fn get(&self, index: usize) -> Option<&Container> {
        self.clients.get(index)
    }
    pub fn contain(&self, id: xlib::Window) -> Option<usize>{
        self.clients.iter().position(|x| (*x).id == id)
    }

    pub fn configure(&self, x: i32, y: i32, width: usize, height: usize) {
        let mask = CWX | CWY | CWHeight | CWWidth;

        let mut change = xlib::XWindowChanges {
            x: x,
            y: y,
            width: width as i32,
            height: height as i32,
            border_width: 0,
            sibling: 0,
            stack_mode: 0
        };
        libx::configure_window(self.context, self.id, mask, change);

        // layout for children clients
        self.update();
    }

    pub fn update(&self) {
        self.layout.configure(self);
    }

    pub fn map(&self) {
        // self.visible = true;
        libx::map_window(self.context, self.id);
        for client in self.clients.iter() {
            client.map();
        }
    }

    pub fn unmap(&self) {
        // self.visible = false;
        for client in self.clients.iter() {
            client.unmap();
        }
        libx::unmap_window(self.context, self.id);
    }

    pub fn destroy(&self) -> bool {
        // can distroy only if it has no clients
        if self.clients.is_empty() {
            unsafe{
                xlib::XDestroyWindow(self.context.display, self.id);
                true
            }
        }
        else {
            false
        }
    }

    pub fn next_client(&self, id: xlib::Window) -> Option<&Container>{
        match self.contain(id) {
            Some(i) => {
                let mut next = i+1;
                if next == self.size() {
                    next = 0;
                }
                self.get(next)
            }
            None => {
                None
            }
        }
    }

    pub fn last_client(&self, id: xlib::Window) -> Option<&Container>{
        match self.contain(id) {
            Some(i) => {
                let mut last = i-1;
                if last < 0 {
                    last = self.size() - 1
                }
                self.get(last)
            }
            None => {
                None
            }
        }
    }

    pub fn change_layout(&mut self, layout_type: layout::Type) {
        let t = self.layout.get_type();
        if t == layout_type {
            self.layout.toggle();
        }
        else{
            match layout_type {
                layout::Type::Tiling => {
                    let tmp = layout::TilingLayout::new(layout::Direction::Horizontal);
                    self.layout = Box::new(tmp);
                }
                layout::Type::Tab => {
                    let tmp = layout::TabLayout::new();
                    self.layout = Box::new(tmp);
                }
            }
        }
    }

    // pub fn split(&self, index: usize) -> bool {
    //     let res = self.remove(index);
    //     match res {
    //         Some(client) => {
    //             if client.is_empty() {
    //                 let container = Container::new(self.context, self);
    //                 container.add(client);
    //                 self.clients[index] = container;
    //                 true
    //             }
    //             else{
    //                 // client is not a leaf node, can't split
    //                 false
    //             }
    //         }
    //         None => { false }
    //     }
    // }

    pub fn focus(&self) {
        libx::set_input_focus(self.context, self.id);
        // match self.client {
        //     Some(id) => {
        //         libx::set_input_focus(self.context, id);
        //         self.draw_titlebar(true);
        //     }
        //     None => {
        //         libx::set_input_focus(self.context, self.id);
        //     }
        // }
    }

    pub fn unfocus(&self) {

    }

    pub fn switch_client(&self) {
        let (x, _) = libx::get_input_focus(self.context);

    }

    pub fn decorate(&self) {
        let attrs = libx::get_window_attributes(self.context, self.id);
        let screen = self.context.screen_num;
        let root = self.context.root;
        let display = self.context.display;
        let mut values: xlib::XGCValues = unsafe{ mem::zeroed() };
        // let gc = libx::create_gc(self.context, self.id, 0, values);
        let gc = libx::default_gc(self.context, screen);

        unsafe {
            let black = xlib::XBlackPixel(self.context.display, screen);
            let white = xlib::XWhitePixel(self.context.display, screen);

            xlib::XSetLineAttributes(self.context.display, gc, 5, 0, 0, 0);

            let cmap = xlib::XDefaultColormap(self.context.display, screen);
            let mut color: xlib::XColor = mem::zeroed();
            let name = ffi::CString::new("blue").unwrap().as_ptr();
            let r = xlib::XParseColor(self.context.display, cmap, name, &mut color);
            xlib::XAllocColor(self.context.display, cmap, &mut color);

            let (focus_id,_) = libx::get_input_focus(self.context);
            // try draw rectangle
            if focus_id == self.id || self.contain(focus_id).is_some(){
                xlib::XSetBackground(self.context.display, gc,
                                     black);
                xlib::XSetForeground(self.context.display, gc,
                                     color.pixel);
            }
            else {
                xlib::XSetBackground(self.context.display, gc,
                                     black);
                xlib::XSetForeground(self.context.display, gc,
                                     black);
            }
            let r = xlib::XFillRectangle(self.context.display,
                                         self.id, gc,
                                         1, 1,
                                         attrs.width as libc::c_uint,
                                         TITLE_HEIGHT as libc::c_uint);
        }
    }

}

// #[test]
// fn window_eq() {
//     use std::ptr;
//     let c1 = libx::Context {
//         display: ptr::null_mut()
//     };
//     let w1 = Window::new(c1, 1);
//     let c2 = libx::Context {
//         display: ptr::null_mut()
//     };
//     let w2 = Window::new(c2, 1);
//     assert_eq!(w1, w2);
// }
<|endoftext|>


<commit_before><commit_msg>128bit stable<commit_after><|endoftext|>


<commit_before>import driver::session;

import option::{none, some};

import std::map::hashmap;
import vec;

import syntax::ast::{crate, expr_, expr_mac, mac_invoc};
import syntax::fold::*;
import syntax::ext::base::*;
import syntax::parse::parser::parse_expr_from_source_str;

fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt, e: expr_,
               fld: ast_fold, orig: fn@(expr_, ast_fold) -> expr_) -> expr_ {
    ret alt e {
          expr_mac(mac) {
            alt mac.node {
              mac_invoc(pth, args, body) {
                assert (vec::len(pth.node.idents) > 0u);
                let extname = pth.node.idents[0];
                alt exts.find(extname) {
                  none {
                    cx.span_fatal(pth.span,
                                  #fmt["macro undefined: '%s'", extname])
                  }
                  some(normal(ext)) {
                    let expanded = ext(cx, pth.span, args, body);

                    cx.bt_push(mac.span);
                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    fully_expanded
                  }
                  some(macro_defining(ext)) {
                    let named_extension = ext(cx, pth.span, args, body);
                    exts.insert(named_extension.ident, named_extension.ext);
                    ast::expr_rec([], none)
                  }
                }
              }
              _ { cx.span_bug(mac.span, "naked syntactic bit") }
            }
          }
          _ { orig(e, fld) }
        };
}

// FIXME: this is a terrible kludge to inject some macros into the default
// compilation environment. When the macro-definition system is substantially
// more mature, these should move from here, into a compiled part of libcore
// at very least.

fn core_macros() -> str {
    ret
"{
    #macro([#error[f, ...], log(core::error, #fmt[f, ...])]);
    #macro([#warn[f, ...], log(core::warn, #fmt[f, ...])]);
    #macro([#info[f, ...], log(core::info, #fmt[f, ...])]);
    #macro([#debug[f, ...], log(core::debug, #fmt[f, ...])]);
}";
}

fn expand_crate(sess: session::session, c: @crate) -> @crate {
    let exts = syntax_expander_table();
    let afp = default_ast_fold();
    let cx: ext_ctxt = mk_ctxt(sess);
    let f_pre =
        {fold_expr: bind expand_expr(exts, cx, _, _, afp.fold_expr)
            with *afp};
    let f = make_fold(f_pre);
    let cm = parse_expr_from_source_str("-", core_macros(),
                                        sess.opts.cfg,
                                        sess.parse_sess);

    // This is run for its side-effects on the expander env,
    // as it registers all the core macros as expanders.
    f.fold_expr(cm);

    let res = @f.fold_crate(*c);
    ret res;
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Change "file" of injected string from "-" to "<anon>", less confusing that way.<commit_after>import driver::session;

import option::{none, some};

import std::map::hashmap;
import vec;

import syntax::ast::{crate, expr_, expr_mac, mac_invoc};
import syntax::fold::*;
import syntax::ext::base::*;
import syntax::parse::parser::parse_expr_from_source_str;

fn expand_expr(exts: hashmap<str, syntax_extension>, cx: ext_ctxt, e: expr_,
               fld: ast_fold, orig: fn@(expr_, ast_fold) -> expr_) -> expr_ {
    ret alt e {
          expr_mac(mac) {
            alt mac.node {
              mac_invoc(pth, args, body) {
                assert (vec::len(pth.node.idents) > 0u);
                let extname = pth.node.idents[0];
                alt exts.find(extname) {
                  none {
                    cx.span_fatal(pth.span,
                                  #fmt["macro undefined: '%s'", extname])
                  }
                  some(normal(ext)) {
                    let expanded = ext(cx, pth.span, args, body);

                    cx.bt_push(mac.span);
                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    fully_expanded
                  }
                  some(macro_defining(ext)) {
                    let named_extension = ext(cx, pth.span, args, body);
                    exts.insert(named_extension.ident, named_extension.ext);
                    ast::expr_rec([], none)
                  }
                }
              }
              _ { cx.span_bug(mac.span, "naked syntactic bit") }
            }
          }
          _ { orig(e, fld) }
        };
}

// FIXME: this is a terrible kludge to inject some macros into the default
// compilation environment. When the macro-definition system is substantially
// more mature, these should move from here, into a compiled part of libcore
// at very least.

fn core_macros() -> str {
    ret
"{
    #macro([#error[f, ...], log(core::error, #fmt[f, ...])]);
    #macro([#warn[f, ...], log(core::warn, #fmt[f, ...])]);
    #macro([#info[f, ...], log(core::info, #fmt[f, ...])]);
    #macro([#debug[f, ...], log(core::debug, #fmt[f, ...])]);
}";
}

fn expand_crate(sess: session::session, c: @crate) -> @crate {
    let exts = syntax_expander_table();
    let afp = default_ast_fold();
    let cx: ext_ctxt = mk_ctxt(sess);
    let f_pre =
        {fold_expr: bind expand_expr(exts, cx, _, _, afp.fold_expr)
            with *afp};
    let f = make_fold(f_pre);
    let cm = parse_expr_from_source_str("<anon>", core_macros(),
                                        sess.opts.cfg,
                                        sess.parse_sess);

    // This is run for its side-effects on the expander env,
    // as it registers all the core macros as expanders.
    f.fold_expr(cm);

    let res = @f.fold_crate(*c);
    ret res;
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before><commit_msg>Presort routes instead of sorting on each route.<commit_after><|endoftext|>


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

//! Synchronous, in-memory pipes.
//!
//! Currently these aren't particularly useful, there only exists bindings
//! enough so that pipes can be created to child processes.

#![allow(missing_docs)]

use prelude::*;

use io::IoResult;
use libc;
use sync::Arc;

use sys_common;
use sys;
use sys::fs::FileDesc as FileDesc;

/// A synchronous, in-memory pipe.
pub struct PipeStream {
    inner: Arc<FileDesc>
}

pub struct PipePair {
    pub reader: PipeStream,
    pub writer: PipeStream,
}

impl PipeStream {
    /// Consumes a file descriptor to return a pipe stream that will have
    /// synchronous, but non-blocking reads/writes. This is useful if the file
    /// descriptor is acquired via means other than the standard methods.
    ///
    /// This operation consumes ownership of the file descriptor and it will be
    /// closed once the object is deallocated.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #![allow(unused_must_use)]
    /// extern crate libc;
    ///
    /// use std::io::pipe::PipeStream;
    ///
    /// fn main() {
    ///     let mut pipe = PipeStream::open(libc::STDERR_FILENO);
    ///     pipe.write(b"Hello, stderr!");
    /// }
    /// ```
    pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
        Ok(PipeStream::from_filedesc(FileDesc::new(fd, true)))
    }

    // FIXME: expose this some other way
    /// Wrap a FileDesc directly, taking ownership.
    #[doc(hidden)]
    pub fn from_filedesc(fd: FileDesc) -> PipeStream {
        PipeStream { inner: Arc::new(fd) }
    }

    /// Creates a pair of in-memory OS pipes for a unidirectional communication
    /// stream.
    ///
    /// The structure returned contains a reader and writer I/O object. Data
    /// written to the writer can be read from the reader.
    ///
    /// # Errors
    ///
    /// This function can fail to succeed if the underlying OS has run out of
    /// available resources to allocate a new pipe.
    pub fn pair() -> IoResult<PipePair> {
        let (reader, writer) = try!(unsafe { sys::os::pipe() });
        Ok(PipePair {
            reader: PipeStream::from_filedesc(reader),
            writer: PipeStream::from_filedesc(writer),
        })
    }
}

impl sys_common::AsFileDesc for PipeStream {
    fn as_fd(&self) -> &sys::fs::FileDesc {
        &*self.inner
    }
}

impl Clone for PipeStream {
    fn clone(&self) -> PipeStream {
        PipeStream { inner: self.inner.clone() }
    }
}

impl Reader for PipeStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.inner.read(buf)
    }
}

impl Writer for PipeStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.inner.write(buf)
    }
}

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

    #[test]
    fn partial_read() {
        use os;
        use io::pipe::PipeStream;

        let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
        let out = PipeStream::open(writer);
        let mut input = PipeStream::open(reader);
        let (tx, rx) = channel();
        spawn(proc() {
            let mut out = out;
            out.write(&[10]).unwrap();
            rx.recv(); // don't close the pipe until the other read has finished
        });

        let mut buf = [0, ..10];
        input.read(&mut buf).unwrap();
        tx.send(());
    }
}
<commit_msg>Disable dubious pipe test<commit_after>// Copyright 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.

//! Synchronous, in-memory pipes.
//!
//! Currently these aren't particularly useful, there only exists bindings
//! enough so that pipes can be created to child processes.

#![allow(missing_docs)]

use prelude::*;

use io::IoResult;
use libc;
use sync::Arc;

use sys_common;
use sys;
use sys::fs::FileDesc as FileDesc;

/// A synchronous, in-memory pipe.
pub struct PipeStream {
    inner: Arc<FileDesc>
}

pub struct PipePair {
    pub reader: PipeStream,
    pub writer: PipeStream,
}

impl PipeStream {
    /// Consumes a file descriptor to return a pipe stream that will have
    /// synchronous, but non-blocking reads/writes. This is useful if the file
    /// descriptor is acquired via means other than the standard methods.
    ///
    /// This operation consumes ownership of the file descriptor and it will be
    /// closed once the object is deallocated.
    ///
    /// # Example
    ///
    /// ```{rust,no_run}
    /// # #![allow(unused_must_use)]
    /// extern crate libc;
    ///
    /// use std::io::pipe::PipeStream;
    ///
    /// fn main() {
    ///     let mut pipe = PipeStream::open(libc::STDERR_FILENO);
    ///     pipe.write(b"Hello, stderr!");
    /// }
    /// ```
    pub fn open(fd: libc::c_int) -> IoResult<PipeStream> {
        Ok(PipeStream::from_filedesc(FileDesc::new(fd, true)))
    }

    // FIXME: expose this some other way
    /// Wrap a FileDesc directly, taking ownership.
    #[doc(hidden)]
    pub fn from_filedesc(fd: FileDesc) -> PipeStream {
        PipeStream { inner: Arc::new(fd) }
    }

    /// Creates a pair of in-memory OS pipes for a unidirectional communication
    /// stream.
    ///
    /// The structure returned contains a reader and writer I/O object. Data
    /// written to the writer can be read from the reader.
    ///
    /// # Errors
    ///
    /// This function can fail to succeed if the underlying OS has run out of
    /// available resources to allocate a new pipe.
    pub fn pair() -> IoResult<PipePair> {
        let (reader, writer) = try!(unsafe { sys::os::pipe() });
        Ok(PipePair {
            reader: PipeStream::from_filedesc(reader),
            writer: PipeStream::from_filedesc(writer),
        })
    }
}

impl sys_common::AsFileDesc for PipeStream {
    fn as_fd(&self) -> &sys::fs::FileDesc {
        &*self.inner
    }
}

impl Clone for PipeStream {
    fn clone(&self) -> PipeStream {
        PipeStream { inner: self.inner.clone() }
    }
}

impl Reader for PipeStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.inner.read(buf)
    }
}

impl Writer for PipeStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.inner.write(buf)
    }
}

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

    #[test]
    fn partial_read() {
        use os;
        use io::pipe::PipeStream;

        let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
        let out = PipeStream::open(writer);
        let mut input = PipeStream::open(reader);
        let (tx, rx) = channel();
        spawn(proc() {
            let mut out = out;
            out.write(&[10]).unwrap();
            rx.recv(); // don't close the pipe until the other read has finished
        });

        let mut buf = [0, ..10];
        input.read(&mut buf).unwrap();
        tx.send(());
    }
}
<|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.

/*!

Logging

This module is used by the compiler when emitting output for the logging family
of macros. The methods of this module shouldn't necessarily be used directly,
but rather through the logging macros defined.

There are five macros that the logging subsystem uses:

* `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
                       related `format!` arguments
* `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
* `info!(...)` - a macro hard-wired to the log level of `INFO`
* `warn!(...)` - a macro hard-wired to the log level of `WARN`
* `error!(...)` - a macro hard-wired to the log level of `ERROR`

All of these macros use the same style of syntax as the `format!` syntax
extension. Details about the syntax can be found in the documentation of
`std::fmt` along with the Rust tutorial/manual.

If you want to check at runtime if a given logging level is enabled (e.g. if the
information you would want to log is expensive to produce), you can use the
following macro:

* `log_enabled!(level)` - returns true if logging of the given level is enabled

## Enabling logging

Log levels are controlled on a per-module basis, and by default all logging is
disabled except for `error!` (a log level of 1). Logging is controlled via the
`RUST_LOG` environment variable. The value of this environment variable is a
comma-separated list of logging directives. A logging directive is of the form:

```
path::to::module=log_level
```

The path to the module is rooted in the name of the crate it was compiled for,
so if your program is contained in a file `hello.rs`, for example, to turn on
logging for this file you would use a value of `RUST_LOG=hello`. Furthermore,
this path is a prefix-search, so all modules nested in the specified module will
also have logging enabled.

The actual `log_level` is optional to specify. If omitted, all logging will be
enabled. If specified, the it must be either a numeric in the range of 1-255, or
it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
is specified, then all logging less than or equal to that numeral is enabled.
For example, if logging level 3 is active, error, warn, and info logs will be
printed, but debug will be omitted.

As the log level for a module is optional, the module to enable logging for is
also optional. If only a `log_level` is provided, then the global log level for
all modules is set to this value.

Some examples of valid values of `RUST_LOG` are:

```
hello                // turns on all logging for the 'hello' module
info                 // turns on all info logging
hello=debug          // turns on debug logging for 'hello'
hello=3              // turns on info logging for 'hello'
hello,std::hashmap   // turns on hello, and std's hashmap logging
error,hello=warn     // turn on global error logging and also warn for hello
```

## Performance and Side Effects

Each of these macros will expand to code similar to:

```rust,ignore
if log_level <= my_module_log_level() {
    ::std::logging::log(log_level, format!(...));
}
```

What this means is that each of these macros are very cheap at runtime if
they're turned off (just a load and an integer comparison). This also means that
if logging is disabled, none of the components of the log will be executed.

## Useful Values

For convenience, if a value of `::help` is set for `RUST_LOG`, a program will
start, print out all modules registered for logging, and then exit.

*/

use fmt;
use option::*;
use rt::local::Local;
use rt::logging::{Logger, StdErrLogger};
use rt::task::Task;

/// Debug log level
pub static DEBUG: u32 = 4;
/// Info log level
pub static INFO: u32 = 3;
/// Warn log level
pub static WARN: u32 = 2;
/// Error log level
pub static ERROR: u32 = 1;

/// This function is called directly by the compiler when using the logging
/// macros. This function does not take into account whether the log level
/// specified is active or not, it will always log something if this method is
/// called.
///
/// It is not recommended to call this function directly, rather it should be
/// invoked through the logging family of macros.
pub fn log(_level: u32, args: &fmt::Arguments) {
    unsafe {
        let optional_task: Option<*mut Task> = Local::try_unsafe_borrow();
        match optional_task {
            Some(local) => {
                // Lazily initialize the local task's logger
                match (*local).logger {
                    // Use the available logger if we have one
                    Some(ref mut logger) => { logger.log(args); }
                    None => {
                        let mut logger = StdErrLogger::new();
                        logger.log(args);
                        (*local).logger = Some(logger);
                    }
                }
            }
            // If there's no local task, then always log to stderr
            None => {
                let mut logger = StdErrLogger::new();
                logger.log(args);
            }
        }
    }
}
<commit_msg>std: Make logging safely implemented<commit_after>// 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.

/*!

Logging

This module is used by the compiler when emitting output for the logging family
of macros. The methods of this module shouldn't necessarily be used directly,
but rather through the logging macros defined.

There are five macros that the logging subsystem uses:

* `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
                       related `format!` arguments
* `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
* `info!(...)` - a macro hard-wired to the log level of `INFO`
* `warn!(...)` - a macro hard-wired to the log level of `WARN`
* `error!(...)` - a macro hard-wired to the log level of `ERROR`

All of these macros use the same style of syntax as the `format!` syntax
extension. Details about the syntax can be found in the documentation of
`std::fmt` along with the Rust tutorial/manual.

If you want to check at runtime if a given logging level is enabled (e.g. if the
information you would want to log is expensive to produce), you can use the
following macro:

* `log_enabled!(level)` - returns true if logging of the given level is enabled

## Enabling logging

Log levels are controlled on a per-module basis, and by default all logging is
disabled except for `error!` (a log level of 1). Logging is controlled via the
`RUST_LOG` environment variable. The value of this environment variable is a
comma-separated list of logging directives. A logging directive is of the form:

```
path::to::module=log_level
```

The path to the module is rooted in the name of the crate it was compiled for,
so if your program is contained in a file `hello.rs`, for example, to turn on
logging for this file you would use a value of `RUST_LOG=hello`. Furthermore,
this path is a prefix-search, so all modules nested in the specified module will
also have logging enabled.

The actual `log_level` is optional to specify. If omitted, all logging will be
enabled. If specified, the it must be either a numeric in the range of 1-255, or
it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
is specified, then all logging less than or equal to that numeral is enabled.
For example, if logging level 3 is active, error, warn, and info logs will be
printed, but debug will be omitted.

As the log level for a module is optional, the module to enable logging for is
also optional. If only a `log_level` is provided, then the global log level for
all modules is set to this value.

Some examples of valid values of `RUST_LOG` are:

```
hello                // turns on all logging for the 'hello' module
info                 // turns on all info logging
hello=debug          // turns on debug logging for 'hello'
hello=3              // turns on info logging for 'hello'
hello,std::hashmap   // turns on hello, and std's hashmap logging
error,hello=warn     // turn on global error logging and also warn for hello
```

## Performance and Side Effects

Each of these macros will expand to code similar to:

```rust,ignore
if log_level <= my_module_log_level() {
    ::std::logging::log(log_level, format!(...));
}
```

What this means is that each of these macros are very cheap at runtime if
they're turned off (just a load and an integer comparison). This also means that
if logging is disabled, none of the components of the log will be executed.

## Useful Values

For convenience, if a value of `::help` is set for `RUST_LOG`, a program will
start, print out all modules registered for logging, and then exit.

*/

use fmt;
use option::*;
use rt::local::Local;
use rt::logging::{Logger, StdErrLogger};
use rt::task::Task;

/// Debug log level
pub static DEBUG: u32 = 4;
/// Info log level
pub static INFO: u32 = 3;
/// Warn log level
pub static WARN: u32 = 2;
/// Error log level
pub static ERROR: u32 = 1;

/// This function is called directly by the compiler when using the logging
/// macros. This function does not take into account whether the log level
/// specified is active or not, it will always log something if this method is
/// called.
///
/// It is not recommended to call this function directly, rather it should be
/// invoked through the logging family of macros.
pub fn log(_level: u32, args: &fmt::Arguments) {
    let mut logger = {
        let mut task = Local::borrow(None::<Task>);
        task.get().logger.take()
    };

    if logger.is_none() {
        logger = Some(StdErrLogger::new());
    }
    logger.get_mut_ref().log(args);

    let mut task = Local::borrow(None::<Task>);
    task.get().logger = logger;
}
<|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.

//! Networking primitives for TCP/UDP communication
//!
//! > **NOTE**: This module is very much a work in progress and is under active
//! > development. At this time it is still recommended to use the `old_io`
//! > module while the details of this module shake out.

#![unstable(feature = "net")]

use prelude::v1::*;

use io::{self, Error, ErrorKind};
use num::Int;
use sys_common::net2 as net_imp;

pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
pub use self::addr::{SocketAddr, ToSocketAddrs};
pub use self::tcp::{TcpStream, TcpListener};
pub use self::udp::UdpSocket;

mod ip;
mod addr;
mod tcp;
mod udp;
mod parser;
#[cfg(test)] mod test;

/// Possible values which can be passed to the `shutdown` method of `TcpStream`
/// and `UdpSocket`.
#[derive(Copy, Clone, PartialEq)]
pub enum Shutdown {
    /// Indicates that the reading portion of this stream/socket should be shut
    /// down. All currently blocked and future reads will return `Ok(0)`.
    Read,
    /// Indicates that the writing portion of this stream/socket should be shut
    /// down. All currently blocked and future writes will return an error.
    Write,
    /// Shut down both the reading and writing portions of this stream.
    ///
    /// See `Shutdown::Read` and `Shutdown::Write` for more information.
    Both
}

fn hton<I: Int>(i: I) -> I { i.to_be() }
fn ntoh<I: Int>(i: I) -> I { Int::from_be(i) }

fn each_addr<A: ToSocketAddrs + ?Sized, F, T>(addr: &A, mut f: F) -> io::Result<T>
    where F: FnMut(&SocketAddr) -> io::Result<T>
{
    let mut last_err = None;
    for addr in try!(addr.to_socket_addrs()) {
        match f(&addr) {
            Ok(l) => return Ok(l),
            Err(e) => last_err = Some(e),
        }
    }
    Err(last_err.unwrap_or_else(|| {
        Error::new(ErrorKind::InvalidInput,
                   "could not resolve to any addresses", None)
    }))
}

/// An iterator over `SocketAddr` values returned from a host lookup operation.
pub struct LookupHost(net_imp::LookupHost);

impl Iterator for LookupHost {
    type Item = io::Result<SocketAddr>;
    fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
}

/// Resolve the host specified by `host` as a number of `SocketAddr` instances.
///
/// This method may perform a DNS query to resolve `host` and may also inspect
/// system configuration to resolve the specified hostname.
///
/// # Examples
///
/// ```no_run
/// use std::net;
///
/// # fn foo() -> std::io::Result<()> {
/// for host in try!(net::lookup_host("rust-lang.org")) {
///     println!("found address: {}", try!(host));
/// }
/// # Ok(())
/// # }
/// ```
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
    net_imp::lookup_host(host).map(LookupHost)
}
<commit_msg>Removed old_io note from std::net<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.

//! Networking primitives for TCP/UDP communication
//!
//! > **NOTE**: This module is very much a work in progress and is under active
//! > development.

#![unstable(feature = "net")]

use prelude::v1::*;

use io::{self, Error, ErrorKind};
use num::Int;
use sys_common::net2 as net_imp;

pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
pub use self::addr::{SocketAddr, ToSocketAddrs};
pub use self::tcp::{TcpStream, TcpListener};
pub use self::udp::UdpSocket;

mod ip;
mod addr;
mod tcp;
mod udp;
mod parser;
#[cfg(test)] mod test;

/// Possible values which can be passed to the `shutdown` method of `TcpStream`
/// and `UdpSocket`.
#[derive(Copy, Clone, PartialEq)]
pub enum Shutdown {
    /// Indicates that the reading portion of this stream/socket should be shut
    /// down. All currently blocked and future reads will return `Ok(0)`.
    Read,
    /// Indicates that the writing portion of this stream/socket should be shut
    /// down. All currently blocked and future writes will return an error.
    Write,
    /// Shut down both the reading and writing portions of this stream.
    ///
    /// See `Shutdown::Read` and `Shutdown::Write` for more information.
    Both
}

fn hton<I: Int>(i: I) -> I { i.to_be() }
fn ntoh<I: Int>(i: I) -> I { Int::from_be(i) }

fn each_addr<A: ToSocketAddrs + ?Sized, F, T>(addr: &A, mut f: F) -> io::Result<T>
    where F: FnMut(&SocketAddr) -> io::Result<T>
{
    let mut last_err = None;
    for addr in try!(addr.to_socket_addrs()) {
        match f(&addr) {
            Ok(l) => return Ok(l),
            Err(e) => last_err = Some(e),
        }
    }
    Err(last_err.unwrap_or_else(|| {
        Error::new(ErrorKind::InvalidInput,
                   "could not resolve to any addresses", None)
    }))
}

/// An iterator over `SocketAddr` values returned from a host lookup operation.
pub struct LookupHost(net_imp::LookupHost);

impl Iterator for LookupHost {
    type Item = io::Result<SocketAddr>;
    fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
}

/// Resolve the host specified by `host` as a number of `SocketAddr` instances.
///
/// This method may perform a DNS query to resolve `host` and may also inspect
/// system configuration to resolve the specified hostname.
///
/// # Examples
///
/// ```no_run
/// use std::net;
///
/// # fn foo() -> std::io::Result<()> {
/// for host in try!(net::lookup_host("rust-lang.org")) {
///     println!("found address: {}", try!(host));
/// }
/// # Ok(())
/// # }
/// ```
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
    net_imp::lookup_host(host).map(LookupHost)
}
<|endoftext|>