git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@611 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2000-02-01 03:12:21 +00:00
Родитель 005f125829
Коммит e4b53b2222
37 изменённых файлов: 1603 добавлений и 691 удалений

Просмотреть файл

@ -1,3 +1,82 @@
Mon Jan 31 15:24:58 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* string.c (rb_str_sub): no bang method returns original string if
no change is made.
* string.c (str_sub_bang): bang method returns string always.
experimental.
Sun Jan 30 17:58:09 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
* eval.c: arrange to use setitimer(2) for BOW, DJGPP
* defines.h: ditto. use random(3) on cygwin b20.1.
Sun Jan 30 17:20:16 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
* eval.c: use getrlimit(2) on DJGPP.
Thu Jan 27 01:27:10 2000 GOTO Kentaro <gotoken@math.sci.hokudai.ac.jp>
* dir.c (glob): glob pattern "/*" did not match.
Wed Jan 26 22:30:47 2000 Shigeo Kobayashi <shigeo@tinyforest.gr.jp>
* numeric.c (flo_modulo): wrong result for negative modulo.
Wed Jan 26 02:01:57 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* file.c (test_c): should use S_ISCHR.
* file.c (rb_stat_c): ditto.
* string.c (rb_str_each_line): should propagate tainting.
Tue Jan 25 04:01:34 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* object.c (rb_obj_freeze): all objects made freezable.
Tue Jan 25 00:37:01 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
* configure.in: use AC_CHECK_TOOL for cross compiling.
Mon Jan 24 19:01:54 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* array.c (rb_protect_inspect): should be checked by id of
objects; not by object themselves.
Mon Jan 24 18:48:08 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
* eval.c (rb_eval): too many warnings; warned on every method
overriding. should be on method discarding.
Mon Jan 24 02:56:44 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* parse.y (yylex): -2.abs should be `(-2).abs' to accomplish the
principle of less surprise. `+2' too.
* eval.c (rb_eval): when defining class is already there, and
superclass differ, throw away the old class.
* variable.c (rb_const_set): gives warining again on constant
redefinition.
* error.c (Init_Exception): SyntaxError, NameError, LoadError and
NotImplementError are subclasses of ScriptError<Exception, not
StandardError. experimental.
Sat Jan 22 00:00:41 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* parse.y (parse_quotedwords): no longer use `String#split'.
and enable space escape within quoted word list.
e.g. %w(a\ b\ c abc) => ["a b c", "abc"].
* string.c (rb_str_slice_bang): new method `slice!'.
Fri Jan 21 16:15:59 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (thgroup_s_new): new class ThreadGroup.
Tue Jan 18 12:24:28 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* struct.c (Init_Struct): remove Struct's own hash and eql?.
@ -68,8 +147,8 @@ Tue Jan 4 06:04:14 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
Sat Jan 1 13:26:14 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (rb_yield_0): force_recycle ruby_dyna_vars to performance
gain.
* eval.c (rb_yield_0): force_recycle ruby_dyna_vars to gain
performance.
* array.c (rb_ary_delete_at_m): takes same argument pattern with
rb_ary_aref.
@ -85,8 +164,8 @@ Sat Jan 1 10:12:26 2000 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* ruby.h (FL_ABLE, FL_SET, FL_UNSET, FL_REVERSE): made expressions
not statements.
* ruby.h (OBJ_INFECT): newly added which copies taint from `s' to
`x'.
* ruby.h (OBJ_INFECT): newly added macro which copies taint from
`s' to `x'.
Sat Jan 1 02:04:18 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
@ -202,7 +281,7 @@ Mon Dec 13 15:15:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
because of major performace drawback.
* class.c (rb_singleton_class): tainted status of the singleton
class must synchronize with the object.
class must be synchronized with the object.
* eval.c (rb_thread_schedule): implement thread priority.
@ -404,7 +483,7 @@ Mon Nov 15 04:50:33 1999 Koji Arai <JCA02266@nifty.ne.jp>
Sat Nov 13 07:34:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* variable.c (rb_mod_constants): traverse superclasses to collect
constants (shared variables).
constants.
* eval.c (assign): modified for shared variables.

31
ToDo
Просмотреть файл

@ -2,31 +2,32 @@ Language Spec.
- def foo; .. rescue .. end
- compile time string concatenation, "hello" "world" => "helloworld"
- assignable constant, which now should be called shared variable.
- class variable (prefix?) -- done by shared variable
- rescue modifier; a rescue b => begin a rescue; b end
* operator !! for rescue.
- %w(a\ b\ c abc) => ["a b c", "abc"]
* class variable (prefix @@?) ??
* operator !! for rescue. ???
* objectify symbols
* objectify characters
* ../... outside condition invokes operator method too.
* ... inside condition turns off just before right condition.???
* %w(a\ b\ c abc) => ["a b c", "abc"]
* package or access control for global variables??
* named arguments like foo(nation:="german") or foo(nation: "german").
* method to retrieve argument information (need new C API)
* method to retrieve argument information (needs new C API)
* multiple return values, yield values. maybe incompatible ???
* cascading method invocation ???
* def Class#method .. end ??
* class Foo::Bar<Baz .. end, module Boo::Bar .. end
* def Foo::Bar::baz() .. end ??
* I18N (or M17N) script/string/regexp
Hacking Interpreter
- use eban's fnmatch
- RUBYOPT environment variable
- alias $defout $>
* retrieve STACK_LEVEL_MAX from users' limit.
* remove end_proc registered out of require only
- retrieve STACK_LEVEL_MAX from users' limit.
- remove end_proc registered out of require only
- all object made freezable
* non-blocking open (e.g. for named pipe) for thread
* avoid blocking with gethostbyname/gethostbyaddr
* objectify interpreters
@ -34,7 +35,6 @@ Hacking Interpreter
* syntax tree -> bytecode ???
* scrambled script, or script filter
* setuid ruby
* freeze all object
Standard Libraries
@ -45,9 +45,12 @@ Standard Libraries
- sprintf/printf's $ to specify argument order
- Dir.glob("**/*.c") ala zsh
- Remove Enumerable#{size,length}
* Marshal should handle generic instance variables.
* SyntaxError and NameError should not be subclasses of StandardError, maybe.
* debugger for thread programming
- Array#slice, Array#slice!
- String#slice, String#slice!
- Marshal should handle generic instance variables.
- debugger for thread programming
- SyntaxError, NameError, LoadError and NotImplementError are subclasses of
ScriptError<Exception, not StandardError.
* Struct::new([name,]member,...) ??
* String#scanf(?)
* Object#fmt(?)
@ -66,14 +69,16 @@ Extension Libraries
Ruby Libraries
* httplib.rb, urllib.rb, nttplib.rb, etc.
- net/http.rb
* urllib.rb, nttplib.rb, etc.
* format like perl's
Tools
- extension library maker like XS or SWIG
- extension library maker using SWIG
* freeze or undump to bundle everything
Misc
- publish Ruby books
* publish Ruby books in English

57
array.c
Просмотреть файл

