about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in18
-rw-r--r--src/comp/driver/rustc.rs202
-rw-r--r--src/comp/middle/ty.rs4
-rw-r--r--src/lib/GetOpts.rs249
-rw-r--r--src/lib/Term.rs54
-rw-r--r--src/lib/_str.rs8
-rw-r--r--src/lib/std.rc2
7 files changed, 401 insertions, 136 deletions
diff --git a/Makefile.in b/Makefile.in
index 160dc8c6a21..2c33bbb28bc 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -16,13 +16,13 @@ CFG_GCC_LINK_FLAGS :=
 CFG_BOOT_FLAGS := $(BOOT_FLAGS)
 ifdef CFG_DISABLE_OPTIMIZE
   $(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE))
-  CFG_RUSTC_FLAGS := -nowarn
+  CFG_RUSTC_FLAGS := --nowarn
 else
-  CFG_RUSTC_FLAGS := -nowarn -O
+  CFG_RUSTC_FLAGS := --nowarn -O
 endif
 
 ifdef SAVE_TEMPS
-  CFG_RUSTC_FLAGS += -save-temps
+  CFG_RUSTC_FLAGS += --save-temps
 endif
 
 # On Darwin, we need to run dsymutil so the debugging information ends
@@ -471,7 +471,7 @@ boot/$(CFG_STDLIB): $(STDLIB_CRATE) $(STDLIB_INPUTS) \
 
 stage0/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage0/rustc$(X) $(MKFILES)
 	@$(call E, compile: $@)
-	$(STAGE0) -c -shared -o $@ $<
+	$(STAGE0) -c --shared -o $@ $<
 
 stage0/$(CFG_STDLIB): stage0/std.o stage0/glue.o
 	@$(call E, link: $@)
@@ -480,7 +480,7 @@ stage0/$(CFG_STDLIB): stage0/std.o stage0/glue.o
 
 stage1/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage1/rustc$(X) $(MKFILES)
 	@$(call E, compile: $@)
-	$(STAGE1) -c -shared -o $@ $<
+	$(STAGE1) -c --shared -o $@ $<
 
 stage1/$(CFG_STDLIB): stage1/std.o stage1/glue.o
 	@$(call E, link: $@)
@@ -489,7 +489,7 @@ stage1/$(CFG_STDLIB): stage1/std.o stage1/glue.o
 
 stage2/std.o: $(STDLIB_CRATE) $(STDLIB_INPUTS) stage2/rustc$(X) $(MKFILES)
 	@$(call E, compile: $@)
-	$(STAGE2) -c -shared -o $@ $<
+	$(STAGE2) -c --shared -o $@ $<
 
 stage2/$(CFG_STDLIB): stage2/std.o stage2/glue.o
 	@$(call E, link: $@)
@@ -516,17 +516,17 @@ stage2/rustc.o: $(COMPILER_CRATE) $(COMPILER_INPUTS) $(SREQ1)
 stage0/glue.o: stage0/rustc$(X) boot/$(CFG_STDLIB) \
                 rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
 	@$(call E, generate: $@)
-	$(STAGE0) -c -o $@ -glue
+	$(STAGE0) -c -o $@ --glue
 
 stage1/glue.o: stage1/rustc$(X) stage0/$(CFG_STDLIB) \
                 rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
 	@$(call E, generate: $@)
-	$(STAGE1) -c -o $@ -glue
+	$(STAGE1) -c -o $@ --glue
 
 stage2/glue.o: stage2/rustc$(X) stage1/$(CFG_STDLIB) \
                 rustllvm/$(CFG_RUSTLLVM) rt/$(CFG_RUNTIME)
 	@$(call E, generate: $@)
-	$(STAGE2) -c -o $@ -glue
+	$(STAGE2) -c -o $@ --glue
 
 # Due to make not wanting to run the same implicit rules twice on the same
 # rule tree (implicit-rule recursion prevention, see "Chains of Implicit
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs
index 890e69da269..c321b3a0973 100644
--- a/src/comp/driver/rustc.rs
+++ b/src/comp/driver/rustc.rs
@@ -20,6 +20,12 @@ import std._str;
 import std._vec;
 import std.io;
 
