summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog55
-rw-r--r--MANIFEST1
-rw-r--r--ToDo2
-rw-r--r--array.c1
-rw-r--r--bignum.c3
-rw-r--r--configure1
-rw-r--r--configure.in1
-rw-r--r--dln.c1
-rw-r--r--eval.c18
-rw-r--r--ext/etc/etc.c5
-rw-r--r--ext/md5/depend2
-rw-r--r--ext/socket/socket.c20
-rw-r--r--ext/socket/sockport.h2
-rw-r--r--file.c9
-rw-r--r--gc.c7
-rw-r--r--hash.c4
-rw-r--r--intern.h8
-rw-r--r--io.c49
-rw-r--r--lib/irb/completion.rb47
-rw-r--r--lib/irb/frame.rb67
-rw-r--r--lib/irb/input-method.rb118
-rw-r--r--lib/irb/loader.rb118
-rw-r--r--lib/irb/main.rb867
-rw-r--r--lib/irb/multi-irb.rb212
-rw-r--r--lib/irb/ruby-lex.rb955
-rw-r--r--lib/irb/ruby-token.rb266
-rw-r--r--lib/irb/slex.rb279
-rw-r--r--lib/irb/version.rb16
-rw-r--r--lib/irb/workspace-binding-2.rb15
-rw-r--r--lib/irb/workspace-binding.rb77
-rw-r--r--lib/irb/xmp.rb84
-rw-r--r--lib/matrix.rb1
-rw-r--r--lib/thread.rb9
-rw-r--r--marshal.c2
-rw-r--r--pack.c78
-rw-r--r--parse.y137
-rw-r--r--regex.c41
-rw-r--r--ruby.c16
-rw-r--r--ruby.h12
-rw-r--r--sample/irb.rb28
-rw-r--r--sample/rbc.rb2
-rw-r--r--string.c4
-rw-r--r--time.c6
-rw-r--r--util.c22
-rw-r--r--variable.c3
-rw-r--r--version.h8
46 files changed, 3491 insertions, 188 deletions
diff --git a/ChangeLog b/ChangeLog
index 07fa720ced..15c28a9e42 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,57 @@
-Tue May 9 17:08:43 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+Fri May 12 17:33:44 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): charset_not should not exclude
+ newline from matching set.
+
+Thu May 11 22:51:05 2000 Ryunosuke Ohshima <ryu@jaist.ac.jp>
+
+ * pack.c (pack_pack): Bignum support.
+
+ * pack.c (pack_unpack): ditto.
+
+Thu May 11 21:19:29 2000 Hiroshi Igarashi <iga@ruby-lang.org>
+
+ * intern.h: add missing declarations of ruby API functions.
+
+ * ruby.h: fix function name in declarations.
+
+Thu May 11 22:29:25 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/md5/depend: add $(topdir)/config.h dependency to md5c.o.
+
+ * ext/md5/extconf.rb: new file to add -DHAVE_CONFIG_H flag for Alpha.
+
+Thu May 11 10:55:52 2000 Ryunosuke Ohshima <ryu@jaist.ac.jp>
- * array.c (Init_Array): prepare 'append' as alias to `push'.
+ * pack.c (pack_pack): packing BER compressed integer by `w'.
+
+ * pack.c (pack_unpack): unpacking BER.
+
+Thu May 11 00:37:55 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (parse_regx): remove in_brack.
+
+Wed May 10 12:51:18 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (proc_options): move adding RUBYLIB and "." to the load
+ path after #! line parsing.
+
+ * parse.y (parse_regx): should parse backslash escape like `\c['
+ here to avoid causing `unterminated regexp' error.
+
+Wed May 10 00:19:53 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * MANIFEST, beos/GNUmakefile.in, configure.in: no longer need
+ beos/GNUmakefile.in to support BeOS R4.5.2 (Intel) as a result
+ of eban's Makefile.in change.
+
+ * io.c: NOFILE is already defined on BeOS R4.5 (Intel) or later.
+
+ * lib/matrix.rb: remove debug print.
+
+ * regex.c: don't use nested comment.
+
+Tue May 9 17:08:43 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (massign): no longer convert nil into empty array.
diff --git a/MANIFEST b/MANIFEST
index b30efedcb2..c2f0dd1e12 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -75,7 +75,6 @@ util.c
variable.c
version.c
version.h
-beos/GNUmakefile.in
cygwin/GNUmakefile.in
ext/Setup
ext/Setup.dj
diff --git a/ToDo b/ToDo
index 9e49c4ba9e..84d0ea128a 100644
--- a/ToDo
+++ b/ToDo
@@ -41,6 +41,7 @@ Hacking Interpreter
* scrambled script, or script filter
* setuid ruby
* performance tune for in-block (dynamic) local variables.
+* generational GC ?? (is it possible?)
Standard Libraries
@@ -64,6 +65,7 @@ Standard Libraries
- Kernel#scan
- call initialize for builtin classes too (not yet: Regexp, Class, Module)
- performance tune for String's non-bang methods.
+- 'w' template for pack/unpack
* String#scanf(?)
* Object#fmt(?)
* Integer#{bin,oct,hex,heX}
diff --git a/array.c b/array.c
index 7b5ec47830..6793fdde88 100644
--- a/array.c
+++ b/array.c
@@ -1601,7 +1601,6 @@ Init_Array()
rb_define_method(rb_cArray, "last", rb_ary_last, 0);
rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
- rb_define_method(rb_cArray, "append", rb_ary_push_m, -1);
rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
rb_define_method(rb_cArray, "pop", rb_ary_pop, 0);
rb_define_method(rb_cArray, "shift", rb_ary_shift, 0);
diff --git a/bignum.c b/bignum.c
index f9dc5fe611..8fb3d39406 100644
--- a/bignum.c
+++ b/bignum.c
@@ -423,6 +423,7 @@ rb_big2ulong(x)
unsigned long num = big2ulong(x, "unsigned long");
if (!RBIGNUM(x)->sign) return -num;
+ return num;
}
long
@@ -944,7 +945,7 @@ rb_big_remainder(x, y)
return rb_big_modulo(x, y, 0);
}
-static VALUE
+VALUE
rb_big_divmod(x, y)
VALUE x, y;
{
diff --git a/configure b/configure
index ec6b66fb1f..e2fdcd92fa 100644
--- a/configure
+++ b/configure
@@ -4870,7 +4870,6 @@ if test "$target_os" = "beos"; then
;;
i586*)
LDFLAGS="$LDFLAGS -L."
- FIRSTMAKEFILE=GNUmakefile:beos/GNUmakefile.in
;;
*)
echo EXPORTS > ruby.def
diff --git a/configure.in b/configure.in
index c83b0ab74c..22e1e68dce 100644
--- a/configure.in
+++ b/configure.in
@@ -707,7 +707,6 @@ if test "$target_os" = "beos"; then
;;
i586*)
LDFLAGS="$LDFLAGS -L."
- FIRSTMAKEFILE=GNUmakefile:beos/GNUmakefile.in
;;
*)
echo EXPORTS > ruby.def
diff --git a/dln.c b/dln.c
index 3a02dbf996..be0aca4353 100644
--- a/dln.c
+++ b/dln.c
@@ -15,6 +15,7 @@
#include "dln.h"
char *dln_argv0;
+void rb_loaderror();
#ifdef _AIX
#pragma alloca
diff --git a/eval.c b/eval.c
index 730b82e59a..7466e587df 100644
--- a/eval.c
+++ b/eval.c
@@ -1362,7 +1362,6 @@ ev_const_set(cref, id, val)
VALUE val;
{
NODE *cbase = cref;
- VALUE tmp;
while (cbase && cbase->nd_clss != rb_cObject) {
struct RClass *klass = RCLASS(cbase->nd_clss);
@@ -2760,9 +2759,12 @@ rb_eval(self, n)
else if (SCOPE_TEST(SCOPE_PROTECTED)) {
noex = NOEX_PROTECTED;
}
- else {
+ else if (ruby_class == rb_cObject) {
noex = node->nd_noex;
}
+ else {
+ noex = NOEX_PUBLIC;
+ }
if (body && origin == ruby_class && body->nd_noex & NOEX_UNDEF) {
noex |= NOEX_UNDEF;
}
@@ -4552,7 +4554,7 @@ rb_f_eval(argc, argv, self)
VALUE *argv;
VALUE self;
{
- VALUE src, scope, vfile, vline, val;
+ VALUE src, scope, vfile, vline;
char *file = "(eval)";
int line = 1;
@@ -4660,7 +4662,7 @@ yield_under_i(self)
if (ruby_block->flags & BLOCK_DYNAMIC) {
struct BLOCK * volatile old_block = ruby_block;
struct BLOCK block;
- volatile VALUE cbase = ruby_block->frame.cbase;
+
/* cbase should be pointed from volatile local variable */
/* to be protected from GC. */
VALUE result;
@@ -4977,9 +4979,8 @@ rb_f_require(obj, fname)
buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5);
strcpy(buf, RSTRING(fname)->ptr);
strcat(buf, ".rb");
- file = rb_find_file(buf);
- if (file) {
- fname = rb_str_new2(file);
+ if (rb_find_file(buf)) {
+ fname = rb_str_new2(buf);
feature = buf;
goto load_rb;
}
@@ -6490,8 +6491,9 @@ thread_switch(n)
break;
case RESTORE_NORMAL:
default:
- return 1;
+ break;
}
+ return 1;
}
#define THREAD_SAVE_CONTEXT(th) \
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index e5f69f9285..049b94ec8f 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -10,6 +10,11 @@
#include "ruby.h"
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifdef HAVE_GETPWENT
#include <pwd.h>
#endif
diff --git a/ext/md5/depend b/ext/md5/depend
index c99f78ee90..14427861f8 100644
--- a/ext/md5/depend
+++ b/ext/md5/depend
@@ -1,2 +1,2 @@
-md5c.o: md5c.c md5.h
+md5c.o: md5c.c md5.h $(topdir)/config.h
md5init.o: md5init.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h md5.h
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index bbd5057741..cadadd2b6c 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -15,6 +15,11 @@
#include "rubysig.h"
#include <stdio.h>
#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifndef NT
#include <sys/socket.h>
#include <netinet/in.h>
@@ -538,7 +543,7 @@ ip_addrsetup(host, port)
portp = 0;
}
else if (FIXNUM_P(port)) {
- snprintf(pbuf, sizeof(pbuf), "%d", FIX2INT(port));
+ snprintf(pbuf, sizeof(pbuf), "%ld", FIX2INT(port));
portp = pbuf;
}
else {
@@ -726,7 +731,7 @@ open_inet(class, h, serv, type)
host = NULL;
}
if (FIXNUM_P(serv)) {
- snprintf(pbuf, sizeof(pbuf), "%d", FIX2UINT(serv));
+ snprintf(pbuf, sizeof(pbuf), "%ld", FIX2UINT(serv));
portp = pbuf;
}
else {
@@ -1748,7 +1753,7 @@ sock_s_getaddrinfo(argc, argv)
pptr = NULL;
}
else if (FIXNUM_P(port)) {
- snprintf(pbuf, sizeof(pbuf), "%d", FIX2INT(port));
+ snprintf(pbuf, sizeof(pbuf), "%ld", FIX2INT(port));
pptr = pbuf;
}
else {
@@ -1788,7 +1793,7 @@ sock_s_getnameinfo(argc, argv)
int argc;
VALUE *argv;
{
- VALUE sa, af, host, port, flags;
+ VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags;
static char hbuf[1024], pbuf[1024];
char *hptr, *pptr;
int fl;
@@ -1824,6 +1829,10 @@ sock_s_getnameinfo(argc, argv)
host = RARRAY(sa)->ptr[2];
}
}
+ else {
+ rb_raise(rb_eArgError, "array size should be 3 or 4, %d given",
+ RARRAY(sa)->len);
+ }
if (NIL_P(host)) {
hptr = NULL;
}
@@ -1837,7 +1846,7 @@ sock_s_getnameinfo(argc, argv)
pptr = NULL;
}
else if (!NIL_P(port)) {
- snprintf(pbuf, sizeof(pbuf), "%d", NUM2INT(port));
+ snprintf(pbuf, sizeof(pbuf), "%ld", NUM2INT(port));
pptr = pbuf;
}
else {
@@ -1872,7 +1881,6 @@ sock_s_getnameinfo(argc, argv)
fl = NUM2INT(flags);
}
- gotsap:
error = getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
pbuf, sizeof(pbuf), fl);
if (error) {
diff --git a/ext/socket/sockport.h b/ext/socket/sockport.h
index 99bec91a1a..1639fcf828 100644
--- a/ext/socket/sockport.h
+++ b/ext/socket/sockport.h
@@ -37,7 +37,7 @@
# define SET_SIN_LEN(si,len) (si)->sin_len = (len)
#else
# define SIN_LEN(si) sizeof(struct sockaddr_in)
-# define SET_SIN_LEN(si,len) (len)
+# define SET_SIN_LEN(si,len)
#endif
#endif
diff --git a/file.c b/file.c
index 19e44c4d13..421929d96f 100644
--- a/file.c
+++ b/file.c
@@ -25,6 +25,12 @@
#include <unistd.h>
#endif
+#ifdef HAVE_SYS_FILE_H
+# include <sys/file.h>
+#else
+int flock _((int, int));
+#endif
+
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#else
@@ -875,6 +881,7 @@ rb_file_s_chmod(argc, argv)
VALUE rest;
int mode, n;
+ rb_secure(2);
rb_scan_args(argc, argv, "1*", &vmode, &rest);
mode = NUM2INT(vmode);
@@ -927,6 +934,7 @@ rb_file_s_chown(argc, argv)
struct chown_args arg;
int n;
+ rb_secure(2);
rb_scan_args(argc, argv, "2*", &o, &g, &rest);
if (NIL_P(o)) {
arg.owner = -1;
@@ -1377,6 +1385,7 @@ static VALUE
rb_file_s_truncate(obj, path, len)
VALUE obj, path, len;
{
+ rb_secure(2);
Check_SafeStr(path);
#ifdef HAVE_TRUNCATE
diff --git a/gc.c b/gc.c
index 086715a569..edb290fbc4 100644
--- a/gc.c
+++ b/gc.c
@@ -52,7 +52,6 @@ static unsigned long malloc_memories = 0;
static unsigned long alloc_objects = 0;
static int malloc_called = 0;
-static int second_mem_error = 0;
static void
mem_error(mesg)
@@ -947,11 +946,7 @@ rb_gc()
setjmp(save_regs_gc_mark);
mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END);
-#if defined(THINK_C) || defined(__human68k__)
-#ifndef __human68k__
- mark_locations_array((VALUE*)((char*)save_regs_gc_mark+2),
- sizeof(save_regs_gc_mark) / sizeof(VALUE *));
-#endif
+#if defined(__human68k__)
rb_gc_mark_locations((VALUE*)((char*)rb_gc_stack_start + 2),
(VALUE*)((char*)STACK_END + 2));
#endif
diff --git a/hash.c b/hash.c
index 14afcbb7f3..dc8bdf5f45 100644
--- a/hash.c
+++ b/hash.c
@@ -688,8 +688,6 @@ static VALUE
rb_hash_to_s(hash)
VALUE hash;
{
- VALUE str;
-
if (rb_inspecting_p(hash)) return rb_str_new2("{...}");
return rb_protect_inspect(to_s_hash, hash, 0);
}
@@ -929,8 +927,6 @@ env_fetch(argc, argv)
char *nam, *env;
int len;
- VALUE val;
-
rb_scan_args(argc, argv, "11", &key, &if_none);
nam = rb_str2cstr(key, &len);
if (strlen(nam) != len) {
diff --git a/intern.h b/intern.h
index 81b1a53a04..e0c365fdca 100644
--- a/intern.h
+++ b/intern.h
@@ -68,6 +68,7 @@ double rb_big2dbl _((VALUE));
VALUE rb_big_plus _((VALUE, VALUE));
VALUE rb_big_minus _((VALUE, VALUE));
VALUE rb_big_mul _((VALUE, VALUE));
+VALUE rb_big_divmod _((VALUE, VALUE));
VALUE rb_big_pow _((VALUE, VALUE));
VALUE rb_big_and _((VALUE, VALUE));
VALUE rb_big_or _((VALUE, VALUE));
@@ -105,6 +106,7 @@ VALUE rb_exc_new3 _((VALUE, VALUE));
void rb_loaderror __((const char*, ...)) NORETURN;
void rb_compile_error __((const char*, ...));
void rb_compile_error_append __((const char*, ...));
+void rb_error_frozen _((char*));
/* eval.c */
void rb_exc_raise _((VALUE)) NORETURN;
void rb_exc_fatal _((VALUE)) NORETURN;
@@ -219,6 +221,7 @@ VALUE rb_obj_clone _((VALUE));
VALUE rb_obj_taint _((VALUE));
VALUE rb_obj_tainted _((VALUE));
VALUE rb_obj_untaint _((VALUE));
+VALUE rb_obj_freeze _((VALUE));
VALUE rb_obj_id _((VALUE));
VALUE rb_convert_type _((VALUE,int,const char*,const char*));
VALUE rb_Integer _((VALUE));
@@ -240,6 +243,7 @@ void rb_parser_append_print _((void));
void rb_parser_while_loop _((int, int));
int rb_is_const_id _((ID));
int rb_is_instance_id _((ID));
+int rb_is_class_id _((ID));
VALUE rb_backref_get _((void));
void rb_backref_set _((VALUE));
VALUE rb_lastline_get _((void));
@@ -352,8 +356,12 @@ int rb_const_defined _((VALUE, ID));
VALUE rb_const_get _((VALUE, ID));
VALUE rb_const_get_at _((VALUE, ID));
void rb_const_set _((VALUE, ID, VALUE));
+void rb_const_assign _((VALUE, ID, VALUE));
VALUE rb_mod_constants _((VALUE));
void rb_autoload_load _((ID));
+void rb_cvar_declare _((VALUE, ID, VALUE));
+VALUE rb_cvar_get _((VALUE, ID));
+void rb_cvar_set _((VALUE, ID, VALUE));
/* version.c */
void ruby_show_version _((void));
void ruby_show_copyright _((void));
diff --git a/io.c b/io.c
index 380e7d4115..9a5ef85845 100644
--- a/io.c
+++ b/io.c
@@ -63,7 +63,7 @@ char *strdup();
extern void Init_File _((void));
#ifdef __BEOS__
-# ifdef _X86_
+# ifdef NOFILE
# define NOFILE (OPEN_MAX)
# endif
#include <net/socket.h>
@@ -170,6 +170,25 @@ rb_read_check(fp)
}
}
+static int
+rb_dup(orig)
+ int orig;
+{
+ int fd;
+
+ fd = dup(orig);
+ if (fd < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ fd = dup(orig);
+ }
+ if (fd < 0) {
+ rb_sys_fail(0);
+ }
+ }
+ return fd;
+}
+
/* writing functions */
static VALUE
io_write(io, str)
@@ -1893,10 +1912,10 @@ rb_io_clone(io)
else mode = "r+";
break;
}
- fd = dup(fileno(orig->f));
+ fd = rb_dup(fileno(orig->f));
fptr->f = rb_fdopen(fd, mode);
if (fptr->f2) {
- fd = dup(fileno(orig->f2));
+ fd = rb_dup(fileno(orig->f2));
fptr->f = rb_fdopen(fd, "w");
}
if (fptr->mode & FMODE_BINMODE) {
@@ -2126,25 +2145,6 @@ rb_io_defset(val, id)
rb_defout = val;
}
-static int
-rb_dup(orig)
- int orig;
-{
- int fd;
-
- fd = dup(orig);
- if (fd < 0) {
- if (errno == EMFILE || errno == ENFILE) {
- rb_gc();
- fd = dup(orig);
- }
- if (fd < 0) {
- rb_sys_fail(0);
- }
- }
- return fd;
-}
-
static void
set_stdin(val, id, var)
VALUE val;
@@ -2152,8 +2152,6 @@ set_stdin(val, id, var)
VALUE *var;
{
OpenFile *fptr;
- int fd;
- char *mode;
if (val == *var) return;
if (TYPE(val) != T_FILE) {
@@ -2180,8 +2178,6 @@ set_outfile(val, var, orig, stdf)
{
OpenFile *fptr;
FILE *f;
- int fd;
- char *mode;
if (val == *var) return;
@@ -2247,7 +2243,6 @@ rb_io_s_new(argc, argv, klass)
VALUE *argv;
VALUE klass;
{
- OpenFile *fp;
NEWOBJ(io, struct RFile);
OBJSETUP(io, klass, T_FILE);
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb
new file mode 100644
index 0000000000..cbd4012773
--- /dev/null
+++ b/lib/irb/completion.rb
@@ -0,0 +1,47 @@
+
+require "readline"
+
+module IRB
+ module InputCompletion
+ ReservedWords = [
+ "BEGIN", "END",
+ "alias", "and",
+ "begin", "break",
+ "case", "class",
+ "def", "defined", "do",
+ "else", "elsif", "end", "ensure",
+ "false", "for",
+ "if", "in",
+ "module",
+ "next", "nil", "not",
+ "or",
+ "redo", "rescue", "retry", "return",
+ "self", "super",
+ "then", "true",
+ "undef", "unless", "until",
+ "when", "while",
+ "yield"
+ ]
+
+ CompletionProc = proc { |input|
+ case input
+ when /^([^.]+)\.([^.]*)$/
+ receiver = $1
+ message = $2
+ if eval("(local_variables|#{receiver}.type.constants).include?('#{receiver}')",
+ IRB.conf[:MAIN_CONTEXT].bind)
+ candidates = eval("#{receiver}.methods", IRB.conf[:MAIN_CONTEXT].bind)
+ else
+ candidates = []
+ end
+ candidates.grep(/^#{Regexp.quote(message)}/).collect{|e| receiver + "." + e}
+ else
+ candidates = eval("methods | private_methods | local_variables | type.constants",
+ IRB.conf[:MAIN_CONTEXT].bind)
+ (candidates|ReservedWords).grep(/^#{Regexp.quote(input)}/)
+ end
+ }
+ end
+end
+
+Readline.completion_proc = IRB::InputCompletion::CompletionProc
diff --git a/lib/irb/frame.rb b/lib/irb/frame.rb
new file mode 100644
index 0000000000..a2d7de3778
--- /dev/null
+++ b/lib/irb/frame.rb
@@ -0,0 +1,67 @@
+#
+# frame.rb -
+# $Release Version: 0.6$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#
+#
+
+require "e2mmap"
+
+module IRB
+ class Frame
+ extend Exception2MessageMapper
+ def_exception :FrameOverflow, "frame overflow"
+ def_exception :FrameUnderflow, "frame underflow"
+
+ INIT_STACK_TIMES = 3
+ CALL_STACK_OFFSET = 3
+
+ def initialize
+ @frames = [TOPLEVEL_BINDING] * INIT_STACK_TIMES
+ end
+
+ def trace_func(event, file, line, id, binding)
+ case event
+ when 'call', 'class'
+ @frames.push binding
+ when 'return', 'end'
+ @frames.pop
+ end
+ end
+
+ def top(n = 0)
+ bind = @frames[-(n + CALL_STACK_OFFSET)]
+ Fail FrameUnderflow unless bind
+ bind
+ end
+
+ def bottom(n = 0)
+ bind = @frames[n]
+ Fail FrameOverflow unless bind
+ bind
+ end
+
+ # singleton functions
+ def Frame.bottom(n = 0)
+ @backtrace.bottom(n)
+ end
+
+ def Frame.top(n = 0)
+ @backtrace.top(n)
+ end
+
+ def Frame.sender
+ eval "self", @backtrace.top
+ end
+
+ @backtrace = Frame.new
+ set_trace_func proc{|event, file, line, id, binding|
+ @backtrace.trace_func(event, file, line, id, binding)
+ }
+ end
+end
diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb
new file mode 100644
index 0000000000..19df0eb073
--- /dev/null
+++ b/lib/irb/input-method.rb
@@ -0,0 +1,118 @@
+#
+# input-method.rb - input methods using irb
+# $Release Version: 0.6$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+module IRB
+ #
+ # InputMethod
+ # StdioInputMethod
+ # FileInputMethod
+ # (ReadlineInputMethod)
+ #
+ STDIN_FILE_NAME = "(line)"
+ class InputMethod
+ @RCS_ID='-$Id$-'
+
+ def initialize(file = STDIN_FILE_NAME)
+ @file_name = file
+ end
+ attr :file_name
+
+ attr :prompt, true
+
+ def gets
+ IRB.fail NotImplementError, "gets"
+ end
+ public :gets
+
+ def readable_atfer_eof?
+ false
+ end
+ end
+
+ class StdioInputMethod < InputMethod
+ def initialize
+ super
+ @line_no = 0
+ @line = []
+ end
+
+ def gets
+ print @prompt
+ @line[@line_no += 1] = $stdin.gets
+ end
+
+ def eof?
+ $stdin.eof?
+ end
+
+ def readable_atfer_eof?
+ true
+ end
+
+ def line(line_no)
+ @line[line_no]
+ end
+ end
+
+ class FileInputMethod < InputMethod
+ def initialize(file)
+ super
+ @io = open(file)
+ end
+ attr :file_name
+
+ def eof?
+ @io.eof?
+ end
+
+ def gets
+ l = @io.gets
+ print @prompt, l
+ l
+ end
+ end
+
+ begin
+ require "readline"
+ class ReadlineInputMethod < InputMethod
+ include Readline
+ def initialize
+ super
+
+ @line_no = 0
+ @line = []
+ @eof = false
+ end
+
+ def gets
+ if l = readline(@prompt, true)
+ @line[@line_no += 1] = l + "\n"
+ else
+ @eof = true
+ l
+ end
+ end
+
+ def eof?
+ @eof
+ end
+
+ def readable_atfer_eof?
+ true
+ end
+
+ def line(line_no)
+ @line[line_no]
+ end
+ end
+ rescue LoadError
+ end
+end
diff --git a/lib/irb/loader.rb b/lib/irb/loader.rb
new file mode 100644
index 0000000000..83b10a55a0
--- /dev/null
+++ b/lib/irb/loader.rb
@@ -0,0 +1,118 @@
+#
+# irb-loader.rb -
+# $Release Version: 0.6$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+
+module IRB
+ class LoadAbort < GlobalExit;end
+
+ module Loader
+ @RCS_ID='-$Id$-'
+
+ alias ruby_load load
+ alias ruby_require require
+
+ def irb_load(file_name)
+ return ruby_load(file_name) unless IRB.conf[:USE_LOADER]
+
+ load_sub(file_name)
+ return true
+ end
+
+ def irb_require(file_name)
+ return ruby_require(file_name) unless IRB.conf[:USE_LOADER]
+
+ rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
+ return false if $".find{|f| f =~ rex}
+
+ case file_name
+ when /\.rb$/
+ begin
+ load_sub(file_name)
+ $".push file_name
+ return true
+ rescue LoadError
+ end
+ when /\.(so|o|sl)$/
+ return ruby_require(file_name)
+ end
+
+ begin
+ load_sub(f = file_name + ".rb")
+ $".push f
+ return true
+ rescue LoadError
+ return ruby_require(file_name)
+ end
+ end
+
+ def load_sub(fn)
+ if fn =~ /^#{Regexp.quote(File::Separator)}/
+ return false unless File.exist?(fn)
+ return irb_context.load_file(fn)
+ end
+
+ for path in $:
+ if File.exist?(f = File.join(path, fn))
+ return irb_context.load_file(f)
+ end
+ end
+ raise LoadError, "No such file to load -- #{file_name}"
+ end
+
+ alias load irb_load
+ alias require irb_require
+ end
+
+# class Context
+# def load_from(file_name)
+# io = FileInputMethod.new(file_name)
+# @irb.signal_status(:IN_LOAD) do
+# switch_io(io, file_name) do
+# eval_input
+# end
+# end
+# end
+# end
+
+ class Context
+ def load_file(path)
+ back_io = @io
+ back_path = @irb_path
+ back_name = @irb_name
+ back_scanner = @irb.scanner
+ begin
+ @io = FileInputMethod.new(path)
+ @irb_name = File.basename(path)
+ @irb_path = path
+ @irb.signal_status(:IN_LOAD) do
+ if back_io.kind_of?(FileInputMethod)
+ @irb.eval_input
+ else
+ begin
+ @irb.eval_input
+ rescue LoadAbort
+ print "load abort!!\n"
+ end
+ end
+ end
+ ensure
+ @io = back_io
+ @irb_name = back_name
+ @irb_path = back_path
+ @irb.scanner = back_scanner
+ end
+ end
+ end
+
+ module ExtendCommand
+ include Loader
+ end
+end
diff --git a/lib/irb/main.rb b/lib/irb/main.rb
new file mode 100644
index 0000000000..4c7dac240b
--- /dev/null
+++ b/lib/irb/main.rb
@@ -0,0 +1,867 @@
+#
+# main.rb - irb main module
+# $Release Version: 0.6 $
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+require "e2mmap"
+require "irb/ruby-lex"
+require "irb/input-method"
+require "irb/workspace-binding"
+
+STDOUT.sync = true
+
+module IRB
+ @RCS_ID='-$Id$-'
+
+ # exceptions
+ extend Exception2MessageMapper
+ def_exception :UnrecognizedSwitch, "Unrecognized switch: %s"
+ def_exception :NotImplementError, "Need to define `%s'"
+ def_exception :CantRetuenNormalMode, "Can't return normal mode."
+ def_exception :IllegalParameter, "Illegal parameter(%s)."
+ def_exception :IrbAlreadyDead, "Irb is already dead."
+ def_exception :IrbSwitchToCurrentThread, "Change to current thread."
+ def_exception :NoSuchJob, "No such job(%s)."
+ def_exception :CanNotGoMultiIrbMode, "Can't go multi irb mode."
+ def_exception :CanNotChangeBinding, "Can't change binding to (%s)."
+ def_exception :UndefinedPromptMode, "Undefined prompt mode(%s)."
+
+ class Abort < Exception;end
+
+ # initialize IRB and start TOP_LEVEL irb
+ def IRB.start(ap_path = nil)
+ $0 = File::basename(ap_path, ".rb") if ap_path
+
+ IRB.initialize(ap_path)
+ IRB.parse_opts
+ IRB.load_modules
+
+ bind = workspace_binding
+ main = eval("self", bind)
+
+ if @CONF[:SCRIPT]
+ irb = Irb.new(main, bind, @CONF[:SCRIPT])
+ else
+ irb = Irb.new(main, bind)
+ end
+
+ @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
+ @CONF[:MAIN_CONTEXT] = irb.context
+
+ trap("SIGINT") do
+ irb.signal_handle
+ end
+
+ catch(:IRB_EXIT) do
+ irb.eval_input
+ end
+ print "\n"
+ end
+
+ # initialize config
+ def IRB.initialize(ap_path)
+ IRB.init_config(ap_path)
+ IRB.run_config
+ end
+
+ #
+ # @CONF functions
+ #
+ @CONF = {}
+ # @CONF default setting
+ def IRB.init_config(ap_path)
+ # class instance variables
+ @TRACER_INITIALIZED = false
+ @MATHN_INITIALIZED = false
+
+ # default configurations
+ unless ap_path and @CONF[:AP_NAME]
+ ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb")
+ end
+ @CONF[:AP_NAME] = File::basename(ap_path, ".rb")
+
+ @CONF[:IRB_NAME] = "irb"
+ @CONF[:IRB_LIB_PATH] = File.dirname(__FILE__)
+
+ @CONF[:RC] = true
+ @CONF[:LOAD_MODULES] = []
+ @CONF[:IRB_RC] = nil
+
+ @CONF[:MATH_MODE] = false
+ @CONF[:USE_READLINE] = false unless defined?(ReadlineInputMethod)
+ @CONF[:INSPECT_MODE] = nil
+ @CONF[:USE_TRACER] = false
+ @CONF[:USE_LOADER] = false
+ @CONF[:IGNORE_SIGINT] = true
+ @CONF[:IGNORE_EOF] = false
+
+ @CONF[:BACK_TRACE_LIMIT] = 16
+
+ @CONF[:PROMPT] = {
+ :NULL => {
+ :PROMPT_I => nil,
+ :PROMPT_S => nil,
+ :PROMPT_C => nil,
+ :RETURN => "%s\n"
+ },
+ :DEFAULT => {
+ :PROMPT_I => "%N(%m):%03n:%i> ",
+ :PROMPT_S => "%N(%m):%03n:%i%l ",
+ :PROMPT_C => "%N(%m):%03n:%i* ",
+ :RETURN => "%s\n"
+ },
+ :SIMPLE => {
+ :PROMPT_I => ">> ",
+ :PROMPT_S => nil,
+ :PROMPT_C => "?> ",
+ :RETURN => "=> %s\n"
+ },
+ :INF_RUBY => {
+ :PROMPT_I => "%N(%m):%03n:%i> ",
+ :PROMPT_S => nil,
+ :PROMPT_C => nil,
+ :RETURN => "%s\n",
+ :AUTO_INDENT => true
+ },
+ :XMP => {
+ :PROMPT_I => nil,
+ :PROMPT_S => nil,
+ :PROMPT_C => nil,
+ :RETURN => " ==>%s\n"
+ }
+ }
+
+ @CONF[:PROMPT_MODE] = :DEFAULT
+ @CONF[:AUTO_INDENT] = false
+
+ @CONF[:CONTEXT_MODE] = 3
+ @CONF[:SINGLE_IRB] = false
+
+ @CONF[:DEBUG_LEVEL] = 1
+ @CONF[:VERBOSE] = true
+ end
+
+ # IRB version method
+ def IRB.version
+ if v = @CONF[:VERSION] then return v end
+
+ require "irb/version"
+ rv = @RELEASE_VERSION.sub(/\.0/, "")
+ @CONF[:VERSION] = format("irb %s(%s)", rv, @LAST_UPDATE_DATE)
+ end
+
+ def IRB.conf
+ @CONF
+ end
+
+ # option analyzing
+ def IRB.parse_opts
+ while opt = ARGV.shift
+ case opt
+ when "-f"
+ opt = ARGV.shift
+ @CONF[:RC] = false
+ when "-m"
+ @CONF[:MATH_MODE] = true
+ when "-d"
+ $DEBUG = true
+ when "-r"
+ opt = ARGV.shift
+ @CONF[:LOAD_MODULES].push opt if opt
+ when "--inspect"
+ @CONF[:INSPECT_MODE] = true
+ when "--noinspect"
+ @CONF[:INSPECT_MODE] = false
+ when "--readline"
+ @CONF[:USE_READLINE] = true
+ when "--noreadline"
+ @CONF[:USE_READLINE] = false
+ when "--prompt-mode", "--prompt"
+ prompt_mode = ARGV.shift.upcase.tr("-", "_").intern
+ IRB.fail(UndefinedPromptMode,
+ prompt_mode.id2name) unless @CONF[:PROMPT][prompt_mode]
+ @CONF[:PROMPT_MODE] = prompt_mode
+ when "--noprompt"
+ @CONF[:PROMPT_MODE] = :NULL
+ when "--inf-ruby-mode"
+ @CONF[:PROMPT_MODE] = :INF_RUBY
+ when "--sample-book-mode", "--simple-prompt"
+ @CONF[:PROMPT_MODE] = :SIMPLE
+ when "--tracer"
+ @CONF[:USE_TRACER] = true
+ when "--back-trace-limit"
+ @CONF[:BACK_TRACE_LIMIT] = ARGV.shift.to_i
+ when "--context-mode"
+ @CONF[:CONTEXT_MODE] = ARGV.shift.to_i
+ when "--single-irb"
+ @CONF[:SINGLE_IRB] = true
+ when "--irb_debug"
+ @CONF[:DEBUG_LEVEL] = ARGV.shift.to_i
+ when "-v", "--version"
+ print IRB.version, "\n"
+ exit(0)
+ when /^-/
+ IRB.fail UnrecognizedSwitch, opt
+ else
+ @CONF[:USE_READLINE] = false
+ @CONF[:SCRIPT] = opt
+ $0 = opt
+ break
+ end
+ end
+ end
+
+ # running config
+ def IRB.run_config
+ if @CONF[:RC]
+ rcs = []
+ rcs.push File.expand_path("~/.irbrc") if ENV.key?("HOME")
+ rcs.push ".irbrc"
+ rcs.push "irb.rc"
+ rcs.push "_irbrc"
+ rcs.push "$irbrc"
+ catch(:EXIT) do
+ for rc in rcs
+ begin
+ load rc
+ throw :EXIT
+ rescue LoadError, Errno::ENOENT
+ rescue
+ print "load error: #{rc}\n"
+ print $!.type, ": ", $!, "\n"
+ for err in $@[0, $@.size - 2]
+ print "\t", err, "\n"
+ end
+ throw :EXIT
+ end
+ end
+ end
+ end
+ end
+
+ # loading modules
+ def IRB.load_modules
+ for m in @CONF[:LOAD_MODULES]
+ begin
+ require m
+ rescue
+ print $@[0], ":", $!.type, ": ", $!, "\n"
+ end
+ end
+ end
+
+ # initialize tracing function
+ def IRB.initialize_tracer
+ unless @TRACER_INITIALIZED
+ require("tracer")
+ Tracer.verbose = false
+ Tracer.add_filter {
+ |event, file, line, id, binding|
+ File::dirname(file) != @CONF[:IRB_LIB_PATH]
+ }
+ @TRACER_INITIALIZED = true
+ end
+ end
+
+ # initialize mathn function
+ def IRB.initialize_mathn
+ unless @MATHN_INITIALIZED
+ require "mathn"
+ @MATHN_INITIALIZED = true
+ end
+ end
+
+ # initialize loader function
+ def IRB.initialize_loader
+ unless @LOADER_INITIALIZED
+ require "irb/loader"
+ @LOADER_INITIALIZED = true
+ end
+ end
+
+ def IRB.irb_exit(irb, ret)
+ throw :IRB_EXIT, ret
+ end
+
+ def IRB.irb_abort(irb, exception = Abort)
+ if defined? Thread
+ irb.context.thread.raise exception, "abort then interrupt!!"
+ else
+ raise exception, "abort then interrupt!!"
+ end
+ end
+
+ #
+ # irb interpriter main routine
+ #
+ class Irb
+ def initialize(main, bind, input_method = nil)
+ @context = Context.new(self, main, bind, input_method)
+ main.extend ExtendCommand
+ @signal_status = :IN_IRB
+
+ @scanner = RubyLex.new
+ @scanner.exception_on_syntax_error = false
+ end
+ attr :context
+ attr :scanner, true
+
+ def eval_input
+# @scanner = RubyLex.new
+ @scanner.set_input(@context.io) do
+ signal_status(:IN_INPUT) do
+ unless l = @context.io.gets
+ if @context.ignore_eof? and @context.io.readable_atfer_eof?
+ l = "\n"
+ if @context.verbose?
+ printf "Use \"exit\" to leave %s\n", @context.ap_name
+ end
+ end
+ end
+ l
+ end
+ end
+
+ @scanner.set_prompt do
+ |ltype, indent, continue, line_no|
+ if ltype
+ f = @context.prompt_s
+ elsif continue
+ f = @context.prompt_c
+ else @context.prompt_i
+ f = @context.prompt_i
+ end
+ f = "" unless f
+ @context.io.prompt = p = prompt(f, ltype, indent, line_no)
+ if @context.auto_indent_mode
+ unless ltype
+ ind = prompt(@context.prompt_i, ltype, indent, line_no).size +
+ indent * 2 - p.size
+ ind += 2 if continue
+ @context.io.prompt = p + " " * ind if ind > 0
+ end
+ end
+ end
+
+ @scanner.each_top_level_statement do
+ |line, line_no|
+ signal_status(:IN_EVAL) do
+ begin
+ trace_in do
+ @context._ = eval(line, @context.bind, @context.irb_path, line_no)
+# @context._ = irb_eval(line, @context.bind, @context.irb_path, line_no)
+ end
+
+ if @context.inspect?
+ printf @context.return_format, @context._.inspect
+ else
+ printf @context.return_format, @context._
+ end
+ rescue StandardError, ScriptError, Abort
+ $! = RuntimeError.new("unknown exception raised") unless $!
+ print $!.type, ": ", $!, "\n"
+ if $@[0] =~ /irb(2)?(\/.*|-.*|\.rb)?:/ && $!.type.to_s !~ /^IRB/
+ irb_bug = true
+ else
+ irb_bug = false
+ end
+
+ messages = []
+ lasts = []
+ levels = 0
+ for m in $@
+ if m !~ /irb2?(\/.*|-.*|\.rb)?:/ or irb_bug
+ if messages.size < @context.back_trace_limit
+ messages.push m
+ else
+ lasts.push m
+ if lasts.size > @context.back_trace_limit
+ lasts.shift
+ levels += 1
+ end
+ end
+ end
+ end
+ print messages.join("\n"), "\n"
+ unless lasts.empty?
+ printf "... %d levels...\n", levels if levels > 0
+ print lasts.join("\n")
+ end
+ print "Maybe IRB bug!!\n" if irb_bug
+ end
+ end
+ end
+ end
+
+# def irb_eval(line, bind, path, line_no)
+# id, str = catch(:IRB_TOPLEVEL_EVAL){
+# return eval(line, bind, path, line_no)
+# }
+# case id
+# when :EVAL_TOPLEVEL
+# eval(str, bind, "(irb_internal)", 1)
+# when :EVAL_CONTEXT
+# @context.instance_eval(str)
+# else
+# IRB.fail IllegalParameter
+# end
+# end
+
+ def signal_handle
+ unless @context.ignore_sigint?
+ print "\nabort!!\n" if @context.verbose?
+ exit
+ end
+
+ case @signal_status
+ when :IN_INPUT
+ print "^C\n"
+ @scanner.initialize_input
+ print @context.io.prompt
+ when :IN_EVAL
+ IRB.irb_abort(self)
+ when :IN_LOAD
+ IRB.irb_abort(self, LoadAbort)
+ when :IN_IRB
+ # ignore
+ else
+ # ignore
+ end
+ end
+
+ def signal_status(status)
+ return yield if @signal_status == :IN_LOAD
+
+ signal_status_back = @signal_status
+ @signal_status = status
+ begin
+ yield
+ ensure
+ @signal_status = signal_status_back
+ end
+ end
+
+ def trace_in
+ Tracer.on if @context.use_tracer?
+ begin
+ yield
+ ensure
+ Tracer.off if @context.use_tracer?
+ end
+ end
+
+ def prompt(prompt, ltype, indent, line_no)
+ p = prompt.dup
+ p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
+ case $2
+ when "N"
+ @context.irb_name
+ when "m"
+ @context.main.to_s
+ when "M"
+ @context.main.inspect
+ when "l"
+ ltype
+ when "i"
+ if $1
+ format("%" + $1 + "d", indent)
+ else
+ indent.to_s
+ end
+ when "n"
+ if $1
+ format("%" + $1 + "d", line_no)
+ else
+ line_no.to_s
+ end
+ when "%"
+ "%"
+ end
+ end
+ p
+ end
+
+ def inspect
+ ary = []
+ for iv in instance_variables
+ case iv
+ when "@signal_status"
+ ary.push format("%s=:%s", iv, @signal_status.id2name)
+ when "@context"
+ ary.push format("%s=%s", iv, eval(iv).__to_s__)
+ else
+ ary.push format("%s=%s", iv, eval(iv))
+ end
+ end
+ format("#<%s: %s>", type, ary.join(", "))
+ end
+ end
+
+ #
+ # irb context
+ #
+ class Context
+ #
+ # Arguments:
+ # input_method: nil -- stdin or readline
+ # String -- File
+ # other -- using this as InputMethod
+ #
+ def initialize(irb, main, bind, input_method = nil)
+ @irb = irb
+ @main = main
+ @bind = bind
+ @thread = Thread.current if defined? Thread
+ @irb_level = 0
+
+ # copy of default configuration
+ @ap_name = IRB.conf[:AP_NAME]
+ @rc = IRB.conf[:RC]
+ @load_modules = IRB.conf[:LOAD_MODULES]
+
+ self.math_mode = IRB.conf[:MATH_MODE]
+ @use_readline = IRB.conf[:USE_READLINE]
+ @inspect_mode = IRB.conf[:INSPECT_MODE]
+ @use_tracer = IRB.conf[:USE_TRACER]
+# @use_loader = IRB.conf[:USE_LOADER]
+
+ self.prompt_mode = IRB.conf[:PROMPT_MODE]
+
+ @ignore_sigint = IRB.conf[:IGNORE_SIGINT]
+ @ignore_eof = IRB.conf[:IGNORE_EOF]
+
+ @back_trace_limit = IRB.conf[:BACK_TRACE_LIMIT]
+
+ debug_level = IRB.conf[:DEBUG_LEVEL]
+ @verbose = IRB.conf[:VERBOSE]
+
+ @tracer_initialized = false
+
+ if IRB.conf[:SINGLE_IRB] or !defined?(JobManager)
+ @irb_name = IRB.conf[:IRB_NAME]
+ else
+ @irb_name = "irb#"+IRB.JobManager.n_jobs.to_s
+ end
+ @irb_path = "(" + @irb_name + ")"
+
+ case input_method
+ when nil
+ if (use_readline.nil? && IRB.conf[:PROMPT_MODE] != :INF_RUBY ||
+ use_readline?)
+ @io = ReadlineInputMethod.new
+ else
+ @io = StdioInputMethod.new
+ end
+ when String
+ @io = FileInputMethod.new(input_method)
+ @irb_name = File.basename(input_method)
+ @irb_path = input_method
+ else
+ @io = input_method
+ end
+ end
+
+ attr :bind, true
+ attr :main, true
+ attr :thread
+ attr :io, true
+
+ attr :_
+
+ attr :irb
+ attr :ap_name
+ attr :rc
+ attr :load_modules
+ attr :irb_name
+ attr :irb_path
+
+ attr :math_mode, true
+ attr :use_readline, true
+ attr :inspect_mode
+ attr :use_tracer
+# attr :use_loader
+
+ attr :debug_level
+ attr :verbose, true
+
+ attr :prompt_mode
+ attr :prompt_i, true
+ attr :prompt_s, true
+ attr :prompt_c, true
+ attr :auto_indent_mode, true
+ attr :return_format, true
+
+ attr :ignore_sigint, true
+ attr :ignore_eof, true
+
+ attr :back_trace_limit
+
+# alias use_loader? use_loader
+ alias use_tracer? use_tracer
+ alias use_readline? use_readline
+ alias rc? rc
+ alias math? math_mode
+ alias verbose? verbose
+ alias ignore_sigint? ignore_sigint
+ alias ignore_eof? ignore_eof
+
+ def _=(value)
+ @_ = value
+ eval "_ = IRB.conf[:MAIN_CONTEXT]._", @bind
+ end
+
+ def irb_name
+ if @irb_level == 0
+ @irb_name
+ elsif @irb_name =~ /#[0-9]*$/
+ @irb_name + "." + @irb_level.to_s
+ else
+ @irb_name + "#0." + @irb_level.to_s
+ end
+ end
+
+ def prompt_mode=(mode)
+ @prompt_mode = mode
+ pconf = IRB.conf[:PROMPT][mode]
+ @prompt_i = pconf[:PROMPT_I]
+ @prompt_s = pconf[:PROMPT_S]
+ @prompt_c = pconf[:PROMPT_C]
+ @return_format = pconf[:RETURN]
+ if ai = pconf.include?(:AUTO_INDENT)
+ @auto_indent_mode = ai
+ else
+ @auto_indent_mode = IRB.conf[:AUTO_INDENT]
+ end
+ end
+
+ def inspect?
+ @inspect_mode.nil? && !@math_mode or @inspect_mode
+ end
+
+ def file_input?
+ @io.type == FileInputMethod
+ end
+
+ def use_tracer=(opt)
+ if opt
+ IRB.initialize_tracer
+ unless @tracer_initialized
+ Tracer.set_get_line_procs(@irb_path) {
+ |line_no|
+ @io.line(line_no)
+ }
+ @tracer_initialized = true
+ end
+ elsif !opt && @use_tracer
+ Tracer.off
+ end
+ @use_tracer=opt
+ end
+
+ def use_loader
+ IRB.conf[:USE_LOADER]
+ end
+
+ def use_loader=(opt)
+ IRB.conf[:USE_LOADER] = opt
+ if opt
+ IRB.initialize_loader
+ end
+ print "Switch to load/require#{unless use_loader; ' non';end} trace mode.\n" if verbose?
+ opt
+ end
+
+ def inspect_mode=(opt)
+ if opt
+ @inspect_mode = opt
+ else
+ @inspect_mode = !@inspect_mode
+ end
+ print "Switch to#{unless @inspect_mode; ' non';end} inspect mode.\n" if verbose?
+ @inspect_mode
+ end
+
+ def math_mode=(opt)
+ if @math_mode == true && opt == false
+ IRB.fail CantRetuenNormalMode
+ return
+ end
+
+ @math_mode = opt
+ if math_mode
+ IRB.initialize_mathn
+ @main.instance_eval("include Math")
+ print "start math mode\n" if verbose?
+ end
+ end
+
+ def use_readline=(opt)
+ @use_readline = opt
+ print "use readline module\n" if @use_readline
+ end
+
+ def debug_level=(value)
+ @debug_level = value
+ RubyLex.debug_level = value
+ SLex.debug_level = value
+ end
+
+ def debug?
+ @debug_level > 0
+ end
+
+ def change_binding(*main)
+ back = [@bind, @main]
+ @bind = IRB.workspace_binding(*main)
+ unless main.empty?
+ @main = eval("self", @bind)
+ begin
+ @main.extend ExtendCommand
+ rescue
+ print "can't change binding to: ", @main.inspect, "\n"
+ @bind, @main = back
+ return nil
+ end
+ end
+ @irb_level += 1
+ begin
+ catch(:SU_EXIT) do
+ @irb.eval_input
+ end
+ ensure
+ @irb_level -= 1
+ @bind, @main = back
+ end
+ end
+
+ alias __exit__ exit
+ def exit(ret = 0)
+ if @irb_level == 0
+ IRB.irb_exit(@irb, ret)
+ else
+ throw :SU_EXIT, ret
+ end
+ end
+
+ NOPRINTING_IVARS = ["@_"]
+ NO_INSPECTING_IVARS = ["@irb", "@io"]
+ IDNAME_IVARS = ["@prompt_mode"]
+
+ alias __inspect__ inspect
+ def inspect
+ array = []
+ for ivar in instance_variables.sort{|e1, e2| e1 <=> e2}
+ name = ivar.sub(/^@(.*)$/){$1}
+ val = instance_eval(ivar)
+ case ivar
+ when *NOPRINTING_IVARS
+ next
+ when *NO_INSPECTING_IVARS
+ array.push format("conf.%s=%s", name, val.to_s)
+ when *IDNAME_IVARS
+ array.push format("conf.%s=:%s", name, val.id2name)
+ else
+ array.push format("conf.%s=%s", name, val.inspect)
+ end
+ end
+ array.join("\n")
+ end
+ alias __to_s__ to_s
+ alias to_s inspect
+
+ end
+
+ #
+ # IRB extended command
+ #
+ module Loader; end
+ module ExtendCommand
+ include Loader
+
+ alias irb_exit_org exit
+ def irb_exit(ret = 0)
+ irb_context.exit(ret)
+ end
+ alias exit irb_exit
+ alias quit irb_exit
+
+ alias irb_fork fork
+ def fork(&block)
+ unless irb_fork
+ eval "alias exit irb_exit_org"
+ instance_eval "alias exit irb_exit_org"
+ if iterator?
+ yield
+ exit
+ end
+ end
+ end
+
+ def irb_change_binding(*main)
+ irb_context.change_binding(*main)
+ end
+ alias cb irb_change_binding
+
+ def irb_source(file)
+ irb_context.source(file)
+ end
+ alias source irb_source
+
+ def irb(*obj)
+ require "irb/multi-irb"
+ IRB.irb(nil, *obj)
+ end
+
+ def irb_context
+ IRB.conf[:MAIN_CONTEXT]
+ end
+ alias conf irb_context
+
+ def irb_jobs
+ require "irb/multi-irb"
+ IRB.JobManager
+ end
+ alias jobs irb_jobs
+
+ def irb_fg(key)
+ require "irb/multi-irb"
+ IRB.JobManager.switch(key)
+ end
+ alias fg irb_fg
+
+ def irb_kill(*keys)
+ require "irb/multi-irb"
+ IRB.JobManager.kill(*keys)
+ end
+ alias kill irb_kill
+ end
+
+ # Singleton method
+ def @CONF.inspect
+ IRB.version unless self[:VERSION]
+
+ array = []
+ for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
+ case k
+ when :MAIN_CONTEXT
+ next
+ when :PROMPT
+ s = v.collect{
+ |kk, vv|
+ ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
+ format(":%s=>{%s}", kk.id2name, ss.join(", "))
+ }
+ array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
+ else
+ array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
+ end
+ end
+ array.join("\n")
+ end
+end
diff --git a/lib/irb/multi-irb.rb b/lib/irb/multi-irb.rb
new file mode 100644
index 0000000000..39dbcbae3c
--- /dev/null
+++ b/lib/irb/multi-irb.rb
@@ -0,0 +1,212 @@
+#
+# multi-irb.rb - multiple irb module
+# $Release Version: 0.6$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+IRB.fail CanNotGoMultiIrbMode unless defined?(Thread)
+require "thread"
+
+module IRB
+ # job management class
+ class JobManager
+ @RCS_ID='-$Id$-'
+
+ def initialize
+ # @jobs = [[thread, irb],...]
+ @jobs = []
+ @current_job = nil
+ end
+
+ attr :current_job, true
+
+ def n_jobs
+ @jobs.size
+ end
+
+ def thread(key)
+ th, irb = search(key)
+ irb
+ end
+
+ def irb(key)
+ th, irb = search(key)
+ irb
+ end
+
+ def main_thread
+ @jobs[0][0]
+ end
+
+ def main_irb
+ @jobs[0][1]
+ end
+
+ def insert(irb)
+ @jobs.push [Thread.current, irb]
+ end
+
+ def switch(key)
+ th, irb = search(key)
+ IRB.fail IrbAlreadyDead unless th.alive?
+ IRB.fail IrbSwitchToCurrentThread if th == Thread.current
+ @current_job = irb
+ th.run
+ Thread.stop
+ @current_job = irb(Thread.current)
+ end
+
+ def kill(*keys)
+ for key in keys
+ th, irb = search(key)
+ IRB.fail IrbAlreadyDead unless th.alive?
+ th.exit
+ end
+ end
+
+ def search(key)
+ case key
+ when Integer
+ @jobs[key]
+ when Irb
+ @jobs.find{|k, v| v.equal?(irb)}
+ when Thread
+ @jobs.assoc(key)
+ else
+ assoc = @jobs.find{|k, v| v.context.main.equal?(key)}
+ IRB.fail NoSuchJob, key if assoc.nil?
+ assoc
+ end
+ end
+
+ def delete(key)
+ case key
+ when Integer
+ IRB.fail NoSuchJob, key unless @jobs[key]
+ @jobs[key] = nil
+ else
+ catch (:EXISTS) do
+ @jobs.each_index do
+ |i|
+ if @jobs[i] and (@jobs[i][0] == key ||
+ @jobs[i][1] == key ||
+ @jobs[i][1].context.main.equal?(key))
+ @jobs[i] = nil
+ throw :EXISTS
+ end
+ end
+ IRB.fail NoSuchJob, key
+ end
+ end
+ until assoc = @jobs.pop; end unless @jobs.empty?
+ @jobs.push assoc
+ end
+
+ def inspect
+ ary = []
+ @jobs.each_index do
+ |i|
+ th, irb = @jobs[i]
+ next if th.nil?
+
+ if th.alive?
+ if th.stop?
+ t_status = "stop"
+ else
+ t_status = "running"
+ end
+ else
+ t_status = "exited"
+ end
+ ary.push format("#%d->%s on %s (%s: %s)",
+ i,
+ irb.context.irb_name,
+ irb.context.main,
+ th,
+ t_status)
+ end
+ ary.join("\n")
+ end
+ end
+
+ @JobManager = JobManager.new
+
+ def IRB.JobManager
+ @JobManager
+ end
+
+ # invoke multiple irb
+ def IRB.irb(file = nil, *main)
+ workspace = IRB.workspace_binding(*main)
+ if main.empty?
+ main = eval("self", workspace)
+ else
+ main = main[0]
+ end
+ parent_thread = Thread.current
+ Thread.start do
+ begin
+ irb = Irb.new(main, workspace, file)
+ rescue
+ print "Subirb can't start with context(self): ", main.inspect, "\n"
+ print "return to main irb\n"
+ Thread.pass
+ Thread.main.wakeup
+ Thread.exit
+ end
+ @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
+ @JobManager.insert(irb)
+ begin
+ system_exit = false
+ catch(:IRB_EXIT) do
+ irb.eval_input
+ end
+ rescue SystemExit
+ system_exit = true
+ raise
+ #fail
+ ensure
+ unless system_exit
+ @JobManager.delete(irb)
+ if parent_thread.alive?
+ @JobManager.current_job = @JobManager.irb(parent_thread)
+ parent_thread.run
+ else
+ @JobManager.current_job = @JobManager.main_irb
+ @JobManager.main_thread.run
+ end
+ end
+ end
+ end
+ Thread.stop
+ @JobManager.current_job = @JobManager.irb(Thread.current)
+ end
+
+ class Context
+ def _=(value)
+ @_ = value
+ eval "_ = IRB.JobManager.irb(Thread.current).context._", @bind
+ end
+ end
+
+ module ExtendCommand
+ def irb_context
+ IRB.JobManager.irb(Thread.current).context
+ end
+ alias conf irb_context
+ end
+
+ @CONF[:SINGLE_IRB_MODE] = false
+ @JobManager.insert(@CONF[:MAIN_CONTEXT].irb)
+ @JobManager.current_job = @CONF[:MAIN_CONTEXT].irb
+
+ trap("SIGINT") do
+ @JobManager.current_job.signal_handle
+ end
+
+end
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
new file mode 100644
index 0000000000..e66ba8879e
--- /dev/null
+++ b/lib/irb/ruby-lex.rb
@@ -0,0 +1,955 @@
+#
+# ruby-lex.rb - ruby lexcal analizer
+# $Release Version: 0.6$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+
+require "e2mmap"
+require "irb/slex"
+require "irb/ruby-token"
+
+class RubyLex
+ @RCS_ID='-$Id$-'
+
+ extend Exception2MessageMapper
+ def_exception(:AlreadyDefinedToken, "Already defined token(%s)")
+ def_exception(:TkReading2TokenNoKey, "key nothing(key='%s')")
+ def_exception(:TkSymbol2TokenNoKey, "key nothing(key='%s')")
+ def_exception(:TkReading2TokenDuplicateError,
+ "key duplicate(token_n='%s', key='%s')")
+ def_exception(:SyntaxError, "%s")
+
+ include RubyToken
+
+ class << self
+ attr :debug_level, TRUE
+ def debug?
+ @debug_level > 0
+ end
+ end
+ @debug_level = 0
+
+ def initialize
+ lex_init
+ set_input(STDIN)
+
+ @seek = 0
+ @exp_line_no = @line_no = 1
+ @base_char_no = 0
+ @char_no = 0
+ @rests = []
+ @readed = []
+ @here_readed = []
+
+ @indent = 0
+
+ @skip_space = false
+ @readed_auto_clean_up = false
+ @exception_on_syntax_error = true
+ end
+
+ attr :skip_space, true
+ attr :readed_auto_clean_up, true
+ attr :exception_on_syntax_error, true
+
+ attr :seek
+ attr :char_no
+ attr :line_no
+ attr :indent
+
+ # io functions
+ def set_input(io, p = nil)
+ @io = io
+ if p.kind_of?(Proc)
+ @input = p
+ elsif iterator?
+ @input = proc
+ else
+ @input = proc{@io.gets}
+ end
+ end
+
+ def get_readed
+ if idx = @readed.reverse.index("\n")
+ @base_char_no = idx
+ else
+ @base_char_no += @readed.size
+ end
+
+ readed = @readed.join("")
+ @readed = []
+ readed
+ end
+
+ def getc
+ while @rests.empty?
+ return nil unless buf_input
+ end
+ c = @rests.shift
+ if @here_header
+ @here_readed.push c
+ else
+ @readed.push c
+ end
+ @seek += 1
+ if c == "\n"
+ @line_no += 1
+ @char_no = 0
+ else
+ @char_no += 1
+ end
+ c
+ end
+
+ def gets
+ l = ""
+ while c = getc
+ l.concat c
+ break if c == "\n"
+ end
+ l
+ end
+
+ def eof?
+ @io.eof?
+ end
+
+ def getc_of_rests
+ if @rests.empty?
+ nil
+ else
+ getc
+ end
+ end
+
+ def ungetc(c = nil)
+ if @here_readed.empty?
+ c2 = @readed.pop
+ else
+ c2 = @here_readed.pop
+ end
+ c = c2 unless c
+ @rests.unshift c #c =
+ @seek -= 1
+ if c == "\n"
+ @line_no -= 1
+ if idx = @readed.reverse.index("\n")
+ @char_no = @readed.size - idx
+ else
+ @char_no = @base_char_no + @readed.size
+ end
+ else
+ @char_no -= 1
+ end
+ end
+
+ def peek_equal?(str)
+ chrs = str.split(//)
+ until @rests.size >= chrs.size
+ return false unless buf_input
+ end
+ @rests[0, chrs.size] == chrs
+ end
+
+ def peek_match?(regexp)
+ while @rests.empty?
+ return false unless buf_input
+ end
+ regexp =~ @rests.join("")
+ end
+
+ def peek(i = 0)
+ while @rests.size <= i
+ return nil unless buf_input
+ end
+ @rests[i]
+ end
+
+ def buf_input
+ prompt
+ line = @input.call
+ return nil unless line
+ @rests.concat line.split(//)
+ true
+ end
+ private :buf_input
+
+ def set_prompt(p = proc)
+ if p.kind_of?(Proc)
+ @prompt = p
+ else
+ @prompt = proc{print p}
+ end
+ end
+
+ def prompt
+ if @prompt
+ @prompt.call(@ltype, @indent, @continue, @line_no)
+ end
+ end
+
+ def initialize_input
+ @ltype = nil
+ @quoted = nil
+ @indent = 0
+ @lex_state = EXPR_BEG
+ @space_seen = false
+ @here_header = false
+
+ prompt
+ @continue = FALSE
+
+ @line = ""
+ @exp_line_no = @line_no
+ end
+
+ def each_top_level_statement
+ initialize_input
+ loop do
+ @continue = FALSE
+ prompt
+ unless l = lex
+ break if @line == ''
+ else
+ # p l
+ @line.concat l
+ if @ltype or @continue or @indent > 0
+ next
+ end
+ end
+ if @line != "\n"
+ yield @line, @exp_line_no
+ end
+ break unless l
+ @line = ''
+ @exp_line_no = @line_no
+
+ @indent = 0
+ prompt
+ end
+ end
+
+ def lex
+ until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) &&
+ !@continue or
+ tk.nil?)
+ # p tk
+ # p self
+ end
+ line = get_readed
+ # print self.inspect
+ if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil?
+ nil
+ else
+ line
+ end
+ end
+
+ def token
+ # require "tracer"
+ # Tracer.on
+ @prev_seek = @seek
+ @prev_line_no = @line_no
+ @prev_char_no = @char_no
+ begin
+ begin
+ tk = @OP.match(self)
+ @space_seen = tk.kind_of?(TkSPACE)
+ rescue SyntaxError
+ abort if @exception_on_syntax_error
+ tk = TkError.new(@seek, @line_no, @char_no)
+ end
+ end while @skip_space and tk.kind_of?(TkSPACE)
+ if @readed_auto_clean_up
+ get_readed
+ end
+ # Tracer.off
+ tk
+ end
+
+ ENINDENT_CLAUSE = [
+ "case", "class", "def", "do", "for", "if",
+ "module", "unless", "until", "while", "begin" #, "when"
+ ]
+ DEINDENT_CLAUSE = ["end" #, "when"
+ ]
+
+ PERCENT_LTYPE = {
+ "q" => "\'",
+ "Q" => "\"",
+ "x" => "\`",
+ "r" => "\/",
+ "w" => "]"
+ }
+
+ PERCENT_PAREN = {
+ "{" => "}",
+ "[" => "]",
+ "<" => ">",
+ "(" => ")"
+ }
+
+ Ltype2Token = {
+ "\'" => TkSTRING,
+ "\"" => TkSTRING,
+ "\`" => TkXSTRING,
+ "\/" => TkREGEXP,
+ "]" => TkDSTRING
+ }
+ DLtype2Token = {
+ "\"" => TkDSTRING,
+ "\`" => TkDXSTRING,
+ "\/" => TkDREGEXP,
+ }
+
+ def lex_init()
+ @OP = SLex.new
+ @OP.def_rules("\0", "\004", "\032") do
+ Token(TkEND_OF_SCRIPT)
+ end
+
+ @OP.def_rules(" ", "\t", "\f", "\r", "\13") do
+ @space_seen = TRUE
+ while getc =~ /[ \t\f\r\13]/; end
+ ungetc
+ Token(TkSPACE)
+ end
+
+ @OP.def_rule("#") do
+ |op, io|
+ identify_comment
+ end
+
+ @OP.def_rule("=begin", proc{@prev_char_no == 0 && peek(0) =~ /\s/}) do
+ |op, io|
+ @ltype = "="
+ until getc == "\n"; end
+ until peek_equal?("=end") && peek(4) =~ /\s/
+ until getc == "\n"; end
+ end
+ getc; getc; getc; getc
+ @ltype = nil
+ Token(TkRD_COMMENT)
+ end
+
+ @OP.def_rule("\n") do
+ print "\\n\n" if RubyLex.debug?
+ case @lex_state
+ when EXPR_BEG, EXPR_FNAME, EXPR_DOT
+ @continue = TRUE
+ else
+ @continue = FALSE
+ @lex_state = EXPR_BEG
+ end
+ @here_header = false
+ @here_readed = []
+ Token(TkNL)
+ end
+
+ @OP.def_rules("*", "**",
+ "!", "!=", "!~",
+ "=", "==", "===",
+ "=~", "<=>",
+ "<", "<=",
+ ">", ">=", ">>") do
+ |op, io|
+ @lex_state = EXPR_BEG
+ Token(op)
+ end
+
+ @OP.def_rules("<<") do
+ |op, io|
+ if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
+ (@lex_state != EXPR_ARG || @space_seen)
+ c = peek(0)
+ if /\S/ =~ c && (/["'`]/ =~ c || /[\w_]/ =~ c)
+ tk = identify_here_document;
+ end
+ else
+ tk = Token(op)
+ end
+ tk
+ end
+
+ @OP.def_rules("'", '"') do
+ |op, io|
+ identify_string(op)
+ end
+
+ @OP.def_rules("`") do
+ |op, io|
+ if @lex_state == EXPR_FNAME
+ Token(op)
+ else
+ identify_string(op)
+ end
+ end
+
+ @OP.def_rules('?') do
+ |op, io|
+ if @lex_state == EXPR_END
+ @lex_state = EXPR_BEG
+ Token(TkQUESTION)
+ else
+ ch = getc
+ if @lex_state == EXPR_ARG && ch !~ /\s/
+ ungetc
+ @lex_state = EXPR_BEG;
+ Token(TkQUESTION)
+ else
+ if (ch == '\\')
+ read_escape
+ end
+ @lex_state = EXPR_END
+ Token(TkINTEGER)
+ end
+ end
+ end
+
+ @OP.def_rules("&", "&&", "|", "||") do
+ |op, io|
+ @lex_state = EXPR_BEG
+ Token(op)
+ end
+
+ @OP.def_rules("+=", "-=", "*=", "**=",
+ "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do
+ |op, io|
+ @lex_state = EXPR_BEG
+ op =~ /^(.*)=$/
+ Token(TkOPASGN, $1)
+ end
+
+ @OP.def_rule("+@", proc{@lex_state == EXPR_FNAME}) do
+ Token(TkUPLUS)
+ end
+
+ @OP.def_rule("-@", proc{@lex_state == EXPR_FNAME}) do
+ Token(TkUMINUS)
+ end
+
+ @OP.def_rules("+", "-") do
+ |op, io|
+ catch(:RET) do
+ if @lex_state == EXPR_ARG
+ if @space_seen and peek(0) =~ /[0-9]/
+ throw :RET, identify_number
+ else
+ @lex_state = EXPR_BEG
+ end
+ elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/
+ throw :RET, identify_number
+ else
+ @lex_state = EXPR_BEG
+ end
+ Token(op)
+ end
+ end
+
+ @OP.def_rule(".") do
+ @lex_state = EXPR_BEG
+ if peek(0) =~ /[0-9]/
+ ungetc
+ identify_number
+ else
+ # for obj.if
+ @lex_state = EXPR_DOT
+ Token(TkDOT)
+ end
+ end
+
+ @OP.def_rules("..", "...") do
+ |op, io|
+ @lex_state = EXPR_BEG
+ Token(op)
+ end
+
+ lex_int2
+ end
+
+ def lex_int2
+ @OP.def_rules("]", "}", ")") do
+ |op, io|
+ @lex_state = EXPR_END
+ @indent -= 1
+ Token(op)
+ end
+
+ @OP.def_rule(":") do
+ if @lex_state == EXPR_END || peek(0) =~ /\s/
+ @lex_state = EXPR_BEG
+ Token(TkCOLON)
+ else
+ @lex_state = EXPR_FNAME;
+ Token(TkSYMBEG)
+ end
+ end
+
+ @OP.def_rule("::") do
+# p @lex_state.id2name, @space_seen
+ if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen
+ @lex_state = EXPR_BEG
+ Token(TkCOLON3)
+ else
+ @lex_state = EXPR_DOT
+ Token(TkCOLON2)
+ end
+ end
+
+ @OP.def_rule("/") do
+ |op, io|
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+ identify_string(op)
+ elsif peek(0) == '='
+ getc
+ @lex_state = EXPR_BEG
+ Token(TkOPASGN, :/) #/)
+ elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
+ identify_string(op)
+ else
+ @lex_state = EXPR_BEG
+ Token("/") #/)
+ end
+ end
+
+ @OP.def_rules("^") do
+ @lex_state = EXPR_BEG
+ Token("^")
+ end
+
+ # @OP.def_rules("^=") do
+ # @lex_state = EXPR_BEG
+ # Token(OP_ASGN, :^)
+ # end
+
+ @OP.def_rules(",", ";") do
+ |op, io|
+ @lex_state = EXPR_BEG
+ Token(op)
+ end
+
+ @OP.def_rule("~") do
+ @lex_state = EXPR_BEG
+ Token("~")
+ end
+
+ @OP.def_rule("~@", proc{@lex_state = EXPR_FNAME}) do
+ @lex_state = EXPR_BEG
+ Token("~")
+ end
+
+ @OP.def_rule("(") do
+ @indent += 1
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+ @lex_state = EXPR_BEG
+ Token(TkfLPAREN)
+ else
+ @lex_state = EXPR_BEG
+ Token(TkLPAREN)
+ end
+ end
+
+ @OP.def_rule("[]", proc{@lex_state == EXPR_FNAME}) do
+ Token("[]")
+ end
+
+ @OP.def_rule("[]=", proc{@lex_state == EXPR_FNAME}) do
+ Token("[]=")
+ end
+
+ @OP.def_rule("[") do
+ @indent += 1
+ if @lex_state == EXPR_FNAME
+ Token(TkfLBRACK)
+ else
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+ t = Token(TkLBRACK)
+ elsif @lex_state == EXPR_ARG && @space_seen
+ t = Token(TkLBRACK)
+ else
+ t = Token(TkfLBRACK)
+ end
+ @lex_state = EXPR_BEG
+ t
+ end
+ end
+
+ @OP.def_rule("{") do
+ @indent += 1
+ if @lex_state != EXPR_END && @lex_state != EXPR_ARG
+ t = Token(TkLBRACE)
+ else
+ t = Token(TkfLBRACE)
+ end
+ @lex_state = EXPR_BEG
+ t
+ end
+
+ @OP.def_rule('\\') do
+ if getc == "\n"
+ @space_seen = true
+ @continue = true
+ Token(TkSPACE)
+ else
+ ungetc
+ Token("\\")
+ end
+ end
+
+ @OP.def_rule('%') do
+ |op, io|
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+ identify_quotation
+ elsif peek(0) == '='
+ getc
+ Token(OP_ASGIN, "%")
+ elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/
+ identify_quotation
+ else
+ @lex_state = EXPR_BEG
+ Token("%") #))
+ end
+ end
+
+ @OP.def_rule('$') do
+ identify_gvar
+ end
+
+ @OP.def_rule('@') do
+ if peek(0) =~ /[\w_]/
+ ungetc
+ identify_identifier
+ else
+ Token("@")
+ end
+ end
+
+ # @OP.def_rule("def", proc{|op, io| /\s/ =~ io.peek(0)}) do
+ # |op, io|
+ # @indent += 1
+ # @lex_state = EXPR_FNAME
+ # # @lex_state = EXPR_END
+ # # until @rests[0] == "\n" or @rests[0] == ";"
+ # # rests.shift
+ # # end
+ # end
+
+ @OP.def_rule("") do
+ |op, io|
+ printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug?
+ if peek(0) =~ /[0-9]/
+ t = identify_number
+ elsif peek(0) =~ /[\w_]/
+ t = identify_identifier
+ end
+ printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug?
+ t
+ end
+
+ p @OP if RubyLex.debug?
+ end
+
+ def identify_gvar
+ @lex_state = EXPR_END
+
+ case ch = getc
+ when /[~_*$?!@/\\;,=:<>".]/ #"
+ Token(TkGVAR, "$" + ch)
+ when "-"
+ Token(TkGVAR, "$-" + getc)
+ when "&", "`", "'", "+"
+ Token(TkBACK_REF, "$"+ch)
+ when /[1-9]/
+ while getc =~ /[0-9]/; end
+ ungetc
+ Token(TkNTH_REF)
+ when /\w/
+ ungetc
+ ungetc
+ identify_identifier
+ else
+ ungetc
+ Token("$")
+ end
+ end
+
+ def identify_identifier
+ token = ""
+ token.concat getc if peek(0) =~ /[$@]/
+ while (ch = getc) =~ /\w|_/
+ print ":", ch, ":" if RubyLex.debug?
+ token.concat ch
+ end
+ ungetc
+
+ if ch == "!" or ch == "?"
+ token.concat getc
+ end
+ # fix token
+
+ case token
+ when /^\$/
+ return Token(TkGVAR, token)
+ when /^\@/
+ @lex_state = EXPR_END
+ return Token(TkIVAR, token)
+ end
+
+ if @lex_state != EXPR_DOT
+ print token, "\n" if RubyLex.debug?
+
+ token_c, *trans = TkReading2Token[token]
+ if token_c
+ # reserved word?
+
+ if (@lex_state != EXPR_BEG &&
+ @lex_state != EXPR_FNAME &&
+ trans[1])
+ # modifiers
+ token_c = TkSymbol2Token[trans[1]]
+ @lex_state = trans[0]
+ else
+ if @lex_state != EXPR_FNAME
+ if ENINDENT_CLAUSE.include?(token)
+ @indent += 1
+ elsif DEINDENT_CLAUSE.include?(token)
+ @indent -= 1
+ end
+ @lex_state = trans[0]
+ else
+ @lex_state = EXPR_END
+ end
+ end
+ return Token(token_c, token)
+ end
+ end
+
+ if @lex_state == EXPR_FNAME
+ @lex_state = EXPR_END
+ if peek(0) == '='
+ token.concat getc
+ end
+ elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
+ @lex_state = EXPR_ARG
+ else
+ @lex_state = EXPR_END
+ end
+
+ if token[0, 1] =~ /[A-Z]/
+ return Token(TkCONSTANT, token)
+ elsif token[token.size - 1, 1] =~ /[!?]/
+ return Token(TkFID, token)
+ else
+ return Token(TkIDENTIFIER, token)
+ end
+ end
+
+ def identify_here_document
+ ch = getc
+ if lt = PERCENT_LTYPE[ch]
+ quoted = ""
+ while (c = getc) && c != lt
+ quoted.concat c
+ end
+ else
+ lt = '"'
+ quoted = ch.dup
+ while (c = getc) && c =~ /\w/
+ quoted.concat c
+ end
+ ungetc
+ end
+
+ ltback, @ltype = @ltype, lt
+ reserve = []
+ while ch = getc
+ reserve.push ch
+ if ch == "\\"
+ reserve.push ch = getc
+ elsif ch == "\n"
+ break
+ end
+ end
+
+ @here_header = false
+ while (l = gets.chomp) && l != quoted
+ end
+
+ @here_header = true
+ @here_readed.concat reserve
+ while ch = reserve.pop
+ ungetc ch
+ end
+
+ @ltype = ltback
+ @lex_state = EXPR_END
+ Token(Ltype2Token[lt])
+ end
+
+ def identify_quotation
+ ch = getc
+ if lt = PERCENT_LTYPE[ch]
+ ch = getc
+ elsif ch =~ /\W/
+ lt = "\""
+ else
+ RubyLex.fail SyntaxError, "unknown type of %string"
+ end
+# if ch !~ /\W/
+# ungetc
+# next
+# end
+ #@ltype = lt
+ @quoted = ch unless @quoted = PERCENT_PAREN[ch]
+ identify_string(lt, @quoted)
+ end
+
+ def identify_number
+ @lex_state = EXPR_END
+
+ if ch = getc
+ if peek(0) == "x"
+ ch = getc
+ match = /[0-9a-f_]/
+ else
+ match = /[0-7_]/
+ end
+ while ch = getc
+ if ch !~ match
+ ungetc
+ break
+ end
+ end
+ return Token(TkINTEGER)
+ end
+
+ type = TkINTEGER
+ allow_point = TRUE
+ allow_e = TRUE
+ while ch = getc
+ case ch
+ when /[0-9_]/
+ when allow_point && "."
+ type = TkFLOAT
+ if peek(0) !~ /[0-9]/
+ ungetc
+ break
+ end
+ allow_point = false
+ when allow_e && "e", allow_e && "E"
+ type = TkFLOAT
+ if peek(0) =~ /[+-]/
+ getc
+ end
+ allow_e = false
+ allow_point = false
+ else
+ ungetc
+ break
+ end
+ end
+ Token(type)
+ end
+
+ def identify_string(ltype, quoted = ltype)
+ @ltype = ltype
+ @quoted = quoted
+ subtype = nil
+ begin
+ while ch = getc
+ if @quoted == ch
+ break
+ elsif @ltype != "'" && @ltype != "]" and ch == "#"
+ subtype = true
+ elsif ch == '\\' #'
+ read_escape
+ end
+ end
+ if @ltype == "/"
+ if peek(0) =~ /i|o|n|e|s/
+ getc
+ end
+ end
+ if subtype
+ Token(DLtype2Token[ltype])
+ else
+ Token(Ltype2Token[ltype])
+ end
+ ensure
+ @ltype = nil
+ @quoted = nil
+ @lex_state = EXPR_END
+ end
+ end
+
+ def identify_comment
+ @ltype = "#"
+
+ while ch = getc
+ if ch == "\\" #"
+ read_escape
+ end
+ if ch == "\n"
+ @ltype = nil
+ ungetc
+ break
+ end
+ end
+ return Token(TkCOMMENT)
+ end
+
+ def read_escape
+ case ch = getc
+ when "\n", "\r", "\f"
+ when "\\", "n", "t", "r", "f", "v", "a", "e", "b" #"
+ when /[0-7]/
+ ungetc ch
+ 3.times do
+ case ch = getc
+ when /[0-7]/
+ when nil
+ break
+ else
+ ungetc
+ break
+ end
+ end
+
+ when "x"
+ 2.times do
+ case ch = getc
+ when /[0-9a-fA-F]/
+ when nil
+ break
+ else
+ ungetc
+ break
+ end
+ end
+
+ when "M"
+ if (ch = getc) != '-'
+ ungetc
+ else
+ if (ch = getc) == "\\" #"
+ read_escape(chrs)
+ end
+ end
+
+ when "C", "c", "^"
+ if ch == "C" and (ch = getc) != "-"
+ ungetc
+ elsif (ch = getc) == "\\" #"
+ read_escape(chrs)
+ end
+ else
+ # other characters
+ end
+ end
+end
diff --git a/lib/irb/ruby-token.rb b/lib/irb/ruby-token.rb
new file mode 100644
index 0000000000..1532dc78eb
--- /dev/null
+++ b/lib/irb/ruby-token.rb
@@ -0,0 +1,266 @@
+#
+# ruby-token.rb - ruby tokens
+# $Release Version: 0.6$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+module RubyToken
+ EXPR_BEG = :EXPR_BEG
+ EXPR_MID = :EXPR_MID
+ EXPR_END = :EXPR_END
+ EXPR_ARG = :EXPR_ARG
+ EXPR_FNAME = :EXPR_FNAME
+ EXPR_DOT = :EXPR_DOT
+ EXPR_CLASS = :EXPR_CLASS
+
+ class Token
+ def initialize(seek, line_no, char_no)
+ @seek = seek
+ @line_no = line_no
+ @char_no = char_no
+ end
+ attr :seek
+ attr :line_no
+ attr :char_no
+ end
+
+ class TkNode < Token
+ def initialize(seek, line_no, char_no)
+ super
+ end
+ attr :node
+ end
+
+ class TkId < Token
+ def initialize(seek, line_no, char_no, name)
+ super(seek, line_no, char_no)
+ @name = name
+ end
+ attr :name
+ end
+
+ class TkVal < Token
+ def initialize(seek, line_no, char_no, value = nil)
+ super(seek, line_no, char_no)
+ @value = value
+ end
+ attr :value
+ end
+
+ class TkOp < Token
+ attr :name, true
+ end
+
+ class TkOPASGN < TkOp
+ def initialize(seek, line_no, char_no, op)
+ super(seek, line_no, char_no)
+ op = TkReading2Token[op] unless op.kind_of?(Symbol)
+ @op = op
+ end
+ attr :op
+ end
+
+ class TkUnknownChar < Token
+ def initialize(seek, line_no, char_no, id)
+ super(seek, line_no, char_no)
+ @name = name
+ end
+ attr :name
+ end
+
+ class TkError < Token
+ end
+
+ def Token(token, value = nil)
+ case token
+ when String
+ if (tk = TkReading2Token[token]).nil?
+ IRB.fail TkReading2TokenNoKey, token
+ end
+ tk = Token(tk[0], value)
+ if tk.kind_of?(TkOp)
+ tk.name = token
+ end
+ return tk
+ when Symbol
+ if (tk = TkSymbol2Token[token]).nil?
+ IRB.fail TkSymbol2TokenNoKey, token
+ end
+ return Token(tk[0], value)
+ else
+ if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty?
+ token.new(@prev_seek, @prev_line_no, @prev_char_no)
+ else
+ token.new(@prev_seek, @prev_line_no, @prev_char_no, value)
+ end
+ end
+ end
+
+ TokenDefinitions = [
+ [:TkCLASS, TkId, "class", EXPR_CLASS],
+ [:TkMODULE, TkId, "module", EXPR_BEG],
+ [:TkDEF, TkId, "def", EXPR_FNAME],
+ [:TkUNDEF, TkId, "undef", EXPR_FNAME],
+ [:TkBEGIN, TkId, "begin", EXPR_BEG],
+ [:TkRESCUE, TkId, "rescue", EXPR_MID],
+ [:TkENSURE, TkId, "ensure", EXPR_BEG],
+ [:TkEND, TkId, "end", EXPR_END],
+ [:TkIF, TkId, "if", EXPR_BEG, :TkIF_MOD],
+ [:TkUNLESS, TkId, "unless", EXPR_BEG, :TkUNLESS_MOD],
+ [:TkTHEN, TkId, "then", EXPR_BEG],
+ [:TkELSIF, TkId, "elsif", EXPR_BEG],
+ [:TkELSE, TkId, "else", EXPR_BEG],
+ [:TkCASE, TkId, "case", EXPR_BEG],
+ [:TkWHEN, TkId, "when", EXPR_BEG],
+ [:TkWHILE, TkId, "while", EXPR_BEG, :TkWHILE_MOD],
+ [:TkUNTIL, TkId, "until", EXPR_BEG, :TkUNTIL_MOD],
+ [:TkFOR, TkId, "for", EXPR_BEG],
+ [:TkBREAK, TkId, "break", EXPR_END],
+ [:TkNEXT, TkId, "next", EXPR_END],
+ [:TkREDO, TkId, "redo", EXPR_END],
+ [:TkRETRY, TkId, "retry", EXPR_END],
+ [:TkIN, TkId, "in", EXPR_BEG],
+ [:TkDO, TkId, "do", EXPR_BEG],
+ [:TkRETURN, TkId, "return", EXPR_MID],
+ [:TkYIELD, TkId, "yield", EXPR_END],
+ [:TkSUPER, TkId, "super", EXPR_END],
+ [:TkSELF, TkId, "self", EXPR_END],
+ [:TkNIL, TkId, "nil", EXPR_END],
+ [:TkTRUE, TkId, "true", EXPR_END],
+ [:TkFALSE, TkId, "false", EXPR_END],
+ [:TkAND, TkId, "and", EXPR_BEG],
+ [:TkOR, TkId, "or", EXPR_BEG],
+ [:TkNOT, TkId, "not", EXPR_BEG],
+ [:TkIF_MOD, TkId],
+ [:TkUNLESS_MOD, TkId],
+ [:TkWHILE_MOD, TkId],
+ [:TkUNTIL_MOD, TkId],
+ [:TkALIAS, TkId, "alias", EXPR_FNAME],
+ [:TkDEFINED, TkId, "defined?", EXPR_END],
+ [:TklBEGIN, TkId, "BEGIN", EXPR_END],
+ [:TklEND, TkId, "END", EXPR_END],
+ [:Tk__LINE__, TkId, "__LINE__", EXPR_END],
+ [:Tk__FILE__, TkId, "__FILE__", EXPR_END],
+
+ [:TkIDENTIFIER, TkId],
+ [:TkFID, TkId],
+ [:TkGVAR, TkId],
+ [:TkIVAR, TkId],
+ [:TkCONSTANT, TkId],
+
+ [:TkINTEGER, TkVal],
+ [:TkFLOAT, TkVal],
+ [:TkSTRING, TkVal],
+ [:TkXSTRING, TkVal],
+ [:TkREGEXP, TkVal],
+
+ [:TkDSTRING, TkNode],
+ [:TkDXSTRING, TkNode],
+ [:TkDREGEXP, TkNode],
+ [:TkNTH_REF, TkNode],
+ [:TkBACK_REF, TkNode],
+
+ [:TkUPLUS, TkOp, "+@"],
+ [:TkUMINUS, TkOp, "-@"],
+ [:TkPOW, TkOp, "**"],
+ [:TkCMP, TkOp, "<=>"],
+ [:TkEQ, TkOp, "=="],
+ [:TkEQQ, TkOp, "==="],
+ [:TkNEQ, TkOp, "!="],
+ [:TkGEQ, TkOp, ">="],
+ [:TkLEQ, TkOp, "<="],
+ [:TkANDOP, TkOp, "&&"],
+ [:TkOROP, TkOp, "||"],
+ [:TkMATCH, TkOp, "=~"],
+ [:TkNMATCH, TkOp, "!~"],
+ [:TkDOT2, TkOp, ".."],
+ [:TkDOT3, TkOp, "..."],
+ [:TkAREF, TkOp, "[]"],
+ [:TkASET, TkOp, "[]="],
+ [:TkLSHFT, TkOp, "<<"],
+ [:TkRSHFT, TkOp, ">>"],
+ [:TkCOLON2, TkOp],
+ [:TkCOLON3, TkOp],
+# [:OPASGN, TkOp], # +=, -= etc. #
+ [:TkASSOC, TkOp, "=>"],
+ [:TkQUESTION, TkOp, "?"], #?
+ [:TkCOLON, TkOp, ":"], #:
+
+ [:TkfLPAREN], # func( #
+ [:TkfLBRACK], # func[ #
+ [:TkfLBRACE], # func{ #
+ [:TkSTAR], # *arg
+ [:TkAMPER], # &arg #
+ [:TkSYMBEG], # :SYMBOL
+
+ [:TkGT, TkOp, ">"],
+ [:TkLT, TkOp, "<"],
+ [:TkPLUS, TkOp, "+"],
+ [:TkMINUS, TkOp, "-"],
+ [:TkMULT, TkOp, "*"],
+ [:TkDIV, TkOp, "/"],
+ [:TkMOD, TkOp, "%"],
+ [:TkBITOR, TkOp, "|"],
+ [:TkBITXOR, TkOp, "^"],
+ [:TkBITAND, TkOp, "&"],
+ [:TkBITNOT, TkOp, "~"],
+ [:TkNOTOP, TkOp, "!"],
+
+ [:TkBACKQUOTE, TkOp, "`"],
+
+ [:TkASSGIN, Token, "="],
+ [:TkDOT, Token, "."],
+ [:TkLPAREN, Token, "("], #(exp)
+ [:TkLBRACK, Token, "["], #[arry]
+ [:TkLBRACE, Token, "{"], #{hash}
+ [:TkRPAREN, Token, ")"],
+ [:TkRBRACK, Token, "]"],
+ [:TkRBRACE, Token, "}"],
+ [:TkCOMMA, Token, ","],
+ [:TkSEMICOLON, Token, ";"],
+
+ [:TkCOMMENT],
+ [:TkRD_COMMENT],
+ [:TkSPACE],
+ [:TkNL],
+ [:TkEND_OF_SCRIPT],
+
+ [:TkBACKSLASH, TkUnknownChar, "\\"],
+ [:TkAT, TkUnknownChar, "@"],
+ [:TkDOLLAR, TkUnknownChar, "$"],
+ ]
+
+ # {reading => token_class}
+ # {reading => [token_class, *opt]}
+ TkReading2Token = {}
+ TkSymbol2Token = {}
+
+ def RubyToken.def_token(token_n, super_token = Token, reading = nil, *opts)
+ token_n = token_n.id2name unless token_n.kind_of?(String)
+ if RubyToken.const_defined?(token_n)
+ IRB.fail AlreadyDefinedToken, token_n
+ end
+ token_c = eval("class #{token_n} < #{super_token}; end; #{token_n}")
+
+ if reading
+ if TkReading2Token[reading]
+ IRB.fail TkReading2TokenDuplicateError, token_n, reading
+ end
+ if opts.empty?
+ TkReading2Token[reading] = [token_c]
+ else
+ TkReading2Token[reading] = [token_c].concat(opts)
+ end
+ end
+ TkSymbol2Token[token_n.intern] = token_c
+ end
+
+ for defs in TokenDefinitions
+ def_token(*defs)
+ end
+end
diff --git a/lib/irb/slex.rb b/lib/irb/slex.rb
new file mode 100644
index 0000000000..85aa92bd73
--- /dev/null
+++ b/lib/irb/slex.rb
@@ -0,0 +1,279 @@
+#
+# irb-slex.rb - symple lex analizer
+# $Release Version: 0.6$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+
+require "e2mmap"
+
+class SLex
+ @RCS_ID='-$Id$-'
+
+ extend Exception2MessageMapper
+ def_exception :ErrNodeNothing, "node nothing"
+ def_exception :ErrNodeAlreadyExists, "node already exists"
+
+ class << self
+ attr :debug_level, TRUE
+ def debug?
+ debug_level > 0
+ end
+ end
+ @debug_level = 0
+
+ def initialize
+ @head = Node.new("")
+ end
+
+ def def_rule(token, preproc = nil, postproc = nil)
+ # print node.inspect, "\n" if SLex.debug?
+ postproc = proc if iterator?
+ node = create(token, preproc, postproc)
+ end
+
+ def def_rules(*tokens)
+ if iterator?
+ p = proc
+ end
+ for token in tokens
+ def_rule(token, nil, p)
+ end
+ end
+
+ def preporc(token, proc)
+ node = search(token)
+ node.preproc=proc
+ end
+
+ def postproc(token)
+ node = search(token, proc)
+ node.postproc=proc
+ end
+
+ def search(token)
+ @head.search(token.split(//))
+ end
+
+ def create(token, preproc = nil, postproc = nil)
+ @head.create_subnode(token.split(//), preproc, postproc)
+ end
+
+ def match(token)
+ case token
+ when Array
+ when String
+ token = token.split(//)
+ match(token.split(//))
+ else
+ return @head.match_io(token)
+ end
+ ret = @head.match(token)
+ printf "match end: %s:%s", ret, token.inspect if SLex.debug?
+ ret
+ end
+
+ def inspect
+ format("<SLex: @head = %s>", @head.inspect)
+ end
+
+ #----------------------------------------------------------------------
+ #
+ # class Node -
+ #
+ #----------------------------------------------------------------------
+ class Node
+ # if postproc no exist, this node is abstract node.
+ # if postproc isn't nil, this node is real node.
+ def initialize(preproc = nil, postproc = nil)
+ @Tree = {}
+ @preproc = preproc
+ @postproc = postproc
+ end
+
+ attr :preproc, TRUE
+ attr :postproc, TRUE
+
+ def search(chrs, opt = nil)
+ return self if chrs.empty?
+ ch = chrs.shift
+ if node = @Tree[ch]
+ node.search(chrs, opt)
+ else
+ if opt
+ chrs.unshift ch
+ self.create_subnode(chrs)
+ else
+ SLex.fail ErrNodeNothing
+ end
+ end
+ end
+
+ def create_subnode(chrs, preproc = nil, postproc = nil)
+ if chrs.empty?
+ if @postproc
+ p node
+ SLex.fail ErrNodeAlreadyExists
+ else
+ print "Warn: change abstruct node to real node\n" if SLex.debug?
+ @preproc = preproc
+ @postproc = postproc
+ end
+ return self
+ end
+
+ ch = chrs.shift
+ if node = @Tree[ch]
+ if chrs.empty?
+ if node.postproc
+ p node
+ p self
+ p ch
+ p chrs
+ SLex.fail ErrNodeAlreadyExists
+ else
+ print "Warn: change abstruct node to real node\n" if SLex.debug?
+ node.preproc = preproc
+ node.postproc = postproc
+ end
+ else
+ node.create_subnode(chrs, preproc, postproc)
+ end
+ else
+ if chrs.empty?
+ node = Node.new(preproc, postproc)
+ else
+ node = Node.new
+ node.create_subnode(chrs, preproc, postproc)
+ end
+ @Tree[ch] = node
+ end
+ node
+ end
+
+ #
+ # chrs: String
+ # character array
+ # io It must have getc()/ungetc(), and ungetc() can be
+ # called any number of times.
+ #
+ def match(chrs, op = "")
+ print "match>: ", chrs, "op:", op, "\n" if SLex.debug?
+ if chrs.empty?
+ if @preproc.nil? || @preproc.call(op, chrs)
+ printf "op1: %s\n", op if SLex.debug?
+ @postproc.call(op, chrs)
+ else
+ nil
+ end
+ else
+ ch = chrs.shift
+ if node = @Tree[ch]
+ if ret = node.match(chrs, op+ch)
+ return ret
+ else
+ chrs.unshift ch
+ if @postproc and @preproc.nil? || @preproc.call(op, chrs)
+ printf "op2: %s\n", op.inspect if SLex.debug?
+ ret = @postproc.call(op, chrs)
+ return ret
+ else
+ return nil
+ end
+ end
+ else
+ chrs.unshift ch
+ if @postproc and @preproc.nil? || @preproc.call(op, chrs)
+ printf "op3: %s\n", op if SLex.debug?
+ @postproc.call(op, chrs)
+ return ""
+ else
+ return nil
+ end
+ end
+ end
+ end
+
+ def match_io(io, op = "")
+ if op == ""
+ ch = io.getc
+ if ch == nil
+ return nil
+ end
+ else
+ ch = io.getc_of_rests
+ end
+ if ch.nil?
+ if @preproc.nil? || @preproc.call(op, io)
+ printf "op1: %s\n", op if SLex.debug?
+ @postproc.call(op, io)
+ else
+ nil
+ end
+ else
+ if node = @Tree[ch]
+ if ret = node.match_io(io, op+ch)
+ ret
+ else
+ io.ungetc ch
+ if @postproc and @preproc.nil? || @preproc.call(op, io)
+ printf "op2: %s\n", op.inspect if SLex.debug?
+ @postproc.call(op, io)
+ else
+ nil
+ end
+ end
+ else
+ io.ungetc ch
+ if @postproc and @preproc.nil? || @preproc.call(op, io)
+ printf "op3: %s\n", op if SLex.debug?
+ @postproc.call(op, io)
+ else
+ nil
+ end
+ end
+ end
+ end
+ end
+end
+
+if $0 == __FILE__
+ # Tracer.on
+ case $1
+ when "1"
+ tr = SLex.new
+ print "0: ", tr.inspect, "\n"
+ tr.def_rule("=") {print "=\n"}
+ print "1: ", tr.inspect, "\n"
+ tr.def_rule("==") {print "==\n"}
+ print "2: ", tr.inspect, "\n"
+
+ print "case 1:\n"
+ print tr.match("="), "\n"
+ print "case 2:\n"
+ print tr.match("=="), "\n"
+ print "case 3:\n"
+ print tr.match("=>"), "\n"
+
+ when "2"
+ tr = SLex.new
+ print "0: ", tr.inspect, "\n"
+ tr.def_rule("=") {print "=\n"}
+ print "1: ", tr.inspect, "\n"
+ tr.def_rule("==", proc{FALSE}) {print "==\n"}
+ print "2: ", tr.inspect, "\n"
+
+ print "case 1:\n"
+ print tr.match("="), "\n"
+ print "case 2:\n"
+ print tr.match("=="), "\n"
+ print "case 3:\n"
+ print tr.match("=>"), "\n"
+ end
+ exit
+end
diff --git a/lib/irb/version.rb b/lib/irb/version.rb
new file mode 100644
index 0000000000..7179d1c163
--- /dev/null
+++ b/lib/irb/version.rb
@@ -0,0 +1,16 @@
+#
+# version.rb - irb version definition file
+# $Release Version: 0.6.1$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#
+#
+
+module IRB
+ @RELEASE_VERSION = "0.6.1"
+ @LAST_UPDATE_DATE = "99/09/16"
+end
diff --git a/lib/irb/workspace-binding-2.rb b/lib/irb/workspace-binding-2.rb
new file mode 100644
index 0000000000..d005296f6e
--- /dev/null
+++ b/lib/irb/workspace-binding-2.rb
@@ -0,0 +1,15 @@
+#
+# bind.rb -
+# $Release Version: $
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#
+#
+
+while true
+ IRB::BINDING_QUEUE.push b = binding
+end
diff --git a/lib/irb/workspace-binding.rb b/lib/irb/workspace-binding.rb
new file mode 100644
index 0000000000..d58088d9dd
--- /dev/null
+++ b/lib/irb/workspace-binding.rb
@@ -0,0 +1,77 @@
+#
+# workspace-binding.rb -
+# $Release Version: $
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
+#
+# --
+#
+#
+#
+
+
+module IRB
+ # create new workspace.
+ def IRB.workspace_binding(*main)
+ if @CONF[:SINGLE_IRB]
+ bind = TOPLEVEL_BINDING
+ else
+ case @CONF[:CONTEXT_MODE]
+ when 0
+ bind = eval("proc{binding}.call",
+ TOPLEVEL_BINDING,
+ "(irb_local_binding)",
+ 1)
+ when 1
+ require "tempfile"
+ f = Tempfile.open("irb-binding")
+ f.print <<EOF
+ $binding = binding
+EOF
+ f.close
+ load f.path
+ bind = $binding
+
+ when 2
+ unless defined? BINDING_QUEUE
+ require "thread"
+
+ IRB.const_set("BINDING_QUEUE", SizedQueue.new(1))
+ Thread.abort_on_exception = true
+ Thread.start do
+ eval "require \"irb/workspace-binding-2\"", TOPLEVEL_BINDING, __FILE__, __LINE__
+ end
+ Thread.pass
+
+ end
+
+ bind = BINDING_QUEUE.pop
+
+ when 3
+ bind = eval("def irb_binding; binding; end; irb_binding",
+ TOPLEVEL_BINDING,
+ __FILE__,
+ __LINE__ - 3)
+ end
+ end
+ unless main.empty?
+ @CONF[:__MAIN__] = main[0]
+ case main[0]
+ when Module
+ bind = eval("IRB.conf[:__MAIN__].module_eval('binding')", bind)
+ else
+ begin
+ bind = eval("IRB.conf[:__MAIN__].instance_eval('binding')", bind)
+ rescue TypeError
+ IRB.fail CanNotChangeBinding, main[0].inspect
+ end
+ end
+ end
+ eval("_=nil", bind)
+ bind
+ end
+
+ def IRB.delete_caller
+ end
+end
diff --git a/lib/irb/xmp.rb b/lib/irb/xmp.rb
new file mode 100644
index 0000000000..fc745a2757
--- /dev/null
+++ b/lib/irb/xmp.rb
@@ -0,0 +1,84 @@
+#
+# xmp.rb - irb version of gotoken xmp
+# $Release Version: 0.6$
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+#
+#
+#
+
+require "irb/irb"
+require "irb/frame"
+
+class XMP
+ @RCS_ID='-$Id$-'
+
+ def initialize(bind = nil)
+ #IRB.parse_opts
+ #IRB.load_modules
+
+ bind = IRB::Frame.top(1) unless bind
+ main = eval("self", bind)
+ @io = StringInputMethod.new
+ @irb = IRB::Irb.new(main, bind, @io)
+ @irb.context.prompt_mode = :XMP
+ @irb.context.ignore_sigint = false
+
+# IRB.conf[:IRB_RC].call(@irb.context) if IRB.conf[:IRB_RC]
+ IRB.conf[:MAIN_CONTEXT] = @irb.context
+ end
+
+ def puts(exps)
+ @io.puts exps
+
+ if @irb.context.ignore_sigint
+ begin
+ trap_proc_b = trap("SIGINT"){@irb.signal_handle}
+ catch(:IRB_EXIT) do
+ @irb.eval_input
+ end
+ ensure
+ trap("SIGINT", trap_proc_b)
+ end
+ else
+ catch(:IRB_EXIT) do
+ @irb.eval_input
+ end
+ end
+ end
+
+ class StringInputMethod < IRB::InputMethod
+ def initialize
+ super
+ @exps = []
+ end
+
+ def eof?
+ @exps.empty?
+ end
+
+ def gets
+ while l = @exps.shift
+ next if /^\s+$/ =~ l
+ l.concat "\n"
+ print @prompt, l
+ break
+ end
+ l
+ end
+
+ def puts(exps)
+ @exps.concat exps.split(/\n/)
+ end
+ end
+end
+
+def xmp(exps, bind = nil)
+ bind = IRB::Frame.top(1) unless bind
+ xmp = XMP.new(bind)
+ xmp.puts exps
+ xmp
+end
diff --git a/lib/matrix.rb b/lib/matrix.rb
index a80b7dd9f1..80d28148ac 100644
--- a/lib/matrix.rb
+++ b/lib/matrix.rb
@@ -420,7 +420,6 @@ class Matrix
vij = 0
0.upto(column_size - 1) do
|k|
- p [k,j,m[k,j]]
vij += self[i, k] * m[k, j]
end
vij
diff --git a/lib/thread.rb b/lib/thread.rb
index 20ce6aef5d..a0e6967a28 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -157,8 +157,10 @@ class Queue
t.wakeup if t
rescue ThreadError
retry
+ ensure
+ Thread.critical = false
end
- Thread.critical = false
+ t.run if t
end
alias enq push
@@ -250,10 +252,13 @@ class SizedQueue<Queue
if @que.length < @max
begin
t = @queue_wait.shift
- t.run if t
+ t.wakeup if t
rescue ThreadError
retry
+ ensure
+ Thread.critical = false
end
+ t.run if t
end
super
end
diff --git a/marshal.c b/marshal.c
index 0b4f17fac7..c25e0cb0c3 100644
--- a/marshal.c
+++ b/marshal.c
@@ -208,8 +208,6 @@ w_ivar(tbl, arg)
st_table *tbl;
struct dump_call_arg *arg;
{
- struct dump_call_arg c_arg;
-
if (tbl) {
w_long(tbl->num_entries, arg->arg);
st_foreach(tbl, obj_each, arg);
diff --git a/pack.c b/pack.c
index cd24093683..757d841fcc 100644
--- a/pack.c
+++ b/pack.c
@@ -843,6 +843,53 @@ pack_pack(ary, fmt)
}
break;
+ case 'w':
+ while (len-- > 0) {
+ unsigned long ul;
+ VALUE buf = rb_str_new(0, 0);
+ char c, *bufs, *bufe;
+
+ from = NEXTFROM;
+
+ if (TYPE(from) == T_BIGNUM) {
+ VALUE big128 = rb_uint2big(128);
+ while (TYPE(from) == T_BIGNUM) {
+ from = rb_big_divmod(from, big128);
+ c = NUM2INT(RARRAY(from)->ptr[1]) | 0x80; /* mod */
+ rb_str_cat(buf, &c, sizeof(char));
+ from = RARRAY(from)->ptr[0]; /* div */
+ }
+ }
+
+ if (NIL_P(from)) ul = 0;
+ else {
+ ul = NUM2ULONG(from);
+ }
+
+ while (ul) {
+ c = ((ul & 0x7f) | 0x80);
+ rb_str_cat(buf, &c, sizeof(char));
+ ul >>= 7;
+ }
+
+ if (RSTRING(buf)->len) {
+ bufs = RSTRING(buf)->ptr;
+ bufe = bufs + RSTRING(buf)->len - 1;
+ *bufs &= 0x7f; /* clear continue bit */
+ while (bufs < bufe) { /* reverse */
+ c = *bufs;
+ *bufs++ = *bufe;
+ *bufe-- = c;
+ }
+ rb_str_cat(res, RSTRING(buf)->ptr, RSTRING(buf)->len);
+ }
+ else {
+ c = 0;
+ rb_str_cat(res, &c, sizeof(char));
+ }
+ }
+ break;
+
default:
break;
}
@@ -1573,6 +1620,37 @@ pack_unpack(str, fmt)
}
break;
+ case 'w':
+ {
+ unsigned long ul = 0;
+ unsigned long ulmask = 0xfe << ((sizeof(unsigned long) - 1) * 8);
+
+ while (len > 0 && s < send) {
+ ul <<= 7;
+ ul |= (*s & 0x7f);
+ if (!(*s++ & 0x80)) {
+ rb_ary_push(ary, rb_uint2inum(ul));
+ len--;
+ ul = 0;
+ }
+ else if (ul & ulmask) {
+ VALUE big = rb_uint2big(ul);
+ VALUE big128 = rb_uint2big(128);
+ while (s < send) {
+ big = rb_big_mul(big, big128);
+ big = rb_big_plus(big, rb_uint2big(*s & 0x7f));
+ if (!(*s++ & 0x80)) {
+ rb_ary_push(ary, big);
+ len--;
+ ul = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+
default:
break;
}
diff --git a/parse.y b/parse.y
index 6c5aaa7c9d..a34c5aabf3 100644
--- a/parse.y
+++ b/parse.y
@@ -2125,6 +2125,84 @@ read_escape()
}
static int
+tokadd_escape()
+{
+ int c;
+
+ switch (c = nextc()) {
+ case '\n':
+ return 0; /* just ignore */
+
+ case '0': case '1': case '2': case '3': /* octal constant */
+ case '4': case '5': case '6': case '7':
+ {
+ int i;
+
+ tokadd('\\');
+ tokadd(c);
+ for (i=0; i<2; i++) {
+ c = nextc();
+ if (c == -1) goto eof;
+ if (c < '0' || '7' < c) {
+ pushback(c);
+ break;
+ }
+ tokadd(c);
+ }
+ }
+ return 0;
+
+ case 'x': /* hex constant */
+ {
+ int numlen;
+
+ scan_hex(lex_p, 2, &numlen);
+ while (numlen--)
+ tokadd(nextc());
+ }
+ return 0;
+
+ case 'M':
+ if ((c = nextc()) != '-') {
+ yyerror("Invalid escape character syntax");
+ pushback(c);
+ return 0;
+ }
+ tokadd('\\'); tokadd('M'); tokadd('-');
+ goto escaped;
+
+ case 'C':
+ if ((c = nextc()) != '-') {
+ yyerror("Invalid escape character syntax");
+ pushback(c);
+ return 0;
+ }
+ tokadd('\\'); tokadd('C'); tokadd('-');
+ goto escaped;
+
+ case 'c':
+ tokadd('\\'); tokadd('c');
+ escaped:
+ if ((c = nextc()) == '\\') {
+ return tokadd_escape();
+ }
+ else if (c == -1) goto eof;
+ tokadd(c);
+ return 0;
+
+ eof:
+ case -1:
+ yyerror("Invalid escape character syntax");
+ return -1;
+
+ default:
+ tokadd('\\');
+ tokadd(c);
+ }
+ return 0;
+}
+
+static int
parse_regx(term, paren)
int term, paren;
{
@@ -2133,78 +2211,31 @@ parse_regx(term, paren)
int once = 0;
int nest = 0;
int options = 0;
- int in_brack = 0;
int re_start = ruby_sourceline;
NODE *list = 0;
newtok();
while ((c = nextc()) != -1) {
- if (!in_brack && c == term && nest == 0) {
+ if (c == term && nest == 0) {
goto regx_end;
}
switch (c) {
- case '[':
- in_brack = 1;
- break;
- case ']':
- in_brack = 0;
- break;
-
case '#':
list = str_extend(list, term);
if (list == (NODE*)-1) return 0;
continue;
case '\\':
- switch (c = nextc()) {
- case -1:
- ruby_sourceline = re_start;
- rb_compile_error("unterminated regexp meets end of file");
+ if (tokadd_escape() < 0)
return 0;
-
- case '\n':
- break;
-
- case '\\':
- case '^':
- case 's':
- tokadd('\\');
- tokadd(c);
- break;
-
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- case '0': case 'x':
- tokadd('\\');
- tokadd(c);
- break;
-
- case 'b':
- if (!in_brack) {
- tokadd('\\');
- tokadd('b');
- break;
- }
- /* fall through */
- default:
- if (c == term) {
- tokadd(c);
- }
- else {
- tokadd('\\');
- tokadd(c);
- }
- }
continue;
case -1:
- rb_compile_error("unterminated regexp");
- return 0;
+ goto unterminated;
default:
- if (paren && !in_brack) {
+ if (paren) {
if (c == paren) nest++;
if (c == term) nest--;
}
@@ -2272,7 +2303,9 @@ parse_regx(term, paren)
}
tokadd(c);
}
- rb_compile_error("unterminated regexp");
+ unterminated:
+ ruby_sourceline = re_start;
+ rb_compile_error("unterminated regexp meets end of file");
return 0;
}
diff --git a/regex.c b/regex.c
index 9ddc4752de..91fc1d98c1 100644
--- a/regex.c
+++ b/regex.c
@@ -22,13 +22,11 @@
/* UTF-8 extension added Jan 16 1999 by Yoshida Masato <yoshidam@tau.bekkoame.ne.jp> */
#include "config.h"
-#ifdef RUBY_PLATFORM
-# define RUBY
-extern int rb_prohibit_interrupt;
-extern int rb_trap_pending;
-# define CHECK_INTS if (!rb_prohibit_interrupt) {\
- if (rb_trap_pending) rb_trap_exec();\
-}
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
#endif
/* We write fatal error messages on standard error. */
@@ -63,6 +61,17 @@ extern int rb_trap_pending;
# define _(args) ()
#endif
+#ifdef RUBY_PLATFORM
+# define RUBY
+extern int rb_prohibit_interrupt;
+extern int rb_trap_pending;
+void rb_trap_exec _((void));
+
+# define CHECK_INTS if (!rb_prohibit_interrupt) {\
+ if (rb_trap_pending) rb_trap_exec();\
+}
+#endif
+
#ifndef xmalloc
void *xmalloc _((size_t));
void *xcalloc _((size_t,size_t));
@@ -70,7 +79,7 @@ void *xrealloc _((void*,size_t));
void free _((void*));
#endif
-#define NO_ALLOCA /* /* try it out for now */
+#define NO_ALLOCA /* try it out for now */
#ifndef NO_ALLOCA
/* Make alloca work the best possible way. */
#ifdef __GNUC__
@@ -474,7 +483,7 @@ utf8_firstbyte(c)
static void
print_mbc(c)
- unsigned long c;
+ unsigned int c;
{
if (current_mbctype == MBCTYPE_UTF8) {
if (c < 0x80)
@@ -587,13 +596,13 @@ print_mbc(c)
} while (0)
#define EXTRACT_MBC(p) \
- ((unsigned long)((unsigned char)(p)[0] << 24 | \
+ ((unsigned int)((unsigned char)(p)[0] << 24 | \
(unsigned char)(p)[1] << 16 | \
(unsigned char)(p)[2] << 8 | \
(unsigned char)(p)[3]))
#define EXTRACT_MBC_AND_INCR(p) \
- ((unsigned long)((p) += 4, \
+ ((unsigned int)((p) += 4, \
(unsigned char)(p)[-4] << 24 | \
(unsigned char)(p)[-3] << 16 | \
(unsigned char)(p)[-2] << 8 | \
@@ -1398,12 +1407,6 @@ re_compile_pattern(pattern, size, bufp)
had_num_literal = 0;
had_char_class = 0;
- /* charset_not matches newline according to a syntax bit. */
- if ((enum regexpcode)b[-2] == charset_not) {
- if (bufp->options & RE_OPTION_POSIXLINE)
- SET_LIST_BIT ('\n');
- }
-
/* Read in characters and ranges, setting map bits. */
for (;;) {
int size;
@@ -2325,6 +2328,8 @@ re_compile_pattern(pattern, size, bufp)
case dummy_failure_jump:
bufp->options |= RE_OPTIMIZE_ANCHOR;
break;
+ default:
+ break;
}
}
else if (*laststart == charset || *laststart == charset_not) {
@@ -3004,6 +3009,7 @@ re_compile_fastmap(bufp)
}
break;
+ case begpos:
case unused: /* pacify gcc -Wall */
break;
}
@@ -4247,7 +4253,6 @@ re_match(bufp, string_arg, size, pos, regs)
p1 = p;
/* If failed to a backwards jump that's part of a repetition
loop, need to pop this failure point and use the next one. */
- pop_loop:
switch ((enum regexpcode)*p1) {
case jump_n:
case finalize_push_n:
diff --git a/ruby.c b/ruby.c
index 0777ffd574..326c98d2d4 100644
--- a/ruby.c
+++ b/ruby.c
@@ -291,7 +291,7 @@ static char*
moreswitches(s)
char *s;
{
- int argc; char *argv[3]; char **argvp = argv;
+ int argc; char *argv[3];
char *p = s;
argc = 2; argv[0] = argv[2] = 0;
@@ -636,6 +636,12 @@ proc_options(argc, argv)
load_file(script, 1);
}
+ if (rb_safe_level() == 0) {
+ rb_ary_push(rb_load_path, rb_str_new2("."));
+ addpath(getenv("RUBYLIB"));
+ }
+
+
process_sflag();
xflag = 0;
}
@@ -917,10 +923,6 @@ ruby_prog_init()
rb_define_readonly_variable("$-p", &do_print);
rb_define_readonly_variable("$-l", &do_line);
- if (rb_safe_level() == 0) {
- addpath(".");
- }
-
addpath(RUBY_LIB);
#if defined(_WIN32) || defined(DJGPP)
addpath(ruby_libpath());
@@ -942,10 +944,6 @@ ruby_prog_init()
addpath(RUBY_SEARCH_PATH);
#endif
- if (rb_safe_level() == 0) {
- addpath(getenv("RUBYLIB"));
- }
-
rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
rb_argv = rb_ary_new();
diff --git a/ruby.h b/ruby.h
index 1c50d35bb4..149ca98557 100644
--- a/ruby.h
+++ b/ruby.h
@@ -358,13 +358,13 @@ struct RBignum {
#define FL_ABLE(x) (!SPECIAL_CONST_P(x))
#define FL_TEST(x,f) (FL_ABLE(x)?(RBASIC(x)->flags&(f)):0)
-#define FL_SET(x,f) (FL_ABLE(x) && (RBASIC(x)->flags |= (f)))
-#define FL_UNSET(x,f) (FL_ABLE(x) && (RBASIC(x)->flags &= ~(f)))
-#define FL_REVERSE(x,f) (FL_ABLE(x) && (RBASIC(x)->flags ^= (f)))
+#define FL_SET(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags |= (f);} while (0)
+#define FL_UNSET(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags &= ~(f);} while (0)
+#define FL_REVERSE(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags ^= (f);} while (0)
#define OBJ_TAINTED(x) FL_TEST((x), FL_TAINT)
#define OBJ_TAINT(x) FL_SET((x), FL_TAINT)
-#define OBJ_INFECT(x,s) (FL_ABLE(x) && FL_ABLE(s) && (RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT))
+#define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s)) RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT;} while (0)
#define OBJ_FROZEN(x) FL_TEST((x), FL_FREEZE)
#define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE)
@@ -394,8 +394,8 @@ void rb_define_variable _((const char*,VALUE*));
void rb_define_virtual_variable _((const char*,VALUE(*)(),void(*)()));
void rb_define_hooked_variable _((const char*,VALUE*,VALUE(*)(),void(*)()));
void rb_define_readonly_variable _((const char*,VALUE*));
-void rb_define_constants _((VALUE,const char*,VALUE));
-void rb_define_global_constants _((const char*,VALUE));
+void rb_define_const _((VALUE,const char*,VALUE));
+void rb_define_global_const _((const char*,VALUE));
void rb_define_method _((VALUE,const char*,VALUE(*)(),int));
void rb_define_module_function _((VALUE,const char*,VALUE(*)(),int));
diff --git a/sample/irb.rb b/sample/irb.rb
new file mode 100644
index 0000000000..38d184dfd0
--- /dev/null
+++ b/sample/irb.rb
@@ -0,0 +1,28 @@
+#!/usr/bin/env ruby
+#
+# irb.rb - intaractive ruby
+# $Release Version: 0.6 $
+# $Revision$
+# $Date$
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+# Usage:
+#
+# irb.rb [options] file_name opts
+#
+#
+
+require "irb/main"
+
+if __FILE__ == $0
+ IRB.start(__FILE__)
+else
+ # check -e option
+ tmp = ENV["TMP"] || ENV["TMPDIR"] || "/tmp"
+ if %r|#{tmp}/rb| =~ $0
+ IRB.start(__FILE__)
+ else
+ IRB.initialize(__FILE__)
+ end
+end
diff --git a/sample/rbc.rb b/sample/rbc.rb
index 9f1ab9443d..2c18d823a1 100644
--- a/sample/rbc.rb
+++ b/sample/rbc.rb
@@ -413,7 +413,7 @@ module BC_APPLICATION__
ch = chrs.shift
case ch
- when /[_~*$?!@/\\;,.=:<>"]/ #"
+ when /[_~*$?!@\/\\;,.=:<>"]/ #"
return
when "-"
diff --git a/string.c b/string.c
index fe8e8e1cef..711f7d81d3 100644
--- a/string.c
+++ b/string.c
@@ -766,7 +766,7 @@ static VALUE
rb_str_succ(orig)
VALUE orig;
{
- VALUE str, str2;
+ VALUE str;
char *sbeg, *s;
int c = -1;
int n = 0;
@@ -1039,7 +1039,7 @@ rb_str_slice_bang(argc, argv, str)
VALUE str;
{
VALUE arg1, arg2;
- long pos, len, i;
+ long pos, len;
rb_str_modify(str);
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
diff --git a/time.c b/time.c
index 0c04fc72d8..68d7bde561 100644
--- a/time.c
+++ b/time.c
@@ -80,12 +80,6 @@ time_s_new(argc, argv, klass)
}
static VALUE
-time_initialize()
-{
- return Qnil;
-}
-
-static VALUE
time_new_internal(klass, sec, usec)
VALUE klass;
time_t sec, usec;
diff --git a/util.c b/util.c
index 186cfea29d..a8860672c4 100644
--- a/util.c
+++ b/util.c
@@ -593,28 +593,6 @@ static void mmswap(a, b) register char *a, *b;
}
}
-static void mmswapblock(a, b, size) register char *a, *b; int size;
-{
- register int s;
- if (mmkind >= 0) {
- register char *t = a + (size & (-16)); register int lo = (size & 0x0C);
- if (size >= 16) {
- do {
- s = A[0]; A[0] = B[0]; B[0] = s;
- s = A[1]; A[1] = B[1]; B[1] = s;
- s = A[2]; A[2] = B[2]; B[2] = s;
- s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16;
- }while (a < t);
- }
- if (lo != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
- if (lo >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
- if (lo == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
- }else{
- register char *t = a + size;
- do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
- }
-}
-
static void mmrot3(a, b, c) register char *a, *b, *c;
{
register int s;
diff --git a/variable.c b/variable.c
index de034da0dd..e3da3615f0 100644
--- a/variable.c
+++ b/variable.c
@@ -724,7 +724,6 @@ rb_generic_ivar_table(obj)
VALUE obj;
{
st_table *tbl;
- VALUE val;
if (!generic_iv_tbl) return 0;
if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0;
@@ -1336,7 +1335,6 @@ rb_cvar_set(klass, id, val)
ID id;
VALUE val;
{
- VALUE value;
VALUE tmp;
if (FL_TEST(klass, FL_SINGLETON)) {
@@ -1382,7 +1380,6 @@ rb_cvar_defined(klass, id)
VALUE klass;
ID id;
{
- VALUE value;
VALUE tmp;
if (FL_TEST(klass, FL_SINGLETON)) {
diff --git a/version.h b/version.h
index 91f95200f3..d49ce9b854 100644
--- a/version.h
+++ b/version.h
@@ -1,4 +1,4 @@
-#define RUBY_VERSION "1.5.3"
-#define RUBY_RELEASE_DATE "2000-05-10"
-#define RUBY_VERSION_CODE 153
-#define RUBY_RELEASE_CODE 20000510
+#define RUBY_VERSION "1.5.4"
+#define RUBY_RELEASE_DATE "2000-05-12"
+#define RUBY_VERSION_CODE 154
+#define RUBY_RELEASE_CODE 20000512