| $$(TLIB$(1)_T_$(2)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(2)),$$(notdir $$@))
- $$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) -o $$@ $$< && touch $$@
+ $$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(2)),$$(notdir $$@))
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)): \
| $$(TLIB$(1)_T_$(2)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(2)),$$(notdir $$@))
- $$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) -o $$@ $$< && touch $$@
+ $$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(2)),$$(notdir $$@))
$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(3)): \
| $$(TLIB$(1)_T_$(2)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBSYNTAX_GLOB_$(2)),$$(notdir $$@))
- $$(STAGE$(1)_T_$(2)_H_$(3)) $(BORROWCK) -o $$@ $$< && touch $$@
+ $$(STAGE$(1)_T_$(2)_H_$(3)) $(BORROWCK) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBSYNTAX_GLOB_$(2)),$$(notdir $$@))
# Only build the compiler for host triples
| $$(TLIB$(1)_T_$(2)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(2)),$$(notdir $$@))
- $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< && touch $$@
+ $$(STAGE$(1)_T_$(2)_H_$(3)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(2)),$$(notdir $$@))
$$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(3)): \
| $$(TLIB$(1)_T_$(4)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTPKG_GLOB_$(4)),$$(notdir $$@))
- $$(STAGE$(1)_T_$(4)_H_$(3)) $$(WFLAGS_ST$(1)) -o $$@ $$< && touch $$@
+ $$(STAGE$(1)_T_$(4)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTPKG_GLOB_$(4)),$$(notdir $$@))
$$(TBIN$(1)_T_$(4)_H_$(3))/rustpkg$$(X_$(4)): \
| $$(TLIB$(1)_T_$(4)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOC_GLOB_$(4)),$$(notdir $$@))
- $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@
+ $$(STAGE$(1)_T_$(4)_H_$(3)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOC_GLOB_$(4)),$$(notdir $$@))
$$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4)): \
| $$(TLIB$(1)_T_$(4)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTI_GLOB_$(4)),$$(notdir $$@))
- $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@
+ $$(STAGE$(1)_T_$(4)_H_$(3)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTI_GLOB_$(4)),$$(notdir $$@))
$$(TBIN$(1)_T_$(4)_H_$(3))/rusti$$(X_$(4)): \
| $$(TLIB$(1)_T_$(4)_H_$(3))/
@$$(call E, compile_and_link: $$@)
$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUST_GLOB_$(4)),$$(notdir $$@))
- $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@
+ $$(STAGE$(1)_T_$(4)_H_$(3)) --out-dir $$(@D) $$< && touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUST_GLOB_$(4)),$$(notdir $$@))
$$(TBIN$(1)_T_$(4)_H_$(3))/rust$$(X_$(4)): \
#[crate_type = "bin"];
#[allow(non_camel_case_types)];
-#[allow(unrecognized_lint)]; // NOTE: remove after snapshot
#[deny(warnings)];
extern mod extra;
#[fixed_stack_segment]
pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
outdir: &Option<Path>, output: &Option<Path>) {
- let outputs = build_output_filenames(input, outdir, output, [], sess);
// We need nested scopes here, because the intermediate results can keep
// large chunks of memory alive and we want to free them as soon as
// possible to keep the peak memory usage low
- let trans = {
+ let (outputs, trans) = {
let expanded_crate = {
let crate = phase_1_parse_input(sess, cfg.clone(), input);
if stop_after_phase_1(sess) { return; }
};
let analysis = phase_3_run_analysis_passes(sess, expanded_crate);
if stop_after_phase_3(sess) { return; }
- phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs)
+ let outputs = build_output_filenames(input, outdir, output, [], sess);
+ let trans = phase_4_translate_to_llvm(sess, expanded_crate,
+ &analysis, outputs);
+ (outputs, trans)
};
phase_5_run_llvm_passes(sess, &trans, outputs);
if stop_after_phase_5(sess) { return; }
};
if *sess.building_library {
- // FIXME (#2401): We might want to warn here; we're actually not
- // going to respect the user's choice of library name when it
- // comes time to link, we'll be linking to
- // lib<basename>-<hash>-<version>.so no matter what.
+ sess.warn("ignoring specified output filename for library.");
}
if *odir != None {
// Note that `break` and `loop` statements
// may cause additional edges.
- // NOTE: Is the condition considered part of the loop?
+ // Is the condition considered part of the loop?
let loopback = self.add_dummy_node([pred]); // 1
let cond_exit = self.expr(cond, loopback); // 2
let expr_exit = self.add_node(expr.id, [cond_exit]); // 3
use middle::trans::type_of;
use middle::ty;
use util::common::indenter;
+use util::ppaux::{Repr, vec_map_to_str};
use std::hashmap::HashMap;
use std::vec;
use syntax::ast_util::path_to_ident;
use syntax::ast_util;
use syntax::codemap::{span, dummy_sp};
-use syntax::print::pprust::pat_to_str;
// An option identifying a literal: either a unit-like struct or an
// expression.
data: ArmData<'self>
}
-pub fn match_to_str(bcx: @mut Block, m: &Match) -> ~str {
- if bcx.sess().verbose() {
- // for many programs, this just take too long to serialize
- fmt!("%?", m.pats.map(|p| pat_to_str(*p, bcx.sess().intr())))
- } else {
- fmt!("%u pats", m.pats.len())
+impl<'self> Repr for Match<'self> {
+ fn repr(&self, tcx: ty::ctxt) -> ~str {
+ if tcx.sess.verbose() {
+ // for many programs, this just take too long to serialize
+ self.pats.repr(tcx)
+ } else {
+ fmt!("%u pats", self.pats.len())
+ }
}
}
-pub fn matches_to_str(bcx: @mut Block, m: &[Match]) -> ~str {
- fmt!("%?", m.map(|n| match_to_str(bcx, n)))
-}
-
pub fn has_nested_bindings(m: &[Match], col: uint) -> bool {
for br in m.iter() {
match br.pats[col].node {
col: uint,
val: ValueRef)
-> ~[Match<'r>] {
- debug!("expand_nested_bindings(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("expand_nested_bindings(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
bcx.sess().span_bug(
p.span,
fmt!("Expected an identifier pattern but found p: %s",
- pat_to_str(p, bcx.sess().intr())));
+ p.repr(bcx.tcx())));
}
}
val: ValueRef,
e: enter_pat)
-> ~[Match<'r>] {
- debug!("enter_match(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_match(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
}
}
- debug!("result=%s", matches_to_str(bcx, result));
+ debug!("result=%s", result.repr(bcx.tcx()));
return result;
}
col: uint,
val: ValueRef)
-> ~[Match<'r>] {
- debug!("enter_default(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_default(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
variant_size: uint,
val: ValueRef)
-> ~[Match<'r>] {
- debug!("enter_opt(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_opt(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
fields: &[ast::ident],
val: ValueRef)
-> ~[Match<'r>] {
- debug!("enter_rec_or_struct(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_rec_or_struct(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
val: ValueRef,
n_elts: uint)
-> ~[Match<'r>] {
- debug!("enter_tup(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_tup(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
val: ValueRef,
n_elts: uint)
-> ~[Match<'r>] {
- debug!("enter_tuple_struct(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_tuple_struct(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
col: uint,
val: ValueRef)
-> ~[Match<'r>] {
- debug!("enter_box(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_box(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
col: uint,
val: ValueRef)
-> ~[Match<'r>] {
- debug!("enter_uniq(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_uniq(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
col: uint,
val: ValueRef)
-> ~[Match<'r>] {
- debug!("enter_region(bcx=%s, m=%s, col=%u, val=%?)",
+ debug!("enter_region(bcx=%s, m=%s, col=%u, val=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
+ m.repr(bcx.tcx()),
col,
bcx.val_to_str(val));
let _indenter = indenter();
vals: &[ValueRef],
chk: Option<mk_fail>)
-> @mut Block {
- debug!("compile_guard(bcx=%s, guard_expr=%s, m=%s, vals=%?)",
+ debug!("compile_guard(bcx=%s, guard_expr=%s, m=%s, vals=%s)",
bcx.to_str(),
bcx.expr_to_str(guard_expr),
- matches_to_str(bcx, m),
- vals.map(|v| bcx.val_to_str(*v)));
+ m.repr(bcx.tcx()),
+ vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
let _indenter = indenter();
let mut bcx = bcx;
m: &[Match],
vals: &[ValueRef],
chk: Option<mk_fail>) {
- debug!("compile_submatch(bcx=%s, m=%s, vals=%?)",
+ debug!("compile_submatch(bcx=%s, m=%s, vals=%s)",
bcx.to_str(),
- matches_to_str(bcx, m),
- vals.map(|v| bcx.val_to_str(*v)));
+ m.repr(bcx.tcx()),
+ vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
let _indenter = indenter();
/*
// Decide what kind of branch we need
let opts = get_options(bcx, m, col);
+ debug!("options=%?", opts);
let mut kind = no_branch;
let mut test_val = val;
if opts.len() > 0u {
debug!("bind_irrefutable_pat(bcx=%s, pat=%s, binding_mode=%?)",
bcx.to_str(),
- pat_to_str(pat, bcx.sess().intr()),
+ pat.repr(bcx.tcx()),
binding_mode);
if bcx.sess().asm_comments() {
add_comment(bcx, fmt!("bind_irrefutable_pat(pat=%s)",
- pat_to_str(pat, bcx.sess().intr())));
+ pat.repr(bcx.tcx())));
}
let _indenter = indenter();
pub fn register_fn(ccx: @mut CrateContext,
sp: span,
sym: ~str,
- node_id: ast::NodeId)
- -> ValueRef {
- let t = ty::node_id_to_type(ccx.tcx, node_id);
- register_fn_full(ccx, sp, sym, node_id, t)
-}
-
-pub fn register_fn_full(ccx: @mut CrateContext,
- sp: span,
- sym: ~str,
- node_id: ast::NodeId,
- node_type: ty::t)
- -> ValueRef {
+ node_id: ast::NodeId,
+ node_type: ty::t)
+ -> ValueRef {
let llfty = type_of_fn_from_ty(ccx, node_type);
- register_fn_fuller(ccx, sp, sym, node_id, lib::llvm::CCallConv, llfty)
+ register_fn_llvmty(ccx, sp, sym, node_id, lib::llvm::CCallConv, llfty)
}
-pub fn register_fn_fuller(ccx: @mut CrateContext,
+pub fn register_fn_llvmty(ccx: @mut CrateContext,
sp: span,
sym: ~str,
node_id: ast::NodeId,
ast::item_fn(_, purity, _, _, _) => {
let llfn = if purity != ast::extern_fn {
- register_fn_full(ccx, i.span, sym, i.id, ty)
+ register_fn(ccx, i.span, sym, i.id, ty)
} else {
foreign::register_foreign_fn(ccx, i.span, sym, i.id)
};
let path = vec::append((*pth).clone(), [path_name(ni.ident)]);
let sym = exported_name(ccx, path, ty, ni.attrs);
- register_fn_full(ccx, ni.span, sym, ni.id, ty)
+ register_fn(ccx, ni.span, sym, ni.id, ty)
}
ast::foreign_item_static(*) => {
let ident = token::ident_to_str(&ni.ident);
llfn = match enm.node {
ast::item_enum(_, _) => {
- register_fn_full(ccx, (*v).span, sym, id, ty)
+ register_fn(ccx, (*v).span, sym, id, ty)
}
_ => fail!("node_variant, shouldn't happen")
};
let ty = ty::node_id_to_type(ccx.tcx, ctor_id);
let sym = exported_name(ccx, (*struct_path).clone(), ty,
struct_item.attrs);
- let llfn = register_fn_full(ccx, struct_item.span, sym, ctor_id, ty);
+ let llfn = register_fn(ccx, struct_item.span,
+ sym, ctor_id, ty);
set_inline_hint(llfn);
llfn
}
let sym = exported_name(ccx, path, mty, m.attrs);
- let llfn = register_fn_full(ccx, m.span, sym, id, mty);
+ let llfn = register_fn(ccx, m.span, sym, id, mty);
set_inline_hint_if_appr(m.attrs, llfn);
llfn
}
let tys = shim_types(ccx, node_id);
do tys.fn_ty.decl_fn |fnty| {
- register_fn_fuller(ccx, sp, sym.take(), node_id, lib::llvm::CCallConv, fnty)
+ register_fn_llvmty(ccx, sp, sym.take(), node_id, lib::llvm::CCallConv, fnty)
}
}
}
}
+pub fn vec_map_to_str<T>(ts: &[T], f: &fn(t: &T) -> ~str) -> ~str {
+ let tstrs = ts.map(f);
+ fmt!("[%s]", tstrs.connect(", "))
+}
+
pub fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str {
- let tstrs = ts.map(|t| ty_to_str(cx, *t));
- fmt!("(%s)", tstrs.connect(", "))
+ vec_map_to_str(ts, |t| ty_to_str(cx, *t))
}
pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
}
fn repr_vec<T:Repr>(tcx: ctxt, v: &[T]) -> ~str {
- fmt!("[%s]", v.map(|t| t.repr(tcx)).connect(","))
+ vec_map_to_str(v, |t| t.repr(tcx))
}
impl<'self, T:Repr> Repr for &'self [T] {
}
}
- // FIXME: #7220 rusti on 32bit mac doesn't work.
- // FIXME: #7641 rusti on 32bit linux cross compile doesn't work
- // FIXME: #7115 re-enable once LLVM has been upgraded
- #[cfg(thiswillneverbeacfgflag)]
+ #[cfg(not(target_word_size = "32"))]
fn run_program(prog: &str) {
let mut r = repl();
for cmd in prog.split_iter('\n') {
"the command '%s' failed", cmd);
}
}
+ // FIXME: #7220 rusti on 32bit mac doesn't work
+ // FIXME: #7641 rusti on 32bit linux cross compile doesn't work
+ #[cfg(target_word_size = "32")]
fn run_program(_: &str) {}
#[test]
run_program("let a = 3;");
}
- #[test] #[ignore]
+ #[test]
fn new_tasks() {
- // XXX: can't spawn new tasks because the JIT code is cleaned up
- // after the main function is done.
run_program("
- spawn( || println(\"Please don't segfault\") );
- do spawn { println(\"Please?\"); }
+ use std::task::try;
+ try( || println(\"Please don't segfault\") );
+ do try { println(\"Please?\"); }
");
}
//! Some various other I/O types
-// NOTE: These ultimately belong somewhere else
+// FIXME(#3660): should move to libextra
use prelude::*;
use super::*;
/// Create a blocked task, unless the task was already killed.
pub fn try_block(mut task: ~Task) -> Either<~Task, BlockedTask> {
+ // NB: As an optimization, we could give a free pass to being unkillable
+ // to tasks whose taskgroups haven't been initialized yet, but that
+ // introduces complications with select() and with the test cases below,
+ // and it's not clear the uncommon performance boost is worth it.
if task.death.unkillable > 0 {
Right(Unkillable(task))
} else {
let flag_arc = match task.death.spare_kill_flag.take() {
Some(spare_flag) => spare_flag,
None => {
- // FIXME(#7544): Uncomment this when terminate_current_task
- // stops being *terrible*. That's the only place that violates
- // the assumption of "becoming unkillable will fail if the
- // task was killed".
- // rtassert!(task.unwinder.unwinding);
+ // A task that kills us won't have a spare kill flag to
+ // give back to us, so we restore it ourselves here. This
+ // situation should only arise when we're already failing.
+ rtassert!(task.unwinder.unwinding);
(*task.death.kill_handle.get_ref().get()).killed.clone()
}
};
use to_str::{ToStr,ToStrConsume};
use str;
use str::StrSlice;
+use str::OwnedStr;
+use container::Container;
use cast;
+use ptr;
use iterator::{Iterator, IteratorUtil};
use vec::{CopyableVector, ImmutableVector, OwnedVector};
use to_bytes::IterBytes;
/// Convert to lowercase.
#[inline]
pub fn to_lower(self) -> Ascii {
- if self.chr >= 65 && self.chr <= 90 {
- Ascii{chr: self.chr | 0x20 }
- } else {
- self
- }
+ Ascii{chr: ASCII_LOWER_MAP[self.chr]}
}
/// Convert to uppercase.
#[inline]
pub fn to_upper(self) -> Ascii {
- if self.chr >= 97 && self.chr <= 122 {
- Ascii{chr: self.chr & !0x20 }
- } else {
- self
- }
+ Ascii{chr: ASCII_UPPER_MAP[self.chr]}
}
/// Compares two ascii characters of equality, ignoring case.
#[inline]
pub fn eq_ignore_case(self, other: Ascii) -> bool {
- self.to_lower().chr == other.to_lower().chr
+ ASCII_LOWER_MAP[self.chr] == ASCII_LOWER_MAP[other.chr]
}
}
}
}
+
+/// Convert the string to ASCII upper case:
+/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+/// but non-ASCII letters are unchanged.
+#[inline]
+pub fn to_ascii_upper(string: &str) -> ~str {
+ map_bytes(string, ASCII_UPPER_MAP)
+}
+
+/// Convert the string to ASCII lower case:
+/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+/// but non-ASCII letters are unchanged.
+#[inline]
+pub fn to_ascii_lower(string: &str) -> ~str {
+ map_bytes(string, ASCII_LOWER_MAP)
+}
+
+#[inline]
+priv fn map_bytes(string: &str, map: &'static [u8]) -> ~str {
+ let len = string.len();
+ let mut result = str::with_capacity(len);
+ unsafe {
+ do result.as_mut_buf |mut buf, _| {
+ for c in string.as_bytes().iter() {
+ *buf = map[*c];
+ buf = ptr::mut_offset(buf, 1)
+ }
+ }
+ str::raw::set_len(&mut result, len);
+ }
+ result
+}
+
+/// Check that two strings are an ASCII case-insensitive match.
+/// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
+/// but without allocating and copying temporary strings.
+#[inline]
+pub fn eq_ignore_ascii_case(a: &str, b: &str) -> bool {
+ a.len() == b.len() && a.as_bytes().iter().zip(b.as_bytes().iter()).all(
+ |(byte_a, byte_b)| ASCII_LOWER_MAP[*byte_a] == ASCII_LOWER_MAP[*byte_b])
+}
+
+priv static ASCII_LOWER_MAP: &'static [u8] = &[
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+];
+
+priv static ASCII_UPPER_MAP: &'static [u8] = &[
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+];
+
+
#[cfg(test)]
mod tests {
use super::*;
use to_bytes::ToBytes;
+ use str::from_char;
macro_rules! v2ascii (
( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
#[test] #[should_fail]
fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
+
+ #[test]
+ fn test_to_ascii_upper() {
+ assert_eq!(to_ascii_upper("url()URL()uRl()ürl"), ~"URL()URL()URL()üRL");
+ assert_eq!(to_ascii_upper("hıKß"), ~"HıKß");
+
+ let mut i = 0;
+ while i <= 500 {
+ let c = i as char;
+ let upper = if 'a' <= c && c <= 'z' { c + 'A' - 'a' } else { c };
+ assert_eq!(to_ascii_upper(from_char(i as char)), from_char(upper))
+ i += 1;
+ }
+ }
+
+ #[test]
+ fn test_to_ascii_lower() {
+ assert_eq!(to_ascii_lower("url()URL()uRl()Ürl"), ~"url()url()url()Ürl");
+ // Dotted capital I, Kelvin sign, Sharp S.
+ assert_eq!(to_ascii_lower("HİKß"), ~"hİKß");
+
+ let mut i = 0;
+ while i <= 500 {
+ let c = i as char;
+ let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
+ assert_eq!(to_ascii_lower(from_char(i as char)), from_char(lower))
+ i += 1;
+ }
+ }
+
+
+ #[test]
+ fn test_eq_ignore_ascii_case() {
+ assert!(eq_ignore_ascii_case("url()URL()uRl()Ürl", "url()url()url()Ürl"));
+ assert!(!eq_ignore_ascii_case("Ürl", "ürl"));
+ // Dotted capital I, Kelvin sign, Sharp S.
+ assert!(eq_ignore_ascii_case("HİKß", "hİKß"));
+ assert!(!eq_ignore_ascii_case("İ", "i"));
+ assert!(!eq_ignore_ascii_case("K", "k"));
+ assert!(!eq_ignore_ascii_case("ß", "s"));
+
+ let mut i = 0;
+ while i <= 500 {
+ let c = i as char;
+ let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
+ assert!(eq_ignore_ascii_case(from_char(i as char), from_char(lower)));
+ i += 1;
+ }
+ }
}
let me = Local::unsafe_borrow::<Task>();
blk(match (*me).taskgroup {
None => {
- // Main task, doing first spawn ever. Lazily initialize.
+ // First task in its (unlinked/unsupervised) taskgroup.
+ // Lazily initialize.
let mut members = TaskSet::new();
let my_handle = (*me).death.kill_handle.get_ref().clone();
members.insert(NewTask(my_handle));
}
}
+// Returns 'None' in the case where the child's TG should be lazily initialized.
fn gen_child_taskgroup(linked: bool, supervised: bool)
- -> (TaskGroupArc, AncestorList, bool) {
- do RuntimeGlue::with_my_taskgroup |spawner_group| {
- let ancestors = AncestorList(spawner_group.ancestors.map(|x| x.clone()));
- if linked {
- // Child is in the same group as spawner.
- // Child's ancestors are spawner's ancestors.
- // Propagate main-ness.
- (spawner_group.tasks.clone(), ancestors, spawner_group.is_main)
- } else {
- // Child is in a separate group from spawner.
- let g = Exclusive::new(Some(TaskGroupData {
- members: TaskSet::new(),
- descendants: TaskSet::new(),
- }));
- let a = if supervised {
- let new_generation = incr_generation(&ancestors);
- assert!(new_generation < uint::max_value);
- // Child's ancestors start with the spawner.
- // Build a new node in the ancestor list.
- AncestorList(Some(Exclusive::new(AncestorNode {
- generation: new_generation,
- parent_group: spawner_group.tasks.clone(),
- ancestors: ancestors,
- })))
+ -> Option<(TaskGroupArc, AncestorList, bool)> {
+ // FIXME(#7544): Not safe to lazily initialize in the old runtime. Remove
+ // this context check once 'spawn_raw_oldsched' is gone.
+ if context() == OldTaskContext || linked || supervised {
+ // with_my_taskgroup will lazily initialize the parent's taskgroup if
+ // it doesn't yet exist. We don't want to call it in the unlinked case.
+ do RuntimeGlue::with_my_taskgroup |spawner_group| {
+ let ancestors = AncestorList(spawner_group.ancestors.map(|x| x.clone()));
+ if linked {
+ // Child is in the same group as spawner.
+ // Child's ancestors are spawner's ancestors.
+ // Propagate main-ness.
+ Some((spawner_group.tasks.clone(), ancestors, spawner_group.is_main))
} else {
- // Child has no ancestors.
- AncestorList(None)
- };
- (g, a, false)
+ // Child is in a separate group from spawner.
+ let g = Exclusive::new(Some(TaskGroupData {
+ members: TaskSet::new(),
+ descendants: TaskSet::new(),
+ }));
+ let a = if supervised {
+ let new_generation = incr_generation(&ancestors);
+ assert!(new_generation < uint::max_value);
+ // Child's ancestors start with the spawner.
+ // Build a new node in the ancestor list.
+ AncestorList(Some(Exclusive::new(AncestorNode {
+ generation: new_generation,
+ parent_group: spawner_group.tasks.clone(),
+ ancestors: ancestors,
+ })))
+ } else {
+ // Child has no ancestors.
+ AncestorList(None)
+ };
+ Some((g, a, false))
+ }
}
+ } else {
+ None
}
}
let child_wrapper: ~fn() = || {
// Child task runs this code.
- let child_data = Cell::new(child_data.take()); // :(
- let enlist_success = do Local::borrow::<Task, bool> |me| {
- let (child_tg, ancestors, is_main) = child_data.take();
- let mut ancestors = ancestors;
- // FIXME(#7544): Optimize out the xadd in this clone, somehow.
- let handle = me.death.kill_handle.get_ref().clone();
- // Atomically try to get into all of our taskgroups.
- if enlist_many(NewTask(handle), &child_tg, &mut ancestors) {
- // Got in. We can run the provided child body, and can also run
- // the taskgroup's exit-time-destructor afterward.
- me.taskgroup = Some(Taskgroup(child_tg, ancestors, is_main, None));
- true
- } else {
- false
+
+ // If child data is 'None', the enlist is vacuously successful.
+ let enlist_success = do child_data.take().map_consume_default(true) |child_data| {
+ let child_data = Cell::new(child_data); // :(
+ do Local::borrow::<Task, bool> |me| {
+ let (child_tg, ancestors, is_main) = child_data.take();
+ let mut ancestors = ancestors;
+ // FIXME(#7544): Optimize out the xadd in this clone, somehow.
+ let handle = me.death.kill_handle.get_ref().clone();
+ // Atomically try to get into all of our taskgroups.
+ if enlist_many(NewTask(handle), &child_tg, &mut ancestors) {
+ // Got in. We can run the provided child body, and can also run
+ // the taskgroup's exit-time-destructor afterward.
+ me.taskgroup = Some(Taskgroup(child_tg, ancestors, is_main, None));
+ true
+ } else {
+ false
+ }
}
};
// Should be run after the local-borrowed task is returned.
let join_task = join_task_cell.take();
let bootstrap_task = ~do Task::new_root(&mut new_sched.stack_pool) || {
- rtdebug!("boostraping a 1:1 scheduler");
+ rtdebug!("bootstrapping a 1:1 scheduler");
};
new_sched.bootstrap(bootstrap_task);
fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
let (child_tg, ancestors, is_main) =
- gen_child_taskgroup(opts.linked, opts.supervised);
+ gen_child_taskgroup(opts.linked, opts.supervised).expect("old runtime needs TG");
unsafe {
let child_data = Cell::new((child_tg, ancestors, f));
Some(&node_local(ident)) => {
fmt!("local (id=%?, name=%s)", id, itr.get(ident.name))
}
- Some(&node_block(_)) => {
- fmt!("block")
+ Some(&node_block(ref block)) => {
+ fmt!("block %s (id=%?)", pprust::block_to_str(block, itr), id)
}
- Some(&node_struct_ctor(*)) => {
- fmt!("struct_ctor")
+ Some(&node_struct_ctor(_, _, path)) => {
+ fmt!("struct_ctor %s (id=%?)", path_to_str(*path, itr), id)
}
}
}
impl Visitor<()> for IdVisitor {
fn visit_mod(@mut self,
module: &_mod,
- span: span,
+ _span: span,
node_id: NodeId,
env: ()) {
(self.visit_callback)(node_id);