+import std.GetOpts;
+import std.GetOpts.optopt;
+import std.GetOpts.optmulti;
+import std.GetOpts.optflag;
+import std.GetOpts.opt_present;
+
 fn default_environment(session.session sess,
                        str argv0,
                        str input) -> eval.env {
@@ -105,18 +111,18 @@ fn usage(session.session sess, str argv0) {
 options:
 
     -o <filename>      write output to <filename>
-    -nowarn            suppress wrong-compiler warning
-    -glue              generate glue.bc file
-    -shared            compile a shared-library crate
-    -pp                pretty-print the input instead of compiling
-    -ls                list the symbols defined by a crate file
+    --nowarn           suppress wrong-compiler warning
+    --glue             generate glue.bc file
+    --shared           compile a shared-library crate
+    --pretty           pretty-print the input instead of compiling
+    --ls               list the symbols defined by a crate file
     -L <path>          add a directory to the library search path
-    -noverify          suppress LLVM verification step (slight speedup)
-    -parse-only        parse only; do not compile, assemble, or link
+    --noverify         suppress LLVM verification step (slight speedup)
+    --parse-only       parse only; do not compile, assemble, or link
     -O                 optimize
     -S                 compile only; do not assemble or link
     -c                 compile and assemble, but do not link
-    -save-temps        write intermediate files in addition to normal output
+    --save-temps       write intermediate files in addition to normal output
     -h                 display this message\n\n");
 }
 
@@ -142,133 +148,81 @@ fn main(vec[str] args) {
     auto sess = session.session(target_crate_num, target_cfg, crate_cache,
                                 md, front.codemap.new_codemap());
 
-    let option.t[str] input_file = none[str];
-    let option.t[str] output_file = none[str];
-    let vec[str] library_search_paths = vec();
-    let bool do_warn = true;
-    let bool shared = false;
-    let bool pretty = false;
-    let bool ls = false;
-    auto ot = trans.output_type_bitcode;
-    let bool glue = false;
-    let bool verify = true;
-    let bool save_temps = false;
+    auto opts = vec(optflag("nowarn"), optflag("h"), optflag("glue"),
+                    optflag("pretty"), optflag("ls"), optflag("parse-only"),
+                    optflag("O"), optflag("shared"), optmulti("L"),
+                    optflag("S"), optflag("c"), optopt("o"),
+                    optflag("save-temps"), optflag("noverify"));
+    auto binary = _vec.shift[str](args);
+    auto match;
+    alt (GetOpts.getopts(args, opts)) {
+        case (GetOpts.failure(?f)) { sess.err(GetOpts.fail_str(f)); fail; }
+        case (GetOpts.success(?m)) { match = m; }
+    }
+    if (!opt_present(match, "nowarn")) {
+        warn_wrong_compiler();
+    }
+    if (opt_present(match, "h")) {
+        usage(sess, binary);
+        ret;
+    }
 
+    auto pretty = opt_present(match, "pretty");
+    auto ls = opt_present(match, "ls");
+    auto glue = opt_present(match, "glue");
+    auto shared = opt_present(match, "shared");
+    auto output_file = GetOpts.opt_maybe_str(match, "o");
+    auto library_search_paths = GetOpts.opt_strs(match, "L");
+    auto ot = trans.output_type_bitcode;
+    if (opt_present(match, "parse-only")) {
+        ot = trans.output_type_none;
+    } else if (opt_present(match, "S")) {
+        ot = trans.output_type_assembly;
+    } else if (opt_present(match, "c")) {
+        ot = trans.output_type_object;
+    }
+    auto verify = !opt_present(match, "noverify");
+    auto save_temps = opt_present(match, "save-temps");
     // FIXME: Maybe we should support -O0, -O1, -Os, etc
-    let bool optimize = false;
+    auto optimize = opt_present(match, "O");
+    auto n_inputs = _vec.len[str](match.free);
 
-    auto i = 1u;
-    auto len = _vec.len[str](args);
-
-    // FIXME: a getopt module would be nice.
-    while (i < len) {
-        auto arg = args.(i);
-        if (_str.byte_len(arg) > 0u && arg.(0) == '-' as u8) {
-            if (_str.eq(arg, "-nowarn")) {
-                do_warn = false;
-            } else if (_str.eq(arg, "-O")) {
-                optimize = true;
-            } else if (_str.eq(arg, "-glue")) {
-                glue = true;
-            } else if (_str.eq(arg, "-shared")) {
-                shared = true;
-            } else if (_str.eq(arg, "-pp")) {
-                pretty = true;
-            } else if (_str.eq(arg, "-ls")) {
-                ls = true;
-            } else if (_str.eq(arg, "-parse-only")) {
-                ot = trans.output_type_none;
-            } else if (_str.eq(arg, "-S")) {
-                ot = trans.output_type_assembly;
-            } else if (_str.eq(arg, "-c")) {
-                ot = trans.output_type_object;
-            } else if (_str.eq(arg, "-o")) {
-                if (i+1u < len) {
-                    output_file = some(args.(i+1u));
-                    i += 1u;
-                } else {
-                    usage(sess, args.(0));
-                    sess.err("-o requires an argument");
-                }
-            } else if (_str.eq(arg, "-save-temps")) {
-                save_temps = true;
-            } else if (_str.eq(arg, "-L")) {
-                if (i+1u < len) {
-                    library_search_paths += vec(args.(i+1u));
-                    i += 1u;
-                } else {
-                    usage(sess, args.(0));
-                    sess.err("-L requires an argument");
-                }
-            } else if (_str.eq(arg, "-noverify")) {
-                verify = false;
-            } else if (_str.eq(arg, "-h")) {
-                usage(sess, args.(0));
-            } else {
-                usage(sess, args.(0));
-                sess.err("unrecognized option: " + arg);
-            }
-        } else {
-            alt (input_file) {
-                case (some[str](_)) {
-                    usage(sess, args.(0));
-                    sess.err("multiple inputs provided");
-                }
-                case (none[str]) {
-                    input_file = some[str](arg);
-                }
-            }
+    if (glue) {
+        if (n_inputs > 0u) {
+            sess.err("No input files allowed with --glue.");
         }
-        i += 1u;
+        auto out = option.from_maybe[str]("glue.bc", output_file);
+        middle.trans.make_common_glue(out, optimize, verify, save_temps, ot);
+        ret;
     }
 
-    if (do_warn) {
-        warn_wrong_compiler();
+    if (n_inputs == 0u) {
+        sess.err("No input filename given.");
+    } else if (n_inputs > 1u) {
+        sess.err("Multiple input filenames provided.");
     }
 
-    if (glue) {
+    auto ifile = match.free.(0);
+    auto env = default_environment(sess, args.(0), ifile);
+    if (pretty) {
+        pretty_print_input(sess, env, ifile);
+    } else if (ls) {
+        front.creader.list_file_metadata(ifile, std.io.stdout());
+    } else {
         alt (output_file) {
             case (none[str]) {
-                middle.trans.make_common_glue("glue.bc", optimize, verify,
-                                              save_temps, ot);
-            }
-            case (some[str](?s)) {
-                middle.trans.make_common_glue(s, optimize, verify, save_temps,
-                                              ot);
+                let vec[str] parts = _str.split(ifile, '.' as u8);
+                _vec.pop[str](parts);
+                parts += vec(".bc");
+                auto ofile = _str.concat(parts);
+                compile_input(sess, env, ifile, ofile, shared,
+                              optimize, verify, save_temps, ot,
+                              library_search_paths);
             }
-        }
-        ret;
-    }
-
-    alt (input_file) {
-        case (none[str]) {
-            usage(sess, args.(0));
-            sess.err("no input filename");
-        }
-        case (some[str](?ifile)) {
-
-            auto env = default_environment(sess, args.(0), ifile);
-            if (pretty) {
-                pretty_print_input(sess, env, ifile);
-            } else if (ls) {
-                front.creader.list_file_metadata(ifile, std.io.stdout());
-            } else {
-                alt (output_file) {
-                    case (none[str]) {
-                        let vec[str] parts = _str.split(ifile, '.' as u8);
-                        _vec.pop[str](parts);
-                        parts += vec(".bc");
-                        auto ofile = _str.concat(parts);
-                        compile_input(sess, env, ifile, ofile, shared,
-                                      optimize, verify, save_temps, ot,
-                                      library_search_paths);
-                    }
-                    case (some[str](?ofile)) {
-                        compile_input(sess, env, ifile, ofile, shared,
-                                      optimize, verify, save_temps, ot,
-                                      library_search_paths);
-                    }
-                }
+            case (some[str](?ofile)) {
+                compile_input(sess, env, ifile, ofile, shared,
+                              optimize, verify, save_temps, ot,
+                              library_search_paths);
             }
         }
     }
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 04bea450f7d..24078767f19 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -630,7 +630,9 @@ fn ty_to_str(ctxt cx, &t typ) -> str {
 fn ty_to_abbrev_str(ctxt cx, t typ) -> str {
     auto f = def_to_str;
     auto ecx = @rec(ds=f, tcx=cx);
-    ret metadata.Encode.ty_str(ecx, typ);
+    auto s = metadata.Encode.ty_str(ecx, typ);
+    if (_str.byte_len(s) >= 64u) { s = _str.substr(s, 0u, 64u); }
+    ret s;
 }
 
 // Type folds
diff --git a/src/lib/GetOpts.rs b/src/lib/GetOpts.rs
new file mode 100644
index 00000000000..f85ce85c136
--- /dev/null
+++ b/src/lib/GetOpts.rs
@@ -0,0 +1,249 @@
+/* Simple getopt alternative. Construct a vector of options, either by using
+ * reqopt, optopt, and optflag or by building them from components yourself,
+ * and pass them to getopts, along with a vector of actual arguments (not
+ * including argv[0]). You'll either get a failure code back, or a match.
+ * You'll have to verify whether the amount of 'free' arguments in the match
+ * is what you expect. Use opt_* accessors (bottom of the file) to get
+ * argument values out of the match object.
+ */ 
+
+import option.some;
+import option.none;
+
+tag name { long(str); short(char); }
+tag hasarg { yes; no; maybe; }
+tag occur { req; optional; multi; }
+
+type opt = rec(name name, hasarg hasarg, occur occur);
+
+fn mkname(str nm) -> name {
+    if (_str.char_len(nm) == 1u) { ret short(_str.char_at(nm, 0u)); }
+    else { ret long(nm); }
+}
+fn reqopt(str name) -> opt {
+    ret rec(name=mkname(name), hasarg=yes, occur=req);
+}
+fn optopt(str name) -> opt {
+    ret rec(name=mkname(name), hasarg=yes, occur=optional);
+}
+fn optflag(str name) -> opt {
+    ret rec(name=mkname(name), hasarg=no, occur=optional);
+}
+fn optmulti(str name) -> opt {
+    ret rec(name=mkname(name), hasarg=yes, occur=multi);
+}
+
+tag optval {
+    val(str);
+    given;
+}
+
+type match = rec(vec[opt] opts, vec[mutable vec[optval]] vals, vec[str] free);
+
+fn is_arg(str arg) -> bool {
+    ret _str.byte_len(arg) > 1u && arg.(0) == '-' as u8;
+}
+fn name_str(name nm) -> str {
+    alt (nm) {
+        case (short(?ch)) {ret _str.from_char(ch);}
+        case (long(?s)) {ret s;}
+    }
+}
+
+// FIXME rustboot workaround
+fn name_eq(name a, name b) -> bool {
+    alt (a) {
+        case (long(?a)) {
+            alt (b) {
+                case (long(?b)) { ret _str.eq(a, b); }
+                case (_) { ret false; }
+            }
+        }
+        case (_) { if (a == b) { ret true; } else {ret false; } }
+    }
+}
+fn find_opt(vec[opt] opts, name nm) -> option.t[uint] {
+    auto i = 0u;
+    auto l = _vec.len[opt](opts);
+    while (i < l) {
+        if (name_eq(opts.(i).name, nm)) { ret some[uint](i); }
+        i += 1u;
+    }
+    ret none[uint];
+}
+
+tag fail_ {
+    argument_missing(str);
+    unrecognized_option(str);
+    option_missing(str);
+    option_duplicated(str);
+}
+
+fn fail_str(fail_ f) -> str {
+    alt (f) {
+        case (argument_missing(?nm)) {
+            ret "Argument to option '" + nm + "' missing.";
+        }
+        case (unrecognized_option(?nm)) {
+            ret "Unrecognized option: '" + nm + "'.";
+        }
+        case (option_missing(?nm)) {
+            ret "Required option '" + nm + "' missing.";
+        }
+        case (option_duplicated(?nm)) {
+            ret "Option '" + nm + "' given more than once.";
+        }
+    }
+}
+
+tag result {
+    success(match);
+    failure(fail_);
+}
+
+fn getopts(vec[str] args, vec[opt] opts) -> result {
+    auto n_opts = _vec.len[opt](opts);
+    fn empty_(uint x) -> vec[optval]{ret _vec.empty[optval]();}
+    auto f = empty_;
+    auto vals = _vec.init_fn_mut[vec[optval]](f, n_opts);
+    let vec[str] free = vec();
+
+    auto l = _vec.len[str](args);
+    auto i = 0u;
+    while (i < l) {
+        auto cur = args.(i);
+        auto curlen = _str.byte_len(cur);
+        if (!is_arg(cur)) {
+            _vec.push[str](free, cur);
+        } else if (_str.eq(cur, "--")) {
+            free += _vec.slice[str](args, i + 1u, l);
+            break;
+        } else {
+            auto names;
+            auto i_arg = option.none[str];
+            if (cur.(1) == '-' as u8) {
+                auto tail = _str.slice(cur, 2u, curlen);
+                auto eq = _str.index(tail, '=' as u8);
+                if (eq == -1) {
+                    names = vec(long(tail));
+                } else {
+                    names = vec(long(_str.slice(tail, 0u, eq as uint)));
+                    i_arg = option.some[str]
+                        (_str.slice(tail, (eq as uint) + 1u, curlen - 2u));
+                }
+            } else {
+                auto j = 1u;
+                names = vec();
+                while (j < curlen) {
+                    auto range = _str.char_range_at(cur, j);
+                    _vec.push[name](names, short(range._0));
+                    j = range._1;
+                }
+            }
+            auto name_pos = 0u;
+            for (name nm in names) {
+                name_pos += 1u;
+                auto optid;
+                alt (find_opt(opts, nm)) {
+                    case (some[uint](?id)) {optid = id;}
+                    case (none[uint]) {
+                        ret failure(unrecognized_option(name_str(nm)));
+                    }
+                }
+                alt (opts.(optid).hasarg) {
+                    case (no) {
+                        _vec.push[optval](vals.(optid), given);
+                    }
+                    case (maybe) {
+                        if (!option.is_none[str](i_arg)) {
+                            _vec.push[optval](vals.(optid),
+                                              val(option.get[str](i_arg)));
+                        } else if (name_pos < _vec.len[name](names) ||
+                                   i + 1u == l || is_arg(args.(i + 1u))) {
+                            _vec.push[optval](vals.(optid), given);
+                        } else {
+                            i += 1u;
+                            _vec.push[optval](vals.(optid), val(args.(i)));
+                        }
+                    }
+                    case (yes) {
+                        if (!option.is_none[str](i_arg)) {
+                            _vec.push[optval](vals.(optid),
+                                              val(option.get[str](i_arg)));
+                        } else if (i + 1u == l) {
+                            ret failure(argument_missing(name_str(nm)));
+                        } else {
+                            i += 1u;
+                            _vec.push[optval](vals.(optid), val(args.(i)));
+                        }
+                    }
+                }
+            }
+        }
+        i += 1u;
+    }
+
+    i = 0u;
+    while (i < n_opts) {
+        auto n = _vec.len[optval](vals.(i));
+        auto occ = opts.(i).occur;
+        if (occ == req) {if (n == 0u) {
+            ret failure(option_missing(name_str(opts.(i).name)));
+        }}
+        if (occ != multi) {if (n > 1u) {
+            ret failure(option_duplicated(name_str(opts.(i).name)));
+        }}
+        i += 1u;
+    }
+
+    ret success(rec(opts=opts, vals=vals, free=free));
+}
+
+fn opt_vals(match m, str nm) -> vec[optval] {
+    alt (find_opt(m.opts, mkname(nm))) {
+        case (some[uint](?id)) { ret m.vals.(id); }
+        case (none[uint]) {
+            log_err "No option '" + nm + "' defined.";
+            fail;
+        }
+    }
+}
+fn opt_val(match m, str nm) -> optval {
+    ret opt_vals(m, nm).(0);
+}
+fn opt_present(match m, str nm) -> bool {
+    ret _vec.len[optval](opt_vals(m, nm)) > 0u;
+}
+fn opt_str(match m, str nm) -> str {
+    alt (opt_val(m, nm)) {
+        case (val(?s)) { ret s; }
+        case (_) { fail; }
+    }
+}
+fn opt_strs(match m, str nm) -> vec[str] {
+    let vec[str] acc = vec();
+    for (optval v in opt_vals(m, nm)) {
+        alt (v) {
+            case (val(?s)) { _vec.push[str](acc, s); }
+            case (_) {}
+        }
+    }
+    ret acc;
+}
+fn opt_maybe_str(match m, str nm) -> option.t[str] {
+    auto vals = opt_vals(m, nm);
+    if (_vec.len[optval](vals) == 0u) { ret none[str]; }
+    alt (vals.(0)) {
+        case (val(?s)) { ret some[str](s); }
+        case (_) { ret none[str]; }
+    }
+}
+
+// Local Variables:
+// mode: rust;
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
diff --git a/src/lib/Term.rs b/src/lib/Term.rs
new file mode 100644
index 00000000000..9bf90b1cdb0
--- /dev/null
+++ b/src/lib/Term.rs
@@ -0,0 +1,54 @@
+// Simple ANSI color library.
+//
+// TODO: Windows support.
+
+const u8 color_black = 0u8;
+const u8 color_red = 1u8;
+const u8 color_green = 2u8;
+const u8 color_yellow = 3u8;
+const u8 color_blue = 4u8;
+const u8 color_magenta = 5u8;
+const u8 color_cyan = 6u8;
+const u8 color_light_gray = 7u8;
+const u8 color_light_grey = 7u8;
+const u8 color_dark_gray = 8u8;
+const u8 color_dark_grey = 8u8;
+const u8 color_bright_red = 9u8;
+const u8 color_bright_green = 10u8;
+const u8 color_bright_yellow = 11u8;
+const u8 color_bright_blue = 12u8;
+const u8 color_bright_magenta = 13u8;
+const u8 color_bright_cyan = 14u8;
+const u8 color_bright_white = 15u8;
+
+fn esc(io.buf_writer writer) {
+    writer.write(vec(0x1bu8, '[' as u8));
+}
+
+fn reset(io.buf_writer writer) {
+    esc(writer);
+    writer.write(vec('0' as u8, 'm' as u8));
+}
+
+fn set_color(io.buf_writer writer, u8 first_char, u8 color) {
+    check (color < 16u8);
+
+    esc(writer);
+    if (color >= 8u8) {
+        writer.write(vec('1' as u8, ';' as u8));
+        color -= 8u8;
+    }
+    writer.write(vec(first_char, ('0' as u8) + color, 'm' as u8));
+}
+
+fn fg(io.buf_writer writer, u8 color) {
+    ret set_color(writer, '3' as u8, color);
+}
+
+fn bg(io.buf_writer writer, u8 color) {
+    ret set_color(writer, '4' as u8, color);
+}
+
+// export fg;
+// export bg;
+
diff --git a/src/lib/_str.rs b/src/lib/_str.rs
index 3922acb6a92..41a86cf3cbb 100644
--- a/src/lib/_str.rs
+++ b/src/lib/_str.rs
@@ -391,10 +391,14 @@ fn ends_with(str haystack, str needle) -> bool {
 }
 
 fn substr(str s, uint begin, uint len) -> str {
+    ret slice(s, begin, begin + len);
+}
+
+fn slice(str s, uint begin, uint end) -> str {
     let str accum = "";
     let uint i = begin;
-    while (i < begin+len) {
-        accum += unsafe_from_byte(s.(i));
+    while (i < end) {
+        push_byte(accum, s.(i));
         i += 1u;
     }
     ret accum;
diff --git a/src/lib/std.rc b/src/lib/std.rc
index 1056f375138..8a9ee42d0da 100644
--- a/src/lib/std.rc
+++ b/src/lib/std.rc
@@ -70,6 +70,8 @@ mod ebml;
 mod UFind;
 mod ExtFmt;
 mod Box;
+mod GetOpts;
+mod Term;
 
 // Local Variables:
 // mode: rust;