From 7c92435f8f93344330e47fb0cca4f79297896bd2 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 16 Oct 2013 22:23:12 -0400 Subject: [PATCH 1/2] remove the rusti command Closes #9818 Closes #9567 Closes #8924 Closes #8910 Closes #8392 Closes #7692 Closes #7499 Closes #7220 --- Makefile.in | 7 +- RELEASES.txt | 8 + doc/tutorial.md | 4 +- man/rustc.1 | 2 +- man/rustdoc.1 | 2 +- man/rusti.1 | 82 ----- man/rustpkg.1 | 2 +- mk/clean.mk | 6 - mk/dist.mk | 1 - mk/install.mk | 7 - mk/tests.mk | 12 +- mk/tools.mk | 43 --- src/README.txt | 2 - src/librusti/program.rs | 416 --------------------- src/librusti/rusti.rs | 786 ---------------------------------------- src/librusti/utils.rs | 52 --- 16 files changed, 15 insertions(+), 1417 deletions(-) delete mode 100644 man/rusti.1 delete mode 100644 src/librusti/program.rs delete mode 100644 src/librusti/rusti.rs delete mode 100644 src/librusti/utils.rs diff --git a/Makefile.in b/Makefile.in index 3ad038e8358..7e77f6fd678 100644 --- a/Makefile.in +++ b/Makefile.in @@ -221,7 +221,6 @@ CFG_LIBRUSTC_$(1) :=$(call CFG_LIB_NAME_$(1),rustc) CFG_LIBSYNTAX_$(1) :=$(call CFG_LIB_NAME_$(1),syntax) CFG_LIBRUSTPKG_$(1) :=$(call CFG_LIB_NAME_$(1),rustpkg) CFG_LIBRUSTDOC_$(1) :=$(call CFG_LIB_NAME_$(1),rustdoc) -CFG_LIBRUSTI_$(1) :=$(call CFG_LIB_NAME_$(1),rusti) EXTRALIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),extra) STDLIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),std) @@ -229,14 +228,12 @@ LIBRUSTC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustc) LIBSYNTAX_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),syntax) LIBRUSTPKG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustpkg) LIBRUSTDOC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustdoc) -LIBRUSTI_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rusti) EXTRALIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),extra) STDLIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),std) LIBRUSTC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustc) LIBSYNTAX_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),syntax) LIBRUSTPKG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustpkg) LIBRUSTDOC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustdoc) -LIBRUSTI_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rusti) endef @@ -446,14 +443,12 @@ CSREQ$(1)_T_$(2)_H_$(3) = \ $$(HBIN$(1)_H_$(3))/rusti$$(X_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTPKG_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTDOC_$(3)) \ - $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTI_$(3)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTI_$(2)) \ + $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) ifeq ($(1),0) # Don't run the the stage0 compiler under valgrind - that ship has sailed diff --git a/RELEASES.txt b/RELEASES.txt index 9aea24dd22d..e2dfa320327 100644 --- a/RELEASES.txt +++ b/RELEASES.txt @@ -1,3 +1,11 @@ +Version 0.9 (XXX 2013) +-------------------------- + + * ~XXX changes, numerous bugfixes + + * Tooling + * The `rust` and `rusti` commands have been removed, due to lack of maintenance. + Version 0.8 (September 2013) -------------------------- diff --git a/doc/tutorial.md b/doc/tutorial.md index 3723d12262b..241e0367fef 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -113,9 +113,7 @@ for more information on them. When complete, `make install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler; `rustdoc`, the -API-documentation tool; `rustpkg`, the Rust package manager; -`rusti`, the Rust REPL; and `rust`, a tool which acts both as a unified -interface for them, and for a few common command line scenarios. +API-documentation tool; and `rustpkg`, the Rust package manager. [tarball]: http://static.rust-lang.org/dist/rust-0.8.tar.gz [win-exe]: http://static.rust-lang.org/dist/rust-0.8-install.exe diff --git a/man/rustc.1 b/man/rustc.1 index 2298d5e5455..e4cfab7747f 100644 --- a/man/rustc.1 +++ b/man/rustc.1 @@ -130,7 +130,7 @@ To build an executable with debug info (experimental): .SH "SEE ALSO" -rust, rustdoc, rustpkg, rusti +rustdoc, rustpkg .SH "BUGS" See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. diff --git a/man/rustdoc.1 b/man/rustdoc.1 index c7cdb832887..78340984f96 100644 --- a/man/rustdoc.1 +++ b/man/rustdoc.1 @@ -84,7 +84,7 @@ The generated HTML can be viewed with any standard web browser. .SH "SEE ALSO" -rust, rustc, rustpkg, rusti +rustc, rustpkg .SH "BUGS" See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. diff --git a/man/rusti.1 b/man/rusti.1 deleted file mode 100644 index 9f7d1733c65..00000000000 --- a/man/rusti.1 +++ /dev/null @@ -1,82 +0,0 @@ -.TH RUSTI "1" "July 2013" "rusti 0.7" "User Commands" -\" Macros -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.SH NAME -rusti \- Rust interactive shell - -.SH SYNOPSIS -.B rusti - -.SH DESCRIPTION - -This program is a REPL (Read-Eval-Print Loop) for the Rust language, available -at <\fBhttps://www.rust-lang.org\fR>. It provides an interactive shell to -evaluate Rust expressions, functions and code snippets, and to experiment with -Rust code. - -.B WARNING: -The Rust REPL is experimental and may be unstable. If you encounter problems, -please use the compiler instead. - -.SH OPTIONS - -Currently none. - -.SH SPECIAL COMMANDS - -The interactive shell evaluates all input as a sequence of Rust expressions, -except for a set of special commands prefixed by a colon ':'. These special -commands are described below: - -.TP -\fB:help\fR -Display a summary of available commands. -.TP -\fB:{\\n ..lines.. \\n:}\\n\fR -execute multiline command -.TP -\fB:load ...\fR -loads given crates as dynamic libraries -.TP -\fB:clear\fR -clear the bindings -.TP -\fB:exit\fR -exit from the repl - -.SH "EXAMPLES" - -A simple example session, declaring a variable, defining a function, -evaluating an expression and printing the result: - -.PP -.Vb -\& \fBrusti>\fR let x = 42; -\& \fBrusti>\fR fn square(n: int) -> int { n*n } -\& \fBrusti>\fR println(fmt!("%d squared is %d", x, square(x))); -\& 42 squared is 1764 -.Ve - -.SH "SEE ALSO" - -rust, rustc, rustdoc, rustpkg - -.SH "BUGS" -See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. - -.SH "AUTHOR" -See \fBAUTHORS.txt\fR in the rust source distribution. Graydon Hoare -<\fIgraydon@mozilla.com\fR> is the project leader. - -.SH "COPYRIGHT" -This work is dual-licensed under Apache 2.0 and MIT terms. See \fBCOPYRIGHT\fR -file in the rust source distribution. diff --git a/man/rustpkg.1 b/man/rustpkg.1 index d23a1f4368e..856f9022813 100644 --- a/man/rustpkg.1 +++ b/man/rustpkg.1 @@ -181,7 +181,7 @@ custom build logic. .SH "SEE ALSO" -rust, rustc, rustdoc, rusti +rustc, rustdoc .SH "BUGS" See <\fBhttps://github.com/mozilla/rust/issues\fR> for issues. diff --git a/mk/clean.mk b/mk/clean.mk index d1e3afe98a0..09a80c5507b 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -67,7 +67,6 @@ clean$(1)_H_$(2): $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustpkg$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/serializer$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rustdoc$(X_$(2)) - $(Q)rm -f $$(HBIN$(1)_H_$(2))/rusti$(X_$(2)) $(Q)rm -f $$(HBIN$(1)_H_$(2))/rust$(X_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTPKG_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTDOC_$(2)) @@ -76,14 +75,12 @@ clean$(1)_H_$(2): $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_EXTRALIB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTC_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBSYNTAX_$(2)) - $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTI_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(STDLIB_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(EXTRALIB_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTC_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBSYNTAX_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTPKG_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTDOC_GLOB_$(2)) - $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTI_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUSTLLVM_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/libstd.rlib @@ -100,7 +97,6 @@ clean$(1)_T_$(2)_H_$(3): $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/serializer$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustdoc$(X_$(2)) - $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rusti$(X_$(2)) $(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rust$(X_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) @@ -109,14 +105,12 @@ clean$(1)_T_$(2)_H_$(3): $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2)) - $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTI_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(STDLIB_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(EXTRALIB_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTC_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTPKG_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTDOC_GLOB_$(2)) - $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTI_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libstd.rlib $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a diff --git a/mk/dist.mk b/mk/dist.mk index ccb20a164d9..13b9509e667 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -29,7 +29,6 @@ PKG_FILES := \ README.txt \ driver \ librustpkg \ - librusti \ librustc \ compiletest \ etc \ diff --git a/mk/install.mk b/mk/install.mk index 90cdb3939fc..94260056386 100644 --- a/mk/install.mk +++ b/mk/install.mk @@ -104,7 +104,6 @@ install-target-$(1)-host-$(2): $$(CSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(Q)$$(call INSTALL_LIB,$$(LIBSYNTAX_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,$$(LIBRUSTPKG_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,$$(LIBRUSTDOC_GLOB_$(1))) - $$(Q)$$(call INSTALL_LIB,$$(LIBRUSTI_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,libmorestack.a) endef @@ -138,19 +137,16 @@ install-host: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD_TRIPLE)_H_$(CFG_BUILD_TRIPLE)) $(Q)$(call INSTALL,$(HB2),$(PHB),rustc$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rustpkg$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rustdoc$(X_$(CFG_BUILD_TRIPLE))) - $(Q)$(call INSTALL,$(HB2),$(PHB),rusti$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(STDLIB_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(EXTRALIB_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(LIBRUSTC_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(LIBSYNTAX_GLOB_$(CFG_BUILD_TRIPLE))) - $(Q)$(call INSTALL_LIB,$(LIBRUSTI_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HL),$(PHL),$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rustc.1) $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rustdoc.1) - $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rusti.1) $(Q)$(call INSTALL,$(S)/man, $(PREFIX_ROOT)/share/man/man1,rustpkg.1) install-targets: $(INSTALL_TARGET_RULES) @@ -162,7 +158,6 @@ HOST_LIB_FROM_HL_GLOB = \ uninstall: $(Q)rm -f $(PHB)/rustc$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHB)/rustpkg$(X_$(CFG_BUILD_TRIPLE)) - $(Q)rm -f $(PHB)/rusti$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHB)/rustdoc$(X_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHL)/$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHL)/$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE)) @@ -173,14 +168,12 @@ uninstall: $(call HOST_LIB_FROM_HL_GLOB,$(LIBSYNTAX_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD_TRIPLE))) \ - $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTI_GLOB_$(CFG_BUILD_TRIPLE))) \ ; \ do rm -f $$i ; \ done $(Q)rm -Rf $(PHL)/rustc $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rustc.1 $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rustdoc.1 - $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rusti.1 $(Q)rm -f $(PREFIX_ROOT)/share/man/man1/rustpkg.1 # target platform specific variables diff --git a/mk/tests.mk b/mk/tests.mk index c4e3dbbf603..fb5bd094404 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -15,7 +15,7 @@ # The names of crates that must be tested TEST_TARGET_CRATES = std extra -TEST_HOST_CRATES = rusti rustpkg rustc rustdoc syntax +TEST_HOST_CRATES = rustpkg rustc rustdoc syntax TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES) # Markdown files under doc/ that should have their code extracted and run @@ -189,7 +189,7 @@ check-test: cleantestlibs cleantmptestlogs all check-stage2-rfail check-lite: cleantestlibs cleantmptestlogs \ check-stage2-std check-stage2-extra check-stage2-rpass \ - check-stage2-rustpkg check-stage2-rusti \ + check-stage2-rustpkg \ check-stage2-rfail check-stage2-cfail $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log @@ -379,14 +379,6 @@ $(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)): \ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test -$(3)/stage$(1)/test/rustitest-$(2)$$(X_$(2)): \ - $$(RUSTI_LIB) $$(RUSTI_INPUTS) \ - $$(SREQ$(1)_T_$(2)_H_$(3)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) - @$$(call E, compile_and_link: $$@) - $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test - $(3)/stage$(1)/test/rustdoctest-$(2)$$(X_$(2)): \ $$(RUSTDOC_LIB) $$(RUSTDOC_INPUTS) \ $$(SREQ$(1)_T_$(2)_H_$(3)) \ diff --git a/mk/tools.mk b/mk/tools.mk index fa85e9e725a..a9ea12b5b24 100644 --- a/mk/tools.mk +++ b/mk/tools.mk @@ -24,10 +24,6 @@ RUSTDOC_LIB := $(S)src/librustdoc/rustdoc.rs RUSTDOC_INPUTS := $(wildcard $(addprefix $(S)src/librustdoc/, \ *.rs */*.rs */*/*.rs)) -# Rusti, the JIT REPL -RUSTI_LIB := $(S)src/librusti/rusti.rs -RUSTI_INPUTS := $(wildcard $(S)src/librusti/*.rs) - # FIXME: These are only built for the host arch. Eventually we'll # have tools that need to built for other targets. define TOOLS_STAGE_N_TARGET @@ -75,24 +71,6 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4)): \ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rustdoc -o $$@ $$< -$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)): \ - $$(RUSTI_LIB) $$(RUSTI_INPUTS) \ - $$(SREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(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)) $$(WFLAGS_ST$(1)) --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)): \ - $$(DRIVER_CRATE) \ - $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(4))/$(CFG_LIBRUSTI_$(4)) \ - | $$(TBIN$(1)_T_$(4)_H_$(3))/ - @$$(call E, compile_and_link: $$@) - $$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rusti -o $$@ $$< - endef define TOOLS_STAGE_N_HOST @@ -147,27 +125,6 @@ $$(HBIN$(2)_H_$(4))/rustdoc$$(X_$(4)): \ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTI_$(4)): \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)) \ - $$(HSREQ$(2)_H_$(4)) \ - | $$(HLIB$(2)_H_$(4))/ - @$$(call E, cp: $$@) - $$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTI_GLOB_$(4)),$$(notdir $$@)) - $$(Q)cp $$< $$@ - $$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTI_GLOB_$(4)),$$(notdir $$@)) - $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTI_GLOB_$(4)) \ - $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTI_DSYM_GLOB_$(4))) \ - $$(HLIB$(2)_H_$(4)) - -$$(HBIN$(2)_H_$(4))/rusti$$(X_$(4)): \ - $$(TBIN$(1)_T_$(4)_H_$(3))/rusti$$(X_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTI_$(4)) \ - $$(HSREQ$(2)_H_$(4)) \ - | $$(HBIN$(2)_H_$(4))/ - @$$(call E, cp: $$@) - $$(Q)cp $$< $$@ - endef $(foreach host,$(CFG_HOST_TRIPLES), \ diff --git a/src/README.txt b/src/README.txt index f229068731f..7cf523e1017 100644 --- a/src/README.txt +++ b/src/README.txt @@ -31,8 +31,6 @@ compiletest/ The test runner librustpkg/ The package manager and build system -librusti/ The JIT REPL - librustdoc/ The Rust API documentation tool llvm/ The LLVM submodule diff --git a/src/librusti/program.rs b/src/librusti/program.rs deleted file mode 100644 index 4ab9ac4aef5..00000000000 --- a/src/librusti/program.rs +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cast; -use std::util; -use std::hashmap::HashMap; -use std::local_data; - -use syntax::ast; -use syntax::parse::token; -use syntax::print::pprust; -use rustc::middle::ty; -use rustc::util::ppaux; - -use utils::*; - -/// This structure keeps track of the state of the world for the code being -/// executed in rusti. -#[deriving(Clone)] -pub struct Program { - /// All known local variables - local_vars: HashMap<~str, LocalVariable>, - /// New variables which will be present (learned from typechecking) - newvars: HashMap<~str, LocalVariable>, - /// All known view items (use statements), distinct because these must - /// follow extern mods - view_items: ~str, - /// All known 'extern mod' statements (must always come first) - externs: ~str, - /// All known structs defined. These need to have - /// #[deriving(Encodable,Decodable)] to be at all useful in rusti - structs: HashMap<~str, ~str>, - /// All other items, can all be intermingled. Duplicate definitions of the - /// same name have the previous one overwritten. - items: HashMap<~str, ~str>, -} - -/// Represents a local variable that the program is currently using. -#[deriving(Clone)] -struct LocalVariable { - /// Should this variable be locally declared as mutable? - mutable: bool, - /// This is the type of the serialized data below - ty: ~str, - /// This is the serialized version of the variable - data: ~[u8], - /// When taking borrowed pointers or slices, care must be taken to ensure - /// that the deserialization produces what we'd expect. If some magic is in - /// order, the first element of this pair is the actual type of the local - /// variable (which can be different from the deserialized type), and the - /// second element are the '&'s which need to be prepended. - alterations: Option<(~str, ~str)>, -} - -type LocalCache = @mut HashMap<~str, @~[u8]>; -local_data_key!(tls_key: LocalCache) - -impl Program { - pub fn new() -> Program { - Program { - local_vars: HashMap::new(), - newvars: HashMap::new(), - view_items: ~"", - externs: ~"", - structs: HashMap::new(), - items: HashMap::new(), - } - } - - /// Clears all local bindings about variables, items, externs, etc. - pub fn clear(&mut self) { - *self = Program::new(); - } - - /// Creates a block of code to be fed to rustc. This code is not meant to - /// run, but rather it is meant to learn about the input given. This will - /// assert that the types of all bound local variables are encodable, - /// along with checking syntax and other rust-related things. The reason - /// that we only check for encodability is that some super-common types - /// (like &'static str) are not decodable, but are encodable. By doing some - /// mild approximation when decoding, we can emulate at least &str and &[T]. - /// - /// Once this code has been fed to rustc, it is intended that the code() - /// function is used to actually generate code to fully compile and run. - pub fn test_code(&self, user_input: &str, to_print: &Option<~str>, - new_locals: &[(~str, bool)]) -> ~str { - let mut code = self.program_header(); - code.push_str(" - fn assert_encodable>(t: &T) {} - "); - - code.push_str("fn main() {\n"); - // It's easy to initialize things if we don't run things... - for (name, var) in self.local_vars.iter() { - let mt = var.mt(); - code.push_str(format!("let{} {}: {} = fail!();\n", mt, *name, var.ty)); - var.alter(*name, &mut code); - } - code.push_str("{\n"); - code.push_str(user_input); - code.push_char('\n'); - match *to_print { - Some(ref s) => { - code.push_str(*s); - code.push_str(";\n"); - } - None => {} - } - - for p in new_locals.iter() { - code.push_str(format!("assert_encodable(&{});\n", *p.first_ref())); - } - code.push_str("};}"); - return code; - } - - /// Creates a program to be fed into rustc. This program is structured to - /// deserialize all bindings into local variables, run the code input, and - /// then reserialize all the variables back out. - /// - /// This program (unlike test_code) is meant to run to actually execute the - /// user's input - pub fn code(&mut self, user_input: &str, to_print: &Option<~str>) -> ~str { - let mut code = self.program_header(); - code.push_str(" - fn main() { - "); - - let key: uint= unsafe { cast::transmute(tls_key) }; - // First, get a handle to the tls map which stores all the local - // variables. This works by totally legitimately using the 'code' - // pointer of the 'tls_key' function as a uint, and then casting it back - // up to a function - code.push_str(format!(" - let __tls_map: @mut ::std::hashmap::HashMap<~str, @~[u8]> = unsafe \\{ - let key = ::std::cast::transmute({}); - ::std::local_data::get(key, |k| k.map(|&x| *x)).unwrap() - \\};\n", key)); - - // Using this __tls_map handle, deserialize each variable binding that - // we know about - for (name, var) in self.local_vars.iter() { - let mt = var.mt(); - code.push_str(format!("let{} {}: {} = \\{ - let data = __tls_map.get_copy(&~\"{}\"); - let doc = ::extra::ebml::reader::Doc(data); - let mut decoder = ::extra::ebml::reader::Decoder(doc); - ::extra::serialize::Decodable::decode(&mut decoder) - \\};\n", mt, *name, var.ty, *name)); - var.alter(*name, &mut code); - } - - // After all that, actually run the user's code. - code.push_str(user_input); - code.push_char('\n'); - - match *to_print { - Some(ref s) => { code.push_str(format!("pp(\\{\n{}\n\\});", *s)); } - None => {} - } - - let newvars = util::replace(&mut self.newvars, HashMap::new()); - for (name, var) in newvars.move_iter() { - self.local_vars.insert(name, var); - } - - // After the input code is run, we can re-serialize everything back out - // into tls map (to be read later on by this task) - for (name, var) in self.local_vars.iter() { - code.push_str(format!("\\{ - let local: {} = {}; - let bytes = do ::std::io::with_bytes_writer |io| \\{ - let mut enc = ::extra::ebml::writer::Encoder(io); - local.encode(&mut enc); - \\}; - __tls_map.insert(~\"{}\", @bytes); - \\}\n", var.real_ty(), *name, *name)); - } - - // Close things up, and we're done. - code.push_str("}"); - return code; - } - - /// Creates the header of the programs which are generated to send to rustc - fn program_header(&self) -> ~str { - // up front, disable lots of annoying lints, then include all global - // state such as items, view items, and extern mods. - let mut code = format!(" - \\#[allow(warnings)]; - - extern mod extra; - {} // extern mods - - use extra::serialize::*; - {} // view items - ", self.externs, self.view_items); - for (_, s) in self.structs.iter() { - // The structs aren't really useful unless they're encodable - code.push_str("#[deriving(Encodable, Decodable)]"); - code.push_str(*s); - code.push_str("\n"); - } - for (_, s) in self.items.iter() { - code.push_str(*s); - code.push_str("\n"); - } - code.push_str("fn pp(t: T) { println(fmt!(\"%?\", t)); }\n"); - return code; - } - - /// Initializes the task-local cache of all local variables known to the - /// program. This will be used to read local variables out of once the - /// program starts - pub fn set_cache(&self) { - let map = @mut HashMap::new(); - for (name, value) in self.local_vars.iter() { - map.insert((*name).clone(), @(value.data).clone()); - } - local_data::set(tls_key, map); - } - - /// Once the program has finished running, this function will consume the - /// task-local cache of local variables. After the program finishes running, - /// it updates this cache with the new values of each local variable. - pub fn consume_cache(&mut self) { - let map = local_data::pop(tls_key).expect("tls is empty"); - let cons_map = util::replace(map, HashMap::new()); - for (name, value) in cons_map.move_iter() { - match self.local_vars.find_mut(&name) { - Some(v) => { v.data = (*value).clone(); } - None => { fail2!("unknown variable {}", name) } - } - } - } - - // Simple functions to record various global things (as strings) - - pub fn record_view_item(&mut self, vi: &str) { - self.view_items.push_str(vi); - self.view_items.push_char('\n'); - } - - pub fn record_struct(&mut self, name: &str, s: ~str) { - let name = name.to_owned(); - self.items.remove(&name); - self.structs.insert(name, s); - } - - pub fn record_item(&mut self, name: &str, it: ~str) { - let name = name.to_owned(); - self.structs.remove(&name); - self.items.insert(name, it); - } - - pub fn record_extern(&mut self, name: &str) { - self.externs.push_str(name); - self.externs.push_char('\n'); - } - - /// This monster function is responsible for reading the main function - /// generated by test_code() to determine the type of each local binding - /// created by the user's input. - /// - /// Once the types are known, they are inserted into the local_vars map in - /// this Program (to be deserialized later on - pub fn register_new_vars(&mut self, blk: &ast::Block, tcx: ty::ctxt) { - debug2!("looking for new variables"); - let newvars = @mut HashMap::new(); - do each_user_local(blk) |local| { - let mutable = local.is_mutbl; - do each_binding(local) |path, id| { - let name = do with_pp(token::get_ident_interner()) |pp, _| { - pprust::print_path(pp, path, false); - }; - let mut t = ty::node_id_to_type(tcx, id); - let mut tystr = ~""; - let mut lvar = LocalVariable { - ty: ~"", - data: ~[], - mutable: mutable, - alterations: None, - }; - // This loop is responsible for figuring out what "alterations" - // are necessary for this local variable. - loop { - match ty::get(t).sty { - // &T encoded will decode to T, so we need to be sure to - // re-take a loan after decoding - ty::ty_rptr(_, mt) => { - if mt.mutbl == ast::MutMutable { - tystr.push_str("&mut "); - } else { - tystr.push_str("&"); - } - t = mt.ty; - } - // Literals like [1, 2, 3] and (~[0]).slice() will both - // be serialized to ~[T], whereas it's requested to be a - // &[T] instead. - ty::ty_evec(mt, ty::vstore_slice(*)) | - ty::ty_evec(mt, ty::vstore_fixed(*)) => { - let vty = ppaux::ty_to_str(tcx, mt.ty); - let derefs = tystr.clone(); - lvar.ty = tystr + "~[" + vty + "]"; - lvar.alterations = Some((tystr + "&[" + vty + "]", - derefs)); - break; - } - // Similar to vectors, &str serializes to ~str, so a - // borrow must be taken - ty::ty_estr(ty::vstore_slice(*)) => { - let derefs = tystr.clone(); - lvar.ty = tystr + "~str"; - lvar.alterations = Some((tystr + "&str", derefs)); - break; - } - // Don't generate extra stuff if there's no borrowing - // going on here - _ if "" == tystr => { - lvar.ty = ppaux::ty_to_str(tcx, t); - break; - } - // If we're just borrowing (no vectors or strings), then - // we just need to record how many borrows there were. - _ => { - let derefs = tystr.clone(); - let tmptystr = ppaux::ty_to_str(tcx, t); - lvar.alterations = Some((tystr + tmptystr, derefs)); - lvar.ty = tmptystr; - break; - } - } - } - newvars.insert(name, lvar); - } - } - - // I'm not an @ pointer, so this has to be done outside. - let cons_newvars = util::replace(newvars, HashMap::new()); - for (k, v) in cons_newvars.move_iter() { - self.newvars.insert(k, v); - } - - // helper functions to perform ast iteration - fn each_user_local(blk: &ast::Block, f: &fn(@ast::Local)) { - do find_user_block(blk) |blk| { - for stmt in blk.stmts.iter() { - match stmt.node { - ast::StmtDecl(d, _) => { - match d.node { - ast::DeclLocal(l) => { f(l); } - _ => {} - } - } - _ => {} - } - } - } - } - - fn find_user_block(blk: &ast::Block, f: &fn(&ast::Block)) { - for stmt in blk.stmts.iter() { - match stmt.node { - ast::StmtSemi(e, _) => { - match e.node { - ast::ExprBlock(ref blk) => { return f(blk); } - _ => {} - } - } - _ => {} - } - } - fail2!("couldn't find user block"); - } - } -} - -impl LocalVariable { - /// Performs alterations to the code provided, given the name of this - /// variable. - fn alter(&self, name: &str, code: &mut ~str) { - match self.alterations { - Some((ref real_ty, ref prefix)) => { - code.push_str(format!("let{} {}: {} = {}{};\n", - self.mt(), name, - *real_ty, *prefix, name)); - } - None => {} - } - } - - fn real_ty<'a>(&'a self) -> &'a str { - match self.alterations { - Some((ref real_ty, _)) => { - let ret: &'a str = *real_ty; - return ret; - } - None => { - let ret: &'a str = self.ty; - return ret; - } - } - } - - fn mt(&self) -> &'static str { - if self.mutable {" mut"} else {""} - } -} diff --git a/src/librusti/rusti.rs b/src/librusti/rusti.rs deleted file mode 100644 index c025d9b10dd..00000000000 --- a/src/librusti/rusti.rs +++ /dev/null @@ -1,786 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - * rusti - A REPL using the JIT backend - * - * Rusti works by serializing state between lines of input. This means that each - * line can be run in a separate task, and the only limiting factor is that all - * local bound variables are encodable. - * - * This is accomplished by feeding in generated input to rustc for execution in - * the JIT compiler. Currently input actually gets fed in three times to get - * information about the program. - * - * - Pass #1 - * In this pass, the input is simply thrown at the parser and the input comes - * back. This validates the structure of the program, and at this stage the - * global items (fns, structs, impls, traits, etc.) are filtered from the - * input into the "global namespace". These declarations shadow all previous - * declarations of an item by the same name. - * - * - Pass #2 - * After items have been stripped, the remaining input is passed to rustc - * along with all local variables declared (initialized to nothing). This pass - * runs up to typechecking. From this, we can learn about the types of each - * bound variable, what variables are bound, and also ensure that all the - * types are encodable (the input can actually be run). - * - * - Pass #3 - * Finally, a program is generated to deserialize the local variable state, - * run the code input, and then reserialize all bindings back into a local - * hash map. This code is then run in the JIT engine provided by the rust - * compiler. - * - * - Pass #4 - * Once this code runs, the input has fully been run and the hash map of local - * variables from TLS is read back into the local store of variables. This is - * then used later to pass back along to the parent rusti task and then begin - * waiting for input again. - * - * - Pass #5 - * When running rusti code, it's important to consume ownership of the LLVM - * jit contextual information to prevent code from being deallocated too soon - * (before drop glue runs, see #7732). For this reason, the jit context is - * consumed and also passed along to the parent task. The parent task then - * keeps around all contexts while rusti is running. This must be done because - * tasks could in theory be spawned off and running in the background (still - * using the code). - * - * Encoding/decoding is done with EBML, and there is simply a map of ~str -> - * ~[u8] maintaining the values of each local binding (by name). - */ - -#[link(name = "rusti", - vers = "0.9-pre", - uuid = "7fb5bf52-7d45-4fee-8325-5ad3311149fc", - url = "https://github.com/mozilla/rust/tree/master/src/rusti")]; - -#[license = "MIT/ASL2"]; -#[crate_type = "lib"]; - -#[feature(globs)]; - -extern mod extra; -extern mod rustc; -extern mod syntax; - -use std::{libc, io, os, task}; -use std::cell::Cell; -use extra::rl::CompletionCb; -use extra::rl; - -use rustc::driver::{driver, session}; -use rustc::back::link::jit; -use syntax::{ast, codemap, diagnostic}; -use syntax::ast_util::*; -use syntax::diagnostic::Emitter; -use syntax::parse::token; -use syntax::print::pprust; - -use program::Program; -use utils::*; - -mod program; -pub mod utils; - -/** - * A structure shared across REPL instances for storing history - * such as statements and view items. I wish the AST was sendable. - */ -pub struct Repl { - prompt: ~str, - binary: ~str, - running: bool, - lib_search_paths: ~[~str], - engines: ~[~jit::Engine], - - program: ~Program, -} - -// Action to do after reading a :command -enum CmdAction { - action_none, - action_run_line(~str), -} - -struct EncodableWarningEmitter; - -impl diagnostic::Emitter for EncodableWarningEmitter { - fn emit(&self, - cm: Option<(@codemap::CodeMap, codemap::Span)>, - msg: &str, - lvl: diagnostic::level) { - diagnostic::DefaultEmitter.emit(cm, msg, lvl); - if msg.contains("failed to find an implementation of trait") && - msg.contains("extra::serialize::Encodable") { - diagnostic::DefaultEmitter.emit(cm, - "Currrently rusti serializes \ - bound locals between different \ - lines of input. This means that \ - all values of local variables \ - need to be encodable, and this \ - type isn't encodable", - diagnostic::note); - } - } -} - -/// Run an input string in a Repl, returning the new Repl. -fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str], - input: ~str) -> (~Program, Option<~jit::Engine>) -{ - // Build some necessary rustc boilerplate for compiling things - let binary = binary.to_managed(); - let options = @session::options { - crate_type: session::unknown_crate, - binary: binary, - addl_lib_search_paths: @mut lib_search_paths.map(|p| Path::new(p.as_slice())), - jit: true, - .. (*session::basic_options()).clone() - }; - // Because we assume that everything is encodable (and assert so), add some - // extra helpful information if the error crops up. Otherwise people are - // bound to be very confused when they find out code is running that they - // never typed in... - let sess = driver::build_session(options, - @EncodableWarningEmitter as - @diagnostic::Emitter); - let intr = token::get_ident_interner(); - - // - // Stage 1: parse the input and filter it into the program (as necessary) - // - debug2!("parsing: {}", input); - let crate = parse_input(sess, input); - let mut to_run = ~[]; // statements to run (emitted back into code) - let new_locals = @mut ~[]; // new locals being defined - let mut result = None; // resultant expression (to print via pp) - do find_main(&crate, sess) |blk| { - // Fish out all the view items, be sure to record 'extern mod' items - // differently beause they must appear before all 'use' statements - for vi in blk.view_items.iter() { - let s = do with_pp(intr) |pp, _| { - pprust::print_view_item(pp, vi); - }; - match vi.node { - ast::view_item_extern_mod(*) => { - program.record_extern(s); - } - ast::view_item_use(*) => { program.record_view_item(s); } - } - } - - // Iterate through all of the block's statements, inserting them into - // the correct portions of the program - for stmt in blk.stmts.iter() { - let s = do with_pp(intr) |pp, _| { pprust::print_stmt(pp, *stmt); }; - match stmt.node { - ast::StmtDecl(d, _) => { - match d.node { - ast::DeclItem(it) => { - let name = sess.str_of(it.ident); - match it.node { - // Structs are treated specially because to make - // them at all usable they need to be decorated - // with #[deriving(Encoable, Decodable)] - ast::item_struct(*) => { - program.record_struct(name, s); - } - // Item declarations are hoisted out of main() - _ => { program.record_item(name, s); } - } - } - - // Local declarations must be specially dealt with, - // record all local declarations for use later on - ast::DeclLocal(l) => { - let mutbl = l.is_mutbl; - do each_binding(l) |path, _| { - let s = do with_pp(intr) |pp, _| { - pprust::print_path(pp, path, false); - }; - new_locals.push((s, mutbl)); - } - to_run.push(s); - } - } - } - - // run statements with expressions (they have effects) - ast::StmtMac(*) | ast::StmtSemi(*) | ast::StmtExpr(*) => { - to_run.push(s); - } - } - } - result = do blk.expr.map |e| { - do with_pp(intr) |pp, _| { pprust::print_expr(pp, e); } - }; - } - // return fast for empty inputs - if to_run.len() == 0 && result.is_none() { - return (program, None); - } - - // - // Stage 2: run everything up to typeck to learn the types of the new - // variables introduced into the program - // - info2!("Learning about the new types in the program"); - program.set_cache(); // before register_new_vars (which changes them) - let input = to_run.connect("\n"); - let test = program.test_code(input, &result, *new_locals); - debug2!("testing with ^^^^^^ {:?}", (||{ println(test) })()); - let dinput = driver::str_input(test.to_managed()); - let cfg = driver::build_configuration(sess); - - let crate = driver::phase_1_parse_input(sess, cfg.clone(), &dinput); - let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate); - let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate); - - // Once we're typechecked, record the types of all local variables defined - // in this input - do find_main(&expanded_crate, sess) |blk| { - program.register_new_vars(blk, analysis.ty_cx); - } - - // - // Stage 3: Actually run the code in the JIT - // - info2!("actually running code"); - let code = program.code(input, &result); - debug2!("actually running ^^^^^^ {:?}", (||{ println(code) })()); - let input = driver::str_input(code.to_managed()); - let cfg = driver::build_configuration(sess); - let outputs = driver::build_output_filenames(&input, &None, &None, [], sess); - let sess = driver::build_session(options, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); - - let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input); - let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate); - let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate); - let trans = driver::phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs); - driver::phase_5_run_llvm_passes(sess, &trans, outputs); - - // - // Stage 4: Inform the program that computation is done so it can update all - // local variable bindings. - // - info2!("cleaning up after code"); - program.consume_cache(); - - // - // Stage 5: Extract the LLVM execution engine to take ownership of the - // generated JIT code. This means that rusti can spawn parallel - // tasks and we won't deallocate the code emitted until rusti - // itself is destroyed. - // - return (program, jit::consume_engine()); - - fn parse_input(sess: session::Session, input: &str) -> ast::Crate { - let code = format!("fn main() \\{\n {} \n\\}", input); - let input = driver::str_input(code.to_managed()); - let cfg = driver::build_configuration(sess); - driver::phase_1_parse_input(sess, cfg.clone(), &input) - } - - fn find_main(crate: &ast::Crate, sess: session::Session, - f: &fn(&ast::Block)) { - for item in crate.module.items.iter() { - match item.node { - ast::item_fn(_, _, _, _, ref blk) => { - if item.ident == sess.ident_of("main") { - return f(blk); - } - } - _ => {} - } - } - fail2!("main function was expected somewhere..."); - } -} - -// Compiles a crate given by the filename as a library if the compiled -// version doesn't exist or is older than the source file. Binary is -// the name of the compiling executable. Returns Some(true) if it -// successfully compiled, Some(false) if the crate wasn't compiled -// because it already exists and is newer than the source file, or -// None if there were compile errors. -fn compile_crate(src_filename: ~str, binary: ~str) -> Option { - fn has_prefix(v: &[u8], pref: &[u8]) -> bool { - v.len() >= pref.len() && v.slice_to(pref.len()) == pref - } - fn has_extension(v: &[u8], ext: Option<&[u8]>) -> bool { - match ext { - None => true, - Some(ext) => { - v.len() > ext.len() && v[v.len()-ext.len()-1] == '.' as u8 && - v.slice_from(v.len()-ext.len()) == ext - } - } - } - match do task::try { - let src_path = Path::new(src_filename.as_slice()); - let binary = binary.to_managed(); - let options = @session::options { - binary: binary, - addl_lib_search_paths: @mut ~[os::getcwd()], - .. (*session::basic_options()).clone() - }; - let input = driver::file_input(src_path.clone()); - let sess = driver::build_session(options, - @diagnostic::DefaultEmitter as - @diagnostic::Emitter); - *sess.building_library = true; - let cfg = driver::build_configuration(sess); - let outputs = driver::build_output_filenames( - &input, &None, &None, [], sess); - // If the library already exists and is newer than the source - // file, skip compilation and return None. - let mut should_compile = true; - let dir = os::list_dir_path(&outputs.out_filename.dir_path()); - let maybe_lib_path = do dir.iter().find |file| { - // The actual file's name has a hash value and version - // number in it which is unknown at this time, so looking - // for a file that matches out_filename won't work, - // instead we guess which file is the library by matching - // the prefix and suffix of out_filename to files in the - // directory. - let file_vec = file.filename().unwrap(); - has_prefix(file_vec, outputs.out_filename.filestem().unwrap()) && - has_extension(file_vec, outputs.out_filename.extension()) - }; - match maybe_lib_path { - Some(lib_path) => { - let (src_mtime, _) = src_path.get_mtime().unwrap(); - let (lib_mtime, _) = lib_path.get_mtime().unwrap(); - if lib_mtime >= src_mtime { - should_compile = false; - } - }, - None => { }, - } - if (should_compile) { - println(format!("compiling {}...", src_filename)); - let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input); - let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate); - let analysis = driver::phase_3_run_analysis_passes(sess, &expanded_crate); - let trans = driver::phase_4_translate_to_llvm(sess, expanded_crate, &analysis, outputs); - driver::phase_5_run_llvm_passes(sess, &trans, outputs); - true - } else { false } - } { - Ok(true) => Some(true), - Ok(false) => Some(false), - Err(_) => None, - } -} - -/// Tries to get a line from rl after outputting a prompt. Returns -/// None if no input was read (e.g. EOF was reached). -fn get_line(use_rl: bool, prompt: &str) -> Option<~str> { - if use_rl { - let result = rl::read(prompt); - - match result { - None => None, - Some(line) => { - rl::add_history(line); - Some(line) - } - } - } else { - if io::stdin().eof() { - None - } else { - Some(io::stdin().read_line()) - } - } -} - -/// Run a command, e.g. :clear, :exit, etc. -fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, - cmd: ~str, args: ~[~str], use_rl: bool) -> CmdAction { - let mut action = action_none; - match cmd { - ~"exit" => repl.running = false, - ~"clear" => { - repl.program.clear(); - - // XXX: Win32 version of linenoise can't do this - //rl::clear(); - } - ~"help" => { - println( - ":{\\n ..lines.. \\n:}\\n - execute multiline command\n\ - :load ... - loads given crates as dynamic libraries\n\ - :clear - clear the bindings\n\ - :exit - exit from the repl\n\ - :help - show this message"); - } - ~"load" => { - let mut loaded_crates: ~[~str] = ~[]; - for arg in args.iter() { - let (crate, filename) = - if arg.ends_with(".rs") || arg.ends_with(".rc") { - (arg.slice_to(arg.len() - 3).to_owned(), (*arg).clone()) - } else { - ((*arg).clone(), *arg + ".rs") - }; - match compile_crate(filename, repl.binary.clone()) { - Some(_) => loaded_crates.push(crate), - None => { } - } - } - for crate in loaded_crates.iter() { - let crate_path = Path::new(crate.as_slice()); - // FIXME (#9639): This needs to handle non-utf8 paths - let crate_dir = crate_path.dirname_str().unwrap(); - repl.program.record_extern(format!("extern mod {};", *crate)); - if !repl.lib_search_paths.iter().any(|x| crate_dir == *x) { - repl.lib_search_paths.push(crate_dir.to_owned()); - } - } - if loaded_crates.is_empty() { - println("no crates loaded"); - } else { - println!("crates loaded: {}", loaded_crates.connect(", ")); - } - } - ~"{" => { - let mut multiline_cmd = ~""; - let mut end_multiline = false; - while (!end_multiline) { - match get_line(use_rl, "rusti| ") { - None => fail2!("unterminated multiline command :\\{ .. :\\}"), - Some(line) => { - if line.trim() == ":}" { - end_multiline = true; - } else { - multiline_cmd.push_str(line); - multiline_cmd.push_char('\n'); - } - } - } - } - action = action_run_line(multiline_cmd); - } - _ => println(~"unknown cmd: " + cmd) - } - return action; -} - -/// Executes a line of input, which may either be rust code or a -/// :command. Returns a new Repl if it has changed. -pub fn run_line(repl: &mut Repl, input: @io::Reader, out: @io::Writer, line: ~str, - use_rl: bool) -> bool -{ - if line.starts_with(":") { - // drop the : and the \n (one byte each) - let full = line.slice(1, line.len()); - let split: ~[~str] = full.word_iter().map(|s| s.to_owned()).collect(); - let len = split.len(); - - if len > 0 { - let cmd = split[0].clone(); - - if !cmd.is_empty() { - let args = if len > 1 { - split.slice(1, len).to_owned() - } else { ~[] }; - - match run_cmd(repl, input, out, cmd, args, use_rl) { - action_none => { } - action_run_line(multiline_cmd) => { - if !multiline_cmd.is_empty() { - return run_line(repl, input, out, multiline_cmd, use_rl); - } - } - } - return true; - } - } - } - - let line = Cell::new(line); - let program = Cell::new(repl.program.clone()); - let lib_search_paths = Cell::new(repl.lib_search_paths.clone()); - let binary = Cell::new(repl.binary.clone()); - let result = do task::try { - run(program.take(), binary.take(), lib_search_paths.take(), line.take()) - }; - - match result { - Ok((program, engine)) => { - repl.program = program; - match engine { - Some(e) => { repl.engines.push(e); } - None => {} - } - return true; - } - Err(*) => { return false; } - } -} - -pub fn main() { - os::set_exit_status(main_args(os::args())); -} - -struct Completer; - -impl CompletionCb for Completer { - fn complete(&self, line: ~str, suggest: &fn(~str)) { - if line.starts_with(":") { - suggest(~":clear"); - suggest(~":exit"); - suggest(~":help"); - suggest(~":load"); - } - } -} - -pub fn main_args(args: &[~str]) -> int { - #[fixed_stack_segment]; #[inline(never)]; - - let input = io::stdin(); - let out = io::stdout(); - let mut repl = Repl { - prompt: ~"rusti> ", - binary: args[0].clone(), - running: true, - lib_search_paths: ~[], - engines: ~[], - - program: ~Program::new(), - }; - - let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0; - - // only print this stuff if the user is actually typing into rusti - if istty { - println("WARNING: The Rust REPL is experimental and may be"); - println("unstable. If you encounter problems, please use the"); - println("compiler instead. Type :help for help."); - - unsafe { - rl::complete(@Completer as @CompletionCb) - } - } - - while repl.running { - match get_line(istty, repl.prompt) { - None => break, - Some(line) => { - if line.is_empty() { - if istty { - println("()"); - } - continue; - } - run_line(&mut repl, input, out, line, istty); - } - } - } - - return 0; -} - -#[cfg(test)] -mod tests { - use std::io; - use program::Program; - use super::*; - - fn repl() -> Repl { - Repl { - prompt: ~"rusti> ", - binary: ~"rusti", - running: true, - lib_search_paths: ~[], - engines: ~[], - program: ~Program::new(), - } - } - - // 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)] - fn run_program(prog: &str) { - let mut r = repl(); - for cmd in prog.split_iter('\n') { - assert!(run_line(&mut r, io::stdin(), io::stdout(), - cmd.to_owned(), false), - "the command '%s' failed", cmd); - } - } - fn run_program(_: &str) {} - - #[ignore] - #[test] - fn super_basic() { - run_program(""); - } - - #[ignore] - #[test] - fn regression_5937() { - run_program("use std::hashmap;"); - } - - #[ignore] - #[test] - fn regression_5784() { - run_program("let a = 3;"); - } - - #[test] #[ignore] - 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?\"); } - "); - } - - #[ignore] - #[test] - fn inferred_integers_usable() { - run_program("let a = 2;\n()\n"); - run_program(" - let a = 3; - let b = 4u; - assert!((a as uint) + b == 7) - "); - } - - #[ignore] - #[test] - fn local_variables_allow_shadowing() { - run_program(" - let a = 3; - let a = 5; - assert!(a == 5) - "); - } - - #[ignore] - #[test] - fn string_usable() { - run_program(" - let a = ~\"\"; - let b = \"\"; - let c = @\"\"; - let d = a + b + c; - assert!(d.len() == 0); - "); - } - - #[ignore] - #[test] - fn vectors_usable() { - run_program(" - let a = ~[1, 2, 3]; - let b = &[1, 2, 3]; - let c = @[1, 2, 3]; - let d = a + b + c; - assert!(d.len() == 9); - let e: &[int] = []; - "); - } - - #[ignore] - #[test] - fn structs_usable() { - run_program(" - struct A{ a: int } - let b = A{ a: 3 }; - assert!(b.a == 3) - "); - } - - #[ignore] - #[test] - fn mutable_variables_work() { - run_program(" - let mut a = 3; - a = 5; - let mut b = std::hashmap::HashSet::new::(); - b.insert(a); - assert!(b.contains(&5)) - assert!(b.len() == 1) - "); - } - - #[ignore] - #[test] - fn functions_saved() { - run_program(" - fn fib(x: int) -> int { if x < 2 {x} else { fib(x - 1) + fib(x - 2) } } - let a = fib(3); - let a = a + fib(4); - assert!(a == 5) - "); - } - - #[ignore] - #[test] - fn modules_saved() { - run_program(" - mod b { pub fn foo() -> uint { 3 } } - assert!(b::foo() == 3) - "); - } - - #[ignore] - #[test] - fn multiple_functions() { - run_program(" - fn f() {} - fn f() {} - f() - "); - } - - #[ignore] - #[test] - fn multiple_items_same_name() { - run_program(" - fn f() {} - mod f {} - struct f; - enum f {} - fn f() {} - f() - "); - } - - #[ignore] - #[test] - fn simultaneous_definition_and_expression() { - run_program(" - let a = 3; a as u8 - "); - } - - #[ignore] - #[test] - fn exit_quits() { - let mut r = repl(); - assert!(r.running); - let result = run_line(&mut r, io::stdin(), io::stdout(), - ~":exit", false); - assert!(result); - assert!(!r.running); - } -} diff --git a/src/librusti/utils.rs b/src/librusti/utils.rs deleted file mode 100644 index 904594fdfb8..00000000000 --- a/src/librusti/utils.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io; -use syntax::ast; -use syntax::print::pp; -use syntax::print::pprust; -use syntax::parse::token; -use syntax::visit; - -struct EachBindingVisitor<'self> { - f: &'self fn(&ast::Path, ast::NodeId) -} - -impl<'self> visit::Visitor<()> for EachBindingVisitor<'self> { - fn visit_pat(&mut self, pat:@ast::Pat, _:()) { - match pat.node { - ast::PatIdent(_, ref path, _) => { - (self.f)(path, pat.id); - } - _ => {} - } - - visit::walk_pat(self, pat, ()); - } -} - -pub fn each_binding(l: @ast::Local, f: &fn(&ast::Path, ast::NodeId)) { - use syntax::visit::Visitor; - - let mut vt = EachBindingVisitor{ f: f }; - - vt.visit_pat(l.pat, ()); -} - -/// A utility function that hands off a pretty printer to a callback. -pub fn with_pp(intr: @token::ident_interner, - cb: &fn(@pprust::ps, @io::Writer)) -> ~str { - do io::with_str_writer |writer| { - let pp = pprust::rust_printer(writer, intr); - - cb(pp, writer); - pp::eof(pp.s); - } -} From f766acad62cd5cf7ed701a9521db2f2a96039778 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 16 Oct 2013 22:51:51 -0400 Subject: [PATCH 2/2] drop the linenoise library Closes #5038 --- .gitattributes | 1 - configure | 2 +- mk/platform.mk | 2 +- mk/rt.mk | 5 +- mk/tests.mk | 3 - src/README.txt | 1 - src/libextra/extra.rs | 1 - src/libextra/rl.rs | 143 --- src/rt/linenoise/README.markdown | 47 - src/rt/linenoise/example.c | 30 - src/rt/linenoise/linenoise.c | 1581 ---------------------------- src/rt/linenoise/linenoise.h | 61 -- src/rt/linenoise/utf8.c | 115 -- src/rt/linenoise/utf8.h | 79 -- src/rt/rust_builtin.cpp | 12 - src/rt/rustrt.def.in | 9 - src/test/auxiliary/issue_3882.rc | 15 - src/test/auxiliary/issue_3882.rs | 21 - src/test/run-pass/issue_3882.rs | 16 - src/test/run-pass/rl-human-test.rs | 83 -- 20 files changed, 3 insertions(+), 2224 deletions(-) delete mode 100644 src/libextra/rl.rs delete mode 100644 src/rt/linenoise/README.markdown delete mode 100644 src/rt/linenoise/example.c delete mode 100644 src/rt/linenoise/linenoise.c delete mode 100644 src/rt/linenoise/linenoise.h delete mode 100644 src/rt/linenoise/utf8.c delete mode 100644 src/rt/linenoise/utf8.h delete mode 100644 src/test/auxiliary/issue_3882.rc delete mode 100644 src/test/auxiliary/issue_3882.rs delete mode 100644 src/test/run-pass/issue_3882.rs delete mode 100644 src/test/run-pass/rl-human-test.rs diff --git a/.gitattributes b/.gitattributes index 57f8083a556..3e368ce70e9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,5 +7,4 @@ src/etc/pkg/rust-logo.ico binary src/rt/msvc/* -whitespace src/rt/vg/* -whitespace -src/rt/linenoise/* -whitespace src/rt/jemalloc/**/* -whitespace diff --git a/configure b/configure index c2629324d80..eb934c1807f 100755 --- a/configure +++ b/configure @@ -686,7 +686,7 @@ do make_dir $t/rt/libuv/src/ev make_dir $t/rt/jemalloc for i in \ - isaac linenoise sync test \ + isaac sync test \ arch/i386 arch/x86_64 arch/arm arch/mips \ sundown/src sundown/html do diff --git a/mk/platform.mk b/mk/platform.mk index 5885a57f69b..8f9714e62d5 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -29,7 +29,7 @@ $(foreach t,$(CFG_TARGET_TRIPLES),$(info cfg: os for $(t) is $(OSTYPE_$(t)))) # FIXME: no-omit-frame-pointer is just so that task_start_wrapper # has a frame pointer and the stack walker can understand it. Turning off # frame pointers everywhere is overkill -CFG_GCCISH_CFLAGS += -fno-omit-frame-pointer -DUSE_UTF8 +CFG_GCCISH_CFLAGS += -fno-omit-frame-pointer # On Darwin, we need to run dsymutil so the debugging information ends # up in the right place. On other platforms, it automatically gets diff --git a/mk/rt.mk b/mk/rt.mk index 412e25bed4d..347c32f1720 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -96,9 +96,7 @@ RUNTIME_CXXS_$(1)_$(2) := \ rt/rust_android_dummy.cpp \ rt/rust_test_helpers.cpp -RUNTIME_CS_$(1)_$(2) := rt/linenoise/linenoise.c \ - rt/linenoise/utf8.c \ - rt/sundown/src/autolink.c \ +RUNTIME_CS_$(1)_$(2) := rt/sundown/src/autolink.c \ rt/sundown/src/buffer.c \ rt/sundown/src/stack.c \ rt/sundown/src/markdown.c \ @@ -116,7 +114,6 @@ RT_BUILD_DIR_$(1)_$(2) := $$(RT_OUTPUT_DIR_$(1))/stage$(2) RUNTIME_DEF_$(1)_$(2) := $$(RT_OUTPUT_DIR_$(1))/rustrt$$(CFG_DEF_SUFFIX_$(1)) RUNTIME_INCS_$(1)_$(2) := -I $$(S)src/rt -I $$(S)src/rt/isaac -I $$(S)src/rt/uthash \ -I $$(S)src/rt/arch/$$(HOST_$(1)) \ - -I $$(S)src/rt/linenoise \ -I $$(S)src/rt/sundown/src \ -I $$(S)src/rt/sundown/html \ -I $$(S)src/libuv/include diff --git a/mk/tests.mk b/mk/tests.mk index fb5bd094404..9991aacc949 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -227,7 +227,6 @@ ALL_CS := $(wildcard $(S)src/rt/*.cpp \ $(S)src/rt/*/*/*.cpp \ $(S)src/rustllvm/*.cpp) ALL_CS := $(filter-out $(S)src/rt/miniz.cpp \ - $(wildcard $(S)src/rt/linenoise/*.c) \ $(wildcard $(S)src/rt/sundown/src/*.c) \ $(wildcard $(S)src/rt/sundown/html/*.c) \ ,$(ALL_CS)) @@ -240,8 +239,6 @@ ALL_HS := $(filter-out $(S)src/rt/vg/valgrind.h \ $(S)src/rt/msvc/typeof.h \ $(S)src/rt/msvc/stdint.h \ $(S)src/rt/msvc/inttypes.h \ - $(S)src/rt/linenoise/linenoise.h \ - $(S)src/rt/linenoise/utf8.h \ $(wildcard $(S)src/rt/sundown/src/*.h) \ $(wildcard $(S)src/rt/sundown/html/*.h) \ ,$(ALL_HS)) diff --git a/src/README.txt b/src/README.txt index 7cf523e1017..1ee08247c73 100644 --- a/src/README.txt +++ b/src/README.txt @@ -17,7 +17,6 @@ rt/sync - Concurrency utils rt/util - Small utility classes for the runtime. rt/vg - Valgrind headers rt/msvc - MSVC support -rt/linenoise - a readline-like line editing library test/ Testsuite test/compile-fail - Tests that should fail to compile diff --git a/src/libextra/extra.rs b/src/libextra/extra.rs index 3cea76b8edd..4b29709895e 100644 --- a/src/libextra/extra.rs +++ b/src/libextra/extra.rs @@ -94,7 +94,6 @@ pub mod term; pub mod time; pub mod arena; pub mod base64; -pub mod rl; pub mod workcache; pub mod enum_set; #[path="num/bigint.rs"] diff --git a/src/libextra/rl.rs b/src/libextra/rl.rs deleted file mode 100644 index c8a17451a70..00000000000 --- a/src/libextra/rl.rs +++ /dev/null @@ -1,143 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Bindings for the ability to read lines of input from the console - -use std::c_str::ToCStr; -use std::libc::{c_char, c_int}; -use std::{local_data, str, rt}; -use std::unstable::finally::Finally; - -mod rustrt { - use std::libc::{c_char, c_int}; - - externfn!(fn linenoise(prompt: *c_char) -> *c_char) - externfn!(fn linenoiseHistoryAdd(line: *c_char) -> c_int) - externfn!(fn linenoiseHistorySetMaxLen(len: c_int) -> c_int) - externfn!(fn linenoiseHistorySave(file: *c_char) -> c_int) - externfn!(fn linenoiseHistoryLoad(file: *c_char) -> c_int) - externfn!(fn linenoiseSetCompletionCallback(callback: extern "C" fn(*i8, *()))) - externfn!(fn linenoiseAddCompletion(completions: *(), line: *c_char)) - - externfn!(fn rust_take_linenoise_lock()) - externfn!(fn rust_drop_linenoise_lock()) -} - -macro_rules! locked { - ($expr:expr) => { - { - // FIXME #9105: can't use a static mutex in pure Rust yet. - rustrt::rust_take_linenoise_lock(); - let x = $expr; - rustrt::rust_drop_linenoise_lock(); - x - } - } -} - -/// Add a line to history -pub fn add_history(line: &str) -> bool { - do line.with_c_str |buf| { - unsafe { - (locked!(rustrt::linenoiseHistoryAdd(buf))) == 1 as c_int - } - } -} - -/// Set the maximum amount of lines stored -pub fn set_history_max_len(len: int) -> bool { - unsafe { - (locked!(rustrt::linenoiseHistorySetMaxLen(len as c_int))) == 1 - as c_int - } -} - -/// Save line history to a file -pub fn save_history(file: &str) -> bool { - do file.with_c_str |buf| { - // 0 on success, -1 on failure - unsafe { - (locked!(rustrt::linenoiseHistorySave(buf))) == 0 as c_int - } - } -} - -/// Load line history from a file -pub fn load_history(file: &str) -> bool { - do file.with_c_str |buf| { - // 0 on success, -1 on failure - unsafe { - (locked!(rustrt::linenoiseHistoryLoad(buf))) == 0 as c_int - } - } -} - -/// Print out a prompt and then wait for input and return it -pub fn read(prompt: &str) -> Option<~str> { - do prompt.with_c_str |buf| { - let line = unsafe { - locked!(rustrt::linenoise(buf)) - }; - - if line.is_null() { None } - else { - unsafe { - do (|| { - Some(str::raw::from_c_str(line)) - }).finally { - // linenoise's return value is from strdup, so we - // better not leak it. - rt::global_heap::exchange_free(line); - } - } - } - } -} - -/// The callback used to perform completions. -pub trait CompletionCb { - /// Performs a completion. - fn complete(&self, line: ~str, suggestion: &fn(~str)); -} - -local_data_key!(complete_key: @CompletionCb) - -/// Bind to the main completion callback in the current task. -/// -/// The completion callback should not call any `extra::rl` functions -/// other than the closure that it receives as its second -/// argument. Calling such a function will deadlock on the mutex used -/// to ensure that the calls are thread-safe. -pub unsafe fn complete(cb: @CompletionCb) { - local_data::set(complete_key, cb); - - extern fn callback(line: *c_char, completions: *()) { - do local_data::get(complete_key) |opt_cb| { - // only fetch completions if a completion handler has been - // registered in the current task. - match opt_cb { - None => {} - Some(cb) => { - unsafe { - do cb.complete(str::raw::from_c_str(line)) - |suggestion| { - do suggestion.with_c_str |buf| { - rustrt::linenoiseAddCompletion(completions, - buf); - } - } - } - } - } - } - } - - locked!(rustrt::linenoiseSetCompletionCallback(callback)); -} diff --git a/src/rt/linenoise/README.markdown b/src/rt/linenoise/README.markdown deleted file mode 100644 index f008d2d3d5e..00000000000 --- a/src/rt/linenoise/README.markdown +++ /dev/null @@ -1,47 +0,0 @@ -# Linenoise - -A minimal, zero-config, BSD licensed, readline replacement. - -News: linenoise now includes minimal completion support, thanks to Pieter Noordhuis (@pnoordhuis). - -News: linenoise is now part of [Android](http://android.git.kernel.org/?p=platform/system/core.git;a=tree;f=liblinenoise;h=56450eaed7f783760e5e6a5993ef75cde2e29dea;hb=HEAD Android)! - -## Can a line editing library be 20k lines of code? - -Line editing with some support for history is a really important feature for command line utilities. Instead of retyping almost the same stuff again and again it's just much better to hit the up arrow and edit on syntax errors, or in order to try a slightly different command. But apparently code dealing with terminals is some sort of Black Magic: readline is 30k lines of code, libedit 20k. Is it reasonable to link small utilities to huge libraries just to get a minimal support for line editing? - -So what usually happens is either: - - * Large programs with configure scripts disabling line editing if readline is not present in the system, or not supporting it at all since readline is GPL licensed and libedit (the BSD clone) is not as known and available as readline is (Real world example of this problem: Tclsh). - * Smaller programs not using a configure script not supporting line editing at all (A problem we had with Redis-cli for instance). - -The result is a pollution of binaries without line editing support. - -So I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporing line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to linenoise if not. - -## Terminals, in 2010. - -Apparently almost every terminal you can happen to use today has some kind of support for VT100 alike escape sequences. So I tried to write a lib using just very basic VT100 features. The resulting library appears to work everywhere I tried to use it. - -Since it's so young I guess there are a few bugs, or the lib may not compile or work with some operating system, but it's a matter of a few weeks and eventually we'll get it right, and there will be no excuses for not shipping command line tools without built-in line editing support. - -The library is currently less than 400 lines of code. In order to use it in your project just look at the *example.c* file in the source distribution, it is trivial. Linenoise is BSD code, so you can use both in free software and commercial software. - -## Tested with... - - * Linux text only console ($TERM = linux) - * Linux KDE terminal application ($TERM = xterm) - * Linux xterm ($TERM = xterm) - * Mac OS X iTerm ($TERM = xterm) - * Mac OS X default Terminal.app ($TERM = xterm) - * OpenBSD 4.5 through an OSX Terminal.app ($TERM = screen) - * IBM AIX 6.1 - * FreeBSD xterm ($TERM = xterm) - -Please test it everywhere you can and report back! - -## Let's push this forward! - -Please fork it and add something interesting and send me a pull request. What's especially interesting are fixes, new key bindings, completion. - -Send feedbacks to antirez at gmail diff --git a/src/rt/linenoise/example.c b/src/rt/linenoise/example.c deleted file mode 100644 index cb51a0af8f9..00000000000 --- a/src/rt/linenoise/example.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include "linenoise.h" - -#ifndef NO_COMPLETION -void completion(const char *buf, linenoiseCompletions *lc) { - if (buf[0] == 'h') { - linenoiseAddCompletion(lc,"hello"); - linenoiseAddCompletion(lc,"hello there"); - } -} -#endif - -int main(void) { - char *line; - -#ifndef NO_COMPLETION - linenoiseSetCompletionCallback(completion); -#endif - linenoiseHistoryLoad("history.txt"); /* Load the history at startup */ - while((line = linenoise("hello> ")) != NULL) { - if (line[0] != '\0') { - printf("echo: '%s'\n", line); - linenoiseHistoryAdd(line); - linenoiseHistorySave("history.txt"); /* Save every new entry */ - } - free(line); - } - return 0; -} diff --git a/src/rt/linenoise/linenoise.c b/src/rt/linenoise/linenoise.c deleted file mode 100644 index 0ce4d559bed..00000000000 --- a/src/rt/linenoise/linenoise.c +++ /dev/null @@ -1,1581 +0,0 @@ -/* linenoise.c -- guerrilla line editing library against the idea that a - * line editing lib needs to be 20,000 lines of C code. - * - * You can find the latest source code at: - * - * http://github.com/msteveb/linenoise - * (forked from http://github.com/antirez/linenoise) - * - * Does a number of crazy assumptions that happen to be true in 99.9999% of - * the 2010 UNIX computers around. - * - * ------------------------------------------------------------------------ - * - * Copyright (c) 2010, Salvatore Sanfilippo - * Copyright (c) 2010, Pieter Noordhuis - * Copyright (c) 2011, Steve Bennett - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ------------------------------------------------------------------------ - * - * References: - * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html - * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html - * - * Bloat: - * - Completion? - * - * Unix/termios - * ------------ - * List of escape sequences used by this program, we do everything just - * a few sequences. In order to be so cheap we may have some - * flickering effect with some slow terminal, but the lesser sequences - * the more compatible. - * - * EL (Erase Line) - * Sequence: ESC [ n K - * Effect: if n is 0 or missing, clear from cursor to end of line - * Effect: if n is 1, clear from beginning of line to cursor - * Effect: if n is 2, clear entire line - * - * CUF (CUrsor Forward) - * Sequence: ESC [ n C - * Effect: moves cursor forward of n chars - * - * CR (Carriage Return) - * Sequence: \r - * Effect: moves cursor to column 1 - * - * The following are used to clear the screen: ESC [ H ESC [ 2 J - * This is actually composed of two sequences: - * - * cursorhome - * Sequence: ESC [ H - * Effect: moves the cursor to upper left corner - * - * ED2 (Clear entire screen) - * Sequence: ESC [ 2 J - * Effect: clear the whole screen - * - * == For highlighting control characters, we also use the following two == - * SO (enter StandOut) - * Sequence: ESC [ 7 m - * Effect: Uses some standout mode such as reverse video - * - * SE (Standout End) - * Sequence: ESC [ 0 m - * Effect: Exit standout mode - * - * == Only used if TIOCGWINSZ fails == - * DSR/CPR (Report cursor position) - * Sequence: ESC [ 6 n - * Effect: reports current cursor position as ESC [ NNN ; MMM R - * - * win32/console - * ------------- - * If __MINGW32__ is defined, the win32 console API is used. - * This could probably be made to work for the msvc compiler too. - * This support based in part on work by Jon Griffiths. - */ - -#ifdef _WIN32 /* Windows platform, either MinGW or Visual Studio (MSVC) */ -#include -#include -#define USE_WINCONSOLE -#ifdef __MINGW32__ -#define HAVE_UNISTD_H -#else -/* Microsoft headers don't like old POSIX names */ -#define strdup _strdup -#define snprintf _snprintf -#endif -#else -#include -#include -#include -#define USE_TERMIOS -#define HAVE_UNISTD_H -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include "linenoise.h" -#include "utf8.h" - -#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 -#define LINENOISE_MAX_LINE 4096 - -#define ctrl(C) ((C) - '@') - -/* Use -ve numbers here to co-exist with normal unicode chars */ -enum { - SPECIAL_NONE, - SPECIAL_UP = -20, - SPECIAL_DOWN = -21, - SPECIAL_LEFT = -22, - SPECIAL_RIGHT = -23, - SPECIAL_DELETE = -24, - SPECIAL_HOME = -25, - SPECIAL_END = -26, - SPECIAL_INSERT = -27, - SPECIAL_PAGE_UP = -28, - SPECIAL_PAGE_DOWN = -29 -}; - -static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; -static int history_len = 0; -static char **history = NULL; - -/* Structure to contain the status of the current (being edited) line */ -struct current { - char *buf; /* Current buffer. Always null terminated */ - int bufmax; /* Size of the buffer, including space for the null termination */ - int len; /* Number of bytes in 'buf' */ - int chars; /* Number of chars in 'buf' (utf-8 chars) */ - int pos; /* Cursor position, measured in chars */ - int cols; /* Size of the window, in chars */ - const char *prompt; - char *capture; /* Allocated capture buffer, or NULL for none. Always null terminated */ -#if defined(USE_TERMIOS) - int fd; /* Terminal fd */ -#elif defined(USE_WINCONSOLE) - HANDLE outh; /* Console output handle */ - HANDLE inh; /* Console input handle */ - int rows; /* Screen rows */ - int x; /* Current column during output */ - int y; /* Current row */ -#endif -}; - -static int fd_read(struct current *current); -static int getWindowSize(struct current *current); - -void linenoiseHistoryFree(void) { - if (history) { - int j; - - for (j = 0; j < history_len; j++) - free(history[j]); - free(history); - history = NULL; - history_len = 0; - } -} - -#if defined(USE_TERMIOS) -static void linenoiseAtExit(void); -static struct termios orig_termios; /* in order to restore at exit */ -static int rawmode = 0; /* for atexit() function to check if restore is needed*/ -static int atexit_registered = 0; /* register atexit just 1 time */ - -static const char *unsupported_term[] = {"dumb","cons25",NULL}; - -static int isUnsupportedTerm(void) { - char *term = getenv("TERM"); - - if (term) { - int j; - for (j = 0; unsupported_term[j]; j++) { - if (strcasecmp(term, unsupported_term[j]) == 0) { - return 1; - } - } - } - return 0; -} - -static int enableRawMode(struct current *current) { - struct termios raw; - - current->fd = STDIN_FILENO; - - if (!isatty(current->fd) || isUnsupportedTerm() || - tcgetattr(current->fd, &orig_termios) == -1) { -fatal: - errno = ENOTTY; - return -1; - } - - if (!atexit_registered) { - atexit(linenoiseAtExit); - atexit_registered = 1; - } - - raw = orig_termios; /* modify the original mode */ - /* input modes: no break, no CR to NL, no parity check, no strip char, - * no start/stop output control. */ - raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); - /* output modes - disable post processing */ - raw.c_oflag &= ~(OPOST); - /* control modes - set 8 bit chars */ - raw.c_cflag |= (CS8); - /* local modes - choing off, canonical off, no extended functions, - * no signal chars (^Z,^C) */ - raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); - /* control chars - set return condition: min number of bytes and timer. - * We want read to return every single byte, without timeout. */ - raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ - - /* put terminal in raw mode after flushing */ - if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) { - goto fatal; - } - rawmode = 1; - - current->cols = 0; - return 0; -} - -static void disableRawMode(struct current *current) { - /* Don't even check the return value as it's too late. */ - if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1) - rawmode = 0; -} - -/* At exit we'll try to fix the terminal to the initial conditions. */ -static void linenoiseAtExit(void) { - if (rawmode) { - tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios); - } - linenoiseHistoryFree(); -} - -/* gcc/glibc insists that we care about the return code of write! - * Clarification: This means that a void-cast like "(void) (EXPR)" - * does not work. - */ -#define IGNORE_RC(EXPR) if (EXPR) {} - -/* This is fdprintf() on some systems, but use a different - * name to avoid conflicts - */ -static void fd_printf(int fd, const char *format, ...) -{ - va_list args; - char buf[64]; - int n; - - va_start(args, format); - n = vsnprintf(buf, sizeof(buf), format, args); - va_end(args); - IGNORE_RC(write(fd, buf, n)); -} - -static void clearScreen(struct current *current) -{ - fd_printf(current->fd, "\x1b[H\x1b[2J"); -} - -static void cursorToLeft(struct current *current) -{ - fd_printf(current->fd, "\r"); -} - -static int outputChars(struct current *current, const char *buf, int len) -{ - return write(current->fd, buf, len); -} - -static void outputControlChar(struct current *current, char ch) -{ - fd_printf(current->fd, "\x1b[7m^%c\x1b[0m", ch); -} - -static void eraseEol(struct current *current) -{ - fd_printf(current->fd, "\x1b[0K"); -} - -static void setCursorPos(struct current *current, int x) -{ - fd_printf(current->fd, "\r\x1b[%dC", x); -} - -/** - * Reads a char from 'fd', waiting at most 'timeout' milliseconds. - * - * A timeout of -1 means to wait forever. - * - * Returns -1 if no char is received within the time or an error occurs. - */ -static int fd_read_char(int fd, int timeout) -{ - struct pollfd p; - unsigned char c; - - p.fd = fd; - p.events = POLLIN; - - if (poll(&p, 1, timeout) == 0) { - /* timeout */ - return -1; - } - if (read(fd, &c, 1) != 1) { - return -1; - } - return c; -} - -/** - * Reads a complete utf-8 character - * and returns the unicode value, or -1 on error. - */ -static int fd_read(struct current *current) -{ -#ifdef USE_UTF8 - char buf[4]; - int n; - int i; - int c; - - if (read(current->fd, &buf[0], 1) != 1) { - return -1; - } - n = utf8_charlen(buf[0]); - if (n < 1 || n > 3) { - return -1; - } - for (i = 1; i < n; i++) { - if (read(current->fd, &buf[i], 1) != 1) { - return -1; - } - } - buf[n] = 0; - /* decode and return the character */ - utf8_tounicode(buf, &c); - return c; -#else - return fd_read_char(current->fd, -1); -#endif -} - -static int countColorControlChars(const char* prompt, int plen) -{ - /* ANSI color control sequences have the form: - * "\x1b" "[" [0-9;]+ "m" - * We parse them with a simple state machine. - */ - - enum { - search_esc, - expect_bracket, - expect_inner, - expect_trail - } state = search_esc; - int len = 0, found = 0; - char ch; - - /* XXX: Strictly we should be checking utf8 chars rather than - * bytes in case of the extremely unlikely scenario where - * an ANSI sequence is part of a utf8 sequence. - */ - for (; plen ; plen--, prompt++) { - ch = *prompt; - - switch (state) { - case search_esc: - len = 0; - if (ch == '\x1b') { - state = expect_bracket; - len++; - } - break; - case expect_bracket: - if (ch == '[') { - state = expect_inner; - len++; - } else { - state = search_esc; - } - break; - case expect_inner: - if (ch >= '0' && ch <= '9') { - len++; - state = expect_trail; - } else { - state = search_esc; - } - break; - case expect_trail: - if (ch == 'm') { - len++; - found += len; - state = search_esc; - } else if ((ch != ';') && ((ch < '0') || (ch > '9'))) { - state = search_esc; - } - /* 0-9, or semicolon */ - len++; - break; - } - } - - return found; -} - -static int getWindowSize(struct current *current) -{ - struct winsize ws; - - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) { - current->cols = ws.ws_col; - return 0; - } - - /* Failed to query the window size. Perhaps we are on a serial terminal. - * Try to query the width by sending the cursor as far to the right - * and reading back the cursor position. - * Note that this is only done once per call to linenoise rather than - * every time the line is refreshed for efficiency reasons. - */ - if (current->cols == 0) { - current->cols = 80; - - /* Move cursor far right and report cursor position, then back to the left */ - fd_printf(current->fd, "\x1b[999C" "\x1b[6n"); - - /* Parse the response: ESC [ rows ; cols R */ - if (fd_read_char(current->fd, 100) == 0x1b && fd_read_char(current->fd, 100) == '[') { - int n = 0; - while (1) { - int ch = fd_read_char(current->fd, 100); - if (ch == ';') { - /* Ignore rows */ - n = 0; - } - else if (ch == 'R') { - /* Got cols */ - if (n != 0 && n < 1000) { - current->cols = n; - } - break; - } - else if (ch >= 0 && ch <= '9') { - n = n * 10 + ch - '0'; - } - else { - break; - } - } - } - } - return 0; -} - -/** - * If escape (27) was received, reads subsequent - * chars to determine if this is a known special key. - * - * Returns SPECIAL_NONE if unrecognised, or -1 if EOF. - * - * If no additional char is received within a short time, - * 27 is returned. - */ -static int check_special(int fd) -{ - int c = fd_read_char(fd, 50); - int c2; - - if (c < 0) { - return 27; - } - - c2 = fd_read_char(fd, 50); - if (c2 < 0) { - return c2; - } - if (c == '[' || c == 'O') { - /* Potential arrow key */ - switch (c2) { - case 'A': - return SPECIAL_UP; - case 'B': - return SPECIAL_DOWN; - case 'C': - return SPECIAL_RIGHT; - case 'D': - return SPECIAL_LEFT; - case 'F': - return SPECIAL_END; - case 'H': - return SPECIAL_HOME; - } - } - if (c == '[' && c2 >= '1' && c2 <= '8') { - /* extended escape */ - c = fd_read_char(fd, 50); - if (c == '~') { - switch (c2) { - case '2': - return SPECIAL_INSERT; - case '3': - return SPECIAL_DELETE; - case '5': - return SPECIAL_PAGE_UP; - case '6': - return SPECIAL_PAGE_DOWN; - case '7': - return SPECIAL_HOME; - case '8': - return SPECIAL_END; - } - } - while (c != -1 && c != '~') { - /* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */ - c = fd_read_char(fd, 50); - } - } - - return SPECIAL_NONE; -} -#elif defined(USE_WINCONSOLE) - -static DWORD orig_consolemode = 0; - -static int enableRawMode(struct current *current) { - DWORD n; - INPUT_RECORD irec; - - current->outh = GetStdHandle(STD_OUTPUT_HANDLE); - current->inh = GetStdHandle(STD_INPUT_HANDLE); - - if (!PeekConsoleInput(current->inh, &irec, 1, &n)) { - return -1; - } - if (getWindowSize(current) != 0) { - return -1; - } - if (GetConsoleMode(current->inh, &orig_consolemode)) { - SetConsoleMode(current->inh, ENABLE_PROCESSED_INPUT); - } - return 0; -} - -static void disableRawMode(struct current *current) -{ - SetConsoleMode(current->inh, orig_consolemode); -} - -static void clearScreen(struct current *current) -{ - COORD topleft = { 0, 0 }; - DWORD n; - - FillConsoleOutputCharacter(current->outh, ' ', - current->cols * current->rows, topleft, &n); - FillConsoleOutputAttribute(current->outh, - FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, - current->cols * current->rows, topleft, &n); - SetConsoleCursorPosition(current->outh, topleft); -} - -static void cursorToLeft(struct current *current) -{ - COORD pos = { 0, (SHORT)current->y }; - DWORD n; - - FillConsoleOutputAttribute(current->outh, - FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, current->cols, pos, &n); - current->x = 0; -} - -static int outputChars(struct current *current, const char *buf, int len) -{ - COORD pos = { (SHORT)current->x, (SHORT)current->y }; - DWORD n; - - WriteConsoleOutputCharacter(current->outh, buf, len, pos, &n); - current->x += len; - return 0; -} - -static void outputControlChar(struct current *current, char ch) -{ - COORD pos = { (SHORT)current->x, (SHORT)current->y }; - DWORD n; - - FillConsoleOutputAttribute(current->outh, BACKGROUND_INTENSITY, 2, pos, &n); - outputChars(current, "^", 1); - outputChars(current, &ch, 1); -} - -static void eraseEol(struct current *current) -{ - COORD pos = { (SHORT)current->x, (SHORT)current->y }; - DWORD n; - - FillConsoleOutputCharacter(current->outh, ' ', current->cols - current->x, pos, &n); -} - -static void setCursorPos(struct current *current, int x) -{ - COORD pos = { (SHORT)x, (SHORT)current->y }; - - SetConsoleCursorPosition(current->outh, pos); - current->x = x; -} - -static int fd_read(struct current *current) -{ - while (1) { - INPUT_RECORD irec; - DWORD n; - if (WaitForSingleObject(current->inh, INFINITE) != WAIT_OBJECT_0) { - break; - } - if (!ReadConsoleInput (current->inh, &irec, 1, &n)) { - break; - } - if (irec.EventType == KEY_EVENT && irec.Event.KeyEvent.bKeyDown) { - KEY_EVENT_RECORD *k = &irec.Event.KeyEvent; - if (k->dwControlKeyState & ENHANCED_KEY) { - switch (k->wVirtualKeyCode) { - case VK_LEFT: - return SPECIAL_LEFT; - case VK_RIGHT: - return SPECIAL_RIGHT; - case VK_UP: - return SPECIAL_UP; - case VK_DOWN: - return SPECIAL_DOWN; - case VK_INSERT: - return SPECIAL_INSERT; - case VK_DELETE: - return SPECIAL_DELETE; - case VK_HOME: - return SPECIAL_HOME; - case VK_END: - return SPECIAL_END; - case VK_PRIOR: - return SPECIAL_PAGE_UP; - case VK_NEXT: - return SPECIAL_PAGE_DOWN; - } - } - /* Note that control characters are already translated in AsciiChar */ - else { -#ifdef USE_UTF8 - return k->uChar.UnicodeChar; -#else - return k->uChar.AsciiChar; -#endif - } - } - } - return -1; -} - -static int countColorControlChars(const char* prompt, int plen) -{ - /* For windows we assume that there are no embedded ansi color - * control sequences. - */ - return 0; -} - -static int getWindowSize(struct current *current) -{ - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(current->outh, &info)) { - return -1; - } - current->cols = info.dwSize.X; - current->rows = info.dwSize.Y; - if (current->cols <= 0 || current->rows <= 0) { - current->cols = 80; - return -1; - } - current->y = info.dwCursorPosition.Y; - current->x = info.dwCursorPosition.X; - return 0; -} -#endif - -static int utf8_getchars(char *buf, int c) -{ -#ifdef USE_UTF8 - return utf8_fromunicode(buf, c); -#else - *buf = c; - return 1; -#endif -} - -/** - * Returns the unicode character at the given offset, - * or -1 if none. - */ -static int get_char(struct current *current, int pos) -{ - if (pos >= 0 && pos < current->chars) { - int c; - int i = utf8_index(current->buf, pos); - (void)utf8_tounicode(current->buf + i, &c); - return c; - } - return -1; -} - -static void refreshLine(const char *prompt, struct current *current) -{ - int plen; - int pchars; - int backup = 0; - int i; - const char *buf = current->buf; - int chars = current->chars; - int pos = current->pos; - int b; - int ch; - int n; - - /* Should intercept SIGWINCH. For now, just get the size every time */ - getWindowSize(current); - - plen = strlen(prompt); - pchars = utf8_strlen(prompt, plen); - - /* Scan the prompt for embedded ansi color control sequences and - * discount them as characters/columns. - */ - pchars -= countColorControlChars(prompt, plen); - - /* Account for a line which is too long to fit in the window. - * Note that control chars require an extra column - */ - - /* How many cols are required to the left of 'pos'? - * The prompt, plus one extra for each control char - */ - n = pchars + utf8_strlen(buf, current->len); - b = 0; - for (i = 0; i < pos; i++) { - b += utf8_tounicode(buf + b, &ch); - if (ch < ' ') { - n++; - } - } - - /* If too many are needed, strip chars off the front of 'buf' - * until it fits. Note that if the current char is a control character, - * we need one extra col. - */ - if (current->pos < current->chars && get_char(current, current->pos) < ' ') { - n++; - } - - while (n >= current->cols && pos > 0) { - b = utf8_tounicode(buf, &ch); - if (ch < ' ') { - n--; - } - n--; - buf += b; - pos--; - chars--; - } - - /* Cursor to left edge, then the prompt */ - cursorToLeft(current); - outputChars(current, prompt, plen); - - /* Now the current buffer content */ - - /* Need special handling for control characters. - * If we hit 'cols', stop. - */ - b = 0; /* unwritted bytes */ - n = 0; /* How many control chars were written */ - for (i = 0; i < chars; i++) { - int ch; - int w = utf8_tounicode(buf + b, &ch); - if (ch < ' ') { - n++; - } - if (pchars + i + n >= current->cols) { - break; - } - if (ch < ' ') { - /* A control character, so write the buffer so far */ - outputChars(current, buf, b); - buf += b + w; - b = 0; - outputControlChar(current, ch + '@'); - if (i < pos) { - backup++; - } - } - else { - b += w; - } - } - outputChars(current, buf, b); - - /* Erase to right, move cursor to original position */ - eraseEol(current); - setCursorPos(current, pos + pchars + backup); -} - -static void set_current(struct current *current, const char *str) -{ - strncpy(current->buf, str, current->bufmax); - current->buf[current->bufmax - 1] = 0; - current->len = strlen(current->buf); - current->pos = current->chars = utf8_strlen(current->buf, current->len); -} - -static int has_room(struct current *current, int bytes) -{ - return current->len + bytes < current->bufmax - 1; -} - -/** - * Removes the char at 'pos'. - * - * Returns 1 if the line needs to be refreshed, 2 if not - * and 0 if nothing was removed - */ -static int remove_char(struct current *current, int pos) -{ - if (pos >= 0 && pos < current->chars) { - int p1, p2; - int ret = 1; - p1 = utf8_index(current->buf, pos); - p2 = p1 + utf8_index(current->buf + p1, 1); - -#ifdef USE_TERMIOS - /* optimise remove char in the case of removing the last char */ - if (current->pos == pos + 1 && current->pos == current->chars) { - if (current->buf[pos] >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { - ret = 2; - fd_printf(current->fd, "\b \b"); - } - } -#endif - - /* Move the null char too */ - memmove(current->buf + p1, current->buf + p2, current->len - p2 + 1); - current->len -= (p2 - p1); - current->chars--; - - if (current->pos > pos) { - current->pos--; - } - return ret; - } - return 0; -} - -/** - * Insert 'ch' at position 'pos' - * - * Returns 1 if the line needs to be refreshed, 2 if not - * and 0 if nothing was inserted (no room) - */ -static int insert_char(struct current *current, int pos, int ch) -{ - char buf[3]; - int n = utf8_getchars(buf, ch); - - if (has_room(current, n) && pos >= 0 && pos <= current->chars) { - int p1, p2; - int ret = 1; - p1 = utf8_index(current->buf, pos); - p2 = p1 + n; - -#ifdef USE_TERMIOS - /* optimise the case where adding a single char to the end and no scrolling is needed */ - if (current->pos == pos && current->chars == pos) { - if (ch >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { - IGNORE_RC(write(current->fd, buf, n)); - ret = 2; - } - } -#endif - - memmove(current->buf + p2, current->buf + p1, current->len - p1); - memcpy(current->buf + p1, buf, n); - current->len += n; - - current->chars++; - if (current->pos >= pos) { - current->pos++; - } - return ret; - } - return 0; -} - -/** - * Captures up to 'n' characters starting at 'pos' for the cut buffer. - * - * This replaces any existing characters in the cut buffer. - */ -static void capture_chars(struct current *current, int pos, int n) -{ - if (pos >= 0 && (pos + n - 1) < current->chars) { - int p1 = utf8_index(current->buf, pos); - int nbytes = utf8_index(current->buf + p1, n); - - if (nbytes) { - free(current->capture); - /* Include space for the null terminator */ - current->capture = (char *)malloc(nbytes + 1); - memcpy(current->capture, current->buf + p1, nbytes); - current->capture[nbytes] = '\0'; - } - } -} - -/** - * Removes up to 'n' characters at cursor position 'pos'. - * - * Returns 0 if no chars were removed or non-zero otherwise. - */ -static int remove_chars(struct current *current, int pos, int n) -{ - int removed = 0; - - /* First save any chars which will be removed */ - capture_chars(current, pos, n); - - while (n-- && remove_char(current, pos)) { - removed++; - } - return removed; -} -/** - * Inserts the characters (string) 'chars' at the cursor position 'pos'. - * - * Returns 0 if no chars were inserted or non-zero otherwise. - */ -static int insert_chars(struct current *current, int pos, const char *chars) -{ - int inserted = 0; - - while (*chars) { - int ch; - int n = utf8_tounicode(chars, &ch); - if (insert_char(current, pos, ch) == 0) { - break; - } - inserted++; - pos++; - chars += n; - } - return inserted; -} - -#ifndef NO_COMPLETION -static linenoiseCompletionCallback *completionCallback = NULL; - -static void beep() { -#ifdef USE_TERMIOS - fprintf(stderr, "\x7"); - fflush(stderr); -#endif -} - -static void freeCompletions(linenoiseCompletions *lc) { - size_t i; - for (i = 0; i < lc->len; i++) - free(lc->cvec[i]); - free(lc->cvec); -} - -static int completeLine(struct current *current) { - linenoiseCompletions lc = { 0, NULL }; - int c = 0; - - completionCallback(current->buf,&lc); - if (lc.len == 0) { - beep(); - } else { - size_t stop = 0, i = 0; - - while(!stop) { - /* Show completion or original buffer */ - if (i < lc.len) { - struct current tmp = *current; - tmp.buf = lc.cvec[i]; - tmp.pos = tmp.len = strlen(tmp.buf); - tmp.chars = utf8_strlen(tmp.buf, tmp.len); - refreshLine(current->prompt, &tmp); - } else { - refreshLine(current->prompt, current); - } - - c = fd_read(current); - if (c == -1) { - break; - } - - switch(c) { - case '\t': /* tab */ - i = (i+1) % (lc.len+1); - if (i == lc.len) beep(); - break; - case 27: /* escape */ - /* Re-show original buffer */ - if (i < lc.len) { - refreshLine(current->prompt, current); - } - stop = 1; - break; - default: - /* Update buffer and return */ - if (i < lc.len) { - set_current(current,lc.cvec[i]); - } - stop = 1; - break; - } - } - } - - freeCompletions(&lc); - return c; /* Return last read character */ -} - -/* Register a callback function to be called for tab-completion. */ -void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { - completionCallback = fn; -} - -void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { - lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1)); - lc->cvec[lc->len++] = strdup(str); -} - -#endif - -static int linenoiseEdit(struct current *current) { - int history_index = 0; - - /* The latest history entry is always our current buffer, that - * initially is just an empty string. */ - linenoiseHistoryAdd(""); - - set_current(current, ""); - refreshLine(current->prompt, current); - - while(1) { - int dir = -1; - int c = fd_read(current); - -#ifndef NO_COMPLETION - /* Only autocomplete when the callback is set. It returns < 0 when - * there was an error reading from fd. Otherwise it will return the - * character that should be handled next. */ - if (c == '\t' && current->pos == current->chars && completionCallback != NULL) { - c = completeLine(current); - /* Return on errors */ - if (c < 0) return current->len; - /* Read next character when 0 */ - if (c == 0) continue; - } -#endif - -process_char: - if (c == -1) return current->len; -#ifdef USE_TERMIOS - if (c == 27) { /* escape sequence */ - c = check_special(current->fd); - } -#endif - switch(c) { - case '\r': /* enter */ - history_len--; - free(history[history_len]); - return current->len; - case ctrl('C'): /* ctrl-c */ - errno = EAGAIN; - return -1; - case 127: /* backspace */ - case ctrl('H'): - if (remove_char(current, current->pos - 1) == 1) { - refreshLine(current->prompt, current); - } - break; - case ctrl('D'): /* ctrl-d */ - if (current->len == 0) { - /* Empty line, so EOF */ - history_len--; - free(history[history_len]); - return -1; - } - /* Otherwise fall through to delete char to right of cursor */ - case SPECIAL_DELETE: - if (remove_char(current, current->pos) == 1) { - refreshLine(current->prompt, current); - } - break; - case SPECIAL_INSERT: - /* Ignore. Expansion Hook. - * Future possibility: Toggle Insert/Overwrite Modes - */ - break; - case ctrl('W'): /* ctrl-w, delete word at left. save deleted chars */ - /* eat any spaces on the left */ - { - int pos = current->pos; - while (pos > 0 && get_char(current, pos - 1) == ' ') { - pos--; - } - - /* now eat any non-spaces on the left */ - while (pos > 0 && get_char(current, pos - 1) != ' ') { - pos--; - } - - if (remove_chars(current, pos, current->pos - pos)) { - refreshLine(current->prompt, current); - } - } - break; - case ctrl('R'): /* ctrl-r */ - { - /* Display the reverse-i-search prompt and process chars */ - char rbuf[50]; - char rprompt[80]; - int rchars = 0; - int rlen = 0; - int searchpos = history_len - 1; - - rbuf[0] = 0; - while (1) { - int n = 0; - const char *p = NULL; - int skipsame = 0; - int searchdir = -1; - - snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf); - refreshLine(rprompt, current); - c = fd_read(current); - if (c == ctrl('H') || c == 127) { - if (rchars) { - int p = utf8_index(rbuf, --rchars); - rbuf[p] = 0; - rlen = strlen(rbuf); - } - continue; - } -#ifdef USE_TERMIOS - if (c == 27) { - c = check_special(current->fd); - } -#endif - if (c == ctrl('P') || c == SPECIAL_UP) { - /* Search for the previous (earlier) match */ - if (searchpos > 0) { - searchpos--; - } - skipsame = 1; - } - else if (c == ctrl('N') || c == SPECIAL_DOWN) { - /* Search for the next (later) match */ - if (searchpos < history_len) { - searchpos++; - } - searchdir = 1; - skipsame = 1; - } - else if (c >= ' ') { - if (rlen >= (int)sizeof(rbuf) + 3) { - continue; - } - - n = utf8_getchars(rbuf + rlen, c); - rlen += n; - rchars++; - rbuf[rlen] = 0; - - /* Adding a new char resets the search location */ - searchpos = history_len - 1; - } - else { - /* Exit from incremental search mode */ - break; - } - - /* Now search through the history for a match */ - for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) { - p = strstr(history[searchpos], rbuf); - if (p) { - /* Found a match */ - if (skipsame && strcmp(history[searchpos], current->buf) == 0) { - /* But it is identical, so skip it */ - continue; - } - /* Copy the matching line and set the cursor position */ - set_current(current,history[searchpos]); - current->pos = utf8_strlen(history[searchpos], p - history[searchpos]); - break; - } - } - if (!p && n) { - /* No match, so don't add it */ - rchars--; - rlen -= n; - rbuf[rlen] = 0; - } - } - if (c == ctrl('G') || c == ctrl('C')) { - /* ctrl-g terminates the search with no effect */ - set_current(current, ""); - c = 0; - } - else if (c == ctrl('J')) { - /* ctrl-j terminates the search leaving the buffer in place */ - c = 0; - } - /* Go process the char normally */ - refreshLine(current->prompt, current); - goto process_char; - } - break; - case ctrl('T'): /* ctrl-t */ - if (current->pos > 0 && current->pos <= current->chars) { - /* If cursor is at end, transpose the previous two chars */ - int fixer = (current->pos == current->chars); - c = get_char(current, current->pos - fixer); - remove_char(current, current->pos - fixer); - insert_char(current, current->pos - 1, c); - refreshLine(current->prompt, current); - } - break; - case ctrl('V'): /* ctrl-v */ - if (has_room(current, 3)) { - /* Insert the ^V first */ - if (insert_char(current, current->pos, c)) { - refreshLine(current->prompt, current); - /* Now wait for the next char. Can insert anything except \0 */ - c = fd_read(current); - - /* Remove the ^V first */ - remove_char(current, current->pos - 1); - if (c != -1) { - /* Insert the actual char */ - insert_char(current, current->pos, c); - } - refreshLine(current->prompt, current); - } - } - break; - case ctrl('B'): - case SPECIAL_LEFT: - if (current->pos > 0) { - current->pos--; - refreshLine(current->prompt, current); - } - break; - case ctrl('F'): - case SPECIAL_RIGHT: - if (current->pos < current->chars) { - current->pos++; - refreshLine(current->prompt, current); - } - break; - case SPECIAL_PAGE_UP: - dir = history_len - history_index - 1; /* move to start of history */ - goto history_navigation; - case SPECIAL_PAGE_DOWN: - dir = -history_index; /* move to 0 == end of history, i.e. current */ - goto history_navigation; - case ctrl('P'): - case SPECIAL_UP: - dir = 1; - goto history_navigation; - case ctrl('N'): - case SPECIAL_DOWN: -history_navigation: - if (history_len > 1) { - /* Update the current history entry before to - * overwrite it with tne next one. */ - free(history[history_len - 1 - history_index]); - history[history_len - 1 - history_index] = strdup(current->buf); - /* Show the new entry */ - history_index += dir; - if (history_index < 0) { - history_index = 0; - break; - } else if (history_index >= history_len) { - history_index = history_len - 1; - break; - } - set_current(current, history[history_len - 1 - history_index]); - refreshLine(current->prompt, current); - } - break; - case ctrl('A'): /* Ctrl+a, go to the start of the line */ - case SPECIAL_HOME: - current->pos = 0; - refreshLine(current->prompt, current); - break; - case ctrl('E'): /* ctrl+e, go to the end of the line */ - case SPECIAL_END: - current->pos = current->chars; - refreshLine(current->prompt, current); - break; - case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */ - if (remove_chars(current, 0, current->pos)) { - refreshLine(current->prompt, current); - } - break; - case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */ - if (remove_chars(current, current->pos, current->chars - current->pos)) { - refreshLine(current->prompt, current); - } - break; - case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */ - if (current->capture && insert_chars(current, current->pos, current->capture)) { - refreshLine(current->prompt, current); - } - break; - case ctrl('L'): /* Ctrl+L, clear screen */ - clearScreen(current); - /* Force recalc of window size for serial terminals */ - current->cols = 0; - refreshLine(current->prompt, current); - break; - default: - /* Only tab is allowed without ^V */ - if (c == '\t' || c >= ' ') { - if (insert_char(current, current->pos, c) == 1) { - refreshLine(current->prompt, current); - } - } - break; - } - } - return current->len; -} - -int linenoiseColumns(void) -{ - struct current current; - enableRawMode (¤t); - getWindowSize (¤t); - disableRawMode (¤t); - return current.cols; -} - -char *linenoise(const char *prompt) -{ - int count; - struct current current; - char buf[LINENOISE_MAX_LINE]; - - if (enableRawMode(¤t) == -1) { - printf("%s", prompt); - fflush(stdout); - if (fgets(buf, sizeof(buf), stdin) == NULL) { - return NULL; - } - count = strlen(buf); - if (count && buf[count-1] == '\n') { - count--; - buf[count] = '\0'; - } - } - else - { - current.buf = buf; - current.bufmax = sizeof(buf); - current.len = 0; - current.chars = 0; - current.pos = 0; - current.prompt = prompt; - current.capture = NULL; - - count = linenoiseEdit(¤t); - - disableRawMode(¤t); - printf("\n"); - - free(current.capture); - if (count == -1) { - return NULL; - } - } - return strdup(buf); -} - -/* Using a circular buffer is smarter, but a bit more complex to handle. */ -int linenoiseHistoryAdd(const char *line) { - char *linecopy; - - if (history_max_len == 0) return 0; - if (history == NULL) { - history = (char **)malloc(sizeof(char*)*history_max_len); - if (history == NULL) return 0; - memset(history,0,(sizeof(char*)*history_max_len)); - } - - /* do not insert duplicate lines into history */ - if (history_len > 0 && strcmp(line, history[history_len - 1]) == 0) { - return 0; - } - - linecopy = strdup(line); - if (!linecopy) return 0; - if (history_len == history_max_len) { - free(history[0]); - memmove(history,history+1,sizeof(char*)*(history_max_len-1)); - history_len--; - } - history[history_len] = linecopy; - history_len++; - return 1; -} - -int linenoiseHistoryGetMaxLen(void) { - return history_max_len; -} - -int linenoiseHistorySetMaxLen(int len) { - char **newHistory; - - if (len < 1) return 0; - if (history) { - int tocopy = history_len; - - newHistory = (char **)malloc(sizeof(char*)*len); - if (newHistory == NULL) return 0; - - /* If we can't copy everything, free the elements we'll not use. */ - if (len < tocopy) { - int j; - - for (j = 0; j < tocopy-len; j++) free(history[j]); - tocopy = len; - } - memset(newHistory,0,sizeof(char*)*len); - memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy); - free(history); - history = newHistory; - } - history_max_len = len; - if (history_len > history_max_len) - history_len = history_max_len; - return 1; -} - -/* Save the history in the specified file. On success 0 is returned - * otherwise -1 is returned. */ -int linenoiseHistorySave(const char *filename) { - FILE *fp = fopen(filename,"w"); - int j; - - if (fp == NULL) return -1; - for (j = 0; j < history_len; j++) { - const char *str = history[j]; - /* Need to encode backslash, nl and cr */ - while (*str) { - if (*str == '\\') { - fputs("\\\\", fp); - } - else if (*str == '\n') { - fputs("\\n", fp); - } - else if (*str == '\r') { - fputs("\\r", fp); - } - else { - fputc(*str, fp); - } - str++; - } - fputc('\n', fp); - } - - fclose(fp); - return 0; -} - -/* Load the history from the specified file. If the file does not exist - * zero is returned and no operation is performed. - * - * If the file exists and the operation succeeded 0 is returned, otherwise - * on error -1 is returned. */ -int linenoiseHistoryLoad(const char *filename) { - FILE *fp = fopen(filename,"r"); - char buf[LINENOISE_MAX_LINE]; - - if (fp == NULL) return -1; - - while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { - char *src, *dest; - - /* Decode backslash escaped values */ - for (src = dest = buf; *src; src++) { - char ch = *src; - - if (ch == '\\') { - src++; - if (*src == 'n') { - ch = '\n'; - } - else if (*src == 'r') { - ch = '\r'; - } else { - ch = *src; - } - } - *dest++ = ch; - } - /* Remove trailing newline */ - if (dest != buf && (dest[-1] == '\n' || dest[-1] == '\r')) { - dest--; - } - *dest = 0; - - linenoiseHistoryAdd(buf); - } - fclose(fp); - return 0; -} - -/* Provide access to the history buffer. - * - * If 'len' is not NULL, the length is stored in *len. - */ -char **linenoiseHistory(int *len) { - if (len) { - *len = history_len; - } - return history; -} diff --git a/src/rt/linenoise/linenoise.h b/src/rt/linenoise/linenoise.h deleted file mode 100644 index 7ebf244ee80..00000000000 --- a/src/rt/linenoise/linenoise.h +++ /dev/null @@ -1,61 +0,0 @@ -/* linenoise.h -- guerrilla line editing library against the idea that a - * line editing lib needs to be 20,000 lines of C code. - * - * See linenoise.c for more information. - * - * ------------------------------------------------------------------------ - * - * Copyright (c) 2010, Salvatore Sanfilippo - * Copyright (c) 2010, Pieter Noordhuis - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __LINENOISE_H -#define __LINENOISE_H - -#ifndef NO_COMPLETION -typedef struct linenoiseCompletions { - size_t len; - char **cvec; -} linenoiseCompletions; - -typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); -void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); -void linenoiseAddCompletion(linenoiseCompletions *, const char *); -#endif - -char *linenoise(const char *prompt); -int linenoiseHistoryAdd(const char *line); -int linenoiseHistorySetMaxLen(int len); -int linenoiseHistoryGetMaxLen(void); -int linenoiseHistorySave(const char *filename); -int linenoiseHistoryLoad(const char *filename); -void linenoiseHistoryFree(void); -char **linenoiseHistory(int *len); -int linenoiseColumns(void); - -#endif /* __LINENOISE_H */ diff --git a/src/rt/linenoise/utf8.c b/src/rt/linenoise/utf8.c deleted file mode 100644 index 26924b46c19..00000000000 --- a/src/rt/linenoise/utf8.c +++ /dev/null @@ -1,115 +0,0 @@ -/** - * UTF-8 utility functions - * - * (c) 2010 Steve Bennett - * - * See LICENCE for licence details. - */ - -#include -#include -#include -#include -#include "utf8.h" - -#ifdef USE_UTF8 -int utf8_fromunicode(char *p, unsigned short uc) -{ - if (uc <= 0x7f) { - *p = uc; - return 1; - } - else if (uc <= 0x7ff) { - *p++ = 0xc0 | ((uc & 0x7c0) >> 6); - *p = 0x80 | (uc & 0x3f); - return 2; - } - else { - *p++ = 0xe0 | ((uc & 0xf000) >> 12); - *p++ = 0x80 | ((uc & 0xfc0) >> 6); - *p = 0x80 | (uc & 0x3f); - return 3; - } -} - -int utf8_charlen(int c) -{ - if ((c & 0x80) == 0) { - return 1; - } - if ((c & 0xe0) == 0xc0) { - return 2; - } - if ((c & 0xf0) == 0xe0) { - return 3; - } - if ((c & 0xf8) == 0xf0) { - return 4; - } - /* Invalid sequence */ - return -1; -} - -int utf8_strlen(const char *str, int bytelen) -{ - int charlen = 0; - if (bytelen < 0) { - bytelen = strlen(str); - } - while (bytelen) { - int c; - int l = utf8_tounicode(str, &c); - charlen++; - str += l; - bytelen -= l; - } - return charlen; -} - -int utf8_index(const char *str, int index) -{ - const char *s = str; - while (index--) { - int c; - s += utf8_tounicode(s, &c); - } - return s - str; -} - -int utf8_charequal(const char *s1, const char *s2) -{ - int c1, c2; - - utf8_tounicode(s1, &c1); - utf8_tounicode(s2, &c2); - - return c1 == c2; -} - -int utf8_tounicode(const char *str, int *uc) -{ - unsigned const char *s = (unsigned const char *)str; - - if (s[0] < 0xc0) { - *uc = s[0]; - return 1; - } - if (s[0] < 0xe0) { - if ((s[1] & 0xc0) == 0x80) { - *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80); - return 2; - } - } - else if (s[0] < 0xf0) { - if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) { - *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80); - return 3; - } - } - - /* Invalid sequence, so just return the byte */ - *uc = *s; - return 1; -} - -#endif diff --git a/src/rt/linenoise/utf8.h b/src/rt/linenoise/utf8.h deleted file mode 100644 index 9537939876a..00000000000 --- a/src/rt/linenoise/utf8.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef UTF8_UTIL_H -#define UTF8_UTIL_H -/** - * UTF-8 utility functions - * - * (c) 2010 Steve Bennett - * - * See LICENCE for licence details. - */ - -#ifndef USE_UTF8 -#include - -/* No utf-8 support. 1 byte = 1 char */ -#define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B)) -#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) -#define utf8_index(C, I) (I) -#define utf8_charlen(C) 1 - -#else -/** - * Converts the given unicode codepoint (0 - 0xffff) to utf-8 - * and stores the result at 'p'. - * - * Returns the number of utf-8 characters (1-3). - */ -int utf8_fromunicode(char *p, unsigned short uc); - -/** - * Returns the length of the utf-8 sequence starting with 'c'. - * - * Returns 1-4, or -1 if this is not a valid start byte. - * - * Note that charlen=4 is not supported by the rest of the API. - */ -int utf8_charlen(int c); - -/** - * Returns the number of characters in the utf-8 - * string of the given byte length. - * - * Any bytes which are not part of an valid utf-8 - * sequence are treated as individual characters. - * - * The string *must* be null terminated. - * - * Does not support unicode code points > \uffff - */ -int utf8_strlen(const char *str, int bytelen); - -/** - * Returns the byte index of the given character in the utf-8 string. - * - * The string *must* be null terminated. - * - * This will return the byte length of a utf-8 string - * if given the char length. - */ -int utf8_index(const char *str, int charindex); - -/** - * Returns the unicode codepoint corresponding to the - * utf-8 sequence 'str'. - * - * Stores the result in *uc and returns the number of bytes - * consumed. - * - * If 'str' is null terminated, then an invalid utf-8 sequence - * at the end of the string will be returned as individual bytes. - * - * If it is not null terminated, the length *must* be checked first. - * - * Does not support unicode code points > \uffff - */ -int utf8_tounicode(const char *str, int *uc); - -#endif - -#endif diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 13fc3f1aa81..9750e22e945 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -570,18 +570,6 @@ rust_drop_env_lock() { env_lock.unlock(); } -static lock_and_signal linenoise_lock; - -extern "C" CDECL void -rust_take_linenoise_lock() { - linenoise_lock.lock(); -} - -extern "C" CDECL void -rust_drop_linenoise_lock() { - linenoise_lock.unlock(); -} - static lock_and_signal dlerror_lock; extern "C" CDECL void diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 959d1fa85f3..fb9934c7601 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -133,13 +133,6 @@ tinfl_decompress_mem_to_heap rust_uv_ip4_port rust_uv_ip6_port rust_uv_tcp_getpeername -linenoise -linenoiseSetCompletionCallback -linenoiseAddCompletion -linenoiseHistoryAdd -linenoiseHistorySetMaxLen -linenoiseHistorySave -linenoiseHistoryLoad rust_raw_thread_start rust_raw_thread_join rust_raw_thread_delete @@ -187,8 +180,6 @@ rust_get_num_cpus rust_get_global_args_ptr rust_take_global_args_lock rust_drop_global_args_lock -rust_take_linenoise_lock -rust_drop_linenoise_lock rust_get_test_int rust_get_task rust_uv_get_loop_from_getaddrinfo_req diff --git a/src/test/auxiliary/issue_3882.rc b/src/test/auxiliary/issue_3882.rc deleted file mode 100644 index f6124088c9b..00000000000 --- a/src/test/auxiliary/issue_3882.rc +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[link(name = "linenoise", - vers = "0.1")]; -#[crate_type = "lib"]; - -pub mod issue_3882; diff --git a/src/test/auxiliary/issue_3882.rs b/src/test/auxiliary/issue_3882.rs deleted file mode 100644 index bb75758c741..00000000000 --- a/src/test/auxiliary/issue_3882.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -mod issue_3882 { - struct Completions { - len: libc::size_t, - } - - mod c { - extern { - fn linenoiseAddCompletion(lc: *mut Completions); - } - } -} diff --git a/src/test/run-pass/issue_3882.rs b/src/test/run-pass/issue_3882.rs deleted file mode 100644 index 202385681ce..00000000000 --- a/src/test/run-pass/issue_3882.rs +++ /dev/null @@ -1,16 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-test -// aux-build:issue_3882.rc -extern mod linenoise; -use linenoise::issue_3882::*; - -pub fn main() {} diff --git a/src/test/run-pass/rl-human-test.rs b/src/test/run-pass/rl-human-test.rs deleted file mode 100644 index 6a87a6502d2..00000000000 --- a/src/test/run-pass/rl-human-test.rs +++ /dev/null @@ -1,83 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast no compile flags for check-fast - -// we want this to be compiled to avoid bitrot, but the actual test -//has to be conducted by a human, i.e. someone (you?) compiling this -//file with a plain rustc invocation and running it and checking it -//works. - -// compile-flags: --cfg robot_mode - -extern mod extra; -use extra::rl; - -static HISTORY_FILE: &'static str = "rl-human-test-history.txt"; - -struct TestCompleter; - -impl rl::CompletionCb for TestCompleter { - fn complete(&self, line: ~str, suggest: &fn(~str)) { - if line.is_empty() { - suggest(~"empty") - } else { - for c in line.rev_iter().take(3) { - suggest(format!("{0}{1}{1}{1}", line, c)) - } - } - } -} - -fn main() { - // don't run this in robot mode, but still typecheck it. - if !cfg!(robot_mode) { - println("~~ Welcome to the rl test \"suite\". ~~"); - println!("Operations: - - restrict the history to 2 lines, - - set the tab-completion to suggest three copies of each of the last 3 letters (or 'empty'), - - add 'one' and 'two' to the history, - - save it to `{0}`, - - add 'three', - - prompt & save input (check the history & completion work and contains only 'two', 'three'), - - load from `{0}` - - prompt & save input (history should be 'one', 'two' again), - - prompt once more. - -The bool return values of each step are printed.", - HISTORY_FILE); - - println!("restricting history length: {}", rl::set_history_max_len(3)); - - unsafe { - rl::complete(@TestCompleter as @rl::CompletionCb); - } - - println!("adding 'one': {}", rl::add_history("one")); - println!("adding 'two': {}", rl::add_history("two")); - - println!("saving history: {}", rl::save_history(HISTORY_FILE)); - - println!("adding 'three': {}", rl::add_history("three")); - - match rl::read("> ") { - Some(s) => println!("saving input: {}", rl::add_history(s)), - None => return - } - println!("loading history: {}", rl::load_history(HISTORY_FILE)); - - match rl::read("> ") { - Some(s) => println!("saving input: {}", rl::add_history(s)), - None => return - } - - rl::read("> "); - } -}