@ -38,37 +38,24 @@ memfill(mem, size, val)
}
}
#define ARY_FREEZE FL_USER1
#define ARY_TMPLOCK FL_USER2
#define ARY_TMPLOCK FL_USER1
static void
rb_ary_modify(ary)
VALUE ary;
{
if (FL_TEST(ary, ARY_FREEZE))
rb_raise(rb_eTypeError, "can't modify frozen array");
if (OBJ_FROZEN(ary)) rb_error_frozen("array");
if (FL_TEST(ary, ARY_TMPLOCK))
rb_raise(rb_eTypeError, "can't modify array during sort");
if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
VALUE
rb_ary_freeze(ary)
VALUE ary;
{
if (rb_safe_level() >= 4 && !OBJ_TAINTED(ary))
rb_raise(rb_eSecurityError, "Insecure: can't freeze array");
FL_SET(ary, ARY_FREEZE);
return ary;
}
static VALUE
rb_ary_frozen_p(ary)
VALUE ary;
{
if (FL_TEST(ary, ARY_FREEZE|ARY_TMPLOCK))
if (FL_TEST(ary, FL_FREEZE|ARY_TMPLOCK))
return Qtrue;
return Qfalse;
}
@ -355,7 +342,7 @@ rb_ary_entry(ary, offset)
}
static VALUE
rb_ary_subary(ary, beg, len)
rb_ary_subseq(ary, beg, len)
VALUE ary;
long beg, len;
{
@ -397,7 +384,7 @@ rb_ary_aref(argc, argv, ary)
if (beg < 0) {
beg = RARRAY(ary)->len + beg;
}
return rb_ary_subary(ary, beg, len);
return rb_ary_subseq(ary, beg, len);
}
/* special case - speeding up */
@ -415,7 +402,7 @@ rb_ary_aref(argc, argv, ary)
case Qnil:
return Qnil;
default:
return rb_ary_subary(ary, beg, len);
return rb_ary_subseq(ary, beg, len);
}
}
return rb_ary_entry(ary, NUM2LONG(arg1));
@ -790,8 +777,8 @@ rb_protect_inspect(func, obj, arg)
VALUE obj, arg;
{
struct inspect_arg iarg;
VALUE inspect_tbl;
VALUE id;
if (!inspect_key) {
inspect_key = rb_intern("__inspect_key__");
@ -801,10 +788,11 @@ rb_protect_inspect(func, obj, arg)
inspect_tbl = rb_ary_new();
rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl);
}
if (rb_ary_includes(inspect_tbl, obj)) {
id = rb_obj_id(obj);
if (rb_ary_includes(inspect_tbl, id)) {
return (*func)(obj, arg);
}
rb_ary_push(inspect_tbl, obj);
rb_ary_push(inspect_tbl, id);
iarg.func = func;
iarg.arg1 = obj;
iarg.arg2 = arg;
@ -821,7 +809,7 @@ rb_inspecting_p(obj)
if (!inspect_key) return Qfalse;
inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
if (NIL_P(inspect_tbl)) return Qfalse;
return rb_ary_includes(inspect_tbl, obj);
return rb_ary_includes(inspect_tbl, rb_obj_id(obj));
}
static VALUE
@ -1040,7 +1028,7 @@ rb_ary_delete_at_m(argc, argv, ary)
if (pos < 0) {
pos = RARRAY(ary)->len + pos;
}
arg2 = rb_ary_subary(ary, pos, len);
arg2 = rb_ary_subseq(ary, pos, len);
rb_ary_replace(ary, pos, len, Qnil); /* Qnil/rb_ary_new2(0) */
return arg2;
}
@ -1064,6 +1052,7 @@ rb_ary_delete_at_m(argc, argv, ary)
return arg2;
}
static VALUE
rb_ary_delete_if(ary)
VALUE ary;
@ -1500,11 +1489,26 @@ rb_ary_flatten_bang(ary)
{
long i;
int mod = 0;
VALUE flattening = Qnil;
rb_ary_modify(ary);
for (i=0; i<RARRAY(ary)->len; i++) {
VALUE ary2 = RARRAY(ary)->ptr[i];
if (TYPE(ary2) == T_ARRAY) {
if (ary == ary2) {
ary2 = Qnil;
} else {
VALUE id;
if (NIL_P(flattening)) {
flattening = rb_ary_new();
}
id = rb_obj_id(ary2);
if (rb_ary_includes(flattening, id)) {
rb_raise(rb_eArgError, "tryed to flatten recursive array");
}
rb_ary_push(flattening, id);
}
rb_ary_replace(ary, i--, 1, ary2);
mod = 1;
}
@ -1534,8 +1538,6 @@ Init_Array()
rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
rb_define_method(rb_cArray, "to_ary", rb_ary_to_a, 0);
rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
@ -1583,6 +1585,9 @@ Init_Array()
rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
rb_define_method(rb_cArray, "slice!", rb_ary_delete_at_m, -1);
rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);

797
configure поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -68,13 +68,27 @@ fi
AC_ARG_PROGRAM
dnl Checks for programs.
if test x"${build}" != x"${host}"; then
AC_CHECK_TOOL(CC, gcc)
fi
AC_PROG_CC
AC_PROG_GCC_TRADITIONAL
AC_PROG_YACC
AC_PROG_RANLIB
AC_SUBST(AR)
AC_CHECK_TOOL(RANLIB, ranlib, :)
AC_CHECK_TOOL(AR, ar)
AC_CHECK_PROGS(AR, ar aal, ar)
case "$target_os" in
cygwin*)
AC_CHECK_TOOL(NM, nm)
AC_CHECK_TOOL(DLLWRAP, dllwrap)
AC_CHECK_TOOL(AS, as)
AC_CHECK_TOOL(DLLTOOL, dlltool)
;;
esac
AC_PROG_LN_S
AC_PROG_MAKE_SET
@ -310,10 +324,14 @@ AC_SUBST(DEFAULT_KCODE)
AC_ARG_WITH(default-kcode,
[--with-default-kcode=CODE specify default value for \$KCODE (utf8|euc|sjis|none)],
[case $withval in
utf8) AC_DEFINE(DEFAULT_KCODE, KCODE_UTF8);;
euc) AC_DEFINE(DEFAULT_KCODE, KCODE_EUC);;
sjis) AC_DEFINE(DEFAULT_KCODE, KCODE_SJIS);;
none) AC_DEFINE(DEFAULT_KCODE, KCODE_NONE);;
utf8) AC_DEFINE(DEFAULT_KCODE, KCODE_UTF8)
DEFAULT_KCODE="KCODE_UTF8";;
euc) AC_DEFINE(DEFAULT_KCODE, KCODE_EUC)
DEFAULT_KCODE="KCODE_EUC";;
sjis) AC_DEFINE(DEFAULT_KCODE, KCODE_SJIS)
DEFAULT_KCODE="KCODE_SJIS";;
none) AC_DEFINE(DEFAULT_KCODE, KCODE_NONE)
DEFAULT_KCODE="KCODE_NONE";;
*) AC_MSG_WARN($withval is not valid kcode; ignored);;
esac])
@ -327,10 +345,8 @@ AC_ARG_WITH(dln-a-out,
AC_SUBST(XLDFLAGS)dnl
case "$target_os" in
linux*)
AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf,
[AC_TRY_RUN([
AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf,
[AC_TRY_RUN([
/* Test for whether ELF binaries are produced */
#include <fcntl.h>
#include <stdlib.h>
@ -347,15 +363,30 @@ main() {
exit(0); /* succeed (yes, it's ELF) */
}
],
rb_cv_binary_elf=yes,
rb_cv_binary_elf=no,
rb_cv_binary_elf=yes)])
rb_cv_binary_elf=yes,
rb_cv_binary_elf=no,
rb_cv_binary_elf=yes)])
if test "$rb_cv_binary_elf" = yes; then
AC_DEFINE(USE_ELF)
fi
case "$target_os" in
linux*)
if test "$rb_cv_binary_elf" = no; then
with_dln_a_out=yes
target_os=${target_os}-a_out
else
LDFLAGS="-rdynamic"
fi;;
netbsd*)
if [[ "`$CC -dM -E - </dev/null | grep __ELF__`" != "" ]]
then
netbsd_elf=yes
else
netbsd_elf=no
fi
;;
esac
AC_SUBST(DLDFLAGS)dnl
@ -420,20 +451,17 @@ if test "$with_dln_a_out" != yes; then
linux*) LDSHARED="$CC -shared"
rb_cv_dlopen=yes ;;
freebsd*) LDSHARED="$CC -shared"
if test -x /usr/bin/objformat && \
test `/usr/bin/objformat` = "elf" ; then
if test "$rb_cv_binary_elf" = yes; then
LDFLAGS="-rdynamic"
DLDFLAGS='-Wl,-soname,$(.TARGET)'
rb_cv_freebsd_elf=yes
else
test "$GCC" = yes && `$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null || LDSHARED="ld -Bshareable"
fi
rb_cv_dlopen=yes ;;
netbsd*) LDSHARED="ld -shared"
case "$target_cpu" in
alpha)
LDFLAGS="-export-dynamic" ;;
esac
netbsd*) LDSHARED="ld -shared"
if test "$rb_cv_binary_elf" = yes; then
LDFLAGS="-export-dynamic"
fi
rb_cv_dlopen=yes ;;
openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
rb_cv_dlopen=yes ;;
@ -478,7 +506,7 @@ if test "$with_dln_a_out" != yes; then
DLDFLAGS="ruby.def -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
esac
rb_cv_dlopen=yes ;;
cygwin*) : ${LDSHARED='dllwrap --export-all -s'}
cygwin*) : ${LDSHARED="${DLLWRAP} --as=${AS} --dlltool-name=${DLLTOOL} --driver-name=${CC} --export-all -s"}
rb_cv_dlopen=yes ;;
*) LDSHARED='ld' ;;
esac
@ -687,18 +715,18 @@ if test "$enable_shared" = 'yes'; then
;;
freebsd*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR)$(MINOR)'
if test "$rb_cv_freebsd_elf" != "yes" ; then
if test "$rb_cv_binary_elf" != "yes" ; then
LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)"
LIBRUBY_ALIASES=''
fi
;;
netbsd*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)'
case "$target_cpu" in
alpha|mipsel|mipseb|powerpc|sparc64) # ELF platforms
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so' ;;
*) LIBRUBY_ALIASES= ;; # a.out platforms
esac
if test "$rb_cv_binary_elf" = yes; then # ELF platforms
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so'
else
LIBRUBY_ALIASES= # a.out platforms
fi
;;
solaris*)
XLDFLAGS='-R${prefix}/lib'
@ -727,10 +755,6 @@ if test "$enable_shared" = 'yes'; then
FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
LIBOBJS="$LIBOBJS strftime.o"
CCDLFLAGS=-DUSEIMPORTLIB
: ${NM=nm}
AC_SUBST(NM)
: ${DLLWRAP=dllwrap}
AC_SUBST(DLLWRAP)
;;
*)
;;

Просмотреть файл

@ -55,11 +55,15 @@
#endif
#define PATH_SEP_CHAR PATH_SEP[0]
#if defined(__human68k__) || defined(__CYGWIN__)
#if defined(__human68k__)
#undef HAVE_RANDOM
#undef HAVE_SETITIMER
#endif
#if defined(__CYGWIN__) || defined(DJGPP) || defined(__BOW__)
#undef HAVE_SETITIMER
#endif
#ifndef RUBY_PLATFORM
#define RUBY_PLATFORM "unknown-unknown"
#endif

8
dir.c
Просмотреть файл

@ -510,7 +510,7 @@ extract_path(p, pend)
len = pend - p;
alloc = ALLOC_N(char, len+1);
memcpy(alloc, p, len);
if (len > 0 && pend[-1] == '/') {
if (len > 1 && pend[-1] == '/') {
alloc[len-1] = 0;
}
else {
@ -584,19 +584,21 @@ glob(path, func, arg)
free(base);
break;
}
#define BASE (*base && !(*base == '/' && !base[1]))
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
if (recursive) {
if (strcmp(".", dp->d_name) == 0 || strcmp("..", dp->d_name) == 0)
continue;
buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+strlen(m)+6);
sprintf(buf, "%s%s%s/**%s", base, (*base)?"/":"", dp->d_name, m);
sprintf(buf, "%s%s%s/**%s", base, (BASE)?"/":"", dp->d_name, m);
glob(buf, func, arg);
free(buf);
continue;
}
if (fnmatch(magic, dp->d_name, FNM_PERIOD|FNM_PATHNAME) == 0) {
buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+2);
sprintf(buf, "%s%s%s", base, (*base)?"/":"", dp->d_name);
sprintf(buf, "%s%s%s", base, (BASE)?"/":"", dp->d_name);
if (!m) {
(*func)(buf, arg);
free(buf);

2
dln.c
Просмотреть файл

@ -80,7 +80,7 @@ int eaccess();
#endif
#ifndef FUNCNAME_PATTERN
# if defined(__hp9000s300) || (defined(__NetBSD__) && (!defined(__alpha__) && !defined(__mips__))) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(__OpenBSD__) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(__OpenBSD__) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
# define FUNCNAME_PATTERN "_Init_%.200s"
# else
# define FUNCNAME_PATTERN "Init_%.200s"

25
error.c
Просмотреть файл

@ -239,16 +239,18 @@ VALUE rb_eSignal;
VALUE rb_eFatal;
VALUE rb_eStandardError;
VALUE rb_eRuntimeError;
VALUE rb_eSyntaxError;
VALUE rb_eTypeError;
VALUE rb_eArgError;
VALUE rb_eNameError;
VALUE rb_eIndexError;
VALUE rb_eLoadError;
VALUE rb_eSecurityError;
VALUE rb_eNotImpError;
VALUE rb_eNoMemError;
VALUE rb_eScriptError;
VALUE rb_eNameError;
VALUE rb_eSyntaxError;
VALUE rb_eLoadError;
VALUE rb_eSystemCallError;
VALUE rb_mErrno;
@ -533,16 +535,18 @@ Init_Exception()
rb_eSignal = rb_define_class("SignalException", rb_eException);
rb_eStandardError = rb_define_class("StandardError", rb_eException);
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eStandardError);
rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
rb_eNameError = rb_define_class("NameError", rb_eStandardError);
rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
rb_eLoadError = rb_define_class("LoadError", rb_eStandardError);
rb_eScriptError = rb_define_class("ScriptError", rb_eException);
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
rb_eNameError = rb_define_class("NameError", rb_eScriptError);
rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
rb_eNotImpError = rb_define_class("NotImplementError", rb_eScriptError);
rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError);
rb_eNotImpError = rb_define_class("NotImplementError", rb_eException);
rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
init_syserr();
@ -672,6 +676,13 @@ rb_sys_fail(mesg)
rb_exc_raise(ee);
}
void
rb_error_frozen(what)
char *what;
{
rb_raise(rb_eTypeError, "can't modify frozen %s", what);
}
static void
init_syserr()
{

277
eval.c
Просмотреть файл

@ -90,7 +90,7 @@ static int scope_vmode;
#define SCOPE_SET(f) do {scope_vmode=(f);} while(0)
#define SCOPE_TEST(f) (scope_vmode&(f))
static int safe_level = 0;
int ruby_safe_level = 0;
/* safe-level:
0 - strings from streams/environment/ARGV are tainted (default)
1 - no dangerous operation by tainted string
@ -99,25 +99,19 @@ static int safe_level = 0;
4 - no global (non-tainted) variable modification/no direct output
*/
int
rb_safe_level()
{
return safe_level;
}
void
rb_set_safe_level(level)
int level;
{
if (level > safe_level) {
safe_level = level;
if (level > ruby_safe_level) {
ruby_safe_level = level;
}
}
static VALUE
safe_getter()
{
return INT2FIX(safe_level);
return INT2FIX(ruby_safe_level);
}
static void
@ -126,18 +120,18 @@ safe_setter(val)
{
int level = NUM2INT(val);
if (level < safe_level) {
if (level < ruby_safe_level) {
rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d",
safe_level, level);
ruby_safe_level, level);
}
safe_level = level;
ruby_safe_level = level;
}
void
rb_check_safe_str(x)
VALUE x;
{
if (safe_level > 0 && OBJ_TAINTED(x)){
if (ruby_safe_level > 0 && OBJ_TAINTED(x)){
rb_raise(rb_eSecurityError, "Insecure operation - %s",
rb_id2name(ruby_frame->last_func));
}
@ -151,9 +145,9 @@ void
rb_secure(level)
int level;
{
if (level <= safe_level) {
if (level <= ruby_safe_level) {
rb_raise(rb_eSecurityError, "Insecure operation `%s' for level %d",
rb_id2name(ruby_frame->last_func), safe_level);
rb_id2name(ruby_frame->last_func), ruby_safe_level);
}
}
@ -225,9 +219,10 @@ rb_add_method(klass, mid, node, noex)
if (klass == rb_cObject) {
rb_secure(4);
}
if (safe_level >= 4 && !OBJ_TAINTED(klass)) {
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
rb_raise(rb_eSecurityError, "Insecure: can't define method");
}
if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
body = NEW_METHOD(node, noex);
st_insert(RCLASS(klass)->m_tbl, mid, body);
}
@ -306,9 +301,10 @@ remove_method(klass, mid)
if (klass == rb_cObject) {
rb_secure(4);
}
if (safe_level >= 4 && !OBJ_TAINTED(klass)) {
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
rb_raise(rb_eSecurityError, "Insecure: can't remove method");
}
if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
if (!st_delete(RCLASS(klass)->m_tbl, &mid, &body)) {
rb_raise(rb_eNameError, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass));
@ -567,7 +563,7 @@ struct RVarmap *ruby_dyna_vars;
ruby_dyna_vars = _old; \
}
#define DVAR_DONT_RECYCLE FL_USER0
#define DVAR_DONT_RECYCLE FL_USER2
static struct RVarmap*
new_dvar(id, value, prev)
@ -597,6 +593,20 @@ rb_dvar_defined(id)
return Qfalse;
}
VALUE
rb_dvar_curr(id)
ID id;
{
struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
if (vars->id == 0) break;
if (vars->id == id) return Qtrue;
vars = vars->next;
}
return Qfalse;
}
VALUE
rb_dvar_ref(id)
ID id;
@ -621,48 +631,48 @@ rb_dvar_push(id, value)
}
static void
dvar_asgn(id, value, push)
dvar_asgn_internal(id, value, curr)
ID id;
VALUE value;
int push;
int curr;
{
int n = 0;
struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
if (push && vars->id == 0) break;
if (curr && vars->id == 0) {
n++;
if (n == 2) break;
}
if (vars->id == id) {
vars->val = value;
return;
}
vars = vars->next;
}
rb_dvar_push(id, value);
if (!ruby_dyna_vars) {
ruby_dyna_vars = new_dvar(id, value, 0);
}
else {
vars = new_dvar(id, value, ruby_dyna_vars->next);
ruby_dyna_vars->next = vars;
}
}
void
rb_dvar_asgn(id, value)
dvar_asgn(id, value)
ID id;
VALUE value;
{
dvar_asgn(id, value, 0);
dvar_asgn_internal(id, value, 0);
}
static void
dvar_asgn_push(id, value)
dvar_asgn_curr(id, value)
ID id;
VALUE value;
{
struct RVarmap* vars = 0;
if (ruby_dyna_vars && ruby_dyna_vars->id == 0) {
vars = ruby_dyna_vars;
ruby_dyna_vars = ruby_dyna_vars->next;
}
dvar_asgn(id, value, 1);
if (vars) {
vars->next = ruby_dyna_vars;
ruby_dyna_vars = vars;
}
dvar_asgn_internal(id, value, 1);
}
struct iter {
@ -1198,7 +1208,7 @@ rb_eval_cmd(cmd, arg)
int state;
VALUE val; /* OK */
struct SCOPE *saved_scope;
volatile int safe = safe_level;
volatile int safe = ruby_safe_level;
if (TYPE(cmd) != T_STRING) {
return rb_funcall2(cmd, rb_intern("call"),
@ -1212,7 +1222,7 @@ rb_eval_cmd(cmd, arg)
ruby_class = rb_cObject;
if (OBJ_TAINTED(cmd)) {
safe_level = 4;
ruby_safe_level = 4;
}
if ((state = EXEC_TAG()) == 0) {
@ -1222,7 +1232,7 @@ rb_eval_cmd(cmd, arg)
if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE))
FL_SET(saved_scope, SCOPE_DONT_RECYCLE);
ruby_scope = saved_scope;
safe_level = safe;
ruby_safe_level = safe;
POP_TAG();
POP_CLASS();
@ -1405,9 +1415,10 @@ rb_undef(klass, id)
if (ruby_class == rb_cObject) {
rb_secure(4);
}
if (safe_level >= 4 && !OBJ_TAINTED(klass)) {
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
rb_raise(rb_eSecurityError, "Insecure: can't undef");
}
if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
body = search_method(ruby_class, id, &origin);
if (!body || !body->nd_body) {
char *s0 = " class";
@ -1429,7 +1440,6 @@ rb_undef(klass, id)
rb_raise(rb_eNameError, "undefined method `%s' for%s `%s'",
rb_id2name(id),s0,rb_class2name(c));
}
rb_clear_cache_by_id(id);
rb_add_method(klass, id, 0, NOEX_PUBLIC);
rb_clear_cache_by_id(id);
}
@ -1653,7 +1663,7 @@ is_defined(self, node, buf)
case NODE_MASGN:
case NODE_LASGN:
case NODE_DASGN:
case NODE_DASGN_PUSH:
case NODE_DASGN_CURR:
case NODE_GASGN:
case NODE_IASGN:
case NODE_CASGN:
@ -2466,12 +2476,12 @@ rb_eval(self, node)
case NODE_DASGN:
result = rb_eval(self, node->nd_value);
rb_dvar_asgn(node->nd_vid, result);
dvar_asgn(node->nd_vid, result);
break;
case NODE_DASGN_PUSH:
case NODE_DASGN_CURR:
result = rb_eval(self, node->nd_value);
dvar_asgn_push(node->nd_vid, result);
dvar_asgn_curr(node->nd_vid, result);
break;
case NODE_GASGN:
@ -2709,7 +2719,7 @@ rb_eval(self, node)
}
body = search_method(ruby_class, node->nd_mid, &origin);
if (body){
if (RTEST(ruby_verbose)) {
if (RTEST(ruby_verbose) && ruby_class == origin) {
rb_warning("discarding old %s", rb_id2name(node->nd_mid));
}
rb_clear_cache_by_id(node->nd_mid);
@ -2760,12 +2770,13 @@ rb_eval(self, node)
rb_class2name(CLASS_OF(recv)));
}
if (safe_level >= 4 && !OBJ_TAINTED(recv)) {
if (rb_safe_level() >= 4 && !OBJ_TAINTED(recv)) {
rb_raise(rb_eSecurityError, "can't define singleton method");
}
if (OBJ_FROZEN(recv)) rb_error_frozen("object");
klass = rb_singleton_class(recv);
if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &body)) {
if (safe_level >= 4) {
if (rb_safe_level() >= 4) {
rb_raise(rb_eSecurityError, "re-defining method prohibited");
}
if (RTEST(ruby_verbose)) {
@ -2844,16 +2855,17 @@ rb_eval(self, node)
tmp = RCLASS(tmp)->super;
}
if (tmp != super) {
rb_raise(rb_eTypeError, "superclass mismatch for %s",
rb_id2name(node->nd_cname));
super = tmp;
goto override_class;
}
}
if (safe_level >= 4) {
if (rb_safe_level() >= 4) {
rb_raise(rb_eSecurityError, "extending class prohibited");
}
rb_clear_cache();
}
else {
override_class:
if (!super) super = rb_cObject;
klass = rb_define_class_id(node->nd_cname, super);
rb_const_set(ruby_class, node->nd_cname, klass);
@ -2892,7 +2904,7 @@ rb_eval(self, node)
rb_raise(rb_eTypeError, "%s is not a module",
rb_id2name(node->nd_cname));
}
if (safe_level >= 4) {
if (rb_safe_level() >= 4) {
rb_raise(rb_eSecurityError, "extending module prohibited");
}
}
@ -2919,8 +2931,9 @@ rb_eval(self, node)
rb_raise(rb_eTypeError, "no virtual class for %s",
rb_class2name(CLASS_OF(klass)));
}
if (safe_level >= 4 && !OBJ_TAINTED(klass))
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass))
rb_raise(rb_eSecurityError, "Insecure: can't extend object");
if (OBJ_FROZEN(klass)) rb_error_frozen("object");
if (FL_TEST(CLASS_OF(klass), FL_SINGLETON)) {
rb_clear_cache();
}
@ -3221,10 +3234,13 @@ rb_f_raise(argc, argv)
set_backtrace(mesg, (argc>2)?argv[2]:Qnil);
}
PUSH_FRAME(); /* fake frame */
*ruby_frame = *_frame.prev->prev;
if (ruby_frame != top_frame) {
PUSH_FRAME(); /* fake frame */
*ruby_frame = *_frame.prev->prev;
rb_longjmp(TAG_RAISE, mesg);
POP_FRAME();
}
rb_longjmp(TAG_RAISE, mesg);
POP_FRAME();
return Qnil; /* not reached */
}
@ -3455,11 +3471,11 @@ assign(self, lhs, val, check)
break;
case NODE_DASGN:
rb_dvar_asgn(lhs->nd_vid, val);
dvar_asgn(lhs->nd_vid, val);
break;
case NODE_DASGN_PUSH:
dvar_asgn_push(lhs->nd_vid, val);
case NODE_DASGN_CURR:
dvar_asgn_curr(lhs->nd_vid, val);
break;
case NODE_CASGN:
@ -3780,7 +3796,7 @@ rb_undefined(obj, id, argc, argv, call_status)
}
#ifdef DJGPP
# define STACK_LEVEL_MAX 65535
static int STACK_LEVEL_MAX = 65535;
#else
#ifdef __human68k__
extern int _stacksize;
@ -4608,7 +4624,7 @@ static VALUE
yield_under(under, self)
VALUE under, self;
{
if (safe_level >= 4 && !OBJ_TAINTED(self))
if (rb_safe_level() >= 4 && !OBJ_TAINTED(self))
rb_raise(rb_eSecurityError, "Insecure: can't eval");
return exec_under(yield_under_i, under, self);
}
@ -4842,7 +4858,7 @@ rb_f_require(obj, fname)
char *ext, *file, *feature, *buf; /* OK */
volatile VALUE load;
int state;
volatile int safe = safe_level;
volatile int safe = ruby_safe_level;
Check_SafeStr(fname);
if (rb_provided(RSTRING(fname)->ptr))
@ -4910,7 +4926,7 @@ rb_f_require(obj, fname)
return Qtrue;
load_rb:
safe_level = 0;
ruby_safe_level = 0;
if (rb_thread_loading(feature)) return Qfalse;
rb_provide(feature);
@ -4920,7 +4936,7 @@ rb_f_require(obj, fname)
}
POP_TAG();
rb_thread_loading_done(feature);
safe_level = safe;
ruby_safe_level = safe;
if (state) JUMP_TAG(state);
return Qtrue;
@ -5588,7 +5604,7 @@ rb_f_binding(self)
#define PROC_T3 FL_USER1
#define PROC_T4 FL_USER2
#define PROC_T5 (FL_USER1|FL_USER2)
#define PROC_TMAX (FL_USER1|FL_USER2)
#define PROC_TMASK (FL_USER1|FL_USER2)
static void
@ -5596,15 +5612,17 @@ proc_save_safe_level(data)
VALUE data;
{
if (OBJ_TAINTED(data)) {
switch (safe_level) {
switch (rb_safe_level()) {
case 3:
FL_SET(data, PROC_T3);
break;
case 4:
FL_SET(data, PROC_T4);
break;
case 5:
FL_SET(data, PROC_T5);
default:
if (rb_safe_level() > 4) {
FL_SET(data, PROC_TMAX);
}
break;
}
}
@ -5617,13 +5635,13 @@ proc_set_safe_level(data)
if (OBJ_TAINTED(data)) {
switch (RBASIC(data)->flags & PROC_TMASK) {
case PROC_T3:
safe_level = 3;
ruby_safe_level = 3;
break;
case PROC_T4:
safe_level = 4;
ruby_safe_level = 4;
break;
case PROC_T5:
safe_level = 5;
case PROC_TMAX:
ruby_safe_level = 5;
break;
}
}
@ -5695,7 +5713,7 @@ proc_call(proc, args)
volatile VALUE result = Qnil;
int state;
volatile int orphan;
volatile int safe = safe_level;
volatile int safe = ruby_safe_level;
Data_Get_Struct(proc, struct BLOCK, data);
orphan = blk_orphan(data);
@ -5741,7 +5759,7 @@ proc_call(proc, args)
state &= TAG_MASK;
}
ruby_block = old_block;
safe_level = safe;
ruby_safe_level = safe;
if (state) {
if (orphan) {/* orphan procedure */
@ -5799,7 +5817,7 @@ block_pass(self, node)
volatile VALUE result = Qnil;
int state;
volatile int orphan;
volatile int safe = safe_level;
volatile int safe = ruby_safe_level;
if (NIL_P(block)) {
return rb_eval(self, node->nd_iter);
@ -5836,7 +5854,7 @@ block_pass(self, node)
orphan = 2;
}
ruby_block = old_block;
safe_level = safe;
ruby_safe_level = safe;
if (state) {
if (orphan == 2) {/* escape from orphan procedure */
@ -5921,14 +5939,14 @@ method_call(argc, argv, method)
VALUE result;
struct METHOD *data;
int state;
volatile int safe = safe_level;
volatile int safe = ruby_safe_level;
Data_Get_Struct(method, struct METHOD, data);
PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT);
PUSH_TAG(PROT_NONE);
if (OBJ_TAINTED(data->recv) || OBJ_TAINTED(method)) {
OBJ_TAINT(method);
if (safe_level < 4) safe_level = 4;
if (ruby_safe_level < 4) ruby_safe_level = 4;
}
if ((state = EXEC_TAG()) == 0) {
result = rb_call0(data->klass, data->recv, data->id,
@ -5936,7 +5954,7 @@ method_call(argc, argv, method)
}
POP_TAG();
POP_ITER();
safe_level = safe;
ruby_safe_level = safe;
if (state) JUMP_TAG(state);
return result;
}
@ -6123,6 +6141,7 @@ struct thread {
int abort;
int priority;
int gid;
st_table *locals;
@ -6274,7 +6293,7 @@ rb_thread_save_context(th)
th->last_status = rb_last_status;
th->last_line = rb_lastline_get();
th->last_match = rb_backref_get();
th->safe = safe_level;
th->safe = ruby_safe_level;
th->file = ruby_sourcefile;
th->line = ruby_sourceline;
@ -6341,7 +6360,7 @@ rb_thread_restore_context(th, exit)
tracing = th->tracing;
ruby_errinfo = th->errinfo;
rb_last_status = th->last_status;
safe_level = th->safe;
ruby_safe_level = th->safe;
ruby_sourcefile = th->file;
ruby_sourceline = th->line;
@ -6599,9 +6618,10 @@ rb_thread_schedule()
curr_thread->file = ruby_sourcefile;
curr_thread->line = ruby_sourceline;
FOREACH_THREAD_FROM(curr, th) {
fprintf(stderr, "%s:%d:deadlock 0x%lx: %d:%d %s\n",
th->file, th->line, th->thread, th->status,
th->wait_for, th==main_thread?"(main)":"");
fprintf(stderr, "deadlock 0x%lx: %d:%d %s - %s:%d:\n",
th->thread, th->status,
th->wait_for, th==main_thread?"(main)":"",
th->file, th->line);
if (th->status == THREAD_STOPPED) {
next = th;
}
@ -6610,6 +6630,7 @@ rb_thread_schedule()
/* raise fatal error to main thread */
rb_thread_deadlock();
rb_thread_ready(next);
next->gid = 0;
next->status = THREAD_TO_KILL;
}
if (next->status == THREAD_RUNNABLE && next == curr_thread) {
@ -6901,11 +6922,15 @@ rb_thread_kill(thread)
{
thread_t th = rb_thread_check(thread);
if (th != curr_thread && th->safe < 4) {
rb_secure(4);
}
if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED)
return thread;
if (th == th->next || th == main_thread) rb_exit(0);
rb_thread_ready(th);
th->gid = 0;
th->status = THREAD_TO_KILL;
rb_thread_schedule();
return Qnil; /* not reached */
@ -6982,7 +7007,7 @@ rb_thread_priority(thread)
{
thread_t th = rb_thread_check(thread);;
if (safe_level >= 4 && th != curr_thread) {
if (rb_safe_level() >= 4 && th != curr_thread) {
rb_raise(rb_eSecurityError, "Insecure: can't get priority");
}
return INT2NUM(th->priority);
@ -7078,6 +7103,7 @@ rb_thread_abort_exc_set(thread, val)
th->last_match = 0;\
th->abort = 0;\
th->priority = 0;\
th->gid = 1;\
th->locals = 0;\
} while(0)
@ -7096,6 +7122,7 @@ rb_thread_alloc(klass)
th->next = curr_thread->next;
curr_thread->next = th;
th->priority = curr_thread->priority;
th->gid = curr_thread->gid;
}
else {
curr_thread = th->prev = th->next = th;
@ -7105,7 +7132,7 @@ rb_thread_alloc(klass)
return th;
}
#if defined(HAVE_SETITIMER) && !defined(__BOW__)
#if defined(HAVE_SETITIMER)
static void
catch_timer(sig)
int sig;
@ -7128,7 +7155,7 @@ static VALUE rb_thread_raise _((int, VALUE*, VALUE));
#define SCOPE_SHARED FL_USER1
#if defined(HAVE_SETITIMER) && !defined(__BOW__)
#if defined(HAVE_SETITIMER)
static int thread_init = 0;
void
@ -7167,7 +7194,7 @@ rb_thread_create_0(fn, arg, klass)
enum thread_status status;
int state;
#if defined(HAVE_SETITIMER) && !defined(__BOW__)
#if defined(HAVE_SETITIMER)
if (!thread_init) {
#ifdef POSIX_SIGNAL
posix_signal(SIGVTALRM, catch_timer);
@ -7180,6 +7207,7 @@ rb_thread_create_0(fn, arg, klass)
}
#endif
scope_dup(ruby_scope);
FL_SET(ruby_scope, SCOPE_SHARED);
rb_thread_save_context(curr_thread);
if (setjmp(curr_thread->context)) {
@ -7325,6 +7353,7 @@ rb_thread_cleanup()
FOREACH_THREAD(th) {
if (th != curr_thread && th->status != THREAD_KILLED) {
rb_thread_ready(th);
th->gid = 0;
th->status = THREAD_TO_KILL;
}
}
@ -7417,6 +7446,9 @@ rb_thread_raise(argc, argv, thread)
if (curr_thread == th) {
rb_f_raise(argc, argv);
}
if (th->safe < 4) {
rb_secure(4);
}
if (curr_thread->status != THREAD_KILLED)
rb_thread_save_context(curr_thread);
@ -7473,7 +7505,7 @@ rb_thread_local_aref(thread, id)
VALUE val;
th = rb_thread_check(thread);
if (safe_level >= 4 && th != curr_thread) {
if (rb_safe_level() >= 4 && th != curr_thread) {
rb_raise(rb_eSecurityError, "Insecure: thread locals");
}
if (!th->locals) return Qnil;
@ -7498,9 +7530,10 @@ rb_thread_local_aset(thread, id, val)
{
thread_t th = rb_thread_check(thread);
if (safe_level >= 4 && th != curr_thread) {
if (rb_safe_level() >= 4 && th != curr_thread) {
rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
}
if (OBJ_FROZEN(thread)) rb_error_frozen("thread locals");
if (!th->locals) {
th->locals = st_init_numtable();
@ -7613,9 +7646,65 @@ rb_cont_call(argc, argv, cont)
return Qnil;
}
struct thgroup {
int gid;
};
static VALUE
thgroup_s_new(klass)
VALUE klass;
{
VALUE group;
struct thgroup *data;
static int serial = 1;
group = Data_Make_Struct(klass, struct thgroup, 0, free, data);
data->gid = serial++;
return group;
}
static VALUE
thgroup_list(group)
VALUE group;
{
struct thgroup *data;
thread_t th;
VALUE ary;
Data_Get_Struct(group, struct thgroup, data);
ary = rb_ary_new();
FOREACH_THREAD(th) {
if (th->gid == data->gid) {
rb_ary_push(ary, th->thread);
}
}
END_FOREACH(th);
return ary;
}
static VALUE
thgroup_add(group, thread)
VALUE group, thread;
{
thread_t th;
struct thgroup *data;
rb_secure(4);
th = rb_thread_check(thread);
Data_Get_Struct(group, struct thgroup, data);
th->gid = data->gid;
return group;
}
void
Init_Thread()
{
VALUE cThGroup;
rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
rb_cThread = rb_define_class("Thread", rb_cObject);
@ -7669,6 +7758,12 @@ Init_Thread()
rb_undef_method(CLASS_OF(rb_cCont), "new");
rb_define_method(rb_cCont, "call", rb_cont_call, -1);
rb_define_global_function("callcc", rb_callcc, 0);
cThGroup = rb_define_class("ThreadGroup", rb_cObject);
rb_define_singleton_method(cThGroup, "new", thgroup_s_new, 0);
rb_define_method(cThGroup, "list", thgroup_list, 0);
rb_define_method(cThGroup, "add", thgroup_add, 1);
rb_define_const(cThGroup, "Default", thgroup_s_new(cThGroup));
}
static VALUE

Просмотреть файл

@ -41,6 +41,7 @@ end
$ipv6type = nil
$ipv6lib = nil
$ipv6libdir = nil
$ipv6trylibc = nil
if $ipv6
if egrep_cpp("yes", <<EOF)
#include <netinet/in.h>
@ -59,6 +60,7 @@ EOF
$ipv6type = "kame"
$ipv6lib="inet6"
$ipv6libdir="/usr/local/v6/lib"
$ipv6trylibc=true
$CFLAGS="-DINET6 "+$CFLAGS
elsif File.directory? "/usr/inet6"
$ipv6type = "linux"
@ -100,7 +102,7 @@ EOF
if $ipv6lib
if File.directory? $ipv6libdir and File.exist? "#{$ipv6libdir}/lib#{$ipv6lib}.a"
$LOCAL_LIBS = " -L#$ipv6libdir -l#$ipv6lib"
else
elsif !$ipv6trylibc
print <<EOS
Fatal: no #$ipv6lib library found. cannot continue.
@ -135,6 +137,23 @@ end
#include <netdb.h>
#include <string.h>
#include <sys/socket.h>
int
main()
{
struct sockaddr_storage ss;
ss.ss_family;
return 0;
}
EOF
$CFLAGS="-DHAVE_SOCKADDR_STORAGE "+$CFLAGS
end
if try_link(<<EOF)
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
int
main()

Просмотреть файл

@ -81,10 +81,27 @@ int Rconnect();
#define INET_SERVER 1
#define INET_SOCKS 2
#ifndef INET6
# undef ss_family
# define sockaddr_storage sockaddr
# define ss_family sa_family
#ifndef HAVE_SOCKADDR_STORAGE
/*
* RFC 2553: protocol-independent placeholder for socket addresses
*/
#define _SS_MAXSIZE 128
#define _SS_ALIGNSIZE (sizeof(long long))
#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2)
#define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \
_SS_PAD1SIZE - _SS_ALIGNSIZE)
struct sockaddr_storage {
#ifdef HAVE_SA_LEN
unsigned char ss_len; /* address length */
unsigned char ss_family; /* address family */
#else
unsigned short ss_family;
#endif
char __ss_pad1[_SS_PAD1SIZE];
long long __ss_align; /* force desired structure storage alignment */
char __ss_pad2[_SS_PAD2SIZE];
};
#endif
#ifdef NT

Просмотреть файл

@ -69,8 +69,7 @@ _timer_for_tcl(clientData)
VALUE thread;
Tk_DeleteTimerHandler(timer_token);
timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl,
(ClientData)0);
timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, (ClientData)0);
CHECK_INTS;
q = iqueue;
@ -93,8 +92,7 @@ static VALUE
lib_mainloop(self)
VALUE self;
{
timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl,
(ClientData)0);
timer_token = Tk_CreateTimerHandler(100, _timer_for_tcl, (ClientData)0);
DUMP1("start Tk_Mainloop");
Tk_MainLoop();
DUMP1("stop Tk_Mainloop");

Просмотреть файл

@ -196,7 +196,9 @@ module TkComm
def _get_eval_string(str)
return nil if str == None
if str.kind_of?(Hash)
if str.kind_of?(String)
# do nothing
elsif str.kind_of?(Hash)
str = hash_kv(str).join(" ")
elsif str.kind_of?(Array)
str = array2tk_list(str)
@ -417,11 +419,11 @@ module TkCore
INTERP._invoke("proc", "rb_out", "args", "if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $args]} ret]] != 0} {if {[regsub -all {!} $args {\\!} newargs] == 0} {return -code $st $ret} {if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $newargs]} ret]] != 0} {return -code $st $ret} {return $ret}}} {return $ret}")
def callback_break
raise TkCallbackBreak, "Tk callback returns 'break' status"
fail TkCallbackBreak, "Tk callback returns 'break' status"
end
def callback_continue
raise TkCallbackContinue, "Tk callback returns 'continue' status"
fail TkCallbackContinue, "Tk callback returns 'continue' status"
end
def after(ms, cmd=Proc.new)
@ -527,8 +529,8 @@ module TkCore
args.unshift "unknown"
res = INTERP._invoke(*args)
rescue
raise unless /^invalid command/ =~ $!
raise err
fail unless /^invalid command/ =~ $!
fail err
end
end
if INTERP._return_value() != 0
@ -583,6 +585,32 @@ module Tk
def yscrollcommand(cmd=Proc.new)
configure_cmd 'yscrollcommand', cmd
end
def xview(*index)
v = tk_send('xview', *index)
list(v) if index.size == 0
end
def yview(*index)
v = tk_send('yview', *index)
list(v) if index.size == 0
end
def xscrollbar(bar=nil)
if bar
@xscrollbar = bar
@xscrollbar.orient 'horizontal'
self.xscrollcommand {|arg| @xscrollbar.set *arg}
@xscrollbar.command {|arg| self.xview *arg}
end
@xscrollbar
end
def yscrollbar(bar=nil)
if bar
@yscrollbar = bar
@yscrollbar.orient 'vertical'
self.yscrollcommand {|arg| @yscrollbar.set *arg}
@yscrollbar.command {|arg| self.yview *arg}
end
@yscrollbar
end
end
module Wm
@ -784,7 +812,7 @@ class TkVariable
INTERP._eval(format('global %s; set %s', @id, @id))
rescue
if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1"
raise
fail
else
Hash[*tk_split_simplelist(INTERP._eval(format('global %s; array get %s',
@id, @id)))]
@ -798,7 +826,7 @@ class TkVariable
INTERP._eval(format('global %s; set %s %s', @id, @id, s))
rescue
if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1"
raise
fail
else
if val == []
INTERP._eval(format('global %s; unset %s; set %s(0) 0; unset %s(0)',
@ -815,7 +843,7 @@ class TkVariable
INTERP._eval(format('global %s; unset %s; array set %s %s',
@id, @id, @id, s))
else
raise
fail
end
end
end
@ -2149,7 +2177,7 @@ end
class TkTextWin<TkWindow
def create_self
raise TypeError, "TkTextWin is abstract class"
fail TypeError, "TkTextWin is abstract class"
end
def bbox(index)
@ -2195,6 +2223,14 @@ class TkListbox<TkTextWin
def curselection
list(tk_send('curselection'))
end
def get(*index)
v = tk_send('get', *index)
if index.size == 1
v
else
tk_split_simplelist(v)
end
end
def nearest(y)
tk_send('nearest', y).to_i
end
@ -2213,14 +2249,6 @@ class TkListbox<TkTextWin
def selection_set(first, last=None)
tk_send 'selection', 'set', first, last
end
def xview(cmd, *more)
v = tk_send('xview', cmd, *more)
v.to_i if more.size == 0
end
def yview(cmd, *more)
v = tk_send('yview', cmd, *more)
v.to_i if more.size == 0
end
end
module TkTreatMenuEntryFont

Просмотреть файл

@ -6,6 +6,8 @@
require 'tk.rb'
class TkEntry<TkLabel
include Scrollable
WidgetClassName = 'Entry'.freeze
WidgetClassNames[WidgetClassName] = self
def self.to_eval
@ -15,9 +17,6 @@ class TkEntry<TkLabel
def create_self
tk_call 'entry', @path
end
def xscrollcommand(cmd=Proc.new)
configure_cmd 'xscrollcommand', cmd
end
def delete(s, e=None)
tk_send 'delete', s, e
@ -59,9 +58,6 @@ class TkEntry<TkLabel
def selection_to(index)
tk_send 'selection', 'to', index
end
def xview(*index)
tk_send 'xview', *index
end
def value
tk_send 'get'

4
file.c
Просмотреть файл

@ -531,7 +531,7 @@ test_c(obj, fname)
struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse;
if (S_ISBLK(st.st_mode)) return Qtrue;
if (S_ISCHR(st.st_mode)) return Qtrue;
return Qfalse;
}
@ -1738,7 +1738,7 @@ static VALUE
rb_stat_c(obj)
VALUE obj;
{
if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;
if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;
return Qfalse;
}

2
gc.c
Просмотреть файл

@ -492,7 +492,7 @@ rb_gc_mark(ptr)
case NODE_GASGN:
case NODE_LASGN:
case NODE_DASGN:
case NODE_DASGN_PUSH:
case NODE_DASGN_CURR:
case NODE_IASGN:
case NODE_CASGN:
case NODE_MODULE:

29
hash.c
Просмотреть файл

@ -23,39 +23,17 @@ char *strchr _((char*,char));
char* strdup(const char*);
#endif
#define HASH_FREEZE FL_USER1
#define HASH_DELETED FL_USER2
#define HASH_DELETED FL_USER1
static void
rb_hash_modify(hash)
VALUE hash;
{
if (FL_TEST(hash, HASH_FREEZE))
rb_raise(rb_eTypeError, "can't modify frozen hash");
if (OBJ_FROZEN(hash)) rb_error_frozen("hash");
if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
}
VALUE
rb_hash_freeze(hash)
VALUE hash;
{
if (rb_safe_level() >= 4 && !OBJ_TAINTED(hash))
rb_raise(rb_eSecurityError, "Insecure: can't freeze hash");
FL_SET(hash, HASH_FREEZE);
return hash;
}
static VALUE
rb_hash_frozen_p(hash)
VALUE hash;
{
if (FL_TEST(hash, HASH_FREEZE))
return Qtrue;
return Qfalse;
}
VALUE rb_cHash;
static VALUE envtbl;
@ -1387,9 +1365,6 @@ Init_Hash()
rb_define_method(rb_cHash,"dup", rb_hash_dup, 0);
rb_define_method(rb_cHash,"rehash", rb_hash_rehash, 0);
rb_define_method(rb_cHash,"freeze", rb_hash_freeze, 0);
rb_define_method(rb_cHash,"frozen?",rb_hash_frozen_p, 0);
rb_define_method(rb_cHash,"to_hash", rb_hash_to_hash, 0);
rb_define_method(rb_cHash,"to_a", rb_hash_to_a, 0);
rb_define_method(rb_cHash,"to_s", rb_hash_to_s, 0);

Просмотреть файл

@ -101,6 +101,7 @@ void rb_alias _((VALUE, ID, ID));
void rb_attr _((VALUE,ID,int,int,int));
int rb_method_boundp _((VALUE, ID, int));
VALUE rb_dvar_defined _((ID));
VALUE rb_dvar_curr _((ID));
VALUE rb_dvar_ref _((ID));
void rb_dvar_asgn _((ID, VALUE));
void rb_dvar_push _((ID, VALUE));

15
io.c
Просмотреть файл

@ -1576,7 +1576,12 @@ rb_io_s_popen(argc, argv, self)
}
Check_SafeStr(pname);
port = pipe_open(RSTRING(pname)->ptr, mode);
if (NIL_P(port)) return Qnil;
if (NIL_P(port)) {
rb_yield(port);
}
else if (rb_iterator_p()) {
return rb_ensure(rb_yield, port, rb_io_close, port);
}
return port;
}
@ -1647,8 +1652,10 @@ rb_f_open(argc, argv)
}
port = pipe_open(RSTRING(pname)->ptr+1, mode);
if (NIL_P(port)) return Qnil;
if (rb_iterator_p()) {
if (NIL_P(port)) {
rb_yield(port);
}
else if (rb_iterator_p()) {
return rb_ensure(rb_yield, port, rb_io_close, port);
}
@ -3222,7 +3229,7 @@ Init_IO()
rb_rs = rb_default_rs = rb_str_new2("\n"); rb_output_rs = Qnil;
rb_global_variable(&rb_default_rs);
rb_str_freeze(rb_default_rs); /* avoid modifying RS_default */
OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);

Просмотреть файл

@ -35,7 +35,7 @@ class GetoptLong
#
# Status codes.
#
STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0..2
STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2
#
# Error types.

Просмотреть файл

@ -32,7 +32,7 @@ module Observable
def notify_observers(*arg)
if @observer_state
if @observer_peers
for i in @observer_peers
for i in @observer_peers.dup
i.update(*arg)
end
end

Просмотреть файл

@ -27,7 +27,7 @@ module ParseDate
if date.sub!(/(#{DAYPAT})[a-z]*,?/i, ' ')
wday = DAYS[$1.downcase]
end
if date.sub!(/(\d+):(\d+)(?::(\d+))?(?:\s*(am|pm))?(?:\s+([a-z]{1,4}(?:\s+[a-z]{1,4}|[-+]\d{4})?))?/i, ' ')
if date.sub!(/(\d+):(\d+)(?::(\d+))?(?:\s*(am|pm))?(?:\s+([a-z]{1,4}(?:\s+[a-z]{1,4}|[-+]\d{4})?|[-+]\d{4}))?/i, ' ')
hour = $1.to_i
min = $2.to_i
if $3

Просмотреть файл

@ -227,7 +227,7 @@ w_object(obj, arg, limit)
st_table *ivtbl = 0;
if (limit == 0) {
rb_raise(rb_eRuntimeError, "exceed depth limit");
rb_raise(rb_eArgError, "exceed depth limit");
}
if (obj == Qnil) {
w_byte(TYPE_NIL, arg);

4
node.h
Просмотреть файл

@ -45,7 +45,7 @@ enum node_type {
NODE_MASGN,
NODE_LASGN,
NODE_DASGN,
NODE_DASGN_PUSH,
NODE_DASGN_CURR,
NODE_GASGN,
NODE_IASGN,
NODE_CASGN,
@ -260,7 +260,7 @@ typedef struct RNode {
#define NEW_GASGN(v,val) rb_node_newnode(NODE_GASGN,v,val,rb_global_entry(v))
#define NEW_LASGN(v,val) rb_node_newnode(NODE_LASGN,v,val,local_cnt(v))
#define NEW_DASGN(v,val) rb_node_newnode(NODE_DASGN,v,val,0);
#define NEW_DASGN_PUSH(v,val) rb_node_newnode(NODE_DASGN_PUSH,v,val,0);
#define NEW_DASGN_CURR(v,val) rb_node_newnode(NODE_DASGN_CURR,v,val,0);
#define NEW_IASGN(v,val) rb_node_newnode(NODE_IASGN,v,val,0)
#define NEW_CASGN(v,val) rb_node_newnode(NODE_CASGN,v,val,0)
#define NEW_CDECL(v,val) rb_node_newnode(NODE_CDECL,v,val,0)

Просмотреть файл

@ -331,8 +331,7 @@ flo_modulo(x, y, modulo)
result = value1 - value2 * value;
}
#endif
if (modulo &&
(RFLOAT(x)->value < 0.0) != (result < 0.0) && result != 0.0) {
if (modulo && value*result<0.0) {
result += value;
}
return rb_float_new(result);
@ -352,6 +351,45 @@ flo_remainder(x, y)
return flo_modulo(x,y,0);
}
static VALUE
flo_divmod(x, y)
VALUE x, y;
{
double value, div, mod;
switch (TYPE(y)) {
case T_FIXNUM:
value = (double)FIX2LONG(y);
break;
case T_BIGNUM:
value = rb_big2dbl(y);
break;
case T_FLOAT:
value = RFLOAT(y)->value;
break;
default:
return rb_num_coerce_bin(x, y);
}
#ifdef HAVE_FMOD
mod = fmod(RFLOAT(x)->value, value);
#else
{
double value1 = RFLOAT(x)->value;
double value2;
modf(value1/value, &value2);
mod = value1 - value2 * value;
}
#endif
div = (RFLOAT(x)->value - mod) / value;
if (value*mod<0.0) {
mod += value;
div -= 1.0;
}
return rb_assoc_new(rb_float_new(div), rb_float_new(mod));
}
static VALUE
flo_pow(x, y)
VALUE x, y;
@ -1517,6 +1555,7 @@ Init_Numeric()
rb_define_method(rb_cFloat, "*", flo_mul, 1);
rb_define_method(rb_cFloat, "/", flo_div, 1);
rb_define_method(rb_cFloat, "%", flo_mod, 1);
rb_define_method(rb_cFloat, "divmod", flo_divmod, 1);
rb_define_method(rb_cFloat, "remainder", flo_remainder, 1);
rb_define_method(rb_cFloat, "**", flo_pow, 1);
rb_define_method(rb_cFloat, "==", flo_eq, 1);

Просмотреть файл

@ -297,6 +297,25 @@ rb_obj_untaint(obj)
return obj;
}
VALUE
rb_obj_freeze(obj)
VALUE obj;
{
if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj))
rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
OBJ_FREEZE(obj);
return obj;
}
static VALUE
rb_obj_frozen_p(obj)
VALUE obj;
{
if (OBJ_FROZEN(obj)) return Qtrue;
return Qfalse;
}
static VALUE
nil_to_i(obj)
VALUE obj;
@ -1004,6 +1023,8 @@ Init_Object()
rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);
rb_define_method(rb_mKernel, "to_a", rb_any_to_a, 0);
rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);

2
pack.c
Просмотреть файл

@ -305,7 +305,7 @@ static void
pack_add_ptr(str, add)
VALUE str, add;
{
#define STR_NO_ORIG FL_USER3 /* copied from string.c */
#define STR_NO_ORIG FL_USER2 /* copied from string.c */
if (!RSTRING(str)->orig) {
RSTRING(str)->orig = rb_ary_new();
FL_SET(str, STR_NO_ORIG);

199
parse.y
Просмотреть файл

@ -532,6 +532,10 @@ mlhs_node : variable
{
$$ = attrset($1, $3);
}
| primary tCOLON2 tIDENTIFIER
{
$$ = attrset($1, $3);
}
| backref
{
rb_backref_error($1);
@ -550,6 +554,10 @@ lhs : variable
{
$$ = attrset($1, $3);
}
| primary tCOLON2 tIDENTIFIER
{
$$ = attrset($1, $3);
}
| backref
{
rb_backref_error($1);
@ -683,6 +691,17 @@ arg : lhs '=' arg
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
fixpos($$, $1);
}
| primary tCOLON2 tIDENTIFIER tOP_ASGN arg
{
if ($4 == tOROP) {
$4 = 0;
}
else if ($4 == tANDOP) {
$4 = 1;
}
$$ = NEW_OP_ASGN2($1, $3, $4, $5);
fixpos($$, $1);
}
| backref tOP_ASGN arg
{
rb_backref_error($1);
@ -968,15 +987,6 @@ primary : literal
{
$$ = NEW_LIT($1);
}
| primary tCOLON2 tCONSTANT
{
value_expr($1);
$$ = NEW_COLON2($1, $3);
}
| tCOLON3 cname
{
$$ = NEW_COLON3($2);
}
| string
| tXSTRING
{
@ -986,6 +996,43 @@ primary : literal
| tDREGEXP
| var_ref
| backref
| tFID
{
$$ = NEW_VCALL($1);
}
| kBEGIN
compstmt
rescue
opt_else
ensure
kEND
{
if (!$3 && !$4 && !$5)
$$ = NEW_BEGIN($2);
else {
if ($3) $2 = NEW_RESCUE($2, $3, $4);
else if ($4) {
rb_warn("else without rescue is useless");
$2 = block_append($2, $4);
}
if ($5) $2 = NEW_ENSURE($2, $5);
$$ = $2;
}
fixpos($$, $2);
}
| tLPAREN compstmt ')'
{
$$ = $2;
}
| primary tCOLON2 tCONSTANT
{
value_expr($1);
$$ = NEW_COLON2($1, $3);
}
| tCOLON3 cname
{
$$ = NEW_COLON3($2);
}
| primary '[' aref_args ']'
{
value_expr($1);
@ -1040,10 +1087,6 @@ primary : literal
in_defined = 0;
$$ = NEW_DEFINED($5);
}
| tFID
{
$$ = NEW_VCALL($1);
}
| operation brace_block
{
$2->nd_iter = NEW_FCALL($1, 0);
@ -1109,30 +1152,6 @@ primary : literal
$$ = NEW_FOR($2, $5, $8);
fixpos($$, $2);
}
| kBEGIN
compstmt
rescue
opt_else
ensure
kEND
{
if (!$3 && !$4 && !$5)
$$ = NEW_BEGIN($2);
else {
if ($3) $2 = NEW_RESCUE($2, $3, $4);
else if ($4) {
rb_warn("else without rescue is useless");
$2 = block_append($2, $4);
}
if ($5) $2 = NEW_ENSURE($2, $5);
$$ = $2;
}
fixpos($$, $2);
}
| tLPAREN compstmt ')'
{
$$ = $2;
}
| kCLASS cname superclass
{
if (cur_mid || in_single)
@ -2400,11 +2419,80 @@ parse_qstring(term, paren)
}
static int
parse_quotedword(term, paren)
parse_quotedwords(term, paren)
int term, paren;
{
if (parse_qstring(term, paren) == 0) return 0;
yylval.node = NEW_CALL(NEW_STR(yylval.val), rb_intern("split"), 0);
NODE *qwords = 0;
int strstart;
int c;
int nest = 0;
strstart = ruby_sourceline;
newtok();
while ((c = nextc()) == ' ')
; /* skip preceding spaces */
pushback(c);
while ((c = nextc()) != term || nest > 0) {
if (c == -1) {
ruby_sourceline = strstart;
rb_compile_error("unterminated string meets end of file");
return 0;
}
if (ismbchar(c)) {
int i, len = mbclen(c)-1;
for (i = 0; i < len; i++) {
tokadd(c);
c = nextc();
}
}
else if (c == '\\') {
c = nextc();
switch (c) {
case '\n':
continue;
case '\\':
c = '\\';
break;
case ' ':
tokadd(' ');
break;
default:
tokadd('\\');
}
}
else if (c == ' ') {
NODE *str;
tokfix();
str = NEW_STR(rb_str_new(tok(), toklen()));
newtok();
if (!qwords) qwords = NEW_LIST(str);
else list_append(qwords, str);
while ((c = nextc()) == ' ')
; /* skip continuous spaces */
pushback(c);
continue;
}
if (paren) {
if (c == paren) nest++;
if (c == term && nest-- == 0) break;
}
tokadd(c);
}
tokfix();
if (toklen() > 0) {
NODE *str;
str = NEW_STR(rb_str_new(tok(), toklen()));
if (!qwords) qwords = NEW_LIST(str);
else list_append(qwords, str);
}
if (!qwords) qwords = NEW_ZARRAY();
yylval.node = qwords;
lex_state = EXPR_END;
return tDSTRING;
}
@ -2814,6 +2902,8 @@ yylex()
if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
(lex_state == EXPR_ARG && space_seen && !ISSPACE(c))) {
pushback(c);
if (lex_state == EXPR_ARG) arg_ambiguous();
if (ISDIGIT(c)) goto start_num;
lex_state = EXPR_BEG;
return tUPLUS;
}
@ -2837,8 +2927,13 @@ yylex()
}
if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
(lex_state == EXPR_ARG && space_seen && !ISSPACE(c))) {
if (lex_state == EXPR_ARG) arg_ambiguous();
lex_state = EXPR_BEG;
pushback(c);
if (ISDIGIT(c)) {
c = '-';
goto start_num;
}
return tUMINUS;
}
lex_state = EXPR_BEG;
@ -3072,6 +3167,12 @@ yylex()
lex_state = EXPR_BEG;
}
else {
if (lex_state == EXPR_ARG) {
if (space_seen) {
arg_ambiguous();
c = tLPAREN;
}
}
lex_state = EXPR_BEG;
}
return c;
@ -3147,7 +3248,7 @@ yylex()
return parse_qstring(term, paren);
case 'w':
return parse_quotedword(term, paren);
return parse_quotedwords(term, paren);
case 'x':
return parse_string('`', term, paren);
@ -3766,15 +3867,18 @@ assignable(id, val)
yyerror("Can't assign to __LINE__");
}
else if (is_local_id(id)) {
if (rb_dvar_defined(id)) {
if (rb_dvar_curr(id)) {
lhs = NEW_DASGN_CURR(id, val);
}
else if (rb_dvar_defined(id)) {
lhs = NEW_DASGN(id, val);
}
else if (local_id(id) || !dyna_in_block()) {
lhs = NEW_LASGN(id, val);
}
else{
rb_dvar_push(id, 0);
lhs = NEW_DASGN_PUSH(id, val);
rb_dvar_push(id, Qnil);
lhs = NEW_DASGN_CURR(id, val);
}
}
else if (is_global_id(id)) {
@ -3871,7 +3975,7 @@ node_assign(lhs, rhs)
case NODE_IASGN:
case NODE_LASGN:
case NODE_DASGN:
case NODE_DASGN_PUSH:
case NODE_DASGN_CURR:
case NODE_MASGN:
case NODE_CASGN:
case NODE_CDECL:
@ -4354,8 +4458,11 @@ top_local_setup()
static struct RVarmap*
dyna_push()
{
struct RVarmap* vars = ruby_dyna_vars;
rb_dvar_push(0, 0);
lvtbl->dlev++;
return ruby_dyna_vars;
return vars;
}
static void

27
ruby.h
Просмотреть файл

@ -160,11 +160,11 @@ VALUE rb_uint2inum _((unsigned long));
#define T_DATA 0x22
#define T_MATCH 0x23
#define T_VARMAP 0x7d
#define T_SCOPE 0x7e
#define T_NODE 0x7f
#define T_VARMAP 0x3d
#define T_SCOPE 0x3e
#define T_NODE 0x3f
#define T_MASK 0x7f
#define T_MASK 0x3f
#define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
@ -176,6 +176,10 @@ void rb_check_safe_str _((VALUE));
#define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
void rb_secure _((int));
extern int ruby_safe_level;
#define rb_safe_level() (ruby_safe_level)
void rb_set_safe_level _((int));
long rb_num2long _((VALUE));
unsigned long rb_num2ulong _((VALUE));
#define NUM2LONG(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2long((VALUE)x))
@ -326,10 +330,11 @@ struct RBignum {
#define RFILE(obj) (R_CAST(RFile)(obj))
#define FL_SINGLETON FL_USER0
#define FL_MARK (1<<7)
#define FL_FINALIZE (1<<8)
#define FL_TAINT (1<<9)
#define FL_EXIVAR (1<<10)
#define FL_MARK (1<<6)
#define FL_FINALIZE (1<<7)
#define FL_TAINT (1<<8)
#define FL_EXIVAR (1<<9)
#define FL_FREEZE (1<<10)
#define FL_USHIFT 11
@ -356,6 +361,9 @@ struct RBignum {
#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_FROZEN(x) FL_TEST((x), FL_FREEZE)
#define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE)
void *xmalloc _((size_t));
void *xcalloc _((size_t,size_t));
void *xrealloc _((void*,size_t));
@ -417,9 +425,6 @@ VALUE rb_equal _((VALUE,VALUE));
EXTERN VALUE ruby_verbose, ruby_debug;
int rb_safe_level _((void));
void rb_set_safe_level _((int));
void rb_raise __((VALUE, const char*, ...)) NORETURN;
void rb_fatal __((const char*, ...)) NORETURN;
void rb_bug __((const char*, ...)) NORETURN;

Просмотреть файл

@ -137,7 +137,9 @@ tmp.close
$bad = false
tmp = open("while_tmp", "r")
while tmp.gets()
if gsub!('vt100', 'VT100')
line = $_
$_ = gsub(/vt100/, 'VT100')
if $_ != line
gsub!('VT100', 'Vt100')
redo;
end
@ -677,7 +679,8 @@ ok("a".upcase![0] == ?A)
ok("A".downcase![0] == ?a)
ok("abc".tr!("a-z", "A-Z") == "ABC")
ok("aabbcccc".tr_s!("a-z", "A-Z") == "ABC")
ok("abc".tr!("0-9", "A-Z") == nil)
$x = "abc"
ok($x.tr("0-9", "A-Z").equal?($x))
ok("abcc".squeeze!("a-z") == "abc")
ok("abcd".delete!("bc") == "ad")
@ -965,6 +968,7 @@ File.unlink "script_tmp.bak" or `/bin/rm -f "script_tmp.bak"`
$bad = false
for script in Dir["{lib,sample}/*.rb"]
unless `./miniruby -c #{script}`.chomp == "Syntax OK"
p `./miniruby -c #{script}`.chomp
$bad = true
end
end
@ -1009,7 +1013,7 @@ ok(foo.test == "test")
begin
foo.test2
ok false
rescue
rescue NameError
ok true
end
@ -1061,7 +1065,7 @@ ok($$.instance_of?(Fixnum))
begin
$$ = 5
ok false
rescue
rescue NameError
ok true
end

393
string.c
Просмотреть файл

@ -24,8 +24,7 @@
VALUE rb_cString;
#define STR_FREEZE FL_USER1
#define STR_NO_ORIG FL_USER3
#define STR_NO_ORIG FL_USER2
VALUE rb_fs;
@ -94,11 +93,10 @@ VALUE
rb_str_new4(orig)
VALUE orig;
{
if (FL_TEST(orig, STR_FREEZE)) {
return orig;
}
else if (RSTRING(orig)->orig && !FL_TEST(orig, STR_NO_ORIG)) {
return rb_str_freeze(RSTRING(orig)->orig);
if (OBJ_FROZEN(orig)) return orig;
if (RSTRING(orig)->orig && !FL_TEST(orig, STR_NO_ORIG)) {
OBJ_FREEZE(RSTRING(orig)->orig);
return RSTRING(orig)->orig;
}
else {
NEWOBJ(str, struct RString);
@ -111,7 +109,8 @@ rb_str_new4(orig)
if (OBJ_TAINTED(orig)) {
OBJ_TAINT(str);
}
FL_SET(str, STR_FREEZE);
OBJ_FREEZE(str);
return (VALUE)str;
}
}
@ -328,8 +327,7 @@ rb_str_modify(str)
{
char *ptr;
if (FL_TEST(str, STR_FREEZE))
rb_raise(rb_eTypeError, "can't modify frozen string");
if (OBJ_FROZEN(str)) rb_error_frozen("string");
if (!OBJ_TAINTED(str) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return;
@ -342,36 +340,18 @@ rb_str_modify(str)
RSTRING(str)->orig = 0;
}
VALUE
rb_str_freeze(str)
VALUE str;
{
if (rb_safe_level() >= 4 && !OBJ_TAINTED(str))
rb_raise(rb_eSecurityError, "Insecure: can't freeze string");
FL_SET(str, STR_FREEZE);
return str;
}
static VALUE
rb_str_frozen_p(str)
VALUE str;
{
if (FL_TEST(str, STR_FREEZE))
return Qtrue;
return Qfalse;
}
VALUE
rb_str_dup_frozen(str)
VALUE str;
{
if (RSTRING(str)->orig && !FL_TEST(str, STR_NO_ORIG)) {
return rb_str_freeze(RSTRING(str)->orig);
OBJ_FREEZE(RSTRING(str)->orig);
return RSTRING(str)->orig;
}
if (FL_TEST(str, STR_FREEZE))
return str;
return rb_str_freeze(rb_str_dup(str));
if (OBJ_FROZEN(str)) return str;
str = rb_str_dup(str);
OBJ_FREEZE(str);
return str;
}
VALUE
@ -966,6 +946,48 @@ rb_str_aset_m(argc, argv, str)
return rb_str_aset(str, arg1, arg2);
}
static VALUE
rb_str_slice_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
VALUE arg1, arg2;
long pos, len, i;
rb_str_modify(str);
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
pos = NUM2LONG(arg1);
len = NUM2LONG(arg2);
delete_pos_len:
if (pos < 0) {
pos = RSTRING(str)->len + pos;
}
arg2 = rb_str_substr(str, pos, len);
rb_str_replace(str, pos, len, rb_str_new(0,0));
return arg2;
}
if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, RSTRING(str)->len, 0)) {
goto delete_pos_len;
}
pos = NUM2LONG(arg1);
len = RSTRING(str)->len;
if (pos >= len) return Qnil;
if (pos < 0) pos += len;
if (pos < 0) return Qnil;
arg2 = INT2FIX(RSTRING(str)->ptr[pos] & 0xff);
memmove(RSTRING(str)->ptr + pos,
RSTRING(str)->ptr + pos + 1,
RSTRING(str)->len - (pos + 1));
RSTRING(str)->len--;
return arg2;
}
static VALUE
get_pat(pat)
VALUE pat;
@ -986,7 +1008,7 @@ get_pat(pat)
}
static VALUE
rb_str_sub_bang(argc, argv, str)
str_sub_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
@ -1040,19 +1062,33 @@ rb_str_sub_bang(argc, argv, str)
return Qnil;
}
static VALUE
rb_str_sub_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str_sub_bang(argc, argv, str);
return str;
}
static VALUE
rb_str_sub(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str = rb_str_dup(str);
rb_str_sub_bang(argc, argv, str);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(str_sub_bang(argc, argv, dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
rb_str_gsub_bang(argc, argv, str)
str_gsub_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
@ -1150,15 +1186,29 @@ rb_str_gsub_bang(argc, argv, str)
return str;
}
static VALUE
rb_str_gsub_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str_gsub_bang(argc, argv, str);
return str;
}
static VALUE
rb_str_gsub(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str = rb_str_dup(str);
rb_str_gsub_bang(argc, argv, str);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(str_gsub_bang(argc, argv, dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
@ -1200,13 +1250,15 @@ rb_f_sub(argc, argv)
int argc;
VALUE *argv;
{
VALUE line;
VALUE line = uscore_get();
VALUE dup = rb_str_dup(line);
line = rb_str_dup(uscore_get());
if (!NIL_P(rb_str_sub_bang(argc, argv, line))) {
rb_lastline_set(line);
if (NIL_P(str_sub_bang(argc, argv, dup))) {
rb_gc_force_recycle(dup);
return line;
}
return line;
rb_lastline_set(dup);
return dup;
}
static VALUE
@ -1222,13 +1274,15 @@ rb_f_gsub(argc, argv)
int argc;
VALUE *argv;
{
VALUE line;
VALUE line = uscore_get();
VALUE dup = rb_str_dup(line);
line = rb_str_dup(uscore_get());
if (!NIL_P(rb_str_gsub_bang(argc, argv, line = rb_str_dup(line)))) {
rb_lastline_set(line);
if (NIL_P(str_gsub_bang(argc, argv, dup))) {
rb_gc_force_recycle(dup);
return line;
}
return line;
rb_lastline_set(dup);
return dup;
}
static VALUE
@ -1496,7 +1550,7 @@ rb_str_dump(str)
}
static VALUE
rb_str_upcase_bang(str)
str_upcase_bang(str)
VALUE str;
{
char *s, *send;
@ -1520,16 +1574,28 @@ rb_str_upcase_bang(str)
}
static VALUE
rb_str_upcase(str)
rb_str_upcase_bang(str)
VALUE str;
{
str = rb_str_dup(str);
rb_str_upcase_bang(str);
str_upcase_bang(str);
return str;
}
static VALUE
rb_str_downcase_bang(str)
rb_str_upcase(str)
VALUE str;
{
VALUE dup = rb_str_dup(str);
if (NIL_P(str_upcase_bang(dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
str_downcase_bang(str)
VALUE str;
{
char *s, *send;
@ -1553,16 +1619,28 @@ rb_str_downcase_bang(str)
}
static VALUE
rb_str_downcase(str)
rb_str_downcase_bang(str)
VALUE str;
{
str = rb_str_dup(str);
rb_str_downcase_bang(str);
str_downcase_bang(str);
return str;
}
static VALUE
rb_str_capitalize_bang(str)
rb_str_downcase(str)
VALUE str;
{
VALUE dup = rb_str_dup(str);
if (NIL_P(str_downcase_bang(dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
str_capitalize_bang(str)
VALUE str;
{
char *s, *send;
@ -1588,16 +1666,28 @@ rb_str_capitalize_bang(str)
}
static VALUE
rb_str_capitalize(str)
rb_str_capitalize_bang(str)
VALUE str;
{
str = rb_str_dup(str);
rb_str_capitalize_bang(str);
str_capitalize_bang(str);
return str;
}
static VALUE
rb_str_swapcase_bang(str)
rb_str_capitalize(str)
VALUE str;
{
VALUE dup = rb_str_dup(str);
if (NIL_P(str_capitalize_bang(dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
str_swapcase_bang(str)
VALUE str;
{
char *s, *send;
@ -1624,13 +1714,25 @@ rb_str_swapcase_bang(str)
return Qnil;
}
static VALUE
rb_str_swapcase_bang(str)
VALUE str;
{
str_swapcase_bang(str);
return str;
}
static VALUE
rb_str_swapcase(str)
VALUE str;
{
str = rb_str_dup(str);
rb_str_swapcase_bang(str);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(str_swapcase_bang(dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
typedef unsigned char *USTR;
@ -1771,16 +1873,19 @@ static VALUE
rb_str_tr_bang(str, src, repl)
VALUE str, src, repl;
{
return tr_trans(str, src, repl, 0);
tr_trans(str, src, repl, 0);
return str;
}
static VALUE
rb_str_tr(str, src, repl)
VALUE str, src, repl;
{
str = rb_str_dup(str);
tr_trans(str, src, repl, 0);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(tr_trans(str, src, repl, 0)))
return str;
return dup;
}
static void
@ -1818,7 +1923,7 @@ tr_setup_table(str, table, init)
}
static VALUE
rb_str_delete_bang(argc, argv, str)
str_delete_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
@ -1855,19 +1960,33 @@ rb_str_delete_bang(argc, argv, str)
return Qnil;
}
static VALUE
rb_str_delete_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str_delete_bang(argc, argv, str);
return str;
}
static VALUE
rb_str_delete(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str = rb_str_dup(str);
rb_str_delete_bang(argc, argv, str);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(str_delete_bang(argc, argv, dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
rb_str_squeeze_bang(argc, argv, str)
str_squeeze_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
@ -1915,31 +2034,48 @@ rb_str_squeeze_bang(argc, argv, str)
return Qnil;
}
static VALUE
rb_str_squeeze_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str_squeeze_bang(argc, argv, str);
return str;
}
static VALUE
rb_str_squeeze(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str = rb_str_dup(str);
rb_str_squeeze_bang(argc, argv, str);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(str_squeeze_bang(argc, argv, dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
rb_str_tr_s_bang(str, src, repl)
VALUE str, src, repl;
{
return tr_trans(str, src, repl, 1);
tr_trans(str, src, repl, 1);
return str;
}
static VALUE
rb_str_tr_s(str, src, repl)
VALUE str, src, repl;
{
str = rb_str_dup(str);
tr_trans(str, src, repl, 1);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(tr_trans(str, src, repl, 1)))
return str;
return dup;
}
static VALUE
@ -2187,6 +2323,7 @@ rb_str_each_line(argc, argv, str)
if (s != pend) {
if (p > pend) p = pend;
line = rb_str_new(s, p - s);
OBJ_INFECT(line, str);
rb_yield(line);
}
@ -2206,7 +2343,7 @@ rb_str_each_byte(str)
}
static VALUE
rb_str_chop_bang(str)
str_chop_bang(str)
VALUE str;
{
if (RSTRING(str)->len > 0) {
@ -2224,13 +2361,25 @@ rb_str_chop_bang(str)
return Qnil;
}
static VALUE
rb_str_chop_bang(str)
VALUE str;
{
str_chop_bang(str);
return str;
}
static VALUE
rb_str_chop(str)
VALUE str;
{
str = rb_str_dup(str);
rb_str_chop_bang(str);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(str_chop_bang(dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
@ -2243,16 +2392,18 @@ rb_f_chop_bang(str)
static VALUE
rb_f_chop()
{
VALUE str = rb_str_dup(uscore_get());
VALUE line = uscore_get();
VALUE dup = rb_str_dup(line);
if (!NIL_P(rb_str_chop_bang(str))) {
rb_lastline_set(str);
if (!NIL_P(str_chop_bang(dup))) {
rb_lastline_set(dup);
return dup;
}
return str;
return line;
}
static VALUE
rb_str_chomp_bang(argc, argv, str)
str_chomp_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
@ -2294,15 +2445,29 @@ rb_str_chomp_bang(argc, argv, str)
return Qnil;
}
static VALUE
rb_str_chomp_bang(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str_chomp_bang(argc, argv, str);
return str;
}
static VALUE
rb_str_chomp(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
str = rb_str_dup(str);
rb_str_chomp_bang(argc, argv, str);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(str_chomp_bang(argc, argv, dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
@ -2318,15 +2483,18 @@ rb_f_chomp(argc, argv)
int argc;
VALUE *argv;
{
VALUE str = rb_str_dup(uscore_get());
if (!NIL_P(rb_str_chomp_bang(argc, argv, str))) {
rb_lastline_set(str);
VALUE str = uscore_get();
VALUE dup = rb_str_dup(str);
if (!NIL_P(str_chomp_bang(argc, argv, dup))) {
rb_lastline_set(dup);
return dup;
}
return str;
}
static VALUE
rb_str_strip_bang(str)
str_strip_bang(str)
VALUE str;
{
char *s, *t, *e;
@ -2361,13 +2529,25 @@ rb_str_strip_bang(str)
return str;
}
static VALUE
rb_str_strip_bang(str)
VALUE str;
{
str_strip_bang(str);
return str;
}
static VALUE
rb_str_strip(str)
VALUE str;
{
str = rb_str_dup(str);
rb_str_strip_bang(str);
return str;
VALUE dup = rb_str_dup(str);
if (NIL_P(str_strip_bang(dup))) {
rb_gc_force_recycle(dup);
return str;
}
return dup;
}
static VALUE
@ -2621,9 +2801,6 @@ Init_String()
rb_define_method(rb_cString, "rindex", rb_str_rindex, -1);
rb_define_method(rb_cString, "replace", rb_str_replace_m, 1);
rb_define_method(rb_cString, "freeze", rb_str_freeze, 0);
rb_define_method(rb_cString, "frozen?", rb_str_frozen_p, 0);
rb_define_method(rb_cString, "to_i", rb_str_to_i, 0);
rb_define_method(rb_cString, "to_f", rb_str_to_f, 0);
rb_define_method(rb_cString, "to_s", rb_str_to_s, 0);
@ -2702,6 +2879,10 @@ Init_String()
rb_define_global_function("split", rb_f_split, -1);
rb_define_method(rb_cString, "slice", rb_str_aref_m, -1);
rb_define_method(rb_cString, "slice!", rb_str_slice_bang, -1);
rb_define_method(rb_cString, "delete_at", rb_str_slice_bang, -1);
to_str = rb_intern("to_s");
rb_fs = Qnil;

Просмотреть файл

@ -474,6 +474,7 @@ rb_struct_aset_id(s, id, val)
rb_bug("non-initialized struct");
}
if (OBJ_FROZEN(s)) rb_error_frozen("Struct");
len = RARRAY(member)->len;
for (i=0; i<len; i++) {
if (FIX2UINT(RARRAY(member)->ptr[i]) == id) {
@ -502,6 +503,7 @@ rb_struct_aset(s, idx, val)
if (RSTRUCT(s)->len <= i)
rb_raise(rb_eIndexError, "offset %d too large for struct(size:%d)",
i, RSTRUCT(s)->len);
if (OBJ_FROZEN(s)) rb_error_frozen("Struct");
return RSTRUCT(s)->ptr[i] = val;
}

10
time.c
Просмотреть файл

@ -400,14 +400,12 @@ time_cmp(time1, time2)
{
double t;
if (tobj1->tv.tv_sec == (time_t)RFLOAT(time2)->value)
return INT2FIX(0);
t = (double)tobj1->tv.tv_sec + (double)tobj1->tv.tv_usec*1e-6;
if (tobj1->tv.tv_sec == (time_t)RFLOAT(time2)->value)
return INT2FIX(0);
if (tobj1->tv.tv_sec > (time_t)RFLOAT(time2)->value)
if (t > RFLOAT(time2)->value)
return INT2FIX(1);
return FIX2INT(-1);
if (t < RFLOAT(time2)->value)
return INT2FIX(-1);
return INT2FIX(0);
}
}

Просмотреть файл

@ -898,6 +898,7 @@ rb_ivar_set(obj, id, val)
{
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
@ -984,6 +985,7 @@ rb_obj_remove_instance_variable(obj, name)
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
if (!rb_is_instance_id(id)) {
rb_raise(rb_eNameError, "`%s' is not an instance variable",
rb_id2name(id));
@ -1099,11 +1101,12 @@ rb_mod_remove_const(mod, name)
ID id = rb_to_id(name);
VALUE val;
if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
if (!rb_is_const_id(id)) {
rb_raise(rb_eNameError, "`%s' is not constant", rb_id2name(id));
}
if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
return val;
@ -1221,9 +1224,13 @@ rb_const_set(klass, id, val)
{
if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't set constant");
if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
if (!RCLASS(klass)->iv_tbl) {
RCLASS(klass)->iv_tbl = st_init_numtable();
}
else if (st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
rb_warn("already initialized constant %s", rb_id2name(id));
}
st_insert(RCLASS(klass)->iv_tbl, id, val);
}

Просмотреть файл

@ -1,4 +1,4 @@
#define RUBY_VERSION "1.5.2"
#define RUBY_RELEASE_DATE "2000-01-18"
#define RUBY_RELEASE_DATE "2000-02-01"
#define RUBY_VERSION_CODE 152
#define RUBY_RELEASE_CODE 20000118
#define RUBY_RELEASE_CODE 20000201

Просмотреть файл

@ -1619,7 +1619,8 @@ myfdopen (int fd, const char *mode)
void
myfdclose(FILE *fp)
{
fclose(fp);
_free_osfhnd(fileno(fp));
fclose(fp);